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 uint32_t active_connections;
144 static struct notify_back_channel *back_channels;
146 /* Map generic permissions to printer object specific permissions */
148 const struct standard_mapping printer_std_mapping = {
155 /* Map generic permissions to print server object specific permissions */
157 const struct standard_mapping printserver_std_mapping = {
164 /* API table for Xcv Monitor functions */
166 struct xcv_api_table {
168 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
171 static void prune_printername_cache(void);
173 /********************************************************************
174 * Canonicalize servername.
175 ********************************************************************/
177 static const char *canon_servername(const char *servername)
179 const char *pservername = servername;
180 while (*pservername == '\\') {
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
193 return JOB_STATUS_PAUSED;
195 return JOB_STATUS_SPOOLING;
197 return JOB_STATUS_PRINTING;
199 return JOB_STATUS_ERROR;
201 return JOB_STATUS_DELETING;
203 return JOB_STATUS_OFFLINE;
205 return JOB_STATUS_PAPEROUT;
207 return JOB_STATUS_PRINTED;
209 return JOB_STATUS_DELETED;
211 return JOB_STATUS_BLOCKED_DEVQ;
212 case LPQ_USER_INTERVENTION:
213 return JOB_STATUS_USER_INTERVENTION;
218 static int nt_printq_status(int v)
222 return PRINTER_STATUS_PAUSED;
231 /***************************************************************************
232 Disconnect from the client
233 ****************************************************************************/
235 static void srv_spoolss_replycloseprinter(int snum,
236 struct printer_handle *prn_hnd)
242 * Tell the specific printing tdb we no longer want messages for this printer
243 * by deregistering our PID.
246 if (!print_notify_deregister_pid(snum)) {
247 DEBUG(0, ("Failed to register our pid for printer %s\n",
248 lp_const_servicename(snum)));
251 /* weird if the test succeeds !!! */
252 if (prn_hnd->notify.cli_chan == NULL ||
253 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255 prn_hnd->notify.cli_chan->active_connections == 0) {
256 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258 TALLOC_FREE(prn_hnd->notify.cli_chan);
262 status = dcerpc_spoolss_ReplyClosePrinter(
263 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
265 &prn_hnd->notify.cli_hnd,
267 if (!NT_STATUS_IS_OK(status)) {
268 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270 result = ntstatus_to_werror(status);
271 } else if (!W_ERROR_IS_OK(result)) {
272 DEBUG(0, ("reply_close_printer failed [%s].\n",
273 win_errstr(result)));
276 /* if it's the last connection, deconnect the IPC$ share */
277 if (prn_hnd->notify.cli_chan->active_connections == 1) {
279 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281 TALLOC_FREE(prn_hnd->notify.cli_chan);
283 if (prn_hnd->notify.msg_ctx != NULL) {
284 messaging_deregister(prn_hnd->notify.msg_ctx,
285 MSG_PRINTER_NOTIFY2, NULL);
289 if (prn_hnd->notify.cli_chan) {
290 prn_hnd->notify.cli_chan->active_connections--;
291 prn_hnd->notify.cli_chan = NULL;
295 /****************************************************************************
296 Functions to free a printer entry datastruct.
297 ****************************************************************************/
299 static int printer_entry_destructor(struct printer_handle *Printer)
301 if (Printer->notify.cli_chan != NULL &&
302 Printer->notify.cli_chan->active_connections > 0) {
305 switch(Printer->printer_type) {
307 srv_spoolss_replycloseprinter(snum, Printer);
311 snum = print_queue_snum(Printer->sharename);
313 srv_spoolss_replycloseprinter(snum, Printer);
321 Printer->notify.flags=0;
322 Printer->notify.options=0;
323 Printer->notify.localmachine[0]='\0';
324 Printer->notify.printerlocal=0;
325 TALLOC_FREE(Printer->notify.option);
326 TALLOC_FREE(Printer->devmode);
328 /* Remove from the internal list. */
329 DLIST_REMOVE(printers_list, Printer);
333 /****************************************************************************
334 find printer index by handle
335 ****************************************************************************/
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338 struct policy_handle *hnd)
340 struct printer_handle *find_printer = NULL;
342 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
350 /****************************************************************************
351 Close printer index by handle.
352 ****************************************************************************/
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
359 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
364 close_policy_hnd(p, hnd);
369 /****************************************************************************
370 Delete a printer given a handle.
371 ****************************************************************************/
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374 const char *sharename,
375 struct messaging_context *msg_ctx)
377 char *cmd = lp_deleteprinter_cmd();
378 char *command = NULL;
380 bool is_print_op = false;
382 /* can't fail if we don't try */
387 command = talloc_asprintf(ctx,
394 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396 DEBUG(10,("Running [%s]\n", command));
398 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
403 if ( (ret = smbrun(command, NULL)) == 0 ) {
404 /* Tell everyone we updated smb.conf. */
405 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
411 /********** END SePrintOperatorPrivlege BLOCK **********/
413 DEBUGADD(10,("returned [%d]\n", ret));
415 TALLOC_FREE(command);
418 return WERR_BADFID; /* What to return here? */
420 /* go ahead and re-read the services immediately */
422 reload_services(msg_ctx, -1, false);
425 if ( lp_servicenumber( sharename ) >= 0 )
426 return WERR_ACCESS_DENIED;
431 /****************************************************************************
432 Delete a printer given a handle.
433 ****************************************************************************/
435 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
437 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
441 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
447 * It turns out that Windows allows delete printer on a handle
448 * opened by an admin user, then used on a pipe handle created
449 * by an anonymous user..... but they're working on security.... riiight !
453 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
454 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
455 return WERR_ACCESS_DENIED;
458 /* this does not need a become root since the access check has been
459 done on the handle already */
461 result = winreg_delete_printer_key_internal(p->mem_ctx,
462 get_session_info_system(),
466 if (!W_ERROR_IS_OK(result)) {
467 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
471 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
472 Printer->sharename, p->msg_ctx);
473 if (!W_ERROR_IS_OK(result)) {
476 prune_printername_cache();
480 /****************************************************************************
481 Return the snum of a printer corresponding to an handle.
482 ****************************************************************************/
484 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
485 int *number, struct share_params **params)
487 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
490 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
495 switch (Printer->printer_type) {
497 DEBUG(4,("short name:%s\n", Printer->sharename));
498 *number = print_queue_snum(Printer->sharename);
499 return (*number != -1);
507 /****************************************************************************
508 Set printer handle type.
509 Check if it's \\server or \\server\printer
510 ****************************************************************************/
512 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
514 DEBUG(3,("Setting printer type=%s\n", handlename));
516 /* it's a print server */
517 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
518 DEBUGADD(4,("Printer is a print server\n"));
519 Printer->printer_type = SPLHND_SERVER;
521 /* it's a printer (set_printer_hnd_name() will handle port monitors */
523 DEBUGADD(4,("Printer is a printer\n"));
524 Printer->printer_type = SPLHND_PRINTER;
530 static void prune_printername_cache_fn(const char *key, const char *value,
531 time_t timeout, void *private_data)
536 static void prune_printername_cache(void)
538 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
541 /****************************************************************************
542 Set printer handle name.. Accept names like \\server, \\server\printer,
543 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
544 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
545 XcvDataPort() interface.
546 ****************************************************************************/
548 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
549 const struct auth_session_info *session_info,
550 struct messaging_context *msg_ctx,
551 struct printer_handle *Printer,
552 const char *handlename)
555 int n_services=lp_numservices();
557 const char *printername;
558 const char *servername = NULL;
561 struct spoolss_PrinterInfo2 *info2 = NULL;
566 * Hopefully nobody names his printers like this. Maybe \ or ,
567 * are illegal in printer names even?
569 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
573 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
574 (unsigned long)strlen(handlename)));
576 aprinter = discard_const_p(char, handlename);
577 if ( *handlename == '\\' ) {
578 servername = canon_servername(handlename);
579 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
583 if (!is_myname_or_ipaddr(servername)) {
584 return WERR_INVALID_PRINTER_NAME;
586 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
587 if (Printer->servername == NULL) {
592 if (Printer->printer_type == SPLHND_SERVER) {
596 if (Printer->printer_type != SPLHND_PRINTER) {
597 return WERR_INVALID_HANDLE;
600 DEBUGADD(5, ("searching for [%s]\n", aprinter));
602 p = strchr(aprinter, ',');
609 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
611 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
617 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
620 /* check for the Port Monitor Interface */
621 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
622 Printer->printer_type = SPLHND_PORTMON_TCP;
623 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
626 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
627 Printer->printer_type = SPLHND_PORTMON_LOCAL;
628 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
633 * With hundreds of printers, the "for" loop iterating all
634 * shares can be quite expensive, as it is done on every
635 * OpenPrinter. The loop maps "aprinter" to "sname", the
636 * result of which we cache in gencache.
639 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
641 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
643 found = (strcmp(tmp, printer_not_found) != 0);
645 DEBUG(4, ("Printer %s not found\n", aprinter));
647 return WERR_INVALID_PRINTER_NAME;
653 /* Search all sharenames first as this is easier than pulling
654 the printer_info_2 off of disk. Don't use find_service() since
655 that calls out to map_username() */
657 /* do another loop to look for printernames */
658 for (snum = 0; !found && snum < n_services; snum++) {
659 const char *printer = lp_const_servicename(snum);
661 /* no point going on if this is not a printer */
662 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
666 /* ignore [printers] share */
667 if (strequal(printer, "printers")) {
671 fstrcpy(sname, printer);
672 if (strequal(aprinter, printer)) {
677 /* no point looking up the printer object if
678 we aren't allowing printername != sharename */
679 if (lp_force_printername(snum)) {
683 result = winreg_get_printer_internal(mem_ctx,
688 if ( !W_ERROR_IS_OK(result) ) {
689 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
690 sname, win_errstr(result)));
694 printername = strrchr(info2->printername, '\\');
695 if (printername == NULL) {
696 printername = info2->printername;
701 if (strequal(printername, aprinter)) {
706 DEBUGADD(10, ("printername: %s\n", printername));
712 if (cache_key != NULL) {
713 gencache_set(cache_key, printer_not_found,
715 TALLOC_FREE(cache_key);
717 DEBUGADD(4,("Printer not found\n"));
718 return WERR_INVALID_PRINTER_NAME;
721 if (cache_key != NULL) {
722 gencache_set(cache_key, sname, time(NULL)+300);
723 TALLOC_FREE(cache_key);
726 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
728 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
733 /****************************************************************************
734 Find first available printer slot. creates a printer handle for you.
735 ****************************************************************************/
737 static WERROR open_printer_hnd(struct pipes_struct *p,
738 struct policy_handle *hnd,
740 uint32_t access_granted)
742 struct printer_handle *new_printer;
745 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
747 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
748 if (new_printer == NULL) {
751 talloc_set_destructor(new_printer, printer_entry_destructor);
753 /* This also steals the printer_handle on the policy_handle */
754 if (!create_policy_hnd(p, hnd, new_printer)) {
755 TALLOC_FREE(new_printer);
756 return WERR_INVALID_HANDLE;
759 /* Add to the internal list. */
760 DLIST_ADD(printers_list, new_printer);
762 new_printer->notify.option=NULL;
764 if (!set_printer_hnd_printertype(new_printer, name)) {
765 close_printer_handle(p, hnd);
766 return WERR_INVALID_HANDLE;
769 result = set_printer_hnd_name(p->mem_ctx,
770 get_session_info_system(),
773 if (!W_ERROR_IS_OK(result)) {
774 close_printer_handle(p, hnd);
778 new_printer->access_granted = access_granted;
780 DEBUG(5, ("%d printer handles active\n",
781 (int)num_pipe_handles(p)));
786 /***************************************************************************
787 check to see if the client motify handle is monitoring the notification
788 given by (notify_type, notify_field).
789 **************************************************************************/
791 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
792 uint16_t notify_field)
797 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
798 uint16_t notify_field)
800 struct spoolss_NotifyOption *option = p->notify.option;
804 * Flags should always be zero when the change notify
805 * is registered by the client's spooler. A user Win32 app
806 * might use the flags though instead of the NOTIFY_OPTION_INFO
815 return is_monitoring_event_flags(
816 p->notify.flags, notify_type, notify_field);
818 for (i = 0; i < option->count; i++) {
820 /* Check match for notify_type */
822 if (option->types[i].type != notify_type)
825 /* Check match for field */
827 for (j = 0; j < option->types[i].count; j++) {
828 if (option->types[i].fields[j].field == notify_field) {
834 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
835 p->servername, p->sharename, notify_type, notify_field));
840 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
841 _data->data.integer[0] = _integer; \
842 _data->data.integer[1] = 0;
845 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
846 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
847 if (!_data->data.string.string) {\
848 _data->data.string.size = 0; \
850 _data->data.string.size = strlen_m_term(_p) * 2;
852 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
853 _data->data.devmode.devmode = _devmode;
855 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
856 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
857 if (!_data->data.sd.sd) { \
858 _data->data.sd.sd_size = 0; \
860 _data->data.sd.sd_size = \
861 ndr_size_security_descriptor(_data->data.sd.sd, 0);
863 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
868 struct spoolss_Time st;
872 if (!init_systemtime(&st, t)) {
876 p = talloc_array(mem_ctx, char, len);
882 * Systemtime must be linearized as a set of UINT16's.
883 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
886 SSVAL(p, 0, st.year);
887 SSVAL(p, 2, st.month);
888 SSVAL(p, 4, st.day_of_week);
890 SSVAL(p, 8, st.hour);
891 SSVAL(p, 10, st.minute);
892 SSVAL(p, 12, st.second);
893 SSVAL(p, 14, st.millisecond);
899 /* Convert a notification message to a struct spoolss_Notify */
901 static void notify_one_value(struct spoolss_notify_msg *msg,
902 struct spoolss_Notify *data,
905 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
908 static void notify_string(struct spoolss_notify_msg *msg,
909 struct spoolss_Notify *data,
912 /* The length of the message includes the trailing \0 */
914 data->data.string.size = msg->len * 2;
915 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
916 if (!data->data.string.string) {
917 data->data.string.size = 0;
922 static void notify_system_time(struct spoolss_notify_msg *msg,
923 struct spoolss_Notify *data,
926 data->data.string.string = NULL;
927 data->data.string.size = 0;
929 if (msg->len != sizeof(time_t)) {
930 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
935 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
936 &data->data.string.string,
937 &data->data.string.size);
940 struct notify2_message_table {
942 void (*fn)(struct spoolss_notify_msg *msg,
943 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
946 static struct notify2_message_table printer_notify_table[] = {
947 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
948 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
949 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
950 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
951 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
952 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
953 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
954 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
955 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
956 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
957 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
958 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
959 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
960 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
961 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
962 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
963 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
964 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
965 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
968 static struct notify2_message_table job_notify_table[] = {
969 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
970 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
971 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
972 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
973 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
974 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
975 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
976 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
977 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
978 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
979 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
980 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
981 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
982 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
983 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
984 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
985 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
986 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
987 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
988 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
989 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
990 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
991 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
992 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
996 /***********************************************************************
997 Allocate talloc context for container object
998 **********************************************************************/
1000 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1005 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1010 /***********************************************************************
1011 release all allocated memory and zero out structure
1012 **********************************************************************/
1014 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1020 talloc_destroy(ctr->ctx);
1027 /***********************************************************************
1028 **********************************************************************/
1030 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1038 /***********************************************************************
1039 **********************************************************************/
1041 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1043 if ( !ctr || !ctr->msg_groups )
1046 if ( idx >= ctr->num_groups )
1049 return &ctr->msg_groups[idx];
1053 /***********************************************************************
1054 How many groups of change messages do we have ?
1055 **********************************************************************/
1057 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1062 return ctr->num_groups;
1065 /***********************************************************************
1066 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1067 **********************************************************************/
1069 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1071 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1072 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1073 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1079 /* loop over all groups looking for a matching printer name */
1081 for ( i=0; i<ctr->num_groups; i++ ) {
1082 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1086 /* add a new group? */
1088 if ( i == ctr->num_groups ) {
1091 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1092 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1095 ctr->msg_groups = groups;
1097 /* clear the new entry and set the printer name */
1099 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1100 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1103 /* add the change messages; 'i' is the correct index now regardless */
1105 msg_grp = &ctr->msg_groups[i];
1107 msg_grp->num_msgs++;
1109 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1110 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1113 msg_grp->msgs = msg_list;
1115 new_slot = msg_grp->num_msgs-1;
1116 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1118 /* need to allocate own copy of data */
1120 if ( msg->len != 0 )
1121 msg_grp->msgs[new_slot].notify.data = (char *)
1122 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1124 return ctr->num_groups;
1127 static void construct_info_data(struct spoolss_Notify *info_data,
1128 enum spoolss_NotifyType type,
1129 uint16_t field, int id);
1131 /***********************************************************************
1132 Send a change notication message on all handles which have a call
1134 **********************************************************************/
1136 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1137 struct printer_handle *prn_hnd,
1138 SPOOLSS_NOTIFY_MSG *messages,
1140 struct spoolss_Notify **_notifies,
1143 struct spoolss_Notify *notifies;
1144 SPOOLSS_NOTIFY_MSG *msg;
1149 notifies = talloc_zero_array(mem_ctx,
1150 struct spoolss_Notify, num_msgs);
1155 for (i = 0; i < num_msgs; i++) {
1159 /* Are we monitoring this event? */
1161 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1165 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1166 "for printer [%s]\n",
1167 msg->type, msg->field, prn_hnd->sharename));
1170 * if the is a printer notification handle and not a job
1171 * notification type, then set the id to 0.
1172 * Otherwise just use what was specified in the message.
1174 * When registering change notification on a print server
1175 * handle we always need to send back the id (snum) matching
1176 * the printer for which the change took place.
1177 * For change notify registered on a printer handle,
1178 * this does not matter and the id should be 0.
1183 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1184 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1190 /* Convert unix jobid to smb jobid */
1192 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1193 id = sysjob_to_jobid(msg->id);
1196 DEBUG(3, ("no such unix jobid %d\n",
1202 construct_info_data(¬ifies[count],
1203 msg->type, msg->field, id);
1206 case PRINTER_NOTIFY_TYPE:
1207 if (printer_notify_table[msg->field].fn) {
1208 printer_notify_table[msg->field].fn(msg,
1209 ¬ifies[count], mem_ctx);
1213 case JOB_NOTIFY_TYPE:
1214 if (job_notify_table[msg->field].fn) {
1215 job_notify_table[msg->field].fn(msg,
1216 ¬ifies[count], mem_ctx);
1221 DEBUG(5, ("Unknown notification type %d\n",
1229 *_notifies = notifies;
1235 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1236 struct printer_handle *prn_hnd,
1237 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1239 struct spoolss_Notify *notifies;
1241 union spoolss_ReplyPrinterInfo info;
1242 struct spoolss_NotifyInfo info0;
1243 uint32_t reply_result;
1248 /* Is there notification on this handle? */
1249 if (prn_hnd->notify.cli_chan == NULL ||
1250 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1251 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1252 prn_hnd->notify.cli_chan->active_connections == 0) {
1256 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1257 prn_hnd->servername, prn_hnd->sharename));
1259 /* For this printer? Print servers always receive notifications. */
1260 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1261 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1265 DEBUG(10,("Our printer\n"));
1267 /* build the array of change notifications */
1268 ret = build_notify2_messages(mem_ctx, prn_hnd,
1270 msg_group->num_msgs,
1276 info0.version = 0x2;
1277 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1278 info0.count = count;
1279 info0.notifies = notifies;
1281 info.info0 = &info0;
1283 status = dcerpc_spoolss_RouterReplyPrinterEx(
1284 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1286 &prn_hnd->notify.cli_hnd,
1287 prn_hnd->notify.change, /* color */
1288 prn_hnd->notify.flags,
1290 0, /* reply_type, must be 0 */
1292 if (!NT_STATUS_IS_OK(status)) {
1293 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1295 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1296 nt_errstr(status)));
1297 werr = ntstatus_to_werror(status);
1298 } else if (!W_ERROR_IS_OK(werr)) {
1299 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1301 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1304 switch (reply_result) {
1307 case PRINTER_NOTIFY_INFO_DISCARDED:
1308 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1309 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1318 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1320 struct printer_handle *p;
1321 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1322 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1326 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1330 if (!msg_group->msgs) {
1331 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1335 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1337 /* loop over all printers */
1339 for (p = printers_list; p; p = p->next) {
1340 ret = send_notify2_printer(mem_ctx, p, msg_group);
1347 DEBUG(8,("send_notify2_changes: Exit...\n"));
1351 /***********************************************************************
1352 **********************************************************************/
1354 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1357 uint32_t tv_sec, tv_usec;
1360 /* Unpack message */
1362 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1365 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1367 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1370 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1371 &msg->notify.value[0], &msg->notify.value[1]);
1373 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1374 &msg->len, &msg->notify.data);
1376 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1377 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1379 tv->tv_sec = tv_sec;
1380 tv->tv_usec = tv_usec;
1383 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1384 msg->notify.value[1]));
1386 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1391 /********************************************************************
1392 Receive a notify2 message list
1393 ********************************************************************/
1395 static void receive_notify2_message_list(struct messaging_context *msg,
1398 struct server_id server_id,
1401 size_t msg_count, i;
1402 char *buf = (char *)data->data;
1405 SPOOLSS_NOTIFY_MSG notify;
1406 SPOOLSS_NOTIFY_MSG_CTR messages;
1409 if (data->length < 4) {
1410 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1414 msg_count = IVAL(buf, 0);
1417 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1419 if (msg_count == 0) {
1420 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1424 /* initialize the container */
1426 ZERO_STRUCT( messages );
1427 notify_msg_ctr_init( &messages );
1430 * build message groups for each printer identified
1431 * in a change_notify msg. Remember that a PCN message
1432 * includes the handle returned for the srv_spoolss_replyopenprinter()
1433 * call. Therefore messages are grouped according to printer handle.
1436 for ( i=0; i<msg_count; i++ ) {
1437 struct timeval msg_tv;
1439 if (msg_ptr + 4 - buf > data->length) {
1440 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1444 msg_len = IVAL(msg_ptr,0);
1447 if (msg_ptr + msg_len - buf > data->length) {
1448 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1452 /* unpack messages */
1454 ZERO_STRUCT( notify );
1455 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1458 /* add to correct list in container */
1460 notify_msg_ctr_addmsg( &messages, ¬ify );
1462 /* free memory that might have been allocated by notify2_unpack_msg() */
1464 if ( notify.len != 0 )
1465 SAFE_FREE( notify.notify.data );
1468 /* process each group of messages */
1470 num_groups = notify_msg_ctr_numgroups( &messages );
1471 for ( i=0; i<num_groups; i++ )
1472 send_notify2_changes( &messages, i );
1477 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1478 (uint32_t)msg_count ));
1480 notify_msg_ctr_destroy( &messages );
1485 /********************************************************************
1486 Send a message to ourself about new driver being installed
1487 so we can upgrade the information for each printer bound to this
1489 ********************************************************************/
1491 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1492 struct messaging_context *msg_ctx)
1494 int len = strlen(drivername);
1499 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1502 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1503 MSG_PRINTER_DRVUPGRADE,
1504 (const uint8_t *)drivername, len+1);
1509 void srv_spoolss_cleanup(void)
1511 struct printer_session_counter *session_counter;
1513 for (session_counter = counter_list;
1514 session_counter != NULL;
1515 session_counter = counter_list) {
1516 DLIST_REMOVE(counter_list, session_counter);
1517 TALLOC_FREE(session_counter);
1521 /**********************************************************************
1522 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1523 over all printers, upgrading ones as necessary
1524 **********************************************************************/
1526 void do_drv_upgrade_printer(struct messaging_context *msg,
1529 struct server_id server_id,
1532 TALLOC_CTX *tmp_ctx;
1533 const struct auth_session_info *session_info = get_session_info_system();
1534 struct spoolss_PrinterInfo2 *pinfo2;
1536 const char *drivername;
1538 int n_services = lp_numservices();
1539 struct dcerpc_binding_handle *b = NULL;
1541 tmp_ctx = talloc_new(NULL);
1542 if (!tmp_ctx) return;
1544 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1546 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1550 DEBUG(10, ("do_drv_upgrade_printer: "
1551 "Got message for new driver [%s]\n", drivername));
1553 /* Iterate the printer list */
1555 for (snum = 0; snum < n_services; snum++) {
1556 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1560 /* ignore [printers] share */
1561 if (strequal(lp_const_servicename(snum), "printers")) {
1566 result = winreg_printer_binding_handle(tmp_ctx,
1570 if (!W_ERROR_IS_OK(result)) {
1575 result = winreg_get_printer(tmp_ctx, b,
1576 lp_const_servicename(snum),
1579 if (!W_ERROR_IS_OK(result)) {
1583 if (!pinfo2->drivername) {
1587 if (strcmp(drivername, pinfo2->drivername) != 0) {
1591 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1593 /* all we care about currently is the change_id */
1594 result = winreg_printer_update_changeid(tmp_ctx, b,
1595 pinfo2->printername);
1597 if (!W_ERROR_IS_OK(result)) {
1598 DEBUG(3, ("do_drv_upgrade_printer: "
1599 "Failed to update changeid [%s]\n",
1600 win_errstr(result)));
1606 talloc_free(tmp_ctx);
1609 /********************************************************************
1610 Update the cache for all printq's with a registered client
1612 ********************************************************************/
1614 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1616 struct printer_handle *printer = printers_list;
1619 /* loop through all printers and update the cache where
1620 a client is connected */
1622 if ((printer->printer_type == SPLHND_PRINTER) &&
1623 ((printer->notify.cli_chan != NULL) &&
1624 (printer->notify.cli_chan->active_connections > 0))) {
1625 snum = print_queue_snum(printer->sharename);
1626 print_queue_status(msg_ctx, snum, NULL, NULL);
1629 printer = printer->next;
1635 /****************************************************************
1636 _spoolss_OpenPrinter
1637 ****************************************************************/
1639 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1640 struct spoolss_OpenPrinter *r)
1642 struct spoolss_OpenPrinterEx e;
1645 ZERO_STRUCT(e.in.userlevel);
1647 e.in.printername = r->in.printername;
1648 e.in.datatype = r->in.datatype;
1649 e.in.devmode_ctr = r->in.devmode_ctr;
1650 e.in.access_mask = r->in.access_mask;
1653 e.out.handle = r->out.handle;
1655 werr = _spoolss_OpenPrinterEx(p, &e);
1657 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1658 /* OpenPrinterEx returns this for a bad
1659 * printer name. We must return WERR_INVALID_PRINTER_NAME
1662 werr = WERR_INVALID_PRINTER_NAME;
1668 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1669 struct spoolss_DeviceMode *orig,
1670 struct spoolss_DeviceMode **dest)
1672 struct spoolss_DeviceMode *dm;
1674 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1679 /* copy all values, then duplicate strings and structs */
1682 dm->devicename = talloc_strdup(dm, orig->devicename);
1683 if (!dm->devicename) {
1686 dm->formname = talloc_strdup(dm, orig->formname);
1687 if (!dm->formname) {
1690 if (orig->driverextra_data.data) {
1691 dm->driverextra_data.data =
1692 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1693 orig->driverextra_data.length);
1694 if (!dm->driverextra_data.data) {
1703 /****************************************************************
1704 _spoolss_OpenPrinterEx
1705 ****************************************************************/
1707 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1708 struct spoolss_OpenPrinterEx *r)
1713 struct printer_handle *Printer=NULL;
1717 if (!r->in.printername) {
1718 return WERR_INVALID_PARAM;
1721 if (r->in.level > 3) {
1722 return WERR_INVALID_PARAM;
1724 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1725 (r->in.level == 2 && !r->in.userlevel.level2) ||
1726 (r->in.level == 3 && !r->in.userlevel.level3)) {
1727 return WERR_INVALID_PARAM;
1730 /* some sanity check because you can open a printer or a print server */
1731 /* aka: \\server\printer or \\server */
1733 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1735 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1736 if (!W_ERROR_IS_OK(result)) {
1737 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1738 "for printer %s\n", r->in.printername));
1739 ZERO_STRUCTP(r->out.handle);
1743 Printer = find_printer_index_by_hnd(p, r->out.handle);
1745 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1746 "handle we created for printer %s\n", r->in.printername));
1747 close_printer_handle(p, r->out.handle);
1748 ZERO_STRUCTP(r->out.handle);
1749 return WERR_INVALID_PARAM;
1753 * First case: the user is opening the print server:
1755 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1756 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1758 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1759 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1760 * or if the user is listed in the smb.conf printer admin parameter.
1762 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1763 * client view printer folder, but does not show the MSAPW.
1765 * Note: this test needs code to check access rights here too. Jeremy
1766 * could you look at this?
1768 * Second case: the user is opening a printer:
1769 * NT doesn't let us connect to a printer if the connecting user
1770 * doesn't have print permission.
1772 * Third case: user is opening a Port Monitor
1773 * access checks same as opening a handle to the print server.
1776 switch (Printer->printer_type )
1779 case SPLHND_PORTMON_TCP:
1780 case SPLHND_PORTMON_LOCAL:
1781 /* Printserver handles use global struct... */
1785 /* Map standard access rights to object specific access rights */
1787 se_map_standard(&r->in.access_mask,
1788 &printserver_std_mapping);
1790 /* Deny any object specific bits that don't apply to print
1791 servers (i.e printer and job specific bits) */
1793 r->in.access_mask &= SEC_MASK_SPECIFIC;
1795 if (r->in.access_mask &
1796 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1797 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1798 close_printer_handle(p, r->out.handle);
1799 ZERO_STRUCTP(r->out.handle);
1800 return WERR_ACCESS_DENIED;
1803 /* Allow admin access */
1805 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1807 if (!lp_ms_add_printer_wizard()) {
1808 close_printer_handle(p, r->out.handle);
1809 ZERO_STRUCTP(r->out.handle);
1810 return WERR_ACCESS_DENIED;
1813 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1814 and not a printer admin, then fail */
1816 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1817 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1818 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1819 !token_contains_name_in_list(
1820 uidtoname(p->session_info->unix_token->uid),
1821 p->session_info->info->domain_name,
1823 p->session_info->security_token,
1824 lp_printer_admin(snum))) {
1825 close_printer_handle(p, r->out.handle);
1826 ZERO_STRUCTP(r->out.handle);
1827 DEBUG(3,("access DENIED as user is not root, "
1828 "has no printoperator privilege, "
1829 "not a member of the printoperator builtin group and "
1830 "is not in printer admin list"));
1831 return WERR_ACCESS_DENIED;
1834 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1838 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1841 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1842 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1844 /* We fall through to return WERR_OK */
1847 case SPLHND_PRINTER:
1848 /* NT doesn't let us connect to a printer if the connecting user
1849 doesn't have print permission. */
1851 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1852 close_printer_handle(p, r->out.handle);
1853 ZERO_STRUCTP(r->out.handle);
1857 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1858 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1861 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1863 /* map an empty access mask to the minimum access mask */
1864 if (r->in.access_mask == 0x0)
1865 r->in.access_mask = PRINTER_ACCESS_USE;
1868 * If we are not serving the printer driver for this printer,
1869 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1870 * will keep NT clients happy --jerry
1873 if (lp_use_client_driver(snum)
1874 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1876 r->in.access_mask = PRINTER_ACCESS_USE;
1879 /* check smb.conf parameters and the the sec_desc */
1880 raddr = tsocket_address_inet_addr_string(p->remote_address,
1882 if (raddr == NULL) {
1886 rc = get_remote_hostname(p->remote_address,
1892 if (strequal(rhost, "UNKNOWN")) {
1896 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1898 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1899 ZERO_STRUCTP(r->out.handle);
1900 return WERR_ACCESS_DENIED;
1903 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1904 p->session_info->security_token, snum) ||
1905 !print_access_check(p->session_info,
1908 r->in.access_mask)) {
1909 DEBUG(3, ("access DENIED for printer open\n"));
1910 close_printer_handle(p, r->out.handle);
1911 ZERO_STRUCTP(r->out.handle);
1912 return WERR_ACCESS_DENIED;
1915 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1916 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1917 close_printer_handle(p, r->out.handle);
1918 ZERO_STRUCTP(r->out.handle);
1919 return WERR_ACCESS_DENIED;
1922 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1923 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1925 r->in.access_mask = PRINTER_ACCESS_USE;
1927 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1928 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1930 winreg_create_printer_internal(p->mem_ctx,
1931 get_session_info_system(),
1933 lp_const_servicename(snum));
1938 /* sanity check to prevent programmer error */
1939 ZERO_STRUCTP(r->out.handle);
1943 Printer->access_granted = r->in.access_mask;
1946 * If the client sent a devmode in the OpenPrinter() call, then
1947 * save it here in case we get a job submission on this handle
1950 if ((Printer->printer_type != SPLHND_SERVER) &&
1951 r->in.devmode_ctr.devmode) {
1952 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1956 #if 0 /* JERRY -- I'm doubtful this is really effective */
1957 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1958 optimization in Windows 2000 clients --jerry */
1960 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1961 && (RA_WIN2K == get_remote_arch()) )
1963 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1964 sys_usleep( 500000 );
1971 /****************************************************************
1972 _spoolss_ClosePrinter
1973 ****************************************************************/
1975 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1976 struct spoolss_ClosePrinter *r)
1978 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1980 if (Printer && Printer->document_started) {
1981 struct spoolss_EndDocPrinter e;
1983 e.in.handle = r->in.handle;
1985 _spoolss_EndDocPrinter(p, &e);
1988 if (!close_printer_handle(p, r->in.handle))
1991 /* clear the returned printer handle. Observed behavior
1992 from Win2k server. Don't think this really matters.
1993 Previous code just copied the value of the closed
1996 ZERO_STRUCTP(r->out.handle);
2001 /****************************************************************
2002 _spoolss_DeletePrinter
2003 ****************************************************************/
2005 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2006 struct spoolss_DeletePrinter *r)
2008 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2012 if (Printer && Printer->document_started) {
2013 struct spoolss_EndDocPrinter e;
2015 e.in.handle = r->in.handle;
2017 _spoolss_EndDocPrinter(p, &e);
2020 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2021 winreg_delete_printer_key_internal(p->mem_ctx,
2022 get_session_info_system(),
2024 lp_const_servicename(snum),
2028 result = delete_printer_handle(p, r->in.handle);
2033 /*******************************************************************
2034 * static function to lookup the version id corresponding to an
2035 * long architecture string
2036 ******************************************************************/
2038 static const struct print_architecture_table_node archi_table[]= {
2040 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2041 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2042 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2043 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2044 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2045 {"Windows IA64", SPL_ARCH_IA64, 3 },
2046 {"Windows x64", SPL_ARCH_X64, 3 },
2050 static int get_version_id(const char *arch)
2054 for (i=0; archi_table[i].long_archi != NULL; i++)
2056 if (strcmp(arch, archi_table[i].long_archi) == 0)
2057 return (archi_table[i].version);
2063 /****************************************************************
2064 _spoolss_DeletePrinterDriver
2065 ****************************************************************/
2067 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2068 struct spoolss_DeletePrinterDriver *r)
2071 struct spoolss_DriverInfo8 *info = NULL;
2072 struct spoolss_DriverInfo8 *info_win2k = NULL;
2075 struct dcerpc_binding_handle *b;
2076 TALLOC_CTX *tmp_ctx = NULL;
2078 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2079 and not a printer admin, then fail */
2081 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2082 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2083 && !token_contains_name_in_list(
2084 uidtoname(p->session_info->unix_token->uid),
2085 p->session_info->info->domain_name,
2087 p->session_info->security_token,
2088 lp_printer_admin(-1)) )
2090 return WERR_ACCESS_DENIED;
2093 /* check that we have a valid driver name first */
2095 if ((version = get_version_id(r->in.architecture)) == -1) {
2096 return WERR_INVALID_ENVIRONMENT;
2099 tmp_ctx = talloc_new(p->mem_ctx);
2104 status = winreg_printer_binding_handle(tmp_ctx,
2105 get_session_info_system(),
2108 if (!W_ERROR_IS_OK(status)) {
2112 status = winreg_get_driver(tmp_ctx, b,
2113 r->in.architecture, r->in.driver,
2115 if (!W_ERROR_IS_OK(status)) {
2116 /* try for Win2k driver if "Windows NT x86" */
2118 if ( version == 2 ) {
2121 status = winreg_get_driver(tmp_ctx, b,
2125 if (!W_ERROR_IS_OK(status)) {
2126 status = WERR_UNKNOWN_PRINTER_DRIVER;
2130 /* otherwise it was a failure */
2132 status = WERR_UNKNOWN_PRINTER_DRIVER;
2138 if (printer_driver_in_use(tmp_ctx,
2141 status = WERR_PRINTER_DRIVER_IN_USE;
2146 status = winreg_get_driver(tmp_ctx, b,
2148 r->in.driver, 3, &info_win2k);
2149 if (W_ERROR_IS_OK(status)) {
2150 /* if we get to here, we now have 2 driver info structures to remove */
2151 /* remove the Win2k driver first*/
2153 status = winreg_del_driver(tmp_ctx, b,
2155 talloc_free(info_win2k);
2157 /* this should not have failed---if it did, report to client */
2158 if (!W_ERROR_IS_OK(status)) {
2164 status = winreg_del_driver(tmp_ctx, b,
2168 talloc_free(tmp_ctx);
2173 /****************************************************************
2174 _spoolss_DeletePrinterDriverEx
2175 ****************************************************************/
2177 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2178 struct spoolss_DeletePrinterDriverEx *r)
2180 struct spoolss_DriverInfo8 *info = NULL;
2181 struct spoolss_DriverInfo8 *info_win2k = NULL;
2185 struct dcerpc_binding_handle *b;
2186 TALLOC_CTX *tmp_ctx = NULL;
2188 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2189 and not a printer admin, then fail */
2191 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2192 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2193 && !token_contains_name_in_list(
2194 uidtoname(p->session_info->unix_token->uid),
2195 p->session_info->info->domain_name,
2197 p->session_info->security_token, lp_printer_admin(-1)) )
2199 return WERR_ACCESS_DENIED;
2202 /* check that we have a valid driver name first */
2203 if ((version = get_version_id(r->in.architecture)) == -1) {
2204 /* this is what NT returns */
2205 return WERR_INVALID_ENVIRONMENT;
2208 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2209 version = r->in.version;
2212 tmp_ctx = talloc_new(p->mem_ctx);
2217 status = winreg_printer_binding_handle(tmp_ctx,
2218 get_session_info_system(),
2221 if (!W_ERROR_IS_OK(status)) {
2225 status = winreg_get_driver(tmp_ctx, b,
2230 if (!W_ERROR_IS_OK(status)) {
2231 status = WERR_UNKNOWN_PRINTER_DRIVER;
2234 * if the client asked for a specific version,
2235 * or this is something other than Windows NT x86,
2239 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2242 /* try for Win2k driver if "Windows NT x86" */
2245 status = winreg_get_driver(tmp_ctx, b,
2249 if (!W_ERROR_IS_OK(status)) {
2250 status = WERR_UNKNOWN_PRINTER_DRIVER;
2255 if (printer_driver_in_use(tmp_ctx,
2258 status = WERR_PRINTER_DRIVER_IN_USE;
2263 * we have a couple of cases to consider.
2264 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2265 * then the delete should fail if **any** files overlap with
2267 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2268 * non-overlapping files
2269 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2270 * is set, the do not delete any files
2271 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2274 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2276 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2279 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2280 printer_driver_files_in_use(tmp_ctx,
2283 /* no idea of the correct error here */
2284 status = WERR_ACCESS_DENIED;
2289 /* also check for W32X86/3 if necessary; maybe we already have? */
2291 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2292 status = winreg_get_driver(tmp_ctx, b,
2294 r->in.driver, 3, &info_win2k);
2295 if (W_ERROR_IS_OK(status)) {
2298 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2299 printer_driver_files_in_use(info,
2302 /* no idea of the correct error here */
2303 talloc_free(info_win2k);
2304 status = WERR_ACCESS_DENIED;
2308 /* if we get to here, we now have 2 driver info structures to remove */
2309 /* remove the Win2k driver first*/
2311 status = winreg_del_driver(tmp_ctx, b,
2315 /* this should not have failed---if it did, report to client */
2317 if (!W_ERROR_IS_OK(status)) {
2322 * now delete any associated files if delete_files is
2323 * true. Even if this part failes, we return succes
2324 * because the driver doesn not exist any more
2327 delete_driver_files(get_session_info_system(),
2333 status = winreg_del_driver(tmp_ctx, b,
2336 if (!W_ERROR_IS_OK(status)) {
2341 * now delete any associated files if delete_files is
2342 * true. Even if this part failes, we return succes
2343 * because the driver doesn not exist any more
2346 delete_driver_files(get_session_info_system(), info);
2350 talloc_free(tmp_ctx);
2355 /********************************************************************
2356 GetPrinterData on a printer server Handle.
2357 ********************************************************************/
2359 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2361 enum winreg_Type *type,
2362 union spoolss_PrinterData *data)
2364 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2366 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2372 if (!strcasecmp_m(value, "BeepEnabled")) {
2378 if (!strcasecmp_m(value, "EventLog")) {
2380 /* formally was 0x1b */
2385 if (!strcasecmp_m(value, "NetPopup")) {
2391 if (!strcasecmp_m(value, "MajorVersion")) {
2394 /* Windows NT 4.0 seems to not allow uploading of drivers
2395 to a server that reports 0x3 as the MajorVersion.
2396 need to investigate more how Win2k gets around this .
2399 if (RA_WINNT == get_remote_arch()) {
2408 if (!strcasecmp_m(value, "MinorVersion")) {
2415 * uint32_t size = 0x114
2416 * uint32_t major = 5
2417 * uint32_t minor = [0|1]
2418 * uint32_t build = [2195|2600]
2419 * extra unicode string = e.g. "Service Pack 3"
2421 if (!strcasecmp_m(value, "OSVersion")) {
2423 enum ndr_err_code ndr_err;
2424 struct spoolss_OSVersion os;
2426 os.major = 5; /* Windows 2000 == 5.0 */
2428 os.build = 2195; /* build */
2429 os.extra_string = ""; /* leave extra string empty */
2431 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2432 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2433 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2434 return WERR_GENERAL_FAILURE;
2438 data->binary = blob;
2444 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2447 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2448 W_ERROR_HAVE_NO_MEMORY(data->string);
2453 if (!strcasecmp_m(value, "Architecture")) {
2455 data->string = talloc_strdup(mem_ctx,
2456 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2457 W_ERROR_HAVE_NO_MEMORY(data->string);
2462 if (!strcasecmp_m(value, "DsPresent")) {
2465 /* only show the publish check box if we are a
2466 member of a AD domain */
2468 if (lp_security() == SEC_ADS) {
2476 if (!strcasecmp_m(value, "DNSMachineName")) {
2477 const char *hostname = get_mydnsfullname();
2480 return WERR_BADFILE;
2484 data->string = talloc_strdup(mem_ctx, hostname);
2485 W_ERROR_HAVE_NO_MEMORY(data->string);
2492 return WERR_INVALID_PARAM;
2495 /****************************************************************
2496 _spoolss_GetPrinterData
2497 ****************************************************************/
2499 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2500 struct spoolss_GetPrinterData *r)
2502 struct spoolss_GetPrinterDataEx r2;
2504 r2.in.handle = r->in.handle;
2505 r2.in.key_name = "PrinterDriverData";
2506 r2.in.value_name = r->in.value_name;
2507 r2.in.offered = r->in.offered;
2508 r2.out.type = r->out.type;
2509 r2.out.data = r->out.data;
2510 r2.out.needed = r->out.needed;
2512 return _spoolss_GetPrinterDataEx(p, &r2);
2515 /*********************************************************
2516 Connect to the client machine.
2517 **********************************************************/
2519 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2520 struct sockaddr_storage *client_ss, const char *remote_machine)
2523 struct cli_state *the_cli;
2524 struct sockaddr_storage rm_addr;
2525 char addr[INET6_ADDRSTRLEN];
2527 if ( is_zero_addr(client_ss) ) {
2528 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2530 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2531 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2534 print_sockaddr(addr, sizeof(addr), &rm_addr);
2536 rm_addr = *client_ss;
2537 print_sockaddr(addr, sizeof(addr), &rm_addr);
2538 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2542 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2543 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2548 /* setup the connection */
2549 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2550 &rm_addr, 0, "IPC$", "IPC",
2554 0, lp_client_signing());
2556 if ( !NT_STATUS_IS_OK( ret ) ) {
2557 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2562 if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2563 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2564 cli_shutdown(the_cli);
2569 * Ok - we have an anonymous connection to the IPC$ share.
2570 * Now start the NT Domain stuff :-).
2573 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2574 if (!NT_STATUS_IS_OK(ret)) {
2575 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576 remote_machine, nt_errstr(ret)));
2577 cli_shutdown(the_cli);
2584 /***************************************************************************
2585 Connect to the client.
2586 ****************************************************************************/
2588 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2589 uint32_t localprinter,
2590 enum winreg_Type type,
2591 struct policy_handle *handle,
2592 struct notify_back_channel **_chan,
2593 struct sockaddr_storage *client_ss,
2594 struct messaging_context *msg_ctx)
2598 struct notify_back_channel *chan;
2600 for (chan = back_channels; chan; chan = chan->next) {
2601 if (memcmp(&chan->client_address, client_ss,
2602 sizeof(struct sockaddr_storage)) == 0) {
2608 * If it's the first connection, contact the client
2609 * and connect to the IPC$ share anonymously
2612 fstring unix_printer;
2614 /* the +2 is to strip the leading 2 backslashs */
2615 fstrcpy(unix_printer, printer + 2);
2617 chan = talloc_zero(NULL, struct notify_back_channel);
2621 chan->client_address = *client_ss;
2623 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2628 DLIST_ADD(back_channels, chan);
2630 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2631 receive_notify2_message_list);
2634 if (chan->cli_pipe == NULL ||
2635 chan->cli_pipe->binding_handle == NULL) {
2636 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2637 "NULL %s for printer %s\n",
2638 chan->cli_pipe == NULL ?
2639 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2645 * Tell the specific printing tdb we want messages for this printer
2646 * by registering our PID.
2649 if (!print_notify_register_pid(snum)) {
2650 DEBUG(0, ("Failed to register our pid for printer %s\n",
2654 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2663 if (!NT_STATUS_IS_OK(status)) {
2664 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2665 result = ntstatus_to_werror(status);
2666 } else if (!W_ERROR_IS_OK(result)) {
2667 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2670 chan->active_connections++;
2673 return (W_ERROR_IS_OK(result));
2676 /****************************************************************
2677 ****************************************************************/
2679 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2680 const struct spoolss_NotifyOption *r)
2682 struct spoolss_NotifyOption *option;
2689 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2696 if (!option->count) {
2700 option->types = talloc_zero_array(option,
2701 struct spoolss_NotifyOptionType, option->count);
2702 if (!option->types) {
2703 talloc_free(option);
2707 for (i=0; i < option->count; i++) {
2708 option->types[i] = r->types[i];
2710 if (option->types[i].count) {
2711 option->types[i].fields = talloc_zero_array(option,
2712 union spoolss_Field, option->types[i].count);
2713 if (!option->types[i].fields) {
2714 talloc_free(option);
2717 for (k=0; k<option->types[i].count; k++) {
2718 option->types[i].fields[k] =
2719 r->types[i].fields[k];
2727 /****************************************************************
2728 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2730 * before replying OK: status=0 a rpc call is made to the workstation
2731 * asking ReplyOpenPrinter
2733 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2734 * called from api_spoolss_rffpcnex
2735 ****************************************************************/
2737 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2738 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2741 struct spoolss_NotifyOption *option = r->in.notify_options;
2742 struct sockaddr_storage client_ss;
2743 socklen_t client_len;
2745 /* store the notify value in the printer struct */
2747 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2750 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2751 "Invalid handle (%s:%u:%u).\n",
2752 OUR_HANDLE(r->in.handle)));
2756 Printer->notify.flags = r->in.flags;
2757 Printer->notify.options = r->in.options;
2758 Printer->notify.printerlocal = r->in.printer_local;
2759 Printer->notify.msg_ctx = p->msg_ctx;
2761 TALLOC_FREE(Printer->notify.option);
2762 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2764 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2766 /* Connect to the client machine and send a ReplyOpenPrinter */
2768 if ( Printer->printer_type == SPLHND_SERVER)
2770 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2771 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2774 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2775 "remote_address is %s\n",
2776 tsocket_address_string(p->remote_address, p->mem_ctx)));
2778 if (!lp_print_notify_backchannel(snum)) {
2779 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2780 "backchannel disabled\n"));
2781 return WERR_SERVER_UNAVAILABLE;
2784 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2785 (struct sockaddr *) &client_ss,
2786 sizeof(struct sockaddr_storage));
2787 if (client_len < 0) {
2791 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2792 Printer->notify.printerlocal, REG_SZ,
2793 &Printer->notify.cli_hnd,
2794 &Printer->notify.cli_chan,
2795 &client_ss, p->msg_ctx)) {
2796 return WERR_SERVER_UNAVAILABLE;
2802 /*******************************************************************
2803 * fill a notify_info_data with the servername
2804 ********************************************************************/
2806 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2808 struct spoolss_Notify *data,
2809 print_queue_struct *queue,
2810 struct spoolss_PrinterInfo2 *pinfo2,
2811 TALLOC_CTX *mem_ctx)
2813 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2816 /*******************************************************************
2817 * fill a notify_info_data with the printername (not including the servername).
2818 ********************************************************************/
2820 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 struct spoolss_PrinterInfo2 *pinfo2,
2825 TALLOC_CTX *mem_ctx)
2827 /* the notify name should not contain the \\server\ part */
2828 const char *p = strrchr(pinfo2->printername, '\\');
2831 p = pinfo2->printername;
2836 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2839 /*******************************************************************
2840 * fill a notify_info_data with the servicename
2841 ********************************************************************/
2843 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2845 struct spoolss_Notify *data,
2846 print_queue_struct *queue,
2847 struct spoolss_PrinterInfo2 *pinfo2,
2848 TALLOC_CTX *mem_ctx)
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2853 /*******************************************************************
2854 * fill a notify_info_data with the port name
2855 ********************************************************************/
2857 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2859 struct spoolss_Notify *data,
2860 print_queue_struct *queue,
2861 struct spoolss_PrinterInfo2 *pinfo2,
2862 TALLOC_CTX *mem_ctx)
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2867 /*******************************************************************
2868 * fill a notify_info_data with the printername
2869 * but it doesn't exist, have to see what to do
2870 ********************************************************************/
2872 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2874 struct spoolss_Notify *data,
2875 print_queue_struct *queue,
2876 struct spoolss_PrinterInfo2 *pinfo2,
2877 TALLOC_CTX *mem_ctx)
2879 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2882 /*******************************************************************
2883 * fill a notify_info_data with the comment
2884 ********************************************************************/
2886 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2888 struct spoolss_Notify *data,
2889 print_queue_struct *queue,
2890 struct spoolss_PrinterInfo2 *pinfo2,
2891 TALLOC_CTX *mem_ctx)
2895 if (*pinfo2->comment == '\0') {
2896 p = lp_comment(snum);
2898 p = pinfo2->comment;
2901 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2904 /*******************************************************************
2905 * fill a notify_info_data with the comment
2906 * location = "Room 1, floor 2, building 3"
2907 ********************************************************************/
2909 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2911 struct spoolss_Notify *data,
2912 print_queue_struct *queue,
2913 struct spoolss_PrinterInfo2 *pinfo2,
2914 TALLOC_CTX *mem_ctx)
2916 const char *loc = pinfo2->location;
2919 status = printer_list_get_printer(mem_ctx,
2924 if (NT_STATUS_IS_OK(status)) {
2926 loc = pinfo2->location;
2930 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2933 /*******************************************************************
2934 * fill a notify_info_data with the device mode
2935 * jfm:xxxx don't to it for know but that's a real problem !!!
2936 ********************************************************************/
2938 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2940 struct spoolss_Notify *data,
2941 print_queue_struct *queue,
2942 struct spoolss_PrinterInfo2 *pinfo2,
2943 TALLOC_CTX *mem_ctx)
2945 /* for a dummy implementation we have to zero the fields */
2946 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2949 /*******************************************************************
2950 * fill a notify_info_data with the separator file name
2951 ********************************************************************/
2953 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2955 struct spoolss_Notify *data,
2956 print_queue_struct *queue,
2957 struct spoolss_PrinterInfo2 *pinfo2,
2958 TALLOC_CTX *mem_ctx)
2960 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2963 /*******************************************************************
2964 * fill a notify_info_data with the print processor
2965 * jfm:xxxx return always winprint to indicate we don't do anything to it
2966 ********************************************************************/
2968 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2970 struct spoolss_Notify *data,
2971 print_queue_struct *queue,
2972 struct spoolss_PrinterInfo2 *pinfo2,
2973 TALLOC_CTX *mem_ctx)
2975 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2978 /*******************************************************************
2979 * fill a notify_info_data with the print processor options
2980 * jfm:xxxx send an empty string
2981 ********************************************************************/
2983 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2985 struct spoolss_Notify *data,
2986 print_queue_struct *queue,
2987 struct spoolss_PrinterInfo2 *pinfo2,
2988 TALLOC_CTX *mem_ctx)
2990 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2993 /*******************************************************************
2994 * fill a notify_info_data with the data type
2995 * jfm:xxxx always send RAW as data type
2996 ********************************************************************/
2998 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
3000 struct spoolss_Notify *data,
3001 print_queue_struct *queue,
3002 struct spoolss_PrinterInfo2 *pinfo2,
3003 TALLOC_CTX *mem_ctx)
3005 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
3008 /*******************************************************************
3009 * fill a notify_info_data with the security descriptor
3010 * jfm:xxxx send an null pointer to say no security desc
3011 * have to implement security before !
3012 ********************************************************************/
3014 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3016 struct spoolss_Notify *data,
3017 print_queue_struct *queue,
3018 struct spoolss_PrinterInfo2 *pinfo2,
3019 TALLOC_CTX *mem_ctx)
3021 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3024 /*******************************************************************
3025 * fill a notify_info_data with the attributes
3026 * jfm:xxxx a samba printer is always shared
3027 ********************************************************************/
3029 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3031 struct spoolss_Notify *data,
3032 print_queue_struct *queue,
3033 struct spoolss_PrinterInfo2 *pinfo2,
3034 TALLOC_CTX *mem_ctx)
3036 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3039 /*******************************************************************
3040 * fill a notify_info_data with the priority
3041 ********************************************************************/
3043 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3045 struct spoolss_Notify *data,
3046 print_queue_struct *queue,
3047 struct spoolss_PrinterInfo2 *pinfo2,
3048 TALLOC_CTX *mem_ctx)
3050 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3053 /*******************************************************************
3054 * fill a notify_info_data with the default priority
3055 ********************************************************************/
3057 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3059 struct spoolss_Notify *data,
3060 print_queue_struct *queue,
3061 struct spoolss_PrinterInfo2 *pinfo2,
3062 TALLOC_CTX *mem_ctx)
3064 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3067 /*******************************************************************
3068 * fill a notify_info_data with the start time
3069 ********************************************************************/
3071 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3073 struct spoolss_Notify *data,
3074 print_queue_struct *queue,
3075 struct spoolss_PrinterInfo2 *pinfo2,
3076 TALLOC_CTX *mem_ctx)
3078 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3081 /*******************************************************************
3082 * fill a notify_info_data with the until time
3083 ********************************************************************/
3085 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3087 struct spoolss_Notify *data,
3088 print_queue_struct *queue,
3089 struct spoolss_PrinterInfo2 *pinfo2,
3090 TALLOC_CTX *mem_ctx)
3092 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3095 /*******************************************************************
3096 * fill a notify_info_data with the status
3097 ********************************************************************/
3099 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3101 struct spoolss_Notify *data,
3102 print_queue_struct *queue,
3103 struct spoolss_PrinterInfo2 *pinfo2,
3104 TALLOC_CTX *mem_ctx)
3106 print_status_struct status;
3108 print_queue_length(msg_ctx, snum, &status);
3109 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3112 /*******************************************************************
3113 * fill a notify_info_data with the number of jobs queued
3114 ********************************************************************/
3116 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3118 struct spoolss_Notify *data,
3119 print_queue_struct *queue,
3120 struct spoolss_PrinterInfo2 *pinfo2,
3121 TALLOC_CTX *mem_ctx)
3123 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3124 data, print_queue_length(msg_ctx, snum, NULL));
3127 /*******************************************************************
3128 * fill a notify_info_data with the average ppm
3129 ********************************************************************/
3131 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3133 struct spoolss_Notify *data,
3134 print_queue_struct *queue,
3135 struct spoolss_PrinterInfo2 *pinfo2,
3136 TALLOC_CTX *mem_ctx)
3138 /* always respond 8 pages per minutes */
3139 /* a little hard ! */
3140 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3143 /*******************************************************************
3144 * fill a notify_info_data with username
3145 ********************************************************************/
3147 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3149 struct spoolss_Notify *data,
3150 print_queue_struct *queue,
3151 struct spoolss_PrinterInfo2 *pinfo2,
3152 TALLOC_CTX *mem_ctx)
3154 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3157 /*******************************************************************
3158 * fill a notify_info_data with job status
3159 ********************************************************************/
3161 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3163 struct spoolss_Notify *data,
3164 print_queue_struct *queue,
3165 struct spoolss_PrinterInfo2 *pinfo2,
3166 TALLOC_CTX *mem_ctx)
3168 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3171 /*******************************************************************
3172 * fill a notify_info_data with job name
3173 ********************************************************************/
3175 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3177 struct spoolss_Notify *data,
3178 print_queue_struct *queue,
3179 struct spoolss_PrinterInfo2 *pinfo2,
3180 TALLOC_CTX *mem_ctx)
3182 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3185 /*******************************************************************
3186 * fill a notify_info_data with job status
3187 ********************************************************************/
3189 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3191 struct spoolss_Notify *data,
3192 print_queue_struct *queue,
3193 struct spoolss_PrinterInfo2 *pinfo2,
3194 TALLOC_CTX *mem_ctx)
3197 * Now we're returning job status codes we just return a "" here. JRA.
3202 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3205 switch (queue->status) {
3210 p = ""; /* NT provides the paused string */
3219 #endif /* NO LONGER NEEDED. */
3221 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3224 /*******************************************************************
3225 * fill a notify_info_data with job time
3226 ********************************************************************/
3228 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3230 struct spoolss_Notify *data,
3231 print_queue_struct *queue,
3232 struct spoolss_PrinterInfo2 *pinfo2,
3233 TALLOC_CTX *mem_ctx)
3235 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3238 /*******************************************************************
3239 * fill a notify_info_data with job size
3240 ********************************************************************/
3242 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3244 struct spoolss_Notify *data,
3245 print_queue_struct *queue,
3246 struct spoolss_PrinterInfo2 *pinfo2,
3247 TALLOC_CTX *mem_ctx)
3249 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3252 /*******************************************************************
3253 * fill a notify_info_data with page info
3254 ********************************************************************/
3255 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3257 struct spoolss_Notify *data,
3258 print_queue_struct *queue,
3259 struct spoolss_PrinterInfo2 *pinfo2,
3260 TALLOC_CTX *mem_ctx)
3262 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3265 /*******************************************************************
3266 * fill a notify_info_data with pages printed info.
3267 ********************************************************************/
3268 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3270 struct spoolss_Notify *data,
3271 print_queue_struct *queue,
3272 struct spoolss_PrinterInfo2 *pinfo2,
3273 TALLOC_CTX *mem_ctx)
3275 /* Add code when back-end tracks this */
3276 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3279 /*******************************************************************
3280 Fill a notify_info_data with job position.
3281 ********************************************************************/
3283 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3285 struct spoolss_Notify *data,
3286 print_queue_struct *queue,
3287 struct spoolss_PrinterInfo2 *pinfo2,
3288 TALLOC_CTX *mem_ctx)
3290 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3293 /*******************************************************************
3294 Fill a notify_info_data with submitted time.
3295 ********************************************************************/
3297 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3299 struct spoolss_Notify *data,
3300 print_queue_struct *queue,
3301 struct spoolss_PrinterInfo2 *pinfo2,
3302 TALLOC_CTX *mem_ctx)
3304 data->data.string.string = NULL;
3305 data->data.string.size = 0;
3307 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3308 &data->data.string.string,
3309 &data->data.string.size);
3313 struct s_notify_info_data_table
3315 enum spoolss_NotifyType type;
3318 enum spoolss_NotifyTable variable_type;
3319 void (*fn) (struct messaging_context *msg_ctx,
3320 int snum, struct spoolss_Notify *data,
3321 print_queue_struct *queue,
3322 struct spoolss_PrinterInfo2 *pinfo2,
3323 TALLOC_CTX *mem_ctx);
3326 /* A table describing the various print notification constants and
3327 whether the notification data is a pointer to a variable sized
3328 buffer, a one value uint32_t or a two value uint32_t. */
3330 static const struct s_notify_info_data_table notify_info_data_table[] =
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3334 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3350 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3351 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3352 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3353 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3354 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3355 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3356 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3357 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3358 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3359 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3360 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3361 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3362 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3363 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3364 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3365 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3366 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3367 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3368 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3369 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3370 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3371 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3372 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3373 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3374 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3375 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3376 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3377 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3378 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3379 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3380 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3383 /*******************************************************************
3384 Return the variable_type of info_data structure.
3385 ********************************************************************/
3387 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3392 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3393 if ( (notify_info_data_table[i].type == type) &&
3394 (notify_info_data_table[i].field == field) ) {
3395 return notify_info_data_table[i].variable_type;
3399 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3401 return (enum spoolss_NotifyTable) 0;
3404 /****************************************************************************
3405 ****************************************************************************/
3407 static bool search_notify(enum spoolss_NotifyType type,
3413 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3414 if (notify_info_data_table[i].type == type &&
3415 notify_info_data_table[i].field == field &&
3416 notify_info_data_table[i].fn != NULL) {
3425 /****************************************************************************
3426 ****************************************************************************/
3428 static void construct_info_data(struct spoolss_Notify *info_data,
3429 enum spoolss_NotifyType type,
3430 uint16_t field, int id)
3432 info_data->type = type;
3433 info_data->field.field = field;
3434 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3435 info_data->job_id = id;
3438 /*******************************************************************
3440 * fill a notify_info struct with info asked
3442 ********************************************************************/
3444 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3445 struct printer_handle *print_hnd,
3446 struct spoolss_NotifyInfo *info,
3447 struct spoolss_PrinterInfo2 *pinfo2,
3449 const struct spoolss_NotifyOptionType *option_type,
3451 TALLOC_CTX *mem_ctx)
3454 enum spoolss_NotifyType type;
3457 struct spoolss_Notify *current_data;
3459 type = option_type->type;
3461 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3462 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3463 option_type->count, lp_servicename(snum)));
3465 for(field_num=0; field_num < option_type->count; field_num++) {
3466 field = option_type->fields[field_num].field;
3468 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3470 if (!search_notify(type, field, &j) )
3473 info->notifies = talloc_realloc(info, info->notifies,
3474 struct spoolss_Notify,
3476 if (info->notifies == NULL) {
3477 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3481 current_data = &info->notifies[info->count];
3483 construct_info_data(current_data, type, field, id);
3485 DEBUG(10, ("construct_notify_printer_info: "
3486 "calling [%s] snum=%d printername=[%s])\n",
3487 notify_info_data_table[j].name, snum,
3488 pinfo2->printername));
3490 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3491 NULL, pinfo2, mem_ctx);
3499 /*******************************************************************
3501 * fill a notify_info struct with info asked
3503 ********************************************************************/
3505 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3506 print_queue_struct *queue,
3507 struct spoolss_NotifyInfo *info,
3508 struct spoolss_PrinterInfo2 *pinfo2,
3510 const struct spoolss_NotifyOptionType *option_type,
3512 TALLOC_CTX *mem_ctx)
3515 enum spoolss_NotifyType type;
3517 struct spoolss_Notify *current_data;
3519 DEBUG(4,("construct_notify_jobs_info\n"));
3521 type = option_type->type;
3523 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3524 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3525 option_type->count));
3527 for(field_num=0; field_num<option_type->count; field_num++) {
3528 field = option_type->fields[field_num].field;
3530 if (!search_notify(type, field, &j) )
3533 info->notifies = talloc_realloc(info, info->notifies,
3534 struct spoolss_Notify,
3536 if (info->notifies == NULL) {
3537 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3541 current_data=&(info->notifies[info->count]);
3543 construct_info_data(current_data, type, field, id);
3544 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3545 queue, pinfo2, mem_ctx);
3553 * JFM: The enumeration is not that simple, it's even non obvious.
3555 * let's take an example: I want to monitor the PRINTER SERVER for
3556 * the printer's name and the number of jobs currently queued.
3557 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3558 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3560 * I have 3 printers on the back of my server.
3562 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3565 * 1 printer 1 name 1
3566 * 2 printer 1 cjob 1
3567 * 3 printer 2 name 2
3568 * 4 printer 2 cjob 2
3569 * 5 printer 3 name 3
3570 * 6 printer 3 name 3
3572 * that's the print server case, the printer case is even worse.
3575 /*******************************************************************
3577 * enumerate all printers on the printserver
3578 * fill a notify_info struct with info asked
3580 ********************************************************************/
3582 static WERROR printserver_notify_info(struct pipes_struct *p,
3583 struct policy_handle *hnd,
3584 struct spoolss_NotifyInfo *info,
3585 TALLOC_CTX *mem_ctx)
3588 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3589 int n_services=lp_numservices();
3591 struct spoolss_NotifyOption *option;
3592 struct spoolss_NotifyOptionType option_type;
3593 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3596 DEBUG(4,("printserver_notify_info\n"));
3601 option = Printer->notify.option;
3604 info->notifies = NULL;
3607 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3608 sending a ffpcn() request first */
3613 for (i=0; i<option->count; i++) {
3614 option_type = option->types[i];
3616 if (option_type.type != PRINTER_NOTIFY_TYPE)
3619 for (snum = 0; snum < n_services; snum++) {
3620 if (!lp_browseable(snum) ||
3621 !lp_snum_ok(snum) ||
3622 !lp_print_ok(snum)) {
3623 continue; /* skip */
3626 /* Maybe we should use the SYSTEM session_info here... */
3627 result = winreg_get_printer_internal(mem_ctx,
3628 get_session_info_system(),
3630 lp_servicename(snum),
3632 if (!W_ERROR_IS_OK(result)) {
3633 DEBUG(4, ("printserver_notify_info: "
3634 "Failed to get printer [%s]\n",
3635 lp_servicename(snum)));
3640 construct_notify_printer_info(p->msg_ctx,
3646 TALLOC_FREE(pinfo2);
3652 * Debugging information, don't delete.
3655 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3656 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3657 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3659 for (i=0; i<info->count; i++) {
3660 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3661 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3662 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3669 /*******************************************************************
3671 * fill a notify_info struct with info asked
3673 ********************************************************************/
3675 static WERROR printer_notify_info(struct pipes_struct *p,
3676 struct policy_handle *hnd,
3677 struct spoolss_NotifyInfo *info,
3678 TALLOC_CTX *mem_ctx)
3681 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3684 struct spoolss_NotifyOption *option;
3685 struct spoolss_NotifyOptionType option_type;
3687 print_queue_struct *queue=NULL;
3688 print_status_struct status;
3689 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3692 DEBUG(4,("printer_notify_info\n"));
3697 option = Printer->notify.option;
3701 info->notifies = NULL;
3704 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3705 sending a ffpcn() request first */
3710 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3714 /* Maybe we should use the SYSTEM session_info here... */
3715 result = winreg_get_printer_internal(mem_ctx,
3716 get_session_info_system(),
3718 lp_servicename(snum), &pinfo2);
3719 if (!W_ERROR_IS_OK(result)) {
3724 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3725 * correct servername.
3727 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3728 if (pinfo2->servername == NULL) {
3732 for (i=0; i<option->count; i++) {
3733 option_type = option->types[i];
3735 switch (option_type.type) {
3736 case PRINTER_NOTIFY_TYPE:
3737 if (construct_notify_printer_info(p->msg_ctx,
3746 case JOB_NOTIFY_TYPE:
3748 count = print_queue_status(p->msg_ctx, snum, &queue,
3751 for (j=0; j<count; j++) {
3752 construct_notify_jobs_info(p->msg_ctx,
3766 * Debugging information, don't delete.
3769 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3770 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3771 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3773 for (i=0; i<info->count; i++) {
3774 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3775 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3776 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3780 talloc_free(pinfo2);
3784 /****************************************************************
3785 _spoolss_RouterRefreshPrinterChangeNotify
3786 ****************************************************************/
3788 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3789 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3791 struct spoolss_NotifyInfo *info;
3793 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3794 WERROR result = WERR_BADFID;
3796 /* we always have a spoolss_NotifyInfo struct */
3797 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3799 result = WERR_NOMEM;
3803 *r->out.info = info;
3806 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3807 "Invalid handle (%s:%u:%u).\n",
3808 OUR_HANDLE(r->in.handle)));
3812 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3815 * We are now using the change value, and
3816 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3817 * I don't have a global notification system, I'm sending back all the
3818 * information even when _NOTHING_ has changed.
3821 /* We need to keep track of the change value to send back in
3822 RRPCN replies otherwise our updates are ignored. */
3824 Printer->notify.fnpcn = true;
3826 if (Printer->notify.cli_chan != NULL &&
3827 Printer->notify.cli_chan->active_connections > 0) {
3828 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3829 "Saving change value in request [%x]\n",
3831 Printer->notify.change = r->in.change_low;
3834 /* just ignore the spoolss_NotifyOption */
3836 switch (Printer->printer_type) {
3838 result = printserver_notify_info(p, r->in.handle,
3842 case SPLHND_PRINTER:
3843 result = printer_notify_info(p, r->in.handle,
3848 Printer->notify.fnpcn = false;
3854 /********************************************************************
3855 ********************************************************************/
3857 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3858 const char *servername,
3859 const char *printername,
3860 const char **printername_p)
3862 /* FIXME: add lp_force_printername() */
3864 if (servername == NULL) {
3865 *printername_p = talloc_strdup(mem_ctx, printername);
3866 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3870 if (servername[0] == '\\' && servername[1] == '\\') {
3874 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3875 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3880 /********************************************************************
3881 ********************************************************************/
3883 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3884 const char *printername)
3890 dm->devicename = talloc_strndup(dm, printername,
3891 MIN(strlen(printername), 31));
3894 /********************************************************************
3895 * construct_printer_info_0
3896 * fill a printer_info_0 struct
3897 ********************************************************************/
3899 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3900 const struct auth_session_info *session_info,
3901 struct messaging_context *msg_ctx,
3902 struct spoolss_PrinterInfo2 *info2,
3903 const char *servername,
3904 struct spoolss_PrinterInfo0 *r,
3908 struct printer_session_counter *session_counter;
3909 struct timeval setuptime;
3910 print_status_struct status;
3913 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3914 if (!W_ERROR_IS_OK(result)) {
3919 r->servername = talloc_strdup(mem_ctx, servername);
3920 W_ERROR_HAVE_NO_MEMORY(r->servername);
3922 r->servername = NULL;
3925 count = print_queue_length(msg_ctx, snum, &status);
3927 /* check if we already have a counter for this printer */
3928 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3929 if (session_counter->snum == snum)
3933 /* it's the first time, add it to the list */
3934 if (session_counter == NULL) {
3935 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3936 W_ERROR_HAVE_NO_MEMORY(session_counter);
3937 session_counter->snum = snum;
3938 session_counter->counter = 0;
3939 DLIST_ADD(counter_list, session_counter);
3943 session_counter->counter++;
3949 get_startup_time(&setuptime);
3950 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3953 * the global_counter should be stored in a TDB as it's common to all the clients
3954 * and should be zeroed on samba startup
3956 r->global_counter = session_counter->counter;
3958 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3959 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3960 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3961 r->free_build = SPOOLSS_RELEASE_BUILD;
3963 r->max_spooling = 0;
3964 r->session_counter = session_counter->counter;
3965 r->num_error_out_of_paper = 0x0;
3966 r->num_error_not_ready = 0x0; /* number of print failure */
3968 r->number_of_processors = 0x1;
3969 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3970 r->high_part_total_bytes = 0x0;
3972 /* ChangeID in milliseconds*/
3973 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3974 info2->sharename, &r->change_id);
3976 r->last_error = WERR_OK;
3977 r->status = nt_printq_status(status.status);
3978 r->enumerate_network_printers = 0x0;
3979 r->c_setprinter = 0x0;
3980 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3981 r->processor_level = 0x6; /* 6 ???*/
3990 /********************************************************************
3991 * construct_printer_info1
3992 * fill a spoolss_PrinterInfo1 struct
3993 ********************************************************************/
3995 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3996 const struct spoolss_PrinterInfo2 *info2,
3998 const char *servername,
3999 struct spoolss_PrinterInfo1 *r,
4006 if (info2->comment == NULL || info2->comment[0] == '\0') {
4007 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4009 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4011 W_ERROR_HAVE_NO_MEMORY(r->comment);
4013 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4014 if (!W_ERROR_IS_OK(result)) {
4018 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4022 W_ERROR_HAVE_NO_MEMORY(r->description);
4027 /********************************************************************
4028 * construct_printer_info2
4029 * fill a spoolss_PrinterInfo2 struct
4030 ********************************************************************/
4032 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4033 struct messaging_context *msg_ctx,
4034 const struct spoolss_PrinterInfo2 *info2,
4035 const char *servername,
4036 struct spoolss_PrinterInfo2 *r,
4040 print_status_struct status;
4043 count = print_queue_length(msg_ctx, snum, &status);
4046 r->servername = talloc_strdup(mem_ctx, servername);
4047 W_ERROR_HAVE_NO_MEMORY(r->servername);
4049 r->servername = NULL;
4052 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4053 if (!W_ERROR_IS_OK(result)) {
4057 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4058 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4059 r->portname = talloc_strdup(mem_ctx, info2->portname);
4060 W_ERROR_HAVE_NO_MEMORY(r->portname);
4061 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4062 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4064 if (info2->comment[0] == '\0') {
4065 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4067 r->comment = talloc_strdup(mem_ctx, info2->comment);
4069 W_ERROR_HAVE_NO_MEMORY(r->comment);
4071 r->location = talloc_strdup(mem_ctx, info2->location);
4072 if (info2->location[0] == '\0') {
4073 const char *loc = NULL;
4076 nt_status = printer_list_get_printer(mem_ctx,
4081 if (NT_STATUS_IS_OK(nt_status)) {
4083 r->location = talloc_strdup(mem_ctx, loc);
4087 W_ERROR_HAVE_NO_MEMORY(r->location);
4089 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4090 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4091 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4092 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4093 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4094 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4095 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4096 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4098 r->attributes = info2->attributes;
4100 r->priority = info2->priority;
4101 r->defaultpriority = info2->defaultpriority;
4102 r->starttime = info2->starttime;
4103 r->untiltime = info2->untiltime;
4104 r->status = nt_printq_status(status.status);
4106 r->averageppm = info2->averageppm;
4108 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4110 DEBUG(8,("Returning NULL Devicemode!\n"));
4113 compose_devicemode_devicename(r->devmode, r->printername);
4117 if (info2->secdesc != NULL) {
4118 /* don't use talloc_steal() here unless you do a deep steal of all
4119 the SEC_DESC members */
4121 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4127 /********************************************************************
4128 * construct_printer_info3
4129 * fill a spoolss_PrinterInfo3 struct
4130 ********************************************************************/
4132 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4133 const struct spoolss_PrinterInfo2 *info2,
4134 const char *servername,
4135 struct spoolss_PrinterInfo3 *r,
4138 /* These are the components of the SD we are returning. */
4140 if (info2->secdesc != NULL) {
4141 /* don't use talloc_steal() here unless you do a deep steal of all
4142 the SEC_DESC members */
4144 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4145 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4151 /********************************************************************
4152 * construct_printer_info4
4153 * fill a spoolss_PrinterInfo4 struct
4154 ********************************************************************/
4156 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4157 const struct spoolss_PrinterInfo2 *info2,
4158 const char *servername,
4159 struct spoolss_PrinterInfo4 *r,
4164 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4165 if (!W_ERROR_IS_OK(result)) {
4170 r->servername = talloc_strdup(mem_ctx, servername);
4171 W_ERROR_HAVE_NO_MEMORY(r->servername);
4173 r->servername = NULL;
4176 r->attributes = info2->attributes;
4181 /********************************************************************
4182 * construct_printer_info5
4183 * fill a spoolss_PrinterInfo5 struct
4184 ********************************************************************/
4186 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4187 const struct spoolss_PrinterInfo2 *info2,
4188 const char *servername,
4189 struct spoolss_PrinterInfo5 *r,
4194 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4195 if (!W_ERROR_IS_OK(result)) {
4199 r->portname = talloc_strdup(mem_ctx, info2->portname);
4200 W_ERROR_HAVE_NO_MEMORY(r->portname);
4202 r->attributes = info2->attributes;
4204 /* these two are not used by NT+ according to MSDN */
4205 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4206 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4211 /********************************************************************
4212 * construct_printer_info_6
4213 * fill a spoolss_PrinterInfo6 struct
4214 ********************************************************************/
4216 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4217 struct messaging_context *msg_ctx,
4218 const struct spoolss_PrinterInfo2 *info2,
4219 const char *servername,
4220 struct spoolss_PrinterInfo6 *r,
4223 print_status_struct status;
4225 print_queue_length(msg_ctx, snum, &status);
4227 r->status = nt_printq_status(status.status);
4232 /********************************************************************
4233 * construct_printer_info7
4234 * fill a spoolss_PrinterInfo7 struct
4235 ********************************************************************/
4237 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4238 struct messaging_context *msg_ctx,
4239 const char *servername,
4240 struct spoolss_PrinterInfo7 *r,
4243 const struct auth_session_info *session_info = get_session_info_system();
4246 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4248 lp_servicename(snum), &guid, NULL)) {
4249 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4250 r->action = DSPRINT_PUBLISH;
4252 r->guid = talloc_strdup(mem_ctx, "");
4253 r->action = DSPRINT_UNPUBLISH;
4255 W_ERROR_HAVE_NO_MEMORY(r->guid);
4260 /********************************************************************
4261 * construct_printer_info8
4262 * fill a spoolss_PrinterInfo8 struct
4263 ********************************************************************/
4265 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4266 const struct spoolss_PrinterInfo2 *info2,
4267 const char *servername,
4268 struct spoolss_DeviceModeInfo *r,
4272 const char *printername;
4274 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4275 if (!W_ERROR_IS_OK(result)) {
4279 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4281 DEBUG(8,("Returning NULL Devicemode!\n"));
4284 compose_devicemode_devicename(r->devmode, printername);
4290 /********************************************************************
4291 ********************************************************************/
4293 static bool snum_is_shared_printer(int snum)
4295 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4298 /********************************************************************
4299 Spoolss_enumprinters.
4300 ********************************************************************/
4302 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4303 const struct auth_session_info *session_info,
4304 struct messaging_context *msg_ctx,
4305 const char *servername,
4308 union spoolss_PrinterInfo **info_p,
4312 int n_services = lp_numservices();
4313 union spoolss_PrinterInfo *info = NULL;
4315 WERROR result = WERR_OK;
4316 struct dcerpc_binding_handle *b = NULL;
4317 TALLOC_CTX *tmp_ctx = NULL;
4319 tmp_ctx = talloc_new(mem_ctx);
4327 for (snum = 0; snum < n_services; snum++) {
4329 const char *printer;
4330 struct spoolss_PrinterInfo2 *info2;
4332 if (!snum_is_shared_printer(snum)) {
4336 printer = lp_const_servicename(snum);
4338 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4342 result = winreg_printer_binding_handle(tmp_ctx,
4346 if (!W_ERROR_IS_OK(result)) {
4351 result = winreg_create_printer(tmp_ctx, b,
4353 if (!W_ERROR_IS_OK(result)) {
4357 info = talloc_realloc(tmp_ctx, info,
4358 union spoolss_PrinterInfo,
4361 result = WERR_NOMEM;
4365 result = winreg_get_printer(tmp_ctx, b,
4367 if (!W_ERROR_IS_OK(result)) {
4373 result = construct_printer_info0(info, session_info,
4376 &info[count].info0, snum);
4379 result = construct_printer_info1(info, info2, flags,
4381 &info[count].info1, snum);
4384 result = construct_printer_info2(info, msg_ctx, info2,
4386 &info[count].info2, snum);
4389 result = construct_printer_info4(info, info2,
4391 &info[count].info4, snum);
4394 result = construct_printer_info5(info, info2,
4396 &info[count].info5, snum);
4400 result = WERR_UNKNOWN_LEVEL;
4404 if (!W_ERROR_IS_OK(result)) {
4412 if (W_ERROR_IS_OK(result)) {
4413 *info_p = talloc_move(mem_ctx, &info);
4417 talloc_free(tmp_ctx);
4422 /********************************************************************
4423 * handle enumeration of printers at level 0
4424 ********************************************************************/
4426 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4427 const struct auth_session_info *session_info,
4428 struct messaging_context *msg_ctx,
4430 const char *servername,
4431 union spoolss_PrinterInfo **info,
4434 DEBUG(4,("enum_all_printers_info_0\n"));
4436 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4437 servername, 0, flags, info, count);
4441 /********************************************************************
4442 ********************************************************************/
4444 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4445 const struct auth_session_info *session_info,
4446 struct messaging_context *msg_ctx,
4447 const char *servername,
4449 union spoolss_PrinterInfo **info,
4452 DEBUG(4,("enum_all_printers_info_1\n"));
4454 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4455 servername, 1, flags, info, count);
4458 /********************************************************************
4459 enum_all_printers_info_1_local.
4460 *********************************************************************/
4462 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4463 const struct auth_session_info *session_info,
4464 struct messaging_context *msg_ctx,
4465 const char *servername,
4466 union spoolss_PrinterInfo **info,
4469 DEBUG(4,("enum_all_printers_info_1_local\n"));
4471 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4472 servername, PRINTER_ENUM_ICON8, info, count);
4475 /********************************************************************
4476 enum_all_printers_info_1_name.
4477 *********************************************************************/
4479 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4480 const struct auth_session_info *session_info,
4481 struct messaging_context *msg_ctx,
4482 const char *servername,
4483 union spoolss_PrinterInfo **info,
4486 const char *s = servername;
4488 DEBUG(4,("enum_all_printers_info_1_name\n"));
4490 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4494 if (!is_myname_or_ipaddr(s)) {
4495 return WERR_INVALID_NAME;
4498 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4499 servername, PRINTER_ENUM_ICON8, info, count);
4502 /********************************************************************
4503 enum_all_printers_info_1_network.
4504 *********************************************************************/
4506 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4507 const struct auth_session_info *session_info,
4508 struct messaging_context *msg_ctx,
4509 const char *servername,
4510 union spoolss_PrinterInfo **info,
4513 const char *s = servername;
4515 DEBUG(4,("enum_all_printers_info_1_network\n"));
4517 /* If we respond to a enum_printers level 1 on our name with flags
4518 set to PRINTER_ENUM_REMOTE with a list of printers then these
4519 printers incorrectly appear in the APW browse list.
4520 Specifically the printers for the server appear at the workgroup
4521 level where all the other servers in the domain are
4522 listed. Windows responds to this call with a
4523 WERR_CAN_NOT_COMPLETE so we should do the same. */
4525 if (servername[0] == '\\' && servername[1] == '\\') {
4529 if (is_myname_or_ipaddr(s)) {
4530 return WERR_CAN_NOT_COMPLETE;
4533 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4534 servername, PRINTER_ENUM_NAME, info, count);
4537 /********************************************************************
4538 * api_spoolss_enumprinters
4540 * called from api_spoolss_enumprinters (see this to understand)
4541 ********************************************************************/
4543 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4544 const struct auth_session_info *session_info,
4545 struct messaging_context *msg_ctx,
4546 const char *servername,
4547 union spoolss_PrinterInfo **info,
4550 DEBUG(4,("enum_all_printers_info_2\n"));
4552 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4553 servername, 2, 0, info, count);
4556 /********************************************************************
4557 * handle enumeration of printers at level 1
4558 ********************************************************************/
4560 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4561 const struct auth_session_info *session_info,
4562 struct messaging_context *msg_ctx,
4564 const char *servername,
4565 union spoolss_PrinterInfo **info,
4568 /* Not all the flags are equals */
4570 if (flags & PRINTER_ENUM_LOCAL) {
4571 return enum_all_printers_info_1_local(mem_ctx, session_info,
4572 msg_ctx, servername, info, count);
4575 if (flags & PRINTER_ENUM_NAME) {
4576 return enum_all_printers_info_1_name(mem_ctx, session_info,
4577 msg_ctx, servername, info,
4581 if (flags & PRINTER_ENUM_NETWORK) {
4582 return enum_all_printers_info_1_network(mem_ctx, session_info,
4583 msg_ctx, servername, info,
4587 return WERR_OK; /* NT4sp5 does that */
4590 /********************************************************************
4591 * handle enumeration of printers at level 2
4592 ********************************************************************/
4594 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4595 const struct auth_session_info *session_info,
4596 struct messaging_context *msg_ctx,
4598 const char *servername,
4599 union spoolss_PrinterInfo **info,
4602 if (flags & PRINTER_ENUM_LOCAL) {
4604 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4609 if (flags & PRINTER_ENUM_NAME) {
4610 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4611 return WERR_INVALID_NAME;
4614 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4619 if (flags & PRINTER_ENUM_REMOTE) {
4620 return WERR_UNKNOWN_LEVEL;
4626 /********************************************************************
4627 * handle enumeration of printers at level 4
4628 ********************************************************************/
4630 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4631 const struct auth_session_info *session_info,
4632 struct messaging_context *msg_ctx,
4634 const char *servername,
4635 union spoolss_PrinterInfo **info,
4638 DEBUG(4,("enum_all_printers_info_4\n"));
4640 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4641 servername, 4, flags, info, count);
4645 /********************************************************************
4646 * handle enumeration of printers at level 5
4647 ********************************************************************/
4649 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4650 const struct auth_session_info *session_info,
4651 struct messaging_context *msg_ctx,
4653 const char *servername,
4654 union spoolss_PrinterInfo **info,
4657 DEBUG(4,("enum_all_printers_info_5\n"));
4659 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4660 servername, 5, flags, info, count);
4663 /****************************************************************
4664 _spoolss_EnumPrinters
4665 ****************************************************************/
4667 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4668 struct spoolss_EnumPrinters *r)
4670 const struct auth_session_info *session_info = get_session_info_system();
4673 /* that's an [in out] buffer */
4675 if (!r->in.buffer && (r->in.offered != 0)) {
4676 return WERR_INVALID_PARAM;
4679 DEBUG(4,("_spoolss_EnumPrinters\n"));
4683 *r->out.info = NULL;
4687 * flags==PRINTER_ENUM_NAME
4688 * if name=="" then enumerates all printers
4689 * if name!="" then enumerate the printer
4690 * flags==PRINTER_ENUM_REMOTE
4691 * name is NULL, enumerate printers
4692 * Level 2: name!="" enumerates printers, name can't be NULL
4693 * Level 3: doesn't exist
4694 * Level 4: does a local registry lookup
4695 * Level 5: same as Level 2
4698 if (r->in.server && r->in.server[0] == '\0') {
4699 r->in.server = NULL;
4702 switch (r->in.level) {
4704 result = enumprinters_level0(p->mem_ctx, session_info,
4705 p->msg_ctx, r->in.flags,
4707 r->out.info, r->out.count);
4710 result = enumprinters_level1(p->mem_ctx, session_info,
4711 p->msg_ctx, r->in.flags,
4713 r->out.info, r->out.count);
4716 result = enumprinters_level2(p->mem_ctx, session_info,
4717 p->msg_ctx, r->in.flags,
4719 r->out.info, r->out.count);
4722 result = enumprinters_level4(p->mem_ctx, session_info,
4723 p->msg_ctx, r->in.flags,
4725 r->out.info, r->out.count);
4728 result = enumprinters_level5(p->mem_ctx, session_info,
4729 p->msg_ctx, r->in.flags,
4731 r->out.info, r->out.count);
4734 return WERR_UNKNOWN_LEVEL;
4737 if (!W_ERROR_IS_OK(result)) {
4741 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4742 spoolss_EnumPrinters,
4743 *r->out.info, r->in.level,
4745 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4746 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4748 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4751 /****************************************************************
4753 ****************************************************************/
4755 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4756 struct spoolss_GetPrinter *r)
4758 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4759 struct spoolss_PrinterInfo2 *info2 = NULL;
4760 WERROR result = WERR_OK;
4763 /* that's an [in out] buffer */
4765 if (!r->in.buffer && (r->in.offered != 0)) {
4766 return WERR_INVALID_PARAM;
4771 if (Printer == NULL) {
4775 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4779 result = winreg_get_printer_internal(p->mem_ctx,
4780 get_session_info_system(),
4782 lp_const_servicename(snum),
4784 if (!W_ERROR_IS_OK(result)) {
4788 switch (r->in.level) {
4790 result = construct_printer_info0(p->mem_ctx,
4791 get_session_info_system(),
4794 Printer->servername,
4795 &r->out.info->info0,
4799 result = construct_printer_info1(p->mem_ctx, info2,
4801 Printer->servername,
4802 &r->out.info->info1, snum);
4805 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4806 Printer->servername,
4807 &r->out.info->info2, snum);
4810 result = construct_printer_info3(p->mem_ctx, info2,
4811 Printer->servername,
4812 &r->out.info->info3, snum);
4815 result = construct_printer_info4(p->mem_ctx, info2,
4816 Printer->servername,
4817 &r->out.info->info4, snum);
4820 result = construct_printer_info5(p->mem_ctx, info2,
4821 Printer->servername,
4822 &r->out.info->info5, snum);
4825 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4826 Printer->servername,
4827 &r->out.info->info6, snum);
4830 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4831 Printer->servername,
4832 &r->out.info->info7, snum);
4835 result = construct_printer_info8(p->mem_ctx, info2,
4836 Printer->servername,
4837 &r->out.info->info8, snum);
4840 result = WERR_UNKNOWN_LEVEL;
4846 if (!W_ERROR_IS_OK(result)) {
4847 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4848 r->in.level, win_errstr(result)));
4849 TALLOC_FREE(r->out.info);
4853 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4854 r->out.info, r->in.level);
4855 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4857 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4860 /********************************************************************
4861 ********************************************************************/
4863 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4865 if (in && strlen(in)) { \
4866 out = talloc_strdup(mem_ctx, in); \
4868 out = talloc_strdup(mem_ctx, ""); \
4870 W_ERROR_HAVE_NO_MEMORY(out); \
4873 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4875 if (in && strlen(in)) { \
4876 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4878 out = talloc_strdup(mem_ctx, ""); \
4880 W_ERROR_HAVE_NO_MEMORY(out); \
4883 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4884 const char **string_array,
4885 const char ***presult,
4886 const char *cservername,
4890 int i, num_strings = 0;
4891 const char **array = NULL;
4893 if (string_array == NULL) {
4894 return WERR_INVALID_PARAMETER;
4897 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4898 const char *str = NULL;
4900 if (cservername == NULL || arch == NULL) {
4901 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4903 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4906 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4913 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4914 &array, &num_strings);
4924 /********************************************************************
4925 * fill a spoolss_DriverInfo1 struct
4926 ********************************************************************/
4928 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4929 struct spoolss_DriverInfo1 *r,
4930 const struct spoolss_DriverInfo8 *driver,
4931 const char *servername)
4933 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4934 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4939 /********************************************************************
4940 * fill a spoolss_DriverInfo2 struct
4941 ********************************************************************/
4943 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4944 struct spoolss_DriverInfo2 *r,
4945 const struct spoolss_DriverInfo8 *driver,
4946 const char *servername)
4949 const char *cservername = canon_servername(servername);
4951 r->version = driver->version;
4953 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4954 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4955 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4956 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4958 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4959 driver->architecture,
4961 driver->driver_path,
4964 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4965 driver->architecture,
4970 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4971 driver->architecture,
4973 driver->config_file,
4979 /********************************************************************
4980 * fill a spoolss_DriverInfo3 struct
4981 ********************************************************************/
4983 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4984 struct spoolss_DriverInfo3 *r,
4985 const struct spoolss_DriverInfo8 *driver,
4986 const char *servername)
4988 const char *cservername = canon_servername(servername);
4990 r->version = driver->version;
4992 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4993 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4994 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4995 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4997 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998 driver->architecture,
5000 driver->driver_path,
5003 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5004 driver->architecture,
5009 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5010 driver->architecture,
5012 driver->config_file,
5015 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5016 driver->architecture,
5021 FILL_DRIVER_STRING(mem_ctx,
5022 driver->monitor_name,
5025 FILL_DRIVER_STRING(mem_ctx,
5026 driver->default_datatype,
5027 r->default_datatype);
5029 return string_array_from_driver_info(mem_ctx,
5030 driver->dependent_files,
5031 &r->dependent_files,
5033 driver->architecture,
5037 /********************************************************************
5038 * fill a spoolss_DriverInfo4 struct
5039 ********************************************************************/
5041 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5042 struct spoolss_DriverInfo4 *r,
5043 const struct spoolss_DriverInfo8 *driver,
5044 const char *servername)
5046 const char *cservername = canon_servername(servername);
5049 r->version = driver->version;
5051 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5052 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5053 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5054 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5056 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057 driver->architecture,
5059 driver->driver_path,
5062 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5063 driver->architecture,
5068 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5069 driver->architecture,
5071 driver->config_file,
5074 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5075 driver->architecture,
5080 result = string_array_from_driver_info(mem_ctx,
5081 driver->dependent_files,
5082 &r->dependent_files,
5084 driver->architecture,
5086 if (!W_ERROR_IS_OK(result)) {
5090 FILL_DRIVER_STRING(mem_ctx,
5091 driver->monitor_name,
5094 FILL_DRIVER_STRING(mem_ctx,
5095 driver->default_datatype,
5096 r->default_datatype);
5099 result = string_array_from_driver_info(mem_ctx,
5100 driver->previous_names,
5107 /********************************************************************
5108 * fill a spoolss_DriverInfo5 struct
5109 ********************************************************************/
5111 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5112 struct spoolss_DriverInfo5 *r,
5113 const struct spoolss_DriverInfo8 *driver,
5114 const char *servername)
5116 const char *cservername = canon_servername(servername);
5118 r->version = driver->version;
5120 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5121 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5122 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5123 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5125 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126 driver->architecture,
5128 driver->driver_path,
5131 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5132 driver->architecture,
5137 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5138 driver->architecture,
5140 driver->config_file,
5143 r->driver_attributes = 0;
5144 r->config_version = 0;
5145 r->driver_version = 0;
5149 /********************************************************************
5150 * fill a spoolss_DriverInfo6 struct
5151 ********************************************************************/
5153 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5154 struct spoolss_DriverInfo6 *r,
5155 const struct spoolss_DriverInfo8 *driver,
5156 const char *servername)
5158 const char *cservername = canon_servername(servername);
5161 r->version = driver->version;
5163 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5164 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5165 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5166 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5168 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5169 driver->architecture,
5171 driver->driver_path,
5174 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5175 driver->architecture,
5180 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181 driver->architecture,
5183 driver->config_file,
5186 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187 driver->architecture,
5192 FILL_DRIVER_STRING(mem_ctx,
5193 driver->monitor_name,
5196 FILL_DRIVER_STRING(mem_ctx,
5197 driver->default_datatype,
5198 r->default_datatype);
5200 result = string_array_from_driver_info(mem_ctx,
5201 driver->dependent_files,
5202 &r->dependent_files,
5204 driver->architecture,
5206 if (!W_ERROR_IS_OK(result)) {
5210 result = string_array_from_driver_info(mem_ctx,
5211 driver->previous_names,
5214 if (!W_ERROR_IS_OK(result)) {
5218 r->driver_date = driver->driver_date;
5219 r->driver_version = driver->driver_version;
5221 FILL_DRIVER_STRING(mem_ctx,
5222 driver->manufacturer_name,
5223 r->manufacturer_name);
5224 FILL_DRIVER_STRING(mem_ctx,
5225 driver->manufacturer_url,
5226 r->manufacturer_url);
5227 FILL_DRIVER_STRING(mem_ctx,
5228 driver->hardware_id,
5230 FILL_DRIVER_STRING(mem_ctx,
5237 /********************************************************************
5238 * fill a spoolss_DriverInfo8 struct
5239 ********************************************************************/
5241 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5242 struct spoolss_DriverInfo8 *r,
5243 const struct spoolss_DriverInfo8 *driver,
5244 const char *servername)
5246 const char *cservername = canon_servername(servername);
5249 r->version = driver->version;
5251 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5252 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5253 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5254 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5256 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5257 driver->architecture,
5259 driver->driver_path,
5262 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5263 driver->architecture,
5268 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5269 driver->architecture,
5271 driver->config_file,
5274 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5275 driver->architecture,
5280 FILL_DRIVER_STRING(mem_ctx,
5281 driver->monitor_name,
5284 FILL_DRIVER_STRING(mem_ctx,
5285 driver->default_datatype,
5286 r->default_datatype);
5288 result = string_array_from_driver_info(mem_ctx,
5289 driver->dependent_files,
5290 &r->dependent_files,
5292 driver->architecture,
5294 if (!W_ERROR_IS_OK(result)) {
5298 result = string_array_from_driver_info(mem_ctx,
5299 driver->previous_names,
5302 if (!W_ERROR_IS_OK(result)) {
5306 r->driver_date = driver->driver_date;
5307 r->driver_version = driver->driver_version;
5309 FILL_DRIVER_STRING(mem_ctx,
5310 driver->manufacturer_name,
5311 r->manufacturer_name);
5312 FILL_DRIVER_STRING(mem_ctx,
5313 driver->manufacturer_url,
5314 r->manufacturer_url);
5315 FILL_DRIVER_STRING(mem_ctx,
5316 driver->hardware_id,
5318 FILL_DRIVER_STRING(mem_ctx,
5322 FILL_DRIVER_STRING(mem_ctx,
5323 driver->print_processor,
5324 r->print_processor);
5325 FILL_DRIVER_STRING(mem_ctx,
5326 driver->vendor_setup,
5329 result = string_array_from_driver_info(mem_ctx,
5330 driver->color_profiles,
5333 if (!W_ERROR_IS_OK(result)) {
5337 FILL_DRIVER_STRING(mem_ctx,
5341 r->printer_driver_attributes = driver->printer_driver_attributes;
5343 result = string_array_from_driver_info(mem_ctx,
5344 driver->core_driver_dependencies,
5345 &r->core_driver_dependencies,
5347 if (!W_ERROR_IS_OK(result)) {
5351 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5352 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5357 #if 0 /* disabled until marshalling issues are resolved - gd */
5358 /********************************************************************
5359 ********************************************************************/
5361 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5362 struct spoolss_DriverFileInfo *r,
5363 const char *cservername,
5364 const char *file_name,
5365 enum spoolss_DriverFileType file_type,
5366 uint32_t file_version)
5368 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5369 cservername, file_name);
5370 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5371 r->file_type = file_type;
5372 r->file_version = file_version;
5377 /********************************************************************
5378 ********************************************************************/
5380 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5381 const struct spoolss_DriverInfo8 *driver,
5382 const char *cservername,
5383 struct spoolss_DriverFileInfo **info_p,
5386 struct spoolss_DriverFileInfo *info = NULL;
5394 if (strlen(driver->driver_path)) {
5395 info = talloc_realloc(mem_ctx, info,
5396 struct spoolss_DriverFileInfo,
5398 W_ERROR_HAVE_NO_MEMORY(info);
5399 result = fill_spoolss_DriverFileInfo(info,
5402 driver->driver_path,
5403 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5405 W_ERROR_NOT_OK_RETURN(result);
5409 if (strlen(driver->config_file)) {
5410 info = talloc_realloc(mem_ctx, info,
5411 struct spoolss_DriverFileInfo,
5413 W_ERROR_HAVE_NO_MEMORY(info);
5414 result = fill_spoolss_DriverFileInfo(info,
5417 driver->config_file,
5418 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5420 W_ERROR_NOT_OK_RETURN(result);
5424 if (strlen(driver->data_file)) {
5425 info = talloc_realloc(mem_ctx, info,
5426 struct spoolss_DriverFileInfo,
5428 W_ERROR_HAVE_NO_MEMORY(info);
5429 result = fill_spoolss_DriverFileInfo(info,
5433 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5435 W_ERROR_NOT_OK_RETURN(result);
5439 if (strlen(driver->help_file)) {
5440 info = talloc_realloc(mem_ctx, info,
5441 struct spoolss_DriverFileInfo,
5443 W_ERROR_HAVE_NO_MEMORY(info);
5444 result = fill_spoolss_DriverFileInfo(info,
5448 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5450 W_ERROR_NOT_OK_RETURN(result);
5454 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5455 info = talloc_realloc(mem_ctx, info,
5456 struct spoolss_DriverFileInfo,
5458 W_ERROR_HAVE_NO_MEMORY(info);
5459 result = fill_spoolss_DriverFileInfo(info,
5462 driver->dependent_files[i],
5463 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5465 W_ERROR_NOT_OK_RETURN(result);
5475 /********************************************************************
5476 * fill a spoolss_DriverInfo101 struct
5477 ********************************************************************/
5479 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5480 struct spoolss_DriverInfo101 *r,
5481 const struct spoolss_DriverInfo8 *driver,
5482 const char *servername)
5484 const char *cservername = canon_servername(servername);
5487 r->version = driver->version;
5489 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5490 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5491 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5492 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5494 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5498 if (!W_ERROR_IS_OK(result)) {
5502 FILL_DRIVER_STRING(mem_ctx,
5503 driver->monitor_name,
5506 FILL_DRIVER_STRING(mem_ctx,
5507 driver->default_datatype,
5508 r->default_datatype);
5510 result = string_array_from_driver_info(mem_ctx,
5511 driver->previous_names,
5514 if (!W_ERROR_IS_OK(result)) {
5518 r->driver_date = driver->driver_date;
5519 r->driver_version = driver->driver_version;
5521 FILL_DRIVER_STRING(mem_ctx,
5522 driver->manufacturer_name,
5523 r->manufacturer_name);
5524 FILL_DRIVER_STRING(mem_ctx,
5525 driver->manufacturer_url,
5526 r->manufacturer_url);
5527 FILL_DRIVER_STRING(mem_ctx,
5528 driver->hardware_id,
5530 FILL_DRIVER_STRING(mem_ctx,
5537 /********************************************************************
5538 ********************************************************************/
5540 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5541 const struct auth_session_info *session_info,
5542 struct messaging_context *msg_ctx,
5544 union spoolss_DriverInfo *r,
5546 const char *servername,
5547 const char *architecture,
5550 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5551 struct spoolss_DriverInfo8 *driver;
5553 struct dcerpc_binding_handle *b;
5554 TALLOC_CTX *tmp_ctx = NULL;
5557 return WERR_UNKNOWN_LEVEL;
5560 tmp_ctx = talloc_new(mem_ctx);
5565 result = winreg_printer_binding_handle(tmp_ctx,
5569 if (!W_ERROR_IS_OK(result)) {
5573 result = winreg_get_printer(tmp_ctx, b,
5574 lp_const_servicename(snum),
5577 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5578 win_errstr(result)));
5580 if (!W_ERROR_IS_OK(result)) {
5581 result = WERR_INVALID_PRINTER_NAME;
5585 result = winreg_get_driver(tmp_ctx, b,
5587 pinfo2->drivername, version, &driver);
5589 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5590 win_errstr(result)));
5592 if (!W_ERROR_IS_OK(result)) {
5594 * Is this a W2k client ?
5598 result = WERR_UNKNOWN_PRINTER_DRIVER;
5602 /* Yes - try again with a WinNT driver. */
5604 result = winreg_get_driver(tmp_ctx, b,
5608 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5609 win_errstr(result)));
5610 if (!W_ERROR_IS_OK(result)) {
5611 result = WERR_UNKNOWN_PRINTER_DRIVER;
5616 /* these are allocated on mem_ctx and not tmp_ctx because they are
5617 * the 'return value' and need to utlive this call */
5620 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5623 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5626 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5629 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5632 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5635 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5638 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5640 #if 0 /* disabled until marshalling issues are resolved - gd */
5642 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5646 result = WERR_UNKNOWN_LEVEL;
5651 talloc_free(tmp_ctx);
5655 /****************************************************************
5656 _spoolss_GetPrinterDriver2
5657 ****************************************************************/
5659 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5660 struct spoolss_GetPrinterDriver2 *r)
5662 struct printer_handle *printer;
5667 /* that's an [in out] buffer */
5669 if (!r->in.buffer && (r->in.offered != 0)) {
5670 return WERR_INVALID_PARAM;
5673 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5675 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5676 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5677 return WERR_INVALID_PRINTER_NAME;
5681 *r->out.server_major_version = 0;
5682 *r->out.server_minor_version = 0;
5684 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5688 result = construct_printer_driver_info_level(p->mem_ctx,
5689 get_session_info_system(),
5691 r->in.level, r->out.info,
5692 snum, printer->servername,
5694 r->in.client_major_version);
5695 if (!W_ERROR_IS_OK(result)) {
5696 TALLOC_FREE(r->out.info);
5700 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5701 r->out.info, r->in.level);
5702 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5704 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5708 /****************************************************************
5709 _spoolss_StartPagePrinter
5710 ****************************************************************/
5712 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5713 struct spoolss_StartPagePrinter *r)
5715 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5718 DEBUG(3,("_spoolss_StartPagePrinter: "
5719 "Error in startpageprinter printer handle\n"));
5723 Printer->page_started = true;
5727 /****************************************************************
5728 _spoolss_EndPagePrinter
5729 ****************************************************************/
5731 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5732 struct spoolss_EndPagePrinter *r)
5736 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5739 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5740 OUR_HANDLE(r->in.handle)));
5744 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5747 Printer->page_started = false;
5748 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5753 /****************************************************************
5754 _spoolss_StartDocPrinter
5755 ****************************************************************/
5757 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5758 struct spoolss_StartDocPrinter *r)
5760 struct spoolss_DocumentInfo1 *info_1;
5762 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5768 DEBUG(2,("_spoolss_StartDocPrinter: "
5769 "Invalid handle (%s:%u:%u)\n",
5770 OUR_HANDLE(r->in.handle)));
5774 if (Printer->jobid) {
5775 DEBUG(2, ("_spoolss_StartDocPrinter: "
5776 "StartDocPrinter called twice! "
5777 "(existing jobid = %d)\n", Printer->jobid));
5778 return WERR_INVALID_HANDLE;
5781 if (r->in.level != 1) {
5782 return WERR_UNKNOWN_LEVEL;
5785 info_1 = r->in.info.info1;
5788 * a nice thing with NT is it doesn't listen to what you tell it.
5789 * when asked to send _only_ RAW datas, it tries to send datas
5792 * So I add checks like in NT Server ...
5795 if (info_1->datatype) {
5796 if (strcmp(info_1->datatype, "RAW") != 0) {
5798 return WERR_INVALID_DATATYPE;
5802 /* get the share number of the printer */
5803 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5807 rc = get_remote_hostname(p->remote_address,
5813 if (strequal(rhost,"UNKNOWN")) {
5814 rhost = tsocket_address_inet_addr_string(p->remote_address,
5816 if (rhost == NULL) {
5821 werr = print_job_start(p->session_info,
5825 info_1->document_name,
5826 info_1->output_file,
5830 /* An error occured in print_job_start() so return an appropriate
5833 if (!W_ERROR_IS_OK(werr)) {
5837 Printer->document_started = true;
5838 *r->out.job_id = Printer->jobid;
5843 /****************************************************************
5844 _spoolss_EndDocPrinter
5845 ****************************************************************/
5847 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5848 struct spoolss_EndDocPrinter *r)
5850 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5855 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5856 OUR_HANDLE(r->in.handle)));
5860 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5864 Printer->document_started = false;
5865 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5866 if (!NT_STATUS_IS_OK(status)) {
5867 DEBUG(2, ("_spoolss_EndDocPrinter: "
5868 "print_job_end failed [%s]\n",
5869 nt_errstr(status)));
5873 return ntstatus_to_werror(status);
5876 /****************************************************************
5877 _spoolss_WritePrinter
5878 ****************************************************************/
5880 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5881 struct spoolss_WritePrinter *r)
5883 ssize_t buffer_written;
5885 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5888 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5889 OUR_HANDLE(r->in.handle)));
5890 *r->out.num_written = r->in._data_size;
5894 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5897 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5898 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5899 snum, Printer->jobid,
5900 (const char *)r->in.data.data,
5901 (size_t)r->in._data_size);
5902 if (buffer_written == (ssize_t)-1) {
5903 *r->out.num_written = 0;
5904 if (errno == ENOSPC)
5905 return WERR_NO_SPOOL_SPACE;
5907 return WERR_ACCESS_DENIED;
5910 *r->out.num_written = r->in._data_size;
5915 /********************************************************************
5916 * api_spoolss_getprinter
5917 * called from the spoolss dispatcher
5919 ********************************************************************/
5921 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5922 struct pipes_struct *p)
5924 const struct auth_session_info *session_info = p->session_info;
5926 WERROR errcode = WERR_BADFUNC;
5927 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5930 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5931 OUR_HANDLE(handle)));
5935 if (!get_printer_snum(p, handle, &snum, NULL))
5939 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5940 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5942 case SPOOLSS_PRINTER_CONTROL_RESUME:
5943 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5944 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5946 case SPOOLSS_PRINTER_CONTROL_PURGE:
5947 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5950 return WERR_UNKNOWN_LEVEL;
5957 /****************************************************************
5958 _spoolss_AbortPrinter
5959 * From MSDN: "Deletes printer's spool file if printer is configured
5961 ****************************************************************/
5963 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5964 struct spoolss_AbortPrinter *r)
5966 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5968 WERROR errcode = WERR_OK;
5971 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5972 OUR_HANDLE(r->in.handle)));
5976 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5979 if (!Printer->document_started) {
5980 return WERR_SPL_NO_STARTDOC;
5983 errcode = print_job_delete(p->session_info,
5991 /********************************************************************
5992 * called by spoolss_api_setprinter
5993 * when updating a printer description
5994 ********************************************************************/
5996 static WERROR update_printer_sec(struct policy_handle *handle,
5997 struct pipes_struct *p,
5998 struct sec_desc_buf *secdesc_ctr)
6000 struct spoolss_security_descriptor *new_secdesc = NULL;
6001 struct spoolss_security_descriptor *old_secdesc = NULL;
6002 const char *printer;
6005 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6006 struct dcerpc_binding_handle *b;
6007 TALLOC_CTX *tmp_ctx = NULL;
6009 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6010 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6011 OUR_HANDLE(handle)));
6013 result = WERR_BADFID;
6017 if (secdesc_ctr == NULL) {
6018 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6019 result = WERR_INVALID_PARAM;
6022 printer = lp_const_servicename(snum);
6024 /* Check the user has permissions to change the security
6025 descriptor. By experimentation with two NT machines, the user
6026 requires Full Access to the printer to change security
6029 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6030 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6031 result = WERR_ACCESS_DENIED;
6035 tmp_ctx = talloc_new(p->mem_ctx);
6040 result = winreg_printer_binding_handle(tmp_ctx,
6041 get_session_info_system(),
6044 if (!W_ERROR_IS_OK(result)) {
6048 /* NT seems to like setting the security descriptor even though
6049 nothing may have actually changed. */
6050 result = winreg_get_printer_secdesc(tmp_ctx, b,
6053 if (!W_ERROR_IS_OK(result)) {
6054 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6055 result = WERR_BADFID;
6059 if (DEBUGLEVEL >= 10) {
6060 struct security_acl *the_acl;
6063 the_acl = old_secdesc->dacl;
6064 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6065 printer, the_acl->num_aces));
6067 for (i = 0; i < the_acl->num_aces; i++) {
6068 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6069 &the_acl->aces[i].trustee),
6070 the_acl->aces[i].access_mask));
6073 the_acl = secdesc_ctr->sd->dacl;
6076 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6077 printer, the_acl->num_aces));
6079 for (i = 0; i < the_acl->num_aces; i++) {
6080 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6081 &the_acl->aces[i].trustee),
6082 the_acl->aces[i].access_mask));
6085 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6089 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6090 if (new_secdesc == NULL) {
6091 result = WERR_NOMEM;
6095 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6100 result = winreg_set_printer_secdesc(tmp_ctx, b,
6105 talloc_free(tmp_ctx);
6109 /********************************************************************
6110 Canonicalize printer info from a client
6111 ********************************************************************/
6113 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6114 struct spoolss_SetPrinterInfo2 *info2,
6117 fstring printername;
6120 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6121 "portname=%s drivername=%s comment=%s location=%s\n",
6122 info2->servername, info2->printername, info2->sharename,
6123 info2->portname, info2->drivername, info2->comment,
6126 /* we force some elements to "correct" values */
6127 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6128 if (info2->servername == NULL) {
6131 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6132 if (info2->sharename == NULL) {
6136 /* check to see if we allow printername != sharename */
6137 if (lp_force_printername(snum)) {
6138 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6139 lp_netbios_name(), info2->sharename);
6141 /* make sure printername is in \\server\printername format */
6142 fstrcpy(printername, info2->printername);
6144 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6145 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6149 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6150 lp_netbios_name(), p);
6152 if (info2->printername == NULL) {
6156 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6157 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6162 /****************************************************************************
6163 ****************************************************************************/
6165 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6167 char *cmd = lp_addport_cmd();
6168 char *command = NULL;
6170 bool is_print_op = false;
6173 return WERR_ACCESS_DENIED;
6176 command = talloc_asprintf(ctx,
6177 "%s \"%s\" \"%s\"", cmd, portname, uri );
6183 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6185 DEBUG(10,("Running [%s]\n", command));
6187 /********* BEGIN SePrintOperatorPrivilege **********/
6192 ret = smbrun(command, NULL);
6197 /********* END SePrintOperatorPrivilege **********/
6199 DEBUGADD(10,("returned [%d]\n", ret));
6201 TALLOC_FREE(command);
6204 return WERR_ACCESS_DENIED;
6210 /****************************************************************************
6211 ****************************************************************************/
6213 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6214 struct spoolss_SetPrinterInfo2 *info2,
6215 const char *remote_machine,
6216 struct messaging_context *msg_ctx)
6218 char *cmd = lp_addprinter_cmd();
6220 char *command = NULL;
6224 bool is_print_op = false;
6226 if (!remote_machine) {
6230 command = talloc_asprintf(ctx,
6231 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6232 cmd, info2->printername, info2->sharename,
6233 info2->portname, info2->drivername,
6234 info2->location, info2->comment, remote_machine);
6240 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6242 DEBUG(10,("Running [%s]\n", command));
6244 /********* BEGIN SePrintOperatorPrivilege **********/
6249 if ( (ret = smbrun(command, &fd)) == 0 ) {
6250 /* Tell everyone we updated smb.conf. */
6251 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6257 /********* END SePrintOperatorPrivilege **********/
6259 DEBUGADD(10,("returned [%d]\n", ret));
6261 TALLOC_FREE(command);
6269 /* reload our services immediately */
6271 reload_services(msg_ctx, -1, false);
6275 /* Get lines and convert them back to dos-codepage */
6276 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6277 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6280 /* Set the portname to what the script says the portname should be. */
6281 /* but don't require anything to be return from the script exit a good error code */
6284 /* Set the portname to what the script says the portname should be. */
6285 info2->portname = talloc_strdup(ctx, qlines[0]);
6286 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6289 TALLOC_FREE(qlines);
6293 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6294 const struct auth_session_info *session_info,
6295 struct messaging_context *msg_ctx,
6297 struct spoolss_SetPrinterInfo2 *printer,
6298 struct spoolss_PrinterInfo2 *old_printer)
6300 bool force_update = (old_printer == NULL);
6301 const char *dnsdomname;
6302 const char *longname;
6303 const char *uncname;
6304 const char *spooling;
6306 WERROR result = WERR_OK;
6307 struct dcerpc_binding_handle *b;
6308 TALLOC_CTX *tmp_ctx;
6310 tmp_ctx = talloc_new(mem_ctx);
6315 result = winreg_printer_binding_handle(tmp_ctx,
6319 if (!W_ERROR_IS_OK(result)) {
6323 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6324 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6325 winreg_set_printer_dataex(tmp_ctx, b,
6327 SPOOL_DSSPOOLER_KEY,
6328 SPOOL_REG_DRIVERNAME,
6333 if (!force_update) {
6334 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6335 printer->drivername));
6337 notify_printer_driver(server_event_context(), msg_ctx,
6338 snum, printer->drivername ?
6339 printer->drivername : "");
6343 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6344 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6345 winreg_set_printer_dataex(tmp_ctx, b,
6347 SPOOL_DSSPOOLER_KEY,
6348 SPOOL_REG_DESCRIPTION,
6353 if (!force_update) {
6354 notify_printer_comment(server_event_context(), msg_ctx,
6355 snum, printer->comment ?
6356 printer->comment : "");
6360 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6361 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6362 winreg_set_printer_dataex(tmp_ctx, b,
6364 SPOOL_DSSPOOLER_KEY,
6365 SPOOL_REG_PRINTSHARENAME,
6370 if (!force_update) {
6371 notify_printer_sharename(server_event_context(),
6373 snum, printer->sharename ?
6374 printer->sharename : "");
6378 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6381 p = strrchr(printer->printername, '\\' );
6385 p = printer->printername;
6388 push_reg_sz(tmp_ctx, &buffer, p);
6389 winreg_set_printer_dataex(tmp_ctx, b,
6391 SPOOL_DSSPOOLER_KEY,
6392 SPOOL_REG_PRINTERNAME,
6397 if (!force_update) {
6398 notify_printer_printername(server_event_context(),
6399 msg_ctx, snum, p ? p : "");
6403 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6404 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6405 winreg_set_printer_dataex(tmp_ctx, b,
6407 SPOOL_DSSPOOLER_KEY,
6413 if (!force_update) {
6414 notify_printer_port(server_event_context(),
6415 msg_ctx, snum, printer->portname ?
6416 printer->portname : "");
6420 if (force_update || !strequal(printer->location, old_printer->location)) {
6421 push_reg_sz(tmp_ctx, &buffer, printer->location);
6422 winreg_set_printer_dataex(tmp_ctx, b,
6424 SPOOL_DSSPOOLER_KEY,
6430 if (!force_update) {
6431 notify_printer_location(server_event_context(),
6434 printer->location : "");
6438 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6439 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6440 winreg_set_printer_dataex(tmp_ctx, b,
6442 SPOOL_DSSPOOLER_KEY,
6443 SPOOL_REG_PRINTSEPARATORFILE,
6448 if (!force_update) {
6449 notify_printer_sepfile(server_event_context(),
6452 printer->sepfile : "");
6456 if (force_update || printer->starttime != old_printer->starttime) {
6457 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6458 SIVAL(buffer.data, 0, printer->starttime);
6459 winreg_set_printer_dataex(tmp_ctx, b,
6461 SPOOL_DSSPOOLER_KEY,
6462 SPOOL_REG_PRINTSTARTTIME,
6468 if (force_update || printer->untiltime != old_printer->untiltime) {
6469 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6470 SIVAL(buffer.data, 0, printer->untiltime);
6471 winreg_set_printer_dataex(tmp_ctx, b,
6473 SPOOL_DSSPOOLER_KEY,
6474 SPOOL_REG_PRINTENDTIME,
6480 if (force_update || printer->priority != old_printer->priority) {
6481 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6482 SIVAL(buffer.data, 0, printer->priority);
6483 winreg_set_printer_dataex(tmp_ctx, b,
6485 SPOOL_DSSPOOLER_KEY,
6492 if (force_update || printer->attributes != old_printer->attributes) {
6493 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6494 SIVAL(buffer.data, 0, (printer->attributes &
6495 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6496 winreg_set_printer_dataex(tmp_ctx, b,
6498 SPOOL_DSSPOOLER_KEY,
6499 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6504 switch (printer->attributes & 0x3) {
6506 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6509 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6512 spooling = SPOOL_REGVAL_PRINTDIRECT;
6515 spooling = "unknown";
6517 push_reg_sz(tmp_ctx, &buffer, spooling);
6518 winreg_set_printer_dataex(tmp_ctx, b,
6520 SPOOL_DSSPOOLER_KEY,
6521 SPOOL_REG_PRINTSPOOLING,
6527 push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6528 winreg_set_printer_dataex(tmp_ctx, b,
6530 SPOOL_DSSPOOLER_KEY,
6531 SPOOL_REG_SHORTSERVERNAME,
6536 dnsdomname = get_mydnsfullname();
6537 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6538 longname = talloc_strdup(tmp_ctx, dnsdomname);
6540 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6542 if (longname == NULL) {
6543 result = WERR_NOMEM;
6547 push_reg_sz(tmp_ctx, &buffer, longname);
6548 winreg_set_printer_dataex(tmp_ctx, b,
6550 SPOOL_DSSPOOLER_KEY,
6551 SPOOL_REG_SERVERNAME,
6556 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6557 lp_netbios_name(), printer->sharename);
6558 push_reg_sz(tmp_ctx, &buffer, uncname);
6559 winreg_set_printer_dataex(tmp_ctx, b,
6561 SPOOL_DSSPOOLER_KEY,
6568 talloc_free(tmp_ctx);
6572 /********************************************************************
6573 * Called by spoolss_api_setprinter
6574 * when updating a printer description.
6575 ********************************************************************/
6577 static WERROR update_printer(struct pipes_struct *p,
6578 struct policy_handle *handle,
6579 struct spoolss_SetPrinterInfoCtr *info_ctr,
6580 struct spoolss_DeviceMode *devmode)
6582 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6583 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6584 struct spoolss_PrinterInfo2 *old_printer;
6585 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6587 WERROR result = WERR_OK;
6588 TALLOC_CTX *tmp_ctx;
6589 struct dcerpc_binding_handle *b;
6591 DEBUG(8,("update_printer\n"));
6593 tmp_ctx = talloc_new(p->mem_ctx);
6594 if (tmp_ctx == NULL) {
6599 result = WERR_BADFID;
6603 if (!get_printer_snum(p, handle, &snum, NULL)) {
6604 result = WERR_BADFID;
6608 result = winreg_printer_binding_handle(tmp_ctx,
6609 get_session_info_system(),
6612 if (!W_ERROR_IS_OK(result)) {
6616 result = winreg_get_printer(tmp_ctx, b,
6617 lp_const_servicename(snum),
6619 if (!W_ERROR_IS_OK(result)) {
6620 result = WERR_BADFID;
6624 /* Do sanity check on the requested changes for Samba */
6625 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6626 result = WERR_INVALID_PARAM;
6630 /* FIXME!!! If the driver has changed we really should verify that
6631 it is installed before doing much else --jerry */
6633 /* Check calling user has permission to update printer description */
6634 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6635 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6636 result = WERR_ACCESS_DENIED;
6640 /* Call addprinter hook */
6641 /* Check changes to see if this is really needed */
6643 if (*lp_addprinter_cmd() &&
6644 (!strequal(printer->drivername, old_printer->drivername) ||
6645 !strequal(printer->comment, old_printer->comment) ||
6646 !strequal(printer->portname, old_printer->portname) ||
6647 !strequal(printer->location, old_printer->location)) )
6651 raddr = tsocket_address_inet_addr_string(p->remote_address,
6653 if (raddr == NULL) {
6657 /* add_printer_hook() will call reload_services() */
6658 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6661 result = WERR_ACCESS_DENIED;
6666 update_dsspooler(tmp_ctx,
6667 get_session_info_system(),
6673 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6675 if (devmode == NULL) {
6676 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6678 result = winreg_update_printer(tmp_ctx, b,
6686 talloc_free(tmp_ctx);
6691 /****************************************************************************
6692 ****************************************************************************/
6693 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6694 struct policy_handle *handle,
6695 struct spoolss_SetPrinterInfo7 *info7)
6698 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6701 struct printer_handle *Printer;
6703 if ( lp_security() != SEC_ADS ) {
6704 return WERR_UNKNOWN_LEVEL;
6707 Printer = find_printer_index_by_hnd(p, handle);
6709 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6714 if (!get_printer_snum(p, handle, &snum, NULL))
6717 result = winreg_get_printer_internal(p->mem_ctx,
6718 get_session_info_system(),
6720 lp_servicename(snum),
6722 if (!W_ERROR_IS_OK(result)) {
6726 nt_printer_publish(pinfo2,
6727 get_session_info_system(),
6732 TALLOC_FREE(pinfo2);
6735 return WERR_UNKNOWN_LEVEL;
6739 /********************************************************************
6740 ********************************************************************/
6742 static WERROR update_printer_devmode(struct pipes_struct *p,
6743 struct policy_handle *handle,
6744 struct spoolss_DeviceMode *devmode)
6747 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6748 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6750 DEBUG(8,("update_printer_devmode\n"));
6756 if (!get_printer_snum(p, handle, &snum, NULL)) {
6760 /* Check calling user has permission to update printer description */
6761 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6762 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6763 return WERR_ACCESS_DENIED;
6766 return winreg_update_printer_internal(p->mem_ctx,
6767 get_session_info_system(),
6769 lp_const_servicename(snum),
6777 /****************************************************************
6779 ****************************************************************/
6781 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6782 struct spoolss_SetPrinter *r)
6786 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6789 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6790 OUR_HANDLE(r->in.handle)));
6794 /* check the level */
6795 switch (r->in.info_ctr->level) {
6797 return control_printer(r->in.handle, r->in.command, p);
6799 result = update_printer(p, r->in.handle,
6801 r->in.devmode_ctr->devmode);
6802 if (!W_ERROR_IS_OK(result))
6804 if (r->in.secdesc_ctr->sd)
6805 result = update_printer_sec(r->in.handle, p,
6809 return update_printer_sec(r->in.handle, p,
6812 return publish_or_unpublish_printer(p, r->in.handle,
6813 r->in.info_ctr->info.info7);
6815 return update_printer_devmode(p, r->in.handle,
6816 r->in.devmode_ctr->devmode);
6818 return WERR_UNKNOWN_LEVEL;
6822 /****************************************************************
6823 _spoolss_FindClosePrinterNotify
6824 ****************************************************************/
6826 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6827 struct spoolss_FindClosePrinterNotify *r)
6829 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6832 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6833 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6837 if (Printer->notify.cli_chan != NULL &&
6838 Printer->notify.cli_chan->active_connections > 0) {
6841 if (Printer->printer_type == SPLHND_PRINTER) {
6842 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6847 srv_spoolss_replycloseprinter(snum, Printer);
6850 Printer->notify.flags=0;
6851 Printer->notify.options=0;
6852 Printer->notify.localmachine[0]='\0';
6853 Printer->notify.printerlocal=0;
6854 TALLOC_FREE(Printer->notify.option);
6859 /****************************************************************
6861 ****************************************************************/
6863 WERROR _spoolss_AddJob(struct pipes_struct *p,
6864 struct spoolss_AddJob *r)
6866 if (!r->in.buffer && (r->in.offered != 0)) {
6867 return WERR_INVALID_PARAM;
6870 /* this is what a NT server returns for AddJob. AddJob must fail on
6871 * non-local printers */
6873 if (r->in.level != 1) {
6874 return WERR_UNKNOWN_LEVEL;
6877 return WERR_INVALID_PARAM;
6880 /****************************************************************************
6882 ****************************************************************************/
6884 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6885 struct spoolss_JobInfo1 *r,
6886 const print_queue_struct *queue,
6887 int position, int snum,
6888 struct spoolss_PrinterInfo2 *pinfo2)
6892 t = gmtime(&queue->time);
6894 r->job_id = queue->job;
6896 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6897 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6898 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6899 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6900 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6901 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6902 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6903 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6904 r->data_type = talloc_strdup(mem_ctx, "RAW");
6905 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6906 r->text_status = talloc_strdup(mem_ctx, "");
6907 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6909 r->status = nt_printj_status(queue->status);
6910 r->priority = queue->priority;
6911 r->position = position;
6912 r->total_pages = queue->page_count;
6913 r->pages_printed = 0; /* ??? */
6915 init_systemtime(&r->submitted, t);
6920 /****************************************************************************
6922 ****************************************************************************/
6924 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6925 struct spoolss_JobInfo2 *r,
6926 const print_queue_struct *queue,
6927 int position, int snum,
6928 struct spoolss_PrinterInfo2 *pinfo2,
6929 struct spoolss_DeviceMode *devmode)
6933 t = gmtime(&queue->time);
6935 r->job_id = queue->job;
6937 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6938 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6939 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6940 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6941 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6942 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6943 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6944 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6945 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6946 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6947 r->data_type = talloc_strdup(mem_ctx, "RAW");
6948 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6949 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6950 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6951 r->parameters = talloc_strdup(mem_ctx, "");
6952 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6953 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6954 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6956 r->devmode = devmode;
6958 r->text_status = talloc_strdup(mem_ctx, "");
6959 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6963 r->status = nt_printj_status(queue->status);
6964 r->priority = queue->priority;
6965 r->position = position;
6968 r->total_pages = queue->page_count;
6969 r->size = queue->size;
6970 init_systemtime(&r->submitted, t);
6972 r->pages_printed = 0; /* ??? */
6977 /****************************************************************************
6979 ****************************************************************************/
6981 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6982 struct spoolss_JobInfo3 *r,
6983 const print_queue_struct *queue,
6984 const print_queue_struct *next_queue,
6985 int position, int snum,
6986 struct spoolss_PrinterInfo2 *pinfo2)
6988 r->job_id = queue->job;
6991 r->next_job_id = next_queue->job;
6998 /****************************************************************************
6999 Enumjobs at level 1.
7000 ****************************************************************************/
7002 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7003 const print_queue_struct *queue,
7004 uint32_t num_queues, int snum,
7005 struct spoolss_PrinterInfo2 *pinfo2,
7006 union spoolss_JobInfo **info_p,
7009 union spoolss_JobInfo *info;
7011 WERROR result = WERR_OK;
7013 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7014 W_ERROR_HAVE_NO_MEMORY(info);
7016 *count = num_queues;
7018 for (i=0; i<*count; i++) {
7019 result = fill_job_info1(info,
7025 if (!W_ERROR_IS_OK(result)) {
7031 if (!W_ERROR_IS_OK(result)) {
7042 /****************************************************************************
7043 Enumjobs at level 2.
7044 ****************************************************************************/
7046 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7047 const print_queue_struct *queue,
7048 uint32_t num_queues, int snum,
7049 struct spoolss_PrinterInfo2 *pinfo2,
7050 union spoolss_JobInfo **info_p,
7053 union spoolss_JobInfo *info;
7055 WERROR result = WERR_OK;
7057 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7058 W_ERROR_HAVE_NO_MEMORY(info);
7060 *count = num_queues;
7062 for (i=0; i<*count; i++) {
7063 struct spoolss_DeviceMode *devmode;
7065 result = spoolss_create_default_devmode(info,
7066 pinfo2->printername,
7068 if (!W_ERROR_IS_OK(result)) {
7069 DEBUG(3, ("Can't proceed w/o a devmode!"));
7073 result = fill_job_info2(info,
7080 if (!W_ERROR_IS_OK(result)) {
7086 if (!W_ERROR_IS_OK(result)) {
7097 /****************************************************************************
7098 Enumjobs at level 3.
7099 ****************************************************************************/
7101 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7102 const print_queue_struct *queue,
7103 uint32_t num_queues, int snum,
7104 struct spoolss_PrinterInfo2 *pinfo2,
7105 union spoolss_JobInfo **info_p,
7108 union spoolss_JobInfo *info;
7110 WERROR result = WERR_OK;
7112 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7113 W_ERROR_HAVE_NO_MEMORY(info);
7115 *count = num_queues;
7117 for (i=0; i<*count; i++) {
7118 const print_queue_struct *next_queue = NULL;
7121 next_queue = &queue[i+1];
7124 result = fill_job_info3(info,
7131 if (!W_ERROR_IS_OK(result)) {
7137 if (!W_ERROR_IS_OK(result)) {
7148 /****************************************************************
7150 ****************************************************************/
7152 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7153 struct spoolss_EnumJobs *r)
7156 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7158 print_status_struct prt_status;
7159 print_queue_struct *queue = NULL;
7162 /* that's an [in out] buffer */
7164 if (!r->in.buffer && (r->in.offered != 0)) {
7165 return WERR_INVALID_PARAM;
7168 DEBUG(4,("_spoolss_EnumJobs\n"));
7172 *r->out.info = NULL;
7174 /* lookup the printer snum and tdb entry */
7176 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7180 result = winreg_get_printer_internal(p->mem_ctx,
7181 get_session_info_system(),
7183 lp_const_servicename(snum),
7185 if (!W_ERROR_IS_OK(result)) {
7189 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7190 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7191 count, prt_status.status, prt_status.message));
7195 TALLOC_FREE(pinfo2);
7199 switch (r->in.level) {
7201 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7202 pinfo2, r->out.info, r->out.count);
7205 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7206 pinfo2, r->out.info, r->out.count);
7209 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7210 pinfo2, r->out.info, r->out.count);
7213 result = WERR_UNKNOWN_LEVEL;
7218 TALLOC_FREE(pinfo2);
7220 if (!W_ERROR_IS_OK(result)) {
7224 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7226 *r->out.info, r->in.level,
7228 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7229 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7231 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7234 /****************************************************************
7235 _spoolss_ScheduleJob
7236 ****************************************************************/
7238 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7239 struct spoolss_ScheduleJob *r)
7244 /****************************************************************
7245 ****************************************************************/
7247 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7248 struct messaging_context *msg_ctx,
7249 const char *printer_name,
7251 struct spoolss_SetJobInfo1 *r)
7255 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7259 if (strequal(old_doc_name, r->document_name)) {
7263 if (!print_job_set_name(server_event_context(), msg_ctx,
7264 printer_name, job_id, r->document_name)) {
7271 /****************************************************************
7273 ****************************************************************/
7275 WERROR _spoolss_SetJob(struct pipes_struct *p,
7276 struct spoolss_SetJob *r)
7278 const struct auth_session_info *session_info = p->session_info;
7280 WERROR errcode = WERR_BADFUNC;
7282 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7286 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7287 return WERR_INVALID_PRINTER_NAME;
7290 switch (r->in.command) {
7291 case SPOOLSS_JOB_CONTROL_CANCEL:
7292 case SPOOLSS_JOB_CONTROL_DELETE:
7293 errcode = print_job_delete(session_info, p->msg_ctx,
7294 snum, r->in.job_id);
7295 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7299 case SPOOLSS_JOB_CONTROL_PAUSE:
7300 if (print_job_pause(session_info, p->msg_ctx,
7301 snum, r->in.job_id, &errcode)) {
7305 case SPOOLSS_JOB_CONTROL_RESTART:
7306 case SPOOLSS_JOB_CONTROL_RESUME:
7307 if (print_job_resume(session_info, p->msg_ctx,
7308 snum, r->in.job_id, &errcode)) {
7316 return WERR_UNKNOWN_LEVEL;
7319 if (!W_ERROR_IS_OK(errcode)) {
7323 if (r->in.ctr == NULL) {
7327 switch (r->in.ctr->level) {
7329 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7330 lp_const_servicename(snum),
7332 r->in.ctr->info.info1);
7338 return WERR_UNKNOWN_LEVEL;
7344 /****************************************************************************
7345 Enumerates all printer drivers by level and architecture.
7346 ****************************************************************************/
7348 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7349 const struct auth_session_info *session_info,
7350 struct messaging_context *msg_ctx,
7351 const char *servername,
7352 const char *architecture,
7354 union spoolss_DriverInfo **info_p,
7359 struct spoolss_DriverInfo8 *driver;
7360 union spoolss_DriverInfo *info = NULL;
7362 WERROR result = WERR_OK;
7363 uint32_t num_drivers;
7364 const char **drivers;
7365 struct dcerpc_binding_handle *b;
7366 TALLOC_CTX *tmp_ctx = NULL;
7371 tmp_ctx = talloc_new(mem_ctx);
7376 result = winreg_printer_binding_handle(tmp_ctx,
7380 if (!W_ERROR_IS_OK(result)) {
7384 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7385 result = winreg_get_driver_list(tmp_ctx, b,
7386 architecture, version,
7387 &num_drivers, &drivers);
7388 if (!W_ERROR_IS_OK(result)) {
7391 DEBUG(4, ("we have:[%d] drivers in environment"
7392 " [%s] and version [%d]\n",
7393 num_drivers, architecture, version));
7395 if (num_drivers != 0) {
7396 info = talloc_realloc(tmp_ctx, info,
7397 union spoolss_DriverInfo,
7398 count + num_drivers);
7400 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7401 "failed to enlarge driver info buffer!\n"));
7402 result = WERR_NOMEM;
7407 for (i = 0; i < num_drivers; i++) {
7408 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7410 result = winreg_get_driver(tmp_ctx, b,
7411 architecture, drivers[i],
7413 if (!W_ERROR_IS_OK(result)) {
7419 result = fill_printer_driver_info1(info, &info[count+i].info1,
7420 driver, servername);
7423 result = fill_printer_driver_info2(info, &info[count+i].info2,
7424 driver, servername);
7427 result = fill_printer_driver_info3(info, &info[count+i].info3,
7428 driver, servername);
7431 result = fill_printer_driver_info4(info, &info[count+i].info4,
7432 driver, servername);
7435 result = fill_printer_driver_info5(info, &info[count+i].info5,
7436 driver, servername);
7439 result = fill_printer_driver_info6(info, &info[count+i].info6,
7440 driver, servername);
7443 result = fill_printer_driver_info8(info, &info[count+i].info8,
7444 driver, servername);
7447 result = WERR_UNKNOWN_LEVEL;
7451 TALLOC_FREE(driver);
7453 if (!W_ERROR_IS_OK(result)) {
7458 count += num_drivers;
7459 TALLOC_FREE(drivers);
7463 if (W_ERROR_IS_OK(result)) {
7464 *info_p = talloc_move(mem_ctx, &info);
7468 talloc_free(tmp_ctx);
7472 /****************************************************************************
7473 Enumerates all printer drivers by level.
7474 ****************************************************************************/
7476 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7477 const struct auth_session_info *session_info,
7478 struct messaging_context *msg_ctx,
7479 const char *servername,
7480 const char *architecture,
7482 union spoolss_DriverInfo **info_p,
7486 WERROR result = WERR_OK;
7488 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7490 for (a=0; archi_table[a].long_archi != NULL; a++) {
7492 union spoolss_DriverInfo *info = NULL;
7495 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7499 archi_table[a].long_archi,
7503 if (!W_ERROR_IS_OK(result)) {
7507 for (i=0; i < count; i++) {
7508 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7509 info[i], info_p, count_p);
7516 return enumprinterdrivers_level_by_architecture(mem_ctx,
7526 /****************************************************************
7527 _spoolss_EnumPrinterDrivers
7528 ****************************************************************/
7530 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7531 struct spoolss_EnumPrinterDrivers *r)
7533 const char *cservername;
7536 /* that's an [in out] buffer */
7538 if (!r->in.buffer && (r->in.offered != 0)) {
7539 return WERR_INVALID_PARAM;
7542 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7546 *r->out.info = NULL;
7548 cservername = canon_servername(r->in.server);
7550 if (!is_myname_or_ipaddr(cservername)) {
7551 return WERR_UNKNOWN_PRINTER_DRIVER;
7554 result = enumprinterdrivers_level(p->mem_ctx,
7555 get_session_info_system(),
7562 if (!W_ERROR_IS_OK(result)) {
7566 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7567 spoolss_EnumPrinterDrivers,
7568 *r->out.info, r->in.level,
7570 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7571 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7573 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7576 /****************************************************************
7578 ****************************************************************/
7580 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7581 struct spoolss_EnumForms *r)
7587 *r->out.info = NULL;
7589 /* that's an [in out] buffer */
7591 if (!r->in.buffer && (r->in.offered != 0) ) {
7592 return WERR_INVALID_PARAM;
7595 DEBUG(4,("_spoolss_EnumForms\n"));
7596 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7597 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7599 switch (r->in.level) {
7601 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7602 get_session_info_system(),
7608 result = WERR_UNKNOWN_LEVEL;
7612 if (!W_ERROR_IS_OK(result)) {
7616 if (*r->out.count == 0) {
7617 return WERR_NO_MORE_ITEMS;
7620 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7622 *r->out.info, r->in.level,
7624 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7625 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7627 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7630 /****************************************************************
7632 ****************************************************************/
7634 WERROR _spoolss_GetForm(struct pipes_struct *p,
7635 struct spoolss_GetForm *r)
7639 /* that's an [in out] buffer */
7641 if (!r->in.buffer && (r->in.offered != 0)) {
7642 return WERR_INVALID_PARAM;
7645 DEBUG(4,("_spoolss_GetForm\n"));
7646 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7647 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7649 switch (r->in.level) {
7651 result = winreg_printer_getform1_internal(p->mem_ctx,
7652 get_session_info_system(),
7655 &r->out.info->info1);
7658 result = WERR_UNKNOWN_LEVEL;
7662 if (!W_ERROR_IS_OK(result)) {
7663 TALLOC_FREE(r->out.info);
7667 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7668 r->out.info, r->in.level);
7669 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7671 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7674 /****************************************************************************
7675 ****************************************************************************/
7677 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7678 struct spoolss_PortInfo1 *r,
7681 r->port_name = talloc_strdup(mem_ctx, name);
7682 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7687 /****************************************************************************
7688 TODO: This probably needs distinguish between TCP/IP and Local ports
7690 ****************************************************************************/
7692 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7693 struct spoolss_PortInfo2 *r,
7696 r->port_name = talloc_strdup(mem_ctx, name);
7697 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7699 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7700 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7702 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7703 W_ERROR_HAVE_NO_MEMORY(r->description);
7705 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7712 /****************************************************************************
7713 wrapper around the enumer ports command
7714 ****************************************************************************/
7716 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7718 char *cmd = lp_enumports_cmd();
7719 char **qlines = NULL;
7720 char *command = NULL;
7728 /* if no hook then just fill in the default port */
7731 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7734 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7735 TALLOC_FREE(qlines);
7742 /* we have a valid enumport command */
7744 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7749 DEBUG(10,("Running [%s]\n", command));
7750 ret = smbrun(command, &fd);
7751 DEBUG(10,("Returned [%d]\n", ret));
7752 TALLOC_FREE(command);
7757 return WERR_ACCESS_DENIED;
7761 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7762 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7772 /****************************************************************************
7774 ****************************************************************************/
7776 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7777 union spoolss_PortInfo **info_p,
7780 union spoolss_PortInfo *info = NULL;
7782 WERROR result = WERR_OK;
7783 char **qlines = NULL;
7786 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7787 if (!W_ERROR_IS_OK(result)) {
7792 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7794 DEBUG(10,("Returning WERR_NOMEM\n"));
7795 result = WERR_NOMEM;
7799 for (i=0; i<numlines; i++) {
7800 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7801 result = fill_port_1(info, &info[i].info1, qlines[i]);
7802 if (!W_ERROR_IS_OK(result)) {
7807 TALLOC_FREE(qlines);
7810 if (!W_ERROR_IS_OK(result)) {
7812 TALLOC_FREE(qlines);
7824 /****************************************************************************
7826 ****************************************************************************/
7828 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7829 union spoolss_PortInfo **info_p,
7832 union spoolss_PortInfo *info = NULL;
7834 WERROR result = WERR_OK;
7835 char **qlines = NULL;
7838 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7839 if (!W_ERROR_IS_OK(result)) {
7844 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7846 DEBUG(10,("Returning WERR_NOMEM\n"));
7847 result = WERR_NOMEM;
7851 for (i=0; i<numlines; i++) {
7852 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7853 result = fill_port_2(info, &info[i].info2, qlines[i]);
7854 if (!W_ERROR_IS_OK(result)) {
7859 TALLOC_FREE(qlines);
7862 if (!W_ERROR_IS_OK(result)) {
7864 TALLOC_FREE(qlines);
7876 /****************************************************************
7878 ****************************************************************/
7880 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7881 struct spoolss_EnumPorts *r)
7885 /* that's an [in out] buffer */
7887 if (!r->in.buffer && (r->in.offered != 0)) {
7888 return WERR_INVALID_PARAM;
7891 DEBUG(4,("_spoolss_EnumPorts\n"));
7895 *r->out.info = NULL;
7897 switch (r->in.level) {
7899 result = enumports_level_1(p->mem_ctx, r->out.info,
7903 result = enumports_level_2(p->mem_ctx, r->out.info,
7907 return WERR_UNKNOWN_LEVEL;
7910 if (!W_ERROR_IS_OK(result)) {
7914 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7916 *r->out.info, r->in.level,
7918 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7919 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7921 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7924 /****************************************************************************
7925 ****************************************************************************/
7927 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7929 struct spoolss_SetPrinterInfoCtr *info_ctr,
7930 struct spoolss_DeviceMode *devmode,
7931 struct security_descriptor *secdesc,
7932 struct spoolss_UserLevelCtr *user_ctr,
7933 struct policy_handle *handle)
7935 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7936 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7938 WERROR err = WERR_OK;
7940 /* samba does not have a concept of local, non-shared printers yet, so
7941 * make sure we always setup sharename - gd */
7942 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7943 (info2->printername != NULL && info2->printername[0] != '\0')) {
7944 DEBUG(5, ("spoolss_addprinterex_level_2: "
7945 "no sharename has been set, setting printername %s as sharename\n",
7946 info2->printername));
7947 info2->sharename = info2->printername;
7950 /* check to see if the printer already exists */
7951 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7952 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7954 return WERR_PRINTER_ALREADY_EXISTS;
7957 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7958 if ((snum = print_queue_snum(info2->printername)) != -1) {
7959 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7960 info2->printername));
7961 return WERR_PRINTER_ALREADY_EXISTS;
7965 /* validate printer info struct */
7966 if (!info2->printername || strlen(info2->printername) == 0) {
7967 return WERR_INVALID_PRINTER_NAME;
7969 if (!info2->portname || strlen(info2->portname) == 0) {
7970 return WERR_UNKNOWN_PORT;
7972 if (!info2->drivername || strlen(info2->drivername) == 0) {
7973 return WERR_UNKNOWN_PRINTER_DRIVER;
7975 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7976 return WERR_UNKNOWN_PRINTPROCESSOR;
7979 /* FIXME!!! smbd should check to see if the driver is installed before
7980 trying to add a printer like this --jerry */
7982 if (*lp_addprinter_cmd() ) {
7985 raddr = tsocket_address_inet_addr_string(p->remote_address,
7987 if (raddr == NULL) {
7991 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7994 return WERR_ACCESS_DENIED;
7997 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7998 "smb.conf parameter \"addprinter command\" is defined. This "
7999 "parameter must exist for this call to succeed\n",
8000 info2->sharename ));
8003 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8004 return WERR_ACCESS_DENIED;
8007 /* you must be a printer admin to add a new printer */
8008 if (!print_access_check(p->session_info,
8011 PRINTER_ACCESS_ADMINISTER)) {
8012 return WERR_ACCESS_DENIED;
8016 * Do sanity check on the requested changes for Samba.
8019 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8020 return WERR_INVALID_PARAM;
8023 if (devmode == NULL) {
8024 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8027 update_dsspooler(p->mem_ctx,
8028 get_session_info_system(),
8034 err = winreg_update_printer_internal(p->mem_ctx,
8035 get_session_info_system(),
8042 if (!W_ERROR_IS_OK(err)) {
8046 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8047 if (!W_ERROR_IS_OK(err)) {
8048 /* Handle open failed - remove addition. */
8049 ZERO_STRUCTP(handle);
8056 /****************************************************************
8057 _spoolss_AddPrinterEx
8058 ****************************************************************/
8060 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8061 struct spoolss_AddPrinterEx *r)
8063 switch (r->in.info_ctr->level) {
8065 /* we don't handle yet */
8066 /* but I know what to do ... */
8067 return WERR_UNKNOWN_LEVEL;
8069 return spoolss_addprinterex_level_2(p, r->in.server,
8071 r->in.devmode_ctr->devmode,
8072 r->in.secdesc_ctr->sd,
8073 r->in.userlevel_ctr,
8076 return WERR_UNKNOWN_LEVEL;
8080 /****************************************************************
8082 ****************************************************************/
8084 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8085 struct spoolss_AddPrinter *r)
8087 struct spoolss_AddPrinterEx a;
8088 struct spoolss_UserLevelCtr userlevel_ctr;
8090 ZERO_STRUCT(userlevel_ctr);
8092 userlevel_ctr.level = 1;
8094 a.in.server = r->in.server;
8095 a.in.info_ctr = r->in.info_ctr;
8096 a.in.devmode_ctr = r->in.devmode_ctr;
8097 a.in.secdesc_ctr = r->in.secdesc_ctr;
8098 a.in.userlevel_ctr = &userlevel_ctr;
8099 a.out.handle = r->out.handle;
8101 return _spoolss_AddPrinterEx(p, &a);
8104 /****************************************************************
8105 _spoolss_AddPrinterDriverEx
8106 ****************************************************************/
8108 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8109 struct spoolss_AddPrinterDriverEx *r)
8111 WERROR err = WERR_OK;
8112 const char *driver_name = NULL;
8117 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8118 fn = "_spoolss_AddPrinterDriver";
8120 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8121 fn = "_spoolss_AddPrinterDriverEx";
8124 return WERR_INVALID_PARAM;
8128 * we only support the semantics of AddPrinterDriver()
8129 * i.e. only copy files that are newer than existing ones
8132 if (r->in.flags == 0) {
8133 return WERR_INVALID_PARAM;
8136 if (r->in.flags != APD_COPY_NEW_FILES) {
8137 return WERR_ACCESS_DENIED;
8141 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8142 /* Clever hack from Martin Zielinski <mz@seh.de>
8143 * to allow downgrade from level 8 (Vista).
8145 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8146 r->in.info_ctr->level));
8147 return WERR_UNKNOWN_LEVEL;
8150 DEBUG(5,("Cleaning driver's information\n"));
8151 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8152 if (!W_ERROR_IS_OK(err))
8155 DEBUG(5,("Moving driver to final destination\n"));
8156 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8157 if (!W_ERROR_IS_OK(err)) {
8161 err = winreg_add_driver_internal(p->mem_ctx,
8162 get_session_info_system(),
8167 if (!W_ERROR_IS_OK(err)) {
8172 * I think this is where he DrvUpgradePrinter() hook would be
8173 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8174 * server. Right now, we just need to send ourselves a message
8175 * to update each printer bound to this driver. --jerry
8178 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8179 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8187 /****************************************************************
8188 _spoolss_AddPrinterDriver
8189 ****************************************************************/
8191 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8192 struct spoolss_AddPrinterDriver *r)
8194 struct spoolss_AddPrinterDriverEx a;
8196 switch (r->in.info_ctr->level) {
8203 return WERR_UNKNOWN_LEVEL;
8206 a.in.servername = r->in.servername;
8207 a.in.info_ctr = r->in.info_ctr;
8208 a.in.flags = APD_COPY_NEW_FILES;
8210 return _spoolss_AddPrinterDriverEx(p, &a);
8213 /****************************************************************************
8214 ****************************************************************************/
8216 struct _spoolss_paths {
8222 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8224 static const struct _spoolss_paths spoolss_paths[]= {
8225 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8226 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8229 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8230 const char *servername,
8231 const char *environment,
8235 const char *pservername = NULL;
8236 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8237 const char *short_archi;
8241 /* environment may be empty */
8242 if (environment && strlen(environment)) {
8243 long_archi = environment;
8246 /* servername may be empty */
8247 if (servername && strlen(servername)) {
8248 pservername = canon_servername(servername);
8250 if (!is_myname_or_ipaddr(pservername)) {
8251 return WERR_INVALID_PARAM;
8255 if (!(short_archi = get_short_archi(long_archi))) {
8256 return WERR_INVALID_ENVIRONMENT;
8259 switch (component) {
8260 case SPOOLSS_PRTPROCS_PATH:
8261 case SPOOLSS_DRIVER_PATH:
8263 *path = talloc_asprintf(mem_ctx,
8266 spoolss_paths[component].share,
8269 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8270 SPOOLSS_DEFAULT_SERVER_PATH,
8271 spoolss_paths[component].dir,
8276 return WERR_INVALID_PARAM;
8286 /****************************************************************************
8287 ****************************************************************************/
8289 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8290 const char *servername,
8291 const char *environment,
8292 struct spoolss_DriverDirectoryInfo1 *r)
8297 werr = compose_spoolss_server_path(mem_ctx,
8300 SPOOLSS_DRIVER_PATH,
8302 if (!W_ERROR_IS_OK(werr)) {
8306 DEBUG(4,("printer driver directory: [%s]\n", path));
8308 r->directory_name = path;
8313 /****************************************************************
8314 _spoolss_GetPrinterDriverDirectory
8315 ****************************************************************/
8317 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8318 struct spoolss_GetPrinterDriverDirectory *r)
8322 /* that's an [in out] buffer */
8324 if (!r->in.buffer && (r->in.offered != 0)) {
8325 return WERR_INVALID_PARAM;
8328 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8333 /* r->in.level is ignored */
8335 werror = getprinterdriverdir_level_1(p->mem_ctx,
8338 &r->out.info->info1);
8339 if (!W_ERROR_IS_OK(werror)) {
8340 TALLOC_FREE(r->out.info);
8344 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8345 r->out.info, r->in.level);
8346 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8348 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8351 /****************************************************************
8352 _spoolss_EnumPrinterData
8353 ****************************************************************/
8355 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8356 struct spoolss_EnumPrinterData *r)
8359 struct spoolss_EnumPrinterDataEx r2;
8361 struct spoolss_PrinterEnumValues *info, *val = NULL;
8364 r2.in.handle = r->in.handle;
8365 r2.in.key_name = "PrinterDriverData";
8367 r2.out.count = &count;
8368 r2.out.info = &info;
8369 r2.out.needed = &needed;
8371 result = _spoolss_EnumPrinterDataEx(p, &r2);
8372 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8373 r2.in.offered = needed;
8374 result = _spoolss_EnumPrinterDataEx(p, &r2);
8376 if (!W_ERROR_IS_OK(result)) {
8381 * The NT machine wants to know the biggest size of value and data
8383 * cf: MSDN EnumPrinterData remark section
8386 if (!r->in.value_offered && !r->in.data_offered) {
8387 uint32_t biggest_valuesize = 0;
8388 uint32_t biggest_datasize = 0;
8391 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8393 for (i=0; i<count; i++) {
8395 name_length = strlen(info[i].value_name);
8396 if (strlen(info[i].value_name) > biggest_valuesize) {
8397 biggest_valuesize = name_length;
8400 if (info[i].data_length > biggest_datasize) {
8401 biggest_datasize = info[i].data_length;
8404 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8408 /* the value is an UNICODE string but real_value_size is the length
8409 in bytes including the trailing 0 */
8411 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8412 *r->out.data_needed = biggest_datasize;
8414 DEBUG(6,("final values: [%d], [%d]\n",
8415 *r->out.value_needed, *r->out.data_needed));
8420 if (r->in.enum_index < count) {
8421 val = &info[r->in.enum_index];
8425 /* out_value should default to "" or else NT4 has
8426 problems unmarshalling the response */
8428 if (r->in.value_offered) {
8429 *r->out.value_needed = 1;
8430 r->out.value_name = talloc_strdup(r, "");
8431 if (!r->out.value_name) {
8435 r->out.value_name = NULL;
8436 *r->out.value_needed = 0;
8439 /* the data is counted in bytes */
8441 *r->out.data_needed = r->in.data_offered;
8443 result = WERR_NO_MORE_ITEMS;
8447 * - counted in bytes in the request
8448 * - counted in UNICODE chars in the max reply
8449 * - counted in bytes in the real size
8451 * take a pause *before* coding not *during* coding
8455 if (r->in.value_offered) {
8456 r->out.value_name = talloc_strdup(r, val->value_name);
8457 if (!r->out.value_name) {
8460 *r->out.value_needed = val->value_name_len;
8462 r->out.value_name = NULL;
8463 *r->out.value_needed = 0;
8468 *r->out.type = val->type;
8470 /* data - counted in bytes */
8473 * See the section "Dynamically Typed Query Parameters"
8477 if (r->out.data && val->data && val->data->data &&
8478 val->data_length && r->in.data_offered) {
8479 memcpy(r->out.data, val->data->data,
8480 MIN(val->data_length,r->in.data_offered));
8483 *r->out.data_needed = val->data_length;
8491 /****************************************************************
8492 _spoolss_SetPrinterData
8493 ****************************************************************/
8495 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8496 struct spoolss_SetPrinterData *r)
8498 struct spoolss_SetPrinterDataEx r2;
8500 r2.in.handle = r->in.handle;
8501 r2.in.key_name = "PrinterDriverData";
8502 r2.in.value_name = r->in.value_name;
8503 r2.in.type = r->in.type;
8504 r2.in.data = r->in.data;
8505 r2.in.offered = r->in.offered;
8507 return _spoolss_SetPrinterDataEx(p, &r2);
8510 /****************************************************************
8511 _spoolss_ResetPrinter
8512 ****************************************************************/
8514 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8515 struct spoolss_ResetPrinter *r)
8517 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8520 DEBUG(5,("_spoolss_ResetPrinter\n"));
8523 * All we do is to check to see if the handle and queue is valid.
8524 * This call really doesn't mean anything to us because we only
8525 * support RAW printing. --jerry
8529 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8530 OUR_HANDLE(r->in.handle)));
8534 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8538 /* blindly return success */
8542 /****************************************************************
8543 _spoolss_DeletePrinterData
8544 ****************************************************************/
8546 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8547 struct spoolss_DeletePrinterData *r)
8549 struct spoolss_DeletePrinterDataEx r2;
8551 r2.in.handle = r->in.handle;
8552 r2.in.key_name = "PrinterDriverData";
8553 r2.in.value_name = r->in.value_name;
8555 return _spoolss_DeletePrinterDataEx(p, &r2);
8558 /****************************************************************
8560 ****************************************************************/
8562 WERROR _spoolss_AddForm(struct pipes_struct *p,
8563 struct spoolss_AddForm *r)
8565 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8567 WERROR status = WERR_OK;
8568 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8569 struct dcerpc_binding_handle *b;
8570 TALLOC_CTX *tmp_ctx = NULL;
8572 DEBUG(5,("_spoolss_AddForm\n"));
8575 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8576 OUR_HANDLE(r->in.handle)));
8580 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8581 and not a printer admin, then fail */
8583 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8584 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8585 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8586 p->session_info->info->domain_name,
8588 p->session_info->security_token,
8589 lp_printer_admin(snum))) {
8590 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8591 return WERR_ACCESS_DENIED;
8594 switch (form->flags) {
8595 case SPOOLSS_FORM_USER:
8596 case SPOOLSS_FORM_BUILTIN:
8597 case SPOOLSS_FORM_PRINTER:
8600 return WERR_INVALID_PARAM;
8603 tmp_ctx = talloc_new(p->mem_ctx);
8608 status = winreg_printer_binding_handle(tmp_ctx,
8609 get_session_info_system(),
8612 if (!W_ERROR_IS_OK(status)) {
8616 status = winreg_printer_addform1(tmp_ctx, b, form);
8617 if (!W_ERROR_IS_OK(status)) {
8622 * ChangeID must always be set if this is a printer
8624 if (Printer->printer_type == SPLHND_PRINTER) {
8625 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8626 status = WERR_BADFID;
8630 status = winreg_printer_update_changeid(tmp_ctx, b,
8631 lp_const_servicename(snum));
8635 talloc_free(tmp_ctx);
8639 /****************************************************************
8641 ****************************************************************/
8643 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8644 struct spoolss_DeleteForm *r)
8646 const char *form_name = r->in.form_name;
8647 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8649 WERROR status = WERR_OK;
8650 struct dcerpc_binding_handle *b;
8651 TALLOC_CTX *tmp_ctx = NULL;
8653 DEBUG(5,("_spoolss_DeleteForm\n"));
8656 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8657 OUR_HANDLE(r->in.handle)));
8661 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8662 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8663 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8664 p->session_info->info->domain_name,
8666 p->session_info->security_token,
8667 lp_printer_admin(snum))) {
8668 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8669 return WERR_ACCESS_DENIED;
8672 tmp_ctx = talloc_new(p->mem_ctx);
8677 status = winreg_printer_binding_handle(tmp_ctx,
8678 get_session_info_system(),
8681 if (!W_ERROR_IS_OK(status)) {
8685 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8686 if (!W_ERROR_IS_OK(status)) {
8691 * ChangeID must always be set if this is a printer
8693 if (Printer->printer_type == SPLHND_PRINTER) {
8694 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8695 status = WERR_BADFID;
8699 status = winreg_printer_update_changeid(tmp_ctx, b,
8700 lp_const_servicename(snum));
8704 talloc_free(tmp_ctx);
8708 /****************************************************************
8710 ****************************************************************/
8712 WERROR _spoolss_SetForm(struct pipes_struct *p,
8713 struct spoolss_SetForm *r)
8715 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8716 const char *form_name = r->in.form_name;
8718 WERROR status = WERR_OK;
8719 struct dcerpc_binding_handle *b;
8720 TALLOC_CTX *tmp_ctx = NULL;
8722 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8724 DEBUG(5,("_spoolss_SetForm\n"));
8727 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8728 OUR_HANDLE(r->in.handle)));
8732 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8733 and not a printer admin, then fail */
8735 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8736 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8737 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8738 p->session_info->info->domain_name,
8740 p->session_info->security_token,
8741 lp_printer_admin(snum))) {
8742 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8743 return WERR_ACCESS_DENIED;
8746 tmp_ctx = talloc_new(p->mem_ctx);
8751 status = winreg_printer_binding_handle(tmp_ctx,
8752 get_session_info_system(),
8755 if (!W_ERROR_IS_OK(status)) {
8759 status = winreg_printer_setform1(tmp_ctx, b,
8762 if (!W_ERROR_IS_OK(status)) {
8767 * ChangeID must always be set if this is a printer
8769 if (Printer->printer_type == SPLHND_PRINTER) {
8770 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8771 status = WERR_BADFID;
8775 status = winreg_printer_update_changeid(tmp_ctx, b,
8776 lp_const_servicename(snum));
8780 talloc_free(tmp_ctx);
8784 /****************************************************************************
8785 fill_print_processor1
8786 ****************************************************************************/
8788 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8789 struct spoolss_PrintProcessorInfo1 *r,
8790 const char *print_processor_name)
8792 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8793 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8798 /****************************************************************************
8799 enumprintprocessors level 1.
8800 ****************************************************************************/
8802 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8803 union spoolss_PrintProcessorInfo **info_p,
8806 union spoolss_PrintProcessorInfo *info;
8809 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8810 W_ERROR_HAVE_NO_MEMORY(info);
8814 result = fill_print_processor1(info, &info[0].info1, "winprint");
8815 if (!W_ERROR_IS_OK(result)) {
8820 if (!W_ERROR_IS_OK(result)) {
8831 /****************************************************************
8832 _spoolss_EnumPrintProcessors
8833 ****************************************************************/
8835 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8836 struct spoolss_EnumPrintProcessors *r)
8840 /* that's an [in out] buffer */
8842 if (!r->in.buffer && (r->in.offered != 0)) {
8843 return WERR_INVALID_PARAM;
8846 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8849 * Enumerate the print processors ...
8851 * Just reply with "winprint", to keep NT happy
8852 * and I can use my nice printer checker.
8857 *r->out.info = NULL;
8859 if (!get_short_archi(r->in.environment)) {
8860 return WERR_INVALID_ENVIRONMENT;
8863 switch (r->in.level) {
8865 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8869 return WERR_UNKNOWN_LEVEL;
8872 if (!W_ERROR_IS_OK(result)) {
8876 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8877 spoolss_EnumPrintProcessors,
8878 *r->out.info, r->in.level,
8880 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8881 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8883 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8886 /****************************************************************************
8887 fill_printprocdatatype1
8888 ****************************************************************************/
8890 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8891 struct spoolss_PrintProcDataTypesInfo1 *r,
8892 const char *name_array)
8894 r->name_array = talloc_strdup(mem_ctx, name_array);
8895 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8900 /****************************************************************************
8901 enumprintprocdatatypes level 1.
8902 ****************************************************************************/
8904 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8905 union spoolss_PrintProcDataTypesInfo **info_p,
8909 union spoolss_PrintProcDataTypesInfo *info;
8911 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8912 W_ERROR_HAVE_NO_MEMORY(info);
8916 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8917 if (!W_ERROR_IS_OK(result)) {
8922 if (!W_ERROR_IS_OK(result)) {
8933 /****************************************************************
8934 _spoolss_EnumPrintProcDataTypes
8935 ****************************************************************/
8937 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8938 struct spoolss_EnumPrintProcDataTypes *r)
8942 /* that's an [in out] buffer */
8944 if (!r->in.buffer && (r->in.offered != 0)) {
8945 return WERR_INVALID_PARAM;
8948 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8952 *r->out.info = NULL;
8954 if (r->in.print_processor_name == NULL ||
8955 !strequal(r->in.print_processor_name, "winprint")) {
8956 return WERR_UNKNOWN_PRINTPROCESSOR;
8959 switch (r->in.level) {
8961 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8965 return WERR_UNKNOWN_LEVEL;
8968 if (!W_ERROR_IS_OK(result)) {
8972 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8973 spoolss_EnumPrintProcDataTypes,
8974 *r->out.info, r->in.level,
8976 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8977 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8979 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8982 /****************************************************************************
8984 ****************************************************************************/
8986 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8987 struct spoolss_MonitorInfo1 *r,
8988 const char *monitor_name)
8990 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8991 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8996 /****************************************************************************
8998 ****************************************************************************/
9000 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9001 struct spoolss_MonitorInfo2 *r,
9002 const char *monitor_name,
9003 const char *environment,
9004 const char *dll_name)
9006 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9007 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9008 r->environment = talloc_strdup(mem_ctx, environment);
9009 W_ERROR_HAVE_NO_MEMORY(r->environment);
9010 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9011 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9016 /****************************************************************************
9017 enumprintmonitors level 1.
9018 ****************************************************************************/
9020 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9021 union spoolss_MonitorInfo **info_p,
9024 union spoolss_MonitorInfo *info;
9025 WERROR result = WERR_OK;
9027 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9028 W_ERROR_HAVE_NO_MEMORY(info);
9032 result = fill_monitor_1(info, &info[0].info1,
9034 if (!W_ERROR_IS_OK(result)) {
9038 result = fill_monitor_1(info, &info[1].info1,
9040 if (!W_ERROR_IS_OK(result)) {
9045 if (!W_ERROR_IS_OK(result)) {
9056 /****************************************************************************
9057 enumprintmonitors level 2.
9058 ****************************************************************************/
9060 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9061 union spoolss_MonitorInfo **info_p,
9064 union spoolss_MonitorInfo *info;
9065 WERROR result = WERR_OK;
9067 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9068 W_ERROR_HAVE_NO_MEMORY(info);
9072 result = fill_monitor_2(info, &info[0].info2,
9074 "Windows NT X86", /* FIXME */
9076 if (!W_ERROR_IS_OK(result)) {
9080 result = fill_monitor_2(info, &info[1].info2,
9082 "Windows NT X86", /* FIXME */
9084 if (!W_ERROR_IS_OK(result)) {
9089 if (!W_ERROR_IS_OK(result)) {
9100 /****************************************************************
9101 _spoolss_EnumMonitors
9102 ****************************************************************/
9104 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9105 struct spoolss_EnumMonitors *r)
9109 /* that's an [in out] buffer */
9111 if (!r->in.buffer && (r->in.offered != 0)) {
9112 return WERR_INVALID_PARAM;
9115 DEBUG(5,("_spoolss_EnumMonitors\n"));
9118 * Enumerate the print monitors ...
9120 * Just reply with "Local Port", to keep NT happy
9121 * and I can use my nice printer checker.
9126 *r->out.info = NULL;
9128 switch (r->in.level) {
9130 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9134 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9138 return WERR_UNKNOWN_LEVEL;
9141 if (!W_ERROR_IS_OK(result)) {
9145 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9146 spoolss_EnumMonitors,
9147 *r->out.info, r->in.level,
9149 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9150 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9152 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9155 /****************************************************************************
9156 ****************************************************************************/
9158 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9159 const print_queue_struct *queue,
9160 int count, int snum,
9161 struct spoolss_PrinterInfo2 *pinfo2,
9163 struct spoolss_JobInfo1 *r)
9168 for (i=0; i<count; i++) {
9169 if (queue[i].job == (int)jobid) {
9175 if (found == false) {
9176 /* NT treats not found as bad param... yet another bad choice */
9177 return WERR_INVALID_PARAM;
9180 return fill_job_info1(mem_ctx,
9188 /****************************************************************************
9189 ****************************************************************************/
9191 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9192 const print_queue_struct *queue,
9193 int count, int snum,
9194 struct spoolss_PrinterInfo2 *pinfo2,
9196 struct spoolss_JobInfo2 *r)
9200 struct spoolss_DeviceMode *devmode;
9203 for (i=0; i<count; i++) {
9204 if (queue[i].job == (int)jobid) {
9210 if (found == false) {
9211 /* NT treats not found as bad param... yet another bad
9213 return WERR_INVALID_PARAM;
9217 * if the print job does not have a DEVMODE associated with it,
9218 * just use the one for the printer. A NULL devicemode is not
9219 * a failure condition
9222 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9224 result = spoolss_create_default_devmode(mem_ctx,
9225 pinfo2->printername,
9227 if (!W_ERROR_IS_OK(result)) {
9228 DEBUG(3, ("Can't proceed w/o a devmode!"));
9233 return fill_job_info2(mem_ctx,
9242 /****************************************************************
9244 ****************************************************************/
9246 WERROR _spoolss_GetJob(struct pipes_struct *p,
9247 struct spoolss_GetJob *r)
9249 WERROR result = WERR_OK;
9250 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9253 print_queue_struct *queue = NULL;
9254 print_status_struct prt_status;
9256 /* that's an [in out] buffer */
9258 if (!r->in.buffer && (r->in.offered != 0)) {
9259 return WERR_INVALID_PARAM;
9262 DEBUG(5,("_spoolss_GetJob\n"));
9266 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9270 result = winreg_get_printer_internal(p->mem_ctx,
9271 get_session_info_system(),
9273 lp_const_servicename(snum),
9275 if (!W_ERROR_IS_OK(result)) {
9279 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9281 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9282 count, prt_status.status, prt_status.message));
9284 switch (r->in.level) {
9286 result = getjob_level_1(p->mem_ctx,
9287 queue, count, snum, pinfo2,
9288 r->in.job_id, &r->out.info->info1);
9291 result = getjob_level_2(p->mem_ctx,
9292 queue, count, snum, pinfo2,
9293 r->in.job_id, &r->out.info->info2);
9296 result = WERR_UNKNOWN_LEVEL;
9301 TALLOC_FREE(pinfo2);
9303 if (!W_ERROR_IS_OK(result)) {
9304 TALLOC_FREE(r->out.info);
9308 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9310 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9312 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9315 /****************************************************************
9316 _spoolss_GetPrinterDataEx
9317 ****************************************************************/
9319 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9320 struct spoolss_GetPrinterDataEx *r)
9323 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9324 const char *printer;
9326 WERROR result = WERR_OK;
9328 enum winreg_Type val_type = REG_NONE;
9329 uint8_t *val_data = NULL;
9330 uint32_t val_size = 0;
9331 struct dcerpc_binding_handle *b;
9332 TALLOC_CTX *tmp_ctx;
9334 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9336 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9337 r->in.key_name, r->in.value_name));
9339 /* in case of problem, return some default values */
9342 *r->out.type = REG_NONE;
9344 tmp_ctx = talloc_new(p->mem_ctx);
9350 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9351 OUR_HANDLE(r->in.handle)));
9352 result = WERR_BADFID;
9356 /* check to see if the keyname is valid */
9357 if (!strlen(r->in.key_name)) {
9358 result = WERR_INVALID_PARAM;
9362 /* Is the handle to a printer or to the server? */
9364 if (Printer->printer_type == SPLHND_SERVER) {
9366 union spoolss_PrinterData data;
9368 result = getprinterdata_printer_server(tmp_ctx,
9372 if (!W_ERROR_IS_OK(result)) {
9376 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9377 *r->out.type, &data);
9378 if (!W_ERROR_IS_OK(result)) {
9382 *r->out.needed = blob.length;
9384 if (r->in.offered >= *r->out.needed) {
9385 memcpy(r->out.data, blob.data, blob.length);
9392 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9393 result = WERR_BADFID;
9396 printer = lp_const_servicename(snum);
9398 result = winreg_printer_binding_handle(tmp_ctx,
9399 get_session_info_system(),
9402 if (!W_ERROR_IS_OK(result)) {
9406 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9407 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9408 strequal(r->in.value_name, "ChangeId")) {
9409 *r->out.type = REG_DWORD;
9411 if (r->in.offered >= *r->out.needed) {
9412 uint32_t changeid = 0;
9414 result = winreg_printer_get_changeid(tmp_ctx, b,
9417 if (!W_ERROR_IS_OK(result)) {
9421 SIVAL(r->out.data, 0, changeid);
9427 result = winreg_get_printer_dataex(tmp_ctx, b,
9434 if (!W_ERROR_IS_OK(result)) {
9438 *r->out.needed = val_size;
9439 *r->out.type = val_type;
9441 if (r->in.offered >= *r->out.needed) {
9442 memcpy(r->out.data, val_data, val_size);
9446 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9448 if (W_ERROR_IS_OK(result)) {
9449 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9452 talloc_free(tmp_ctx);
9456 /****************************************************************
9457 _spoolss_SetPrinterDataEx
9458 ****************************************************************/
9460 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9461 struct spoolss_SetPrinterDataEx *r)
9463 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9465 WERROR result = WERR_OK;
9466 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9468 struct dcerpc_binding_handle *b;
9469 TALLOC_CTX *tmp_ctx;
9471 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9473 /* From MSDN documentation of SetPrinterDataEx: pass request to
9474 SetPrinterData if key is "PrinterDriverData" */
9477 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9478 OUR_HANDLE(r->in.handle)));
9482 if (Printer->printer_type == SPLHND_SERVER) {
9483 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9484 "Not implemented for server handles yet\n"));
9485 return WERR_INVALID_PARAM;
9488 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9493 * Access check : NT returns "access denied" if you make a
9494 * SetPrinterData call without the necessary privildge.
9495 * we were originally returning OK if nothing changed
9496 * which made Win2k issue **a lot** of SetPrinterData
9497 * when connecting to a printer --jerry
9500 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9501 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9502 "change denied by handle access permissions\n"));
9503 return WERR_ACCESS_DENIED;
9506 tmp_ctx = talloc_new(p->mem_ctx);
9511 result = winreg_printer_binding_handle(tmp_ctx,
9512 get_session_info_system(),
9515 if (!W_ERROR_IS_OK(result)) {
9519 result = winreg_get_printer(tmp_ctx, b,
9520 lp_servicename(snum),
9522 if (!W_ERROR_IS_OK(result)) {
9526 /* check for OID in valuename */
9528 oid_string = strchr(r->in.value_name, ',');
9534 /* save the registry data */
9536 result = winreg_set_printer_dataex(tmp_ctx, b,
9544 if (W_ERROR_IS_OK(result)) {
9545 /* save the OID if one was specified */
9547 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9548 r->in.key_name, SPOOL_OID_KEY);
9550 result = WERR_NOMEM;
9555 * I'm not checking the status here on purpose. Don't know
9556 * if this is right, but I'm returning the status from the
9557 * previous set_printer_dataex() call. I have no idea if
9558 * this is right. --jerry
9560 winreg_set_printer_dataex(tmp_ctx, b,
9565 (uint8_t *) oid_string,
9566 strlen(oid_string) + 1);
9569 result = winreg_printer_update_changeid(tmp_ctx, b,
9570 lp_const_servicename(snum));
9575 talloc_free(tmp_ctx);
9579 /****************************************************************
9580 _spoolss_DeletePrinterDataEx
9581 ****************************************************************/
9583 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9584 struct spoolss_DeletePrinterDataEx *r)
9586 const char *printer;
9588 WERROR status = WERR_OK;
9589 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9591 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9594 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9595 "Invalid handle (%s:%u:%u).\n",
9596 OUR_HANDLE(r->in.handle)));
9600 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9601 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9602 "printer properties change denied by handle\n"));
9603 return WERR_ACCESS_DENIED;
9606 if (!r->in.value_name || !r->in.key_name) {
9610 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9613 printer = lp_const_servicename(snum);
9615 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9616 get_session_info_system(),
9621 if (W_ERROR_IS_OK(status)) {
9622 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9623 get_session_info_system(),
9631 /****************************************************************
9632 _spoolss_EnumPrinterKey
9633 ****************************************************************/
9635 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9636 struct spoolss_EnumPrinterKey *r)
9639 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9641 WERROR result = WERR_BADFILE;
9642 const char **array = NULL;
9645 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9648 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9649 OUR_HANDLE(r->in.handle)));
9653 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9657 result = winreg_enum_printer_key_internal(p->mem_ctx,
9658 get_session_info_system(),
9660 lp_const_servicename(snum),
9664 if (!W_ERROR_IS_OK(result)) {
9668 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9669 result = WERR_NOMEM;
9673 *r->out._ndr_size = r->in.offered / 2;
9674 *r->out.needed = blob.length;
9676 if (r->in.offered < *r->out.needed) {
9677 result = WERR_MORE_DATA;
9680 r->out.key_buffer->string_array = array;
9684 if (!W_ERROR_IS_OK(result)) {
9686 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9694 /****************************************************************
9695 _spoolss_DeletePrinterKey
9696 ****************************************************************/
9698 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9699 struct spoolss_DeletePrinterKey *r)
9701 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9704 const char *printer;
9705 struct dcerpc_binding_handle *b;
9706 TALLOC_CTX *tmp_ctx;
9708 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9711 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9712 OUR_HANDLE(r->in.handle)));
9716 /* if keyname == NULL, return error */
9717 if ( !r->in.key_name )
9718 return WERR_INVALID_PARAM;
9720 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9724 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9725 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9726 "printer properties change denied by handle\n"));
9727 return WERR_ACCESS_DENIED;
9730 printer = lp_const_servicename(snum);
9732 tmp_ctx = talloc_new(p->mem_ctx);
9737 status = winreg_printer_binding_handle(tmp_ctx,
9738 get_session_info_system(),
9741 if (!W_ERROR_IS_OK(status)) {
9745 /* delete the key and all subkeys */
9746 status = winreg_delete_printer_key(tmp_ctx, b,
9749 if (W_ERROR_IS_OK(status)) {
9750 status = winreg_printer_update_changeid(tmp_ctx, b,
9755 talloc_free(tmp_ctx);
9759 /****************************************************************
9760 _spoolss_EnumPrinterDataEx
9761 ****************************************************************/
9763 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9764 struct spoolss_EnumPrinterDataEx *r)
9767 struct spoolss_PrinterEnumValues *info = NULL;
9768 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9772 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9776 *r->out.info = NULL;
9779 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9780 OUR_HANDLE(r->in.handle)));
9785 * first check for a keyname of NULL or "". Win2k seems to send
9786 * this a lot and we should send back WERR_INVALID_PARAM
9787 * no need to spend time looking up the printer in this case.
9791 if (!strlen(r->in.key_name)) {
9792 result = WERR_INVALID_PARAM;
9796 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9800 /* now look for a match on the key name */
9801 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9802 get_session_info_system(),
9804 lp_const_servicename(snum),
9808 if (!W_ERROR_IS_OK(result)) {
9812 #if 0 /* FIXME - gd */
9813 /* housekeeping information in the reply */
9815 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9816 * the hand marshalled container size is a multiple
9817 * of 4 bytes for RPC alignment.
9821 needed += 4-(needed % 4);
9824 *r->out.count = count;
9825 *r->out.info = info;
9828 if (!W_ERROR_IS_OK(result)) {
9832 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9833 spoolss_EnumPrinterDataEx,
9836 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9837 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9839 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9842 /****************************************************************************
9843 ****************************************************************************/
9845 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9846 const char *servername,
9847 const char *environment,
9848 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9853 werr = compose_spoolss_server_path(mem_ctx,
9856 SPOOLSS_PRTPROCS_PATH,
9858 if (!W_ERROR_IS_OK(werr)) {
9862 DEBUG(4,("print processor directory: [%s]\n", path));
9864 r->directory_name = path;
9869 /****************************************************************
9870 _spoolss_GetPrintProcessorDirectory
9871 ****************************************************************/
9873 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9874 struct spoolss_GetPrintProcessorDirectory *r)
9877 char *prnproc_share = NULL;
9878 bool prnproc_share_exists = false;
9881 /* that's an [in out] buffer */
9883 if (!r->in.buffer && (r->in.offered != 0)) {
9884 return WERR_INVALID_PARAM;
9887 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9892 /* r->in.level is ignored */
9894 /* We always should reply with a local print processor directory so that
9895 * users are not forced to have a [prnproc$] share on the Samba spoolss
9896 * server, if users decide to do so, lets announce it though - Guenther */
9898 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9899 if (!prnproc_share) {
9903 prnproc_share_exists = true;
9906 result = getprintprocessordirectory_level_1(p->mem_ctx,
9907 prnproc_share_exists ? r->in.server : NULL,
9909 &r->out.info->info1);
9910 if (!W_ERROR_IS_OK(result)) {
9911 TALLOC_FREE(r->out.info);
9915 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9916 r->out.info, r->in.level);
9917 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9919 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9922 /*******************************************************************
9923 ********************************************************************/
9925 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9926 const char *dllname)
9928 enum ndr_err_code ndr_err;
9929 struct spoolss_MonitorUi ui;
9931 ui.dll_name = dllname;
9933 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9934 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9935 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9936 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9938 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9941 /*******************************************************************
9942 Streams the monitor UI DLL name in UNICODE
9943 *******************************************************************/
9945 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9946 struct security_token *token, DATA_BLOB *in,
9947 DATA_BLOB *out, uint32_t *needed)
9949 const char *dllname = "tcpmonui.dll";
9951 *needed = (strlen(dllname)+1) * 2;
9953 if (out->length < *needed) {
9954 return WERR_INSUFFICIENT_BUFFER;
9957 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9964 /*******************************************************************
9965 ********************************************************************/
9967 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9968 struct spoolss_PortData1 *port1,
9969 const DATA_BLOB *buf)
9971 enum ndr_err_code ndr_err;
9972 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9973 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9974 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9975 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9977 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9980 /*******************************************************************
9981 ********************************************************************/
9983 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9984 struct spoolss_PortData2 *port2,
9985 const DATA_BLOB *buf)
9987 enum ndr_err_code ndr_err;
9988 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9989 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9990 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9991 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9993 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9996 /*******************************************************************
9997 Create a new TCP/IP port
9998 *******************************************************************/
10000 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10001 struct security_token *token, DATA_BLOB *in,
10002 DATA_BLOB *out, uint32_t *needed)
10004 struct spoolss_PortData1 port1;
10005 struct spoolss_PortData2 port2;
10006 char *device_uri = NULL;
10009 const char *portname;
10010 const char *hostaddress;
10012 uint32_t port_number;
10015 /* peek for spoolss_PortData version */
10017 if (!in || (in->length < (128 + 4))) {
10018 return WERR_GENERAL_FAILURE;
10021 version = IVAL(in->data, 128);
10025 ZERO_STRUCT(port1);
10027 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10031 portname = port1.portname;
10032 hostaddress = port1.hostaddress;
10033 queue = port1.queue;
10034 protocol = port1.protocol;
10035 port_number = port1.port_number;
10039 ZERO_STRUCT(port2);
10041 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10045 portname = port2.portname;
10046 hostaddress = port2.hostaddress;
10047 queue = port2.queue;
10048 protocol = port2.protocol;
10049 port_number = port2.port_number;
10053 DEBUG(1,("xcvtcp_addport: "
10054 "unknown version of port_data: %d\n", version));
10055 return WERR_UNKNOWN_PORT;
10058 /* create the device URI and call the add_port_hook() */
10060 switch (protocol) {
10061 case PROTOCOL_RAWTCP_TYPE:
10062 device_uri = talloc_asprintf(mem_ctx,
10063 "socket://%s:%d/", hostaddress,
10067 case PROTOCOL_LPR_TYPE:
10068 device_uri = talloc_asprintf(mem_ctx,
10069 "lpr://%s/%s", hostaddress, queue );
10073 return WERR_UNKNOWN_PORT;
10080 return add_port_hook(mem_ctx, token, portname, device_uri);
10083 /*******************************************************************
10084 *******************************************************************/
10086 struct xcv_api_table xcvtcp_cmds[] = {
10087 { "MonitorUI", xcvtcp_monitorui },
10088 { "AddPort", xcvtcp_addport},
10092 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10093 struct security_token *token, const char *command,
10100 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10102 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10103 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10104 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10107 return WERR_BADFUNC;
10110 /*******************************************************************
10111 *******************************************************************/
10112 #if 0 /* don't support management using the "Local Port" monitor */
10114 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10115 struct security_token *token, DATA_BLOB *in,
10116 DATA_BLOB *out, uint32_t *needed)
10118 const char *dllname = "localui.dll";
10120 *needed = (strlen(dllname)+1) * 2;
10122 if (out->length < *needed) {
10123 return WERR_INSUFFICIENT_BUFFER;
10126 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10133 /*******************************************************************
10134 *******************************************************************/
10136 struct xcv_api_table xcvlocal_cmds[] = {
10137 { "MonitorUI", xcvlocal_monitorui },
10141 struct xcv_api_table xcvlocal_cmds[] = {
10148 /*******************************************************************
10149 *******************************************************************/
10151 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10152 struct security_token *token, const char *command,
10153 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10158 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10160 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10161 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10162 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10164 return WERR_BADFUNC;
10167 /****************************************************************
10169 ****************************************************************/
10171 WERROR _spoolss_XcvData(struct pipes_struct *p,
10172 struct spoolss_XcvData *r)
10174 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10175 DATA_BLOB out_data = data_blob_null;
10179 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10180 OUR_HANDLE(r->in.handle)));
10181 return WERR_BADFID;
10184 /* Has to be a handle to the TCP/IP port monitor */
10186 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10187 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10188 return WERR_BADFID;
10191 /* requires administrative access to the server */
10193 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10194 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10195 return WERR_ACCESS_DENIED;
10198 /* Allocate the outgoing buffer */
10200 if (r->in.out_data_size) {
10201 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10202 if (out_data.data == NULL) {
10207 switch ( Printer->printer_type ) {
10208 case SPLHND_PORTMON_TCP:
10209 werror = process_xcvtcp_command(p->mem_ctx,
10210 p->session_info->security_token,
10211 r->in.function_name,
10212 &r->in.in_data, &out_data,
10215 case SPLHND_PORTMON_LOCAL:
10216 werror = process_xcvlocal_command(p->mem_ctx,
10217 p->session_info->security_token,
10218 r->in.function_name,
10219 &r->in.in_data, &out_data,
10223 werror = WERR_INVALID_PRINT_MONITOR;
10226 if (!W_ERROR_IS_OK(werror)) {
10230 *r->out.status_code = 0;
10232 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10233 memcpy(r->out.out_data, out_data.data,
10234 MIN(r->in.out_data_size, out_data.length));
10240 /****************************************************************
10241 _spoolss_AddPrintProcessor
10242 ****************************************************************/
10244 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10245 struct spoolss_AddPrintProcessor *r)
10247 /* for now, just indicate success and ignore the add. We'll
10248 automatically set the winprint processor for printer
10249 entries later. Used to debug the LexMark Optra S 1855 PCL
10255 /****************************************************************
10257 ****************************************************************/
10259 WERROR _spoolss_AddPort(struct pipes_struct *p,
10260 struct spoolss_AddPort *r)
10262 /* do what w2k3 does */
10264 return WERR_NOT_SUPPORTED;
10267 /****************************************************************
10268 _spoolss_GetPrinterDriver
10269 ****************************************************************/
10271 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10272 struct spoolss_GetPrinterDriver *r)
10274 p->rng_fault_state = true;
10275 return WERR_NOT_SUPPORTED;
10278 /****************************************************************
10279 _spoolss_ReadPrinter
10280 ****************************************************************/
10282 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10283 struct spoolss_ReadPrinter *r)
10285 p->rng_fault_state = true;
10286 return WERR_NOT_SUPPORTED;
10289 /****************************************************************
10290 _spoolss_WaitForPrinterChange
10291 ****************************************************************/
10293 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10294 struct spoolss_WaitForPrinterChange *r)
10296 p->rng_fault_state = true;
10297 return WERR_NOT_SUPPORTED;
10300 /****************************************************************
10301 _spoolss_ConfigurePort
10302 ****************************************************************/
10304 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10305 struct spoolss_ConfigurePort *r)
10307 p->rng_fault_state = true;
10308 return WERR_NOT_SUPPORTED;
10311 /****************************************************************
10312 _spoolss_DeletePort
10313 ****************************************************************/
10315 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10316 struct spoolss_DeletePort *r)
10318 p->rng_fault_state = true;
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_CreatePrinterIC
10324 ****************************************************************/
10326 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10327 struct spoolss_CreatePrinterIC *r)
10329 p->rng_fault_state = true;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_PlayGDIScriptOnPrinterIC
10335 ****************************************************************/
10337 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10338 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10340 p->rng_fault_state = true;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10345 _spoolss_DeletePrinterIC
10346 ****************************************************************/
10348 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10349 struct spoolss_DeletePrinterIC *r)
10351 p->rng_fault_state = true;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10356 _spoolss_AddPrinterConnection
10357 ****************************************************************/
10359 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10360 struct spoolss_AddPrinterConnection *r)
10362 p->rng_fault_state = true;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10367 _spoolss_DeletePrinterConnection
10368 ****************************************************************/
10370 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10371 struct spoolss_DeletePrinterConnection *r)
10373 p->rng_fault_state = true;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10378 _spoolss_PrinterMessageBox
10379 ****************************************************************/
10381 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10382 struct spoolss_PrinterMessageBox *r)
10384 p->rng_fault_state = true;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10389 _spoolss_AddMonitor
10390 ****************************************************************/
10392 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10393 struct spoolss_AddMonitor *r)
10395 p->rng_fault_state = true;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10400 _spoolss_DeleteMonitor
10401 ****************************************************************/
10403 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10404 struct spoolss_DeleteMonitor *r)
10406 p->rng_fault_state = true;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10411 _spoolss_DeletePrintProcessor
10412 ****************************************************************/
10414 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10415 struct spoolss_DeletePrintProcessor *r)
10417 p->rng_fault_state = true;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_AddPrintProvidor
10423 ****************************************************************/
10425 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10426 struct spoolss_AddPrintProvidor *r)
10428 p->rng_fault_state = true;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_DeletePrintProvidor
10434 ****************************************************************/
10436 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10437 struct spoolss_DeletePrintProvidor *r)
10439 p->rng_fault_state = true;
10440 return WERR_NOT_SUPPORTED;
10443 /****************************************************************
10444 _spoolss_FindFirstPrinterChangeNotification
10445 ****************************************************************/
10447 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10448 struct spoolss_FindFirstPrinterChangeNotification *r)
10450 p->rng_fault_state = true;
10451 return WERR_NOT_SUPPORTED;
10454 /****************************************************************
10455 _spoolss_FindNextPrinterChangeNotification
10456 ****************************************************************/
10458 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10459 struct spoolss_FindNextPrinterChangeNotification *r)
10461 p->rng_fault_state = true;
10462 return WERR_NOT_SUPPORTED;
10465 /****************************************************************
10466 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10467 ****************************************************************/
10469 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10470 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10472 p->rng_fault_state = true;
10473 return WERR_NOT_SUPPORTED;
10476 /****************************************************************
10477 _spoolss_ReplyOpenPrinter
10478 ****************************************************************/
10480 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10481 struct spoolss_ReplyOpenPrinter *r)
10483 p->rng_fault_state = true;
10484 return WERR_NOT_SUPPORTED;
10487 /****************************************************************
10488 _spoolss_RouterReplyPrinter
10489 ****************************************************************/
10491 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10492 struct spoolss_RouterReplyPrinter *r)
10494 p->rng_fault_state = true;
10495 return WERR_NOT_SUPPORTED;
10498 /****************************************************************
10499 _spoolss_ReplyClosePrinter
10500 ****************************************************************/
10502 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10503 struct spoolss_ReplyClosePrinter *r)
10505 p->rng_fault_state = true;
10506 return WERR_NOT_SUPPORTED;
10509 /****************************************************************
10511 ****************************************************************/
10513 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10514 struct spoolss_AddPortEx *r)
10516 p->rng_fault_state = true;
10517 return WERR_NOT_SUPPORTED;
10520 /****************************************************************
10521 _spoolss_RouterFindFirstPrinterChangeNotification
10522 ****************************************************************/
10524 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10525 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10527 p->rng_fault_state = true;
10528 return WERR_NOT_SUPPORTED;
10531 /****************************************************************
10532 _spoolss_SpoolerInit
10533 ****************************************************************/
10535 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10536 struct spoolss_SpoolerInit *r)
10538 p->rng_fault_state = true;
10539 return WERR_NOT_SUPPORTED;
10542 /****************************************************************
10543 _spoolss_ResetPrinterEx
10544 ****************************************************************/
10546 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10547 struct spoolss_ResetPrinterEx *r)
10549 p->rng_fault_state = true;
10550 return WERR_NOT_SUPPORTED;
10553 /****************************************************************
10554 _spoolss_RouterReplyPrinterEx
10555 ****************************************************************/
10557 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10558 struct spoolss_RouterReplyPrinterEx *r)
10560 p->rng_fault_state = true;
10561 return WERR_NOT_SUPPORTED;
10564 /****************************************************************
10566 ****************************************************************/
10568 WERROR _spoolss_44(struct pipes_struct *p,
10569 struct spoolss_44 *r)
10571 p->rng_fault_state = true;
10572 return WERR_NOT_SUPPORTED;
10575 /****************************************************************
10577 ****************************************************************/
10579 WERROR _spoolss_SetPort(struct pipes_struct *p,
10580 struct spoolss_SetPort *r)
10582 p->rng_fault_state = true;
10583 return WERR_NOT_SUPPORTED;
10586 /****************************************************************
10588 ****************************************************************/
10590 WERROR _spoolss_4a(struct pipes_struct *p,
10591 struct spoolss_4a *r)
10593 p->rng_fault_state = true;
10594 return WERR_NOT_SUPPORTED;
10597 /****************************************************************
10599 ****************************************************************/
10601 WERROR _spoolss_4b(struct pipes_struct *p,
10602 struct spoolss_4b *r)
10604 p->rng_fault_state = true;
10605 return WERR_NOT_SUPPORTED;
10608 /****************************************************************
10610 ****************************************************************/
10612 WERROR _spoolss_4c(struct pipes_struct *p,
10613 struct spoolss_4c *r)
10615 p->rng_fault_state = true;
10616 return WERR_NOT_SUPPORTED;
10619 /****************************************************************
10621 ****************************************************************/
10623 WERROR _spoolss_53(struct pipes_struct *p,
10624 struct spoolss_53 *r)
10626 p->rng_fault_state = true;
10627 return WERR_NOT_SUPPORTED;
10630 /****************************************************************
10631 _spoolss_AddPerMachineConnection
10632 ****************************************************************/
10634 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10635 struct spoolss_AddPerMachineConnection *r)
10637 p->rng_fault_state = true;
10638 return WERR_NOT_SUPPORTED;
10641 /****************************************************************
10642 _spoolss_DeletePerMachineConnection
10643 ****************************************************************/
10645 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10646 struct spoolss_DeletePerMachineConnection *r)
10648 p->rng_fault_state = true;
10649 return WERR_NOT_SUPPORTED;
10652 /****************************************************************
10653 _spoolss_EnumPerMachineConnections
10654 ****************************************************************/
10656 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10657 struct spoolss_EnumPerMachineConnections *r)
10659 p->rng_fault_state = true;
10660 return WERR_NOT_SUPPORTED;
10663 /****************************************************************
10665 ****************************************************************/
10667 WERROR _spoolss_5a(struct pipes_struct *p,
10668 struct spoolss_5a *r)
10670 p->rng_fault_state = true;
10671 return WERR_NOT_SUPPORTED;
10674 /****************************************************************
10676 ****************************************************************/
10678 WERROR _spoolss_5b(struct pipes_struct *p,
10679 struct spoolss_5b *r)
10681 p->rng_fault_state = true;
10682 return WERR_NOT_SUPPORTED;
10685 /****************************************************************
10687 ****************************************************************/
10689 WERROR _spoolss_5c(struct pipes_struct *p,
10690 struct spoolss_5c *r)
10692 p->rng_fault_state = true;
10693 return WERR_NOT_SUPPORTED;
10696 /****************************************************************
10698 ****************************************************************/
10700 WERROR _spoolss_5d(struct pipes_struct *p,
10701 struct spoolss_5d *r)
10703 p->rng_fault_state = true;
10704 return WERR_NOT_SUPPORTED;
10707 /****************************************************************
10709 ****************************************************************/
10711 WERROR _spoolss_5e(struct pipes_struct *p,
10712 struct spoolss_5e *r)
10714 p->rng_fault_state = true;
10715 return WERR_NOT_SUPPORTED;
10718 /****************************************************************
10720 ****************************************************************/
10722 WERROR _spoolss_5f(struct pipes_struct *p,
10723 struct spoolss_5f *r)
10725 p->rng_fault_state = true;
10726 return WERR_NOT_SUPPORTED;
10729 /****************************************************************
10731 ****************************************************************/
10733 WERROR _spoolss_60(struct pipes_struct *p,
10734 struct spoolss_60 *r)
10736 p->rng_fault_state = true;
10737 return WERR_NOT_SUPPORTED;
10740 /****************************************************************
10742 ****************************************************************/
10744 WERROR _spoolss_61(struct pipes_struct *p,
10745 struct spoolss_61 *r)
10747 p->rng_fault_state = true;
10748 return WERR_NOT_SUPPORTED;
10751 /****************************************************************
10753 ****************************************************************/
10755 WERROR _spoolss_62(struct pipes_struct *p,
10756 struct spoolss_62 *r)
10758 p->rng_fault_state = true;
10759 return WERR_NOT_SUPPORTED;
10762 /****************************************************************
10764 ****************************************************************/
10766 WERROR _spoolss_63(struct pipes_struct *p,
10767 struct spoolss_63 *r)
10769 p->rng_fault_state = true;
10770 return WERR_NOT_SUPPORTED;
10773 /****************************************************************
10775 ****************************************************************/
10777 WERROR _spoolss_64(struct pipes_struct *p,
10778 struct spoolss_64 *r)
10780 p->rng_fault_state = true;
10781 return WERR_NOT_SUPPORTED;
10784 /****************************************************************
10786 ****************************************************************/
10788 WERROR _spoolss_65(struct pipes_struct *p,
10789 struct spoolss_65 *r)
10791 p->rng_fault_state = true;
10792 return WERR_NOT_SUPPORTED;
10795 /****************************************************************
10796 _spoolss_GetCorePrinterDrivers
10797 ****************************************************************/
10799 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10800 struct spoolss_GetCorePrinterDrivers *r)
10802 p->rng_fault_state = true;
10803 return WERR_NOT_SUPPORTED;
10806 /****************************************************************
10808 ****************************************************************/
10810 WERROR _spoolss_67(struct pipes_struct *p,
10811 struct spoolss_67 *r)
10813 p->rng_fault_state = true;
10814 return WERR_NOT_SUPPORTED;
10817 /****************************************************************
10818 _spoolss_GetPrinterDriverPackagePath
10819 ****************************************************************/
10821 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10822 struct spoolss_GetPrinterDriverPackagePath *r)
10824 p->rng_fault_state = true;
10825 return WERR_NOT_SUPPORTED;
10828 /****************************************************************
10830 ****************************************************************/
10832 WERROR _spoolss_69(struct pipes_struct *p,
10833 struct spoolss_69 *r)
10835 p->rng_fault_state = true;
10836 return WERR_NOT_SUPPORTED;
10839 /****************************************************************
10841 ****************************************************************/
10843 WERROR _spoolss_6a(struct pipes_struct *p,
10844 struct spoolss_6a *r)
10846 p->rng_fault_state = true;
10847 return WERR_NOT_SUPPORTED;
10850 /****************************************************************
10852 ****************************************************************/
10854 WERROR _spoolss_6b(struct pipes_struct *p,
10855 struct spoolss_6b *r)
10857 p->rng_fault_state = true;
10858 return WERR_NOT_SUPPORTED;
10861 /****************************************************************
10863 ****************************************************************/
10865 WERROR _spoolss_6c(struct pipes_struct *p,
10866 struct spoolss_6c *r)
10868 p->rng_fault_state = true;
10869 return WERR_NOT_SUPPORTED;
10872 /****************************************************************
10874 ****************************************************************/
10876 WERROR _spoolss_6d(struct pipes_struct *p,
10877 struct spoolss_6d *r)
10879 p->rng_fault_state = true;
10880 return WERR_NOT_SUPPORTED;