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. */
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "librpc/gen_ndr/messaging.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"
51 /* macros stolen from s4 spoolss server */
52 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
53 ((info)?ndr_size_##fn(info, level, 0):0)
55 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
56 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
58 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
59 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
61 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
64 #define DBGC_CLASS DBGC_RPC_SRV
66 #ifndef MAX_OPEN_PRINTER_EXS
67 #define MAX_OPEN_PRINTER_EXS 50
70 struct notify_back_channel;
72 /* structure to store the printer handles */
73 /* and a reference to what it's pointing to */
74 /* and the notify info asked about */
75 /* that's the central struct */
76 struct printer_handle {
77 struct printer_handle *prev, *next;
78 bool document_started;
80 uint32 jobid; /* jobid in printing backend */
82 const char *servername;
85 uint32 access_granted;
91 struct spoolss_NotifyOption *option;
92 struct policy_handle cli_hnd;
93 struct notify_back_channel *cli_chan;
95 /* are we in a FindNextPrinterChangeNotify() call? */
97 struct messaging_context *msg_ctx;
104 /* devmode sent in the OpenPrinter() call */
105 struct spoolss_DeviceMode *devmode;
107 /* TODO cache the printer info2 structure */
108 struct spoolss_PrinterInfo2 *info2;
112 static struct printer_handle *printers_list;
114 struct printer_session_counter {
115 struct printer_session_counter *next;
116 struct printer_session_counter *prev;
122 static struct printer_session_counter *counter_list;
124 struct notify_back_channel {
125 struct notify_back_channel *prev, *next;
127 /* associated client */
128 struct sockaddr_storage client_address;
130 /* print notify back-channel pipe handle*/
131 struct rpc_pipe_client *cli_pipe;
132 struct dcerpc_binding_handle *binding_handle;
133 uint32_t active_connections;
136 static struct notify_back_channel *back_channels;
138 /* Map generic permissions to printer object specific permissions */
140 const struct standard_mapping printer_std_mapping = {
147 /* Map generic permissions to print server object specific permissions */
149 const struct standard_mapping printserver_std_mapping = {
156 /* API table for Xcv Monitor functions */
158 struct xcv_api_table {
160 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
163 static void prune_printername_cache(void);
165 /********************************************************************
166 * Canonicalize servername.
167 ********************************************************************/
169 static const char *canon_servername(const char *servername)
171 const char *pservername = servername;
172 while (*pservername == '\\') {
178 /* translate between internal status numbers and NT status numbers */
179 static int nt_printj_status(int v)
185 return JOB_STATUS_PAUSED;
187 return JOB_STATUS_SPOOLING;
189 return JOB_STATUS_PRINTING;
191 return JOB_STATUS_ERROR;
193 return JOB_STATUS_DELETING;
195 return JOB_STATUS_OFFLINE;
197 return JOB_STATUS_PAPEROUT;
199 return JOB_STATUS_PRINTED;
201 return JOB_STATUS_DELETED;
203 return JOB_STATUS_BLOCKED_DEVQ;
204 case LPQ_USER_INTERVENTION:
205 return JOB_STATUS_USER_INTERVENTION;
210 static int nt_printq_status(int v)
214 return PRINTER_STATUS_PAUSED;
223 /***************************************************************************
224 Disconnect from the client
225 ****************************************************************************/
227 static void srv_spoolss_replycloseprinter(int snum,
228 struct printer_handle *prn_hnd)
234 * Tell the specific printing tdb we no longer want messages for this printer
235 * by deregistering our PID.
238 if (!print_notify_deregister_pid(snum)) {
239 DEBUG(0, ("Failed to register our pid for printer %s\n",
240 lp_const_servicename(snum)));
243 /* weird if the test succeeds !!! */
244 if (prn_hnd->notify.cli_chan == NULL ||
245 prn_hnd->notify.cli_chan->active_connections == 0) {
246 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
247 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
248 TALLOC_FREE(prn_hnd->notify.cli_chan);
252 status = dcerpc_spoolss_ReplyClosePrinter(
253 prn_hnd->notify.cli_chan->binding_handle,
255 &prn_hnd->notify.cli_hnd,
257 if (!NT_STATUS_IS_OK(status)) {
258 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
260 result = ntstatus_to_werror(status);
261 } else if (!W_ERROR_IS_OK(result)) {
262 DEBUG(0, ("reply_close_printer failed [%s].\n",
263 win_errstr(result)));
266 /* if it's the last connection, deconnect the IPC$ share */
267 if (prn_hnd->notify.cli_chan->active_connections == 1) {
269 prn_hnd->notify.cli_chan->binding_handle = NULL;
270 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
271 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
272 TALLOC_FREE(prn_hnd->notify.cli_chan);
274 if (prn_hnd->notify.msg_ctx != NULL) {
275 messaging_deregister(prn_hnd->notify.msg_ctx,
276 MSG_PRINTER_NOTIFY2, NULL);
279 * Tell the serverid.tdb we're no longer
280 * interested in printer notify messages.
283 serverid_register_msg_flags(
284 messaging_server_id(prn_hnd->notify.msg_ctx),
285 false, FLAG_MSG_PRINT_NOTIFY);
289 if (prn_hnd->notify.cli_chan) {
290 prn_hnd->notify.cli_chan->active_connections--;
294 /****************************************************************************
295 Functions to free a printer entry datastruct.
296 ****************************************************************************/
298 static int printer_entry_destructor(struct printer_handle *Printer)
300 if (Printer->notify.cli_chan != NULL &&
301 Printer->notify.cli_chan->active_connections > 0) {
304 switch(Printer->printer_type) {
306 srv_spoolss_replycloseprinter(snum, Printer);
310 snum = print_queue_snum(Printer->sharename);
312 srv_spoolss_replycloseprinter(snum, Printer);
320 Printer->notify.flags=0;
321 Printer->notify.options=0;
322 Printer->notify.localmachine[0]='\0';
323 Printer->notify.printerlocal=0;
324 TALLOC_FREE(Printer->notify.option);
325 TALLOC_FREE(Printer->devmode);
327 /* Remove from the internal list. */
328 DLIST_REMOVE(printers_list, Printer);
332 /****************************************************************************
333 find printer index by handle
334 ****************************************************************************/
336 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
337 struct policy_handle *hnd)
339 struct printer_handle *find_printer = NULL;
341 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
342 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
349 /****************************************************************************
350 Close printer index by handle.
351 ****************************************************************************/
353 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
363 close_policy_hnd(p, hnd);
368 /****************************************************************************
369 Delete a printer given a handle.
370 ****************************************************************************/
372 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
373 const char *sharename,
374 struct messaging_context *msg_ctx)
376 char *cmd = lp_deleteprinter_cmd();
377 char *command = NULL;
379 bool is_print_op = false;
381 /* can't fail if we don't try */
386 command = talloc_asprintf(ctx,
393 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395 DEBUG(10,("Running [%s]\n", command));
397 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
402 if ( (ret = smbrun(command, NULL)) == 0 ) {
403 /* Tell everyone we updated smb.conf. */
404 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
410 /********** END SePrintOperatorPrivlege BLOCK **********/
412 DEBUGADD(10,("returned [%d]\n", ret));
414 TALLOC_FREE(command);
417 return WERR_BADFID; /* What to return here? */
419 /* go ahead and re-read the services immediately */
421 reload_services(msg_ctx, -1, false);
424 if ( lp_servicenumber( sharename ) >= 0 )
425 return WERR_ACCESS_DENIED;
430 /****************************************************************************
431 Delete a printer given a handle.
432 ****************************************************************************/
434 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
436 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
440 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
446 * It turns out that Windows allows delete printer on a handle
447 * opened by an admin user, then used on a pipe handle created
448 * by an anonymous user..... but they're working on security.... riiight !
452 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
453 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
454 return WERR_ACCESS_DENIED;
457 /* this does not need a become root since the access check has been
458 done on the handle already */
460 result = winreg_delete_printer_key(p->mem_ctx,
461 get_session_info_system(),
465 if (!W_ERROR_IS_OK(result)) {
466 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
470 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
471 Printer->sharename, p->msg_ctx);
472 if (!W_ERROR_IS_OK(result)) {
475 prune_printername_cache();
479 /****************************************************************************
480 Return the snum of a printer corresponding to an handle.
481 ****************************************************************************/
483 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
484 int *number, struct share_params **params)
486 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
489 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
494 switch (Printer->printer_type) {
496 DEBUG(4,("short name:%s\n", Printer->sharename));
497 *number = print_queue_snum(Printer->sharename);
498 return (*number != -1);
506 /****************************************************************************
507 Set printer handle type.
508 Check if it's \\server or \\server\printer
509 ****************************************************************************/
511 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
513 DEBUG(3,("Setting printer type=%s\n", handlename));
515 /* it's a print server */
516 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
517 DEBUGADD(4,("Printer is a print server\n"));
518 Printer->printer_type = SPLHND_SERVER;
520 /* it's a printer (set_printer_hnd_name() will handle port monitors */
522 DEBUGADD(4,("Printer is a printer\n"));
523 Printer->printer_type = SPLHND_PRINTER;
529 static void prune_printername_cache_fn(const char *key, const char *value,
530 time_t timeout, void *private_data)
535 static void prune_printername_cache(void)
537 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
540 /****************************************************************************
541 Set printer handle name.. Accept names like \\server, \\server\printer,
542 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
543 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
544 XcvDataPort() interface.
545 ****************************************************************************/
547 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
548 const struct auth_serversupplied_info *session_info,
549 struct messaging_context *msg_ctx,
550 struct printer_handle *Printer,
551 const char *handlename)
554 int n_services=lp_numservices();
556 const char *printername;
557 const char *servername = NULL;
560 struct spoolss_PrinterInfo2 *info2 = NULL;
565 * Hopefully nobody names his printers like this. Maybe \ or ,
566 * are illegal in printer names even?
568 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
572 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
573 (unsigned long)strlen(handlename)));
575 aprinter = CONST_DISCARD(char *, handlename);
576 if ( *handlename == '\\' ) {
577 servername = canon_servername(handlename);
578 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
582 if (!is_myname_or_ipaddr(servername)) {
583 return WERR_INVALID_PRINTER_NAME;
585 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
586 if (Printer->servername == NULL) {
591 if (Printer->printer_type == SPLHND_SERVER) {
595 if (Printer->printer_type != SPLHND_PRINTER) {
596 return WERR_INVALID_HANDLE;
599 DEBUGADD(5, ("searching for [%s]\n", aprinter));
601 p = strchr(aprinter, ',');
608 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
610 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
616 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
619 /* check for the Port Monitor Interface */
620 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
621 Printer->printer_type = SPLHND_PORTMON_TCP;
622 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
625 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
626 Printer->printer_type = SPLHND_PORTMON_LOCAL;
627 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
632 * With hundreds of printers, the "for" loop iterating all
633 * shares can be quite expensive, as it is done on every
634 * OpenPrinter. The loop maps "aprinter" to "sname", the
635 * result of which we cache in gencache.
638 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
640 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
642 found = (strcmp(tmp, printer_not_found) != 0);
644 DEBUG(4, ("Printer %s not found\n", aprinter));
646 return WERR_INVALID_PRINTER_NAME;
652 /* Search all sharenames first as this is easier than pulling
653 the printer_info_2 off of disk. Don't use find_service() since
654 that calls out to map_username() */
656 /* do another loop to look for printernames */
657 for (snum = 0; !found && snum < n_services; snum++) {
658 const char *printer = lp_const_servicename(snum);
660 /* no point going on if this is not a printer */
661 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
665 /* ignore [printers] share */
666 if (strequal(printer, "printers")) {
670 fstrcpy(sname, printer);
671 if (strequal(aprinter, printer)) {
676 /* no point looking up the printer object if
677 we aren't allowing printername != sharename */
678 if (lp_force_printername(snum)) {
682 result = winreg_get_printer(mem_ctx,
687 if ( !W_ERROR_IS_OK(result) ) {
688 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
689 sname, win_errstr(result)));
693 printername = strrchr(info2->printername, '\\');
694 if (printername == NULL) {
695 printername = info2->printername;
700 if (strequal(printername, aprinter)) {
705 DEBUGADD(10, ("printername: %s\n", printername));
711 if (cache_key != NULL) {
712 gencache_set(cache_key, printer_not_found,
714 TALLOC_FREE(cache_key);
716 DEBUGADD(4,("Printer not found\n"));
717 return WERR_INVALID_PRINTER_NAME;
720 if (cache_key != NULL) {
721 gencache_set(cache_key, sname, time(NULL)+300);
722 TALLOC_FREE(cache_key);
725 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
727 fstrcpy(Printer->sharename, sname);
732 /****************************************************************************
733 Find first available printer slot. creates a printer handle for you.
734 ****************************************************************************/
736 static WERROR open_printer_hnd(struct pipes_struct *p,
737 struct policy_handle *hnd,
739 uint32_t access_granted)
741 struct printer_handle *new_printer;
744 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
746 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
747 if (new_printer == NULL) {
750 talloc_set_destructor(new_printer, printer_entry_destructor);
752 /* This also steals the printer_handle on the policy_handle */
753 if (!create_policy_hnd(p, hnd, new_printer)) {
754 TALLOC_FREE(new_printer);
755 return WERR_INVALID_HANDLE;
758 /* Add to the internal list. */
759 DLIST_ADD(printers_list, new_printer);
761 new_printer->notify.option=NULL;
763 if (!set_printer_hnd_printertype(new_printer, name)) {
764 close_printer_handle(p, hnd);
765 return WERR_INVALID_HANDLE;
768 result = set_printer_hnd_name(p->mem_ctx,
769 get_session_info_system(),
772 if (!W_ERROR_IS_OK(result)) {
773 close_printer_handle(p, hnd);
777 new_printer->access_granted = access_granted;
779 DEBUG(5, ("%d printer handles active\n",
780 (int)num_pipe_handles(p)));
785 /***************************************************************************
786 check to see if the client motify handle is monitoring the notification
787 given by (notify_type, notify_field).
788 **************************************************************************/
790 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
791 uint16_t notify_field)
796 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
797 uint16_t notify_field)
799 struct spoolss_NotifyOption *option = p->notify.option;
803 * Flags should always be zero when the change notify
804 * is registered by the client's spooler. A user Win32 app
805 * might use the flags though instead of the NOTIFY_OPTION_INFO
814 return is_monitoring_event_flags(
815 p->notify.flags, notify_type, notify_field);
817 for (i = 0; i < option->count; i++) {
819 /* Check match for notify_type */
821 if (option->types[i].type != notify_type)
824 /* Check match for field */
826 for (j = 0; j < option->types[i].count; j++) {
827 if (option->types[i].fields[j].field == notify_field) {
833 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
834 p->servername, p->sharename, notify_type, notify_field));
839 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
840 _data->data.integer[0] = _integer; \
841 _data->data.integer[1] = 0;
844 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
845 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
846 if (!_data->data.string.string) {\
847 _data->data.string.size = 0; \
849 _data->data.string.size = strlen_m_term(_p) * 2;
851 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
852 _data->data.devmode.devmode = _devmode;
854 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
855 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
856 if (!_data->data.sd.sd) { \
857 _data->data.sd.sd_size = 0; \
859 _data->data.sd.sd_size = \
860 ndr_size_security_descriptor(_data->data.sd.sd, 0);
862 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
867 struct spoolss_Time st;
871 if (!init_systemtime(&st, t)) {
875 p = talloc_array(mem_ctx, char, len);
881 * Systemtime must be linearized as a set of UINT16's.
882 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
885 SSVAL(p, 0, st.year);
886 SSVAL(p, 2, st.month);
887 SSVAL(p, 4, st.day_of_week);
889 SSVAL(p, 8, st.hour);
890 SSVAL(p, 10, st.minute);
891 SSVAL(p, 12, st.second);
892 SSVAL(p, 14, st.millisecond);
898 /* Convert a notification message to a struct spoolss_Notify */
900 static void notify_one_value(struct spoolss_notify_msg *msg,
901 struct spoolss_Notify *data,
904 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
907 static void notify_string(struct spoolss_notify_msg *msg,
908 struct spoolss_Notify *data,
911 /* The length of the message includes the trailing \0 */
913 data->data.string.size = msg->len * 2;
914 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
915 if (!data->data.string.string) {
916 data->data.string.size = 0;
921 static void notify_system_time(struct spoolss_notify_msg *msg,
922 struct spoolss_Notify *data,
925 data->data.string.string = NULL;
926 data->data.string.size = 0;
928 if (msg->len != sizeof(time_t)) {
929 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
934 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
935 &data->data.string.string,
936 &data->data.string.size);
939 struct notify2_message_table {
941 void (*fn)(struct spoolss_notify_msg *msg,
942 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
945 static struct notify2_message_table printer_notify_table[] = {
946 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
947 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
948 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
949 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
950 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
951 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
952 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
953 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
954 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
955 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
956 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
957 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
958 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
959 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
960 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
961 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
962 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
963 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
964 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
967 static struct notify2_message_table job_notify_table[] = {
968 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
969 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
970 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
971 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
972 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
973 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
974 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
975 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
976 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
977 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
978 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
979 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
980 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
981 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
982 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
983 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
984 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
985 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
986 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
987 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
988 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
989 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
990 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
991 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
995 /***********************************************************************
996 Allocate talloc context for container object
997 **********************************************************************/
999 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1004 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1009 /***********************************************************************
1010 release all allocated memory and zero out structure
1011 **********************************************************************/
1013 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1019 talloc_destroy(ctr->ctx);
1026 /***********************************************************************
1027 **********************************************************************/
1029 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1037 /***********************************************************************
1038 **********************************************************************/
1040 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1042 if ( !ctr || !ctr->msg_groups )
1045 if ( idx >= ctr->num_groups )
1048 return &ctr->msg_groups[idx];
1052 /***********************************************************************
1053 How many groups of change messages do we have ?
1054 **********************************************************************/
1056 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1061 return ctr->num_groups;
1064 /***********************************************************************
1065 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1066 **********************************************************************/
1068 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1070 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1071 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1072 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1078 /* loop over all groups looking for a matching printer name */
1080 for ( i=0; i<ctr->num_groups; i++ ) {
1081 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1085 /* add a new group? */
1087 if ( i == ctr->num_groups ) {
1090 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1091 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1094 ctr->msg_groups = groups;
1096 /* clear the new entry and set the printer name */
1098 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1099 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1102 /* add the change messages; 'i' is the correct index now regardless */
1104 msg_grp = &ctr->msg_groups[i];
1106 msg_grp->num_msgs++;
1108 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1109 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1112 msg_grp->msgs = msg_list;
1114 new_slot = msg_grp->num_msgs-1;
1115 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1117 /* need to allocate own copy of data */
1119 if ( msg->len != 0 )
1120 msg_grp->msgs[new_slot].notify.data = (char *)
1121 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1123 return ctr->num_groups;
1126 static void construct_info_data(struct spoolss_Notify *info_data,
1127 enum spoolss_NotifyType type,
1128 uint16_t field, int id);
1130 /***********************************************************************
1131 Send a change notication message on all handles which have a call
1133 **********************************************************************/
1135 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1136 struct printer_handle *prn_hnd,
1137 SPOOLSS_NOTIFY_MSG *messages,
1139 struct spoolss_Notify **_notifies,
1142 struct spoolss_Notify *notifies;
1143 SPOOLSS_NOTIFY_MSG *msg;
1148 notifies = talloc_zero_array(mem_ctx,
1149 struct spoolss_Notify, num_msgs);
1154 for (i = 0; i < num_msgs; i++) {
1158 /* Are we monitoring this event? */
1160 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1164 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1165 "for printer [%s]\n",
1166 msg->type, msg->field, prn_hnd->sharename));
1169 * if the is a printer notification handle and not a job
1170 * notification type, then set the id to 0.
1171 * Otherwise just use what was specified in the message.
1173 * When registering change notification on a print server
1174 * handle we always need to send back the id (snum) matching
1175 * the printer for which the change took place.
1176 * For change notify registered on a printer handle,
1177 * this does not matter and the id should be 0.
1182 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1183 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1189 /* Convert unix jobid to smb jobid */
1191 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1192 id = sysjob_to_jobid(msg->id);
1195 DEBUG(3, ("no such unix jobid %d\n",
1201 construct_info_data(¬ifies[count],
1202 msg->type, msg->field, id);
1205 case PRINTER_NOTIFY_TYPE:
1206 if (printer_notify_table[msg->field].fn) {
1207 printer_notify_table[msg->field].fn(msg,
1208 ¬ifies[count], mem_ctx);
1212 case JOB_NOTIFY_TYPE:
1213 if (job_notify_table[msg->field].fn) {
1214 job_notify_table[msg->field].fn(msg,
1215 ¬ifies[count], mem_ctx);
1220 DEBUG(5, ("Unknown notification type %d\n",
1228 *_notifies = notifies;
1234 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1235 struct printer_handle *prn_hnd,
1236 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1238 struct spoolss_Notify *notifies;
1240 union spoolss_ReplyPrinterInfo info;
1241 struct spoolss_NotifyInfo info0;
1242 uint32_t reply_result;
1247 /* Is there notification on this handle? */
1248 if (prn_hnd->notify.cli_chan == NULL ||
1249 prn_hnd->notify.cli_chan->active_connections == 0) {
1253 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1254 prn_hnd->servername, prn_hnd->sharename));
1256 /* For this printer? Print servers always receive notifications. */
1257 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1258 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1262 DEBUG(10,("Our printer\n"));
1264 /* build the array of change notifications */
1265 ret = build_notify2_messages(mem_ctx, prn_hnd,
1267 msg_group->num_msgs,
1273 info0.version = 0x2;
1274 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1275 info0.count = count;
1276 info0.notifies = notifies;
1278 info.info0 = &info0;
1280 status = dcerpc_spoolss_RouterReplyPrinterEx(
1281 prn_hnd->notify.cli_chan->binding_handle,
1283 &prn_hnd->notify.cli_hnd,
1284 prn_hnd->notify.change, /* color */
1285 prn_hnd->notify.flags,
1287 0, /* reply_type, must be 0 */
1289 if (!NT_STATUS_IS_OK(status)) {
1290 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1292 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1293 nt_errstr(status)));
1294 werr = ntstatus_to_werror(status);
1295 } else if (!W_ERROR_IS_OK(werr)) {
1296 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1298 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301 switch (reply_result) {
1304 case PRINTER_NOTIFY_INFO_DISCARDED:
1305 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1306 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1315 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1317 struct printer_handle *p;
1318 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1319 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1323 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1327 if (!msg_group->msgs) {
1328 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1332 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1334 /* loop over all printers */
1336 for (p = printers_list; p; p = p->next) {
1337 ret = send_notify2_printer(mem_ctx, p, msg_group);
1344 DEBUG(8,("send_notify2_changes: Exit...\n"));
1348 /***********************************************************************
1349 **********************************************************************/
1351 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1354 uint32_t tv_sec, tv_usec;
1357 /* Unpack message */
1359 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1362 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1364 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1367 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1368 &msg->notify.value[0], &msg->notify.value[1]);
1370 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1371 &msg->len, &msg->notify.data);
1373 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1374 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1376 tv->tv_sec = tv_sec;
1377 tv->tv_usec = tv_usec;
1380 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1381 msg->notify.value[1]));
1383 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1388 /********************************************************************
1389 Receive a notify2 message list
1390 ********************************************************************/
1392 static void receive_notify2_message_list(struct messaging_context *msg,
1395 struct server_id server_id,
1398 size_t msg_count, i;
1399 char *buf = (char *)data->data;
1402 SPOOLSS_NOTIFY_MSG notify;
1403 SPOOLSS_NOTIFY_MSG_CTR messages;
1406 if (data->length < 4) {
1407 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1411 msg_count = IVAL(buf, 0);
1414 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1416 if (msg_count == 0) {
1417 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1421 /* initialize the container */
1423 ZERO_STRUCT( messages );
1424 notify_msg_ctr_init( &messages );
1427 * build message groups for each printer identified
1428 * in a change_notify msg. Remember that a PCN message
1429 * includes the handle returned for the srv_spoolss_replyopenprinter()
1430 * call. Therefore messages are grouped according to printer handle.
1433 for ( i=0; i<msg_count; i++ ) {
1434 struct timeval msg_tv;
1436 if (msg_ptr + 4 - buf > data->length) {
1437 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1441 msg_len = IVAL(msg_ptr,0);
1444 if (msg_ptr + msg_len - buf > data->length) {
1445 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1449 /* unpack messages */
1451 ZERO_STRUCT( notify );
1452 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1455 /* add to correct list in container */
1457 notify_msg_ctr_addmsg( &messages, ¬ify );
1459 /* free memory that might have been allocated by notify2_unpack_msg() */
1461 if ( notify.len != 0 )
1462 SAFE_FREE( notify.notify.data );
1465 /* process each group of messages */
1467 num_groups = notify_msg_ctr_numgroups( &messages );
1468 for ( i=0; i<num_groups; i++ )
1469 send_notify2_changes( &messages, i );
1474 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1475 (uint32_t)msg_count ));
1477 notify_msg_ctr_destroy( &messages );
1482 /********************************************************************
1483 Send a message to ourself about new driver being installed
1484 so we can upgrade the information for each printer bound to this
1486 ********************************************************************/
1488 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1489 struct messaging_context *msg_ctx)
1491 int len = strlen(drivername);
1496 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1499 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1500 MSG_PRINTER_DRVUPGRADE,
1501 (uint8_t *)drivername, len+1);
1506 void srv_spoolss_cleanup(void)
1508 struct printer_session_counter *session_counter;
1510 for (session_counter = counter_list;
1511 session_counter != NULL;
1512 session_counter = counter_list) {
1513 DLIST_REMOVE(counter_list, session_counter);
1514 TALLOC_FREE(session_counter);
1518 /**********************************************************************
1519 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1520 over all printers, upgrading ones as necessary
1521 **********************************************************************/
1523 void do_drv_upgrade_printer(struct messaging_context *msg,
1526 struct server_id server_id,
1529 TALLOC_CTX *tmp_ctx;
1530 struct auth_serversupplied_info *session_info = NULL;
1531 struct spoolss_PrinterInfo2 *pinfo2;
1534 const char *drivername;
1536 int n_services = lp_numservices();
1538 tmp_ctx = talloc_new(NULL);
1539 if (!tmp_ctx) return;
1541 status = make_session_info_system(tmp_ctx, &session_info);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 DEBUG(0, ("do_drv_upgrade_printer: "
1544 "Could not create system session_info\n"));
1548 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1550 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1554 DEBUG(10, ("do_drv_upgrade_printer: "
1555 "Got message for new driver [%s]\n", drivername));
1557 /* Iterate the printer list */
1559 for (snum = 0; snum < n_services; snum++) {
1560 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1564 /* ignore [printers] share */
1565 if (strequal(lp_const_servicename(snum), "printers")) {
1569 result = winreg_get_printer(tmp_ctx, session_info, msg,
1570 lp_const_servicename(snum),
1573 if (!W_ERROR_IS_OK(result)) {
1577 if (!pinfo2->drivername) {
1581 if (strcmp(drivername, pinfo2->drivername) != 0) {
1585 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1587 /* all we care about currently is the change_id */
1588 result = winreg_printer_update_changeid(tmp_ctx,
1591 pinfo2->printername);
1593 if (!W_ERROR_IS_OK(result)) {
1594 DEBUG(3, ("do_drv_upgrade_printer: "
1595 "Failed to update changeid [%s]\n",
1596 win_errstr(result)));
1602 talloc_free(tmp_ctx);
1605 /********************************************************************
1606 Update the cache for all printq's with a registered client
1608 ********************************************************************/
1610 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1612 struct printer_handle *printer = printers_list;
1615 /* loop through all printers and update the cache where
1616 a client is connected */
1618 if ((printer->printer_type == SPLHND_PRINTER) &&
1619 ((printer->notify.cli_chan != NULL) &&
1620 (printer->notify.cli_chan->active_connections > 0))) {
1621 snum = print_queue_snum(printer->sharename);
1622 print_queue_status(msg_ctx, snum, NULL, NULL);
1625 printer = printer->next;
1631 /****************************************************************
1632 _spoolss_OpenPrinter
1633 ****************************************************************/
1635 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1636 struct spoolss_OpenPrinter *r)
1638 struct spoolss_OpenPrinterEx e;
1641 ZERO_STRUCT(e.in.userlevel);
1643 e.in.printername = r->in.printername;
1644 e.in.datatype = r->in.datatype;
1645 e.in.devmode_ctr = r->in.devmode_ctr;
1646 e.in.access_mask = r->in.access_mask;
1649 e.out.handle = r->out.handle;
1651 werr = _spoolss_OpenPrinterEx(p, &e);
1653 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1654 /* OpenPrinterEx returns this for a bad
1655 * printer name. We must return WERR_INVALID_PRINTER_NAME
1658 werr = WERR_INVALID_PRINTER_NAME;
1664 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1665 struct spoolss_DeviceMode *orig,
1666 struct spoolss_DeviceMode **dest)
1668 struct spoolss_DeviceMode *dm;
1670 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1675 /* copy all values, then duplicate strings and structs */
1678 dm->devicename = talloc_strdup(dm, orig->devicename);
1679 if (!dm->devicename) {
1682 dm->formname = talloc_strdup(dm, orig->formname);
1683 if (!dm->formname) {
1686 if (orig->driverextra_data.data) {
1687 dm->driverextra_data.data =
1688 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1689 orig->driverextra_data.length);
1690 if (!dm->driverextra_data.data) {
1699 /****************************************************************
1700 _spoolss_OpenPrinterEx
1701 ****************************************************************/
1703 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1704 struct spoolss_OpenPrinterEx *r)
1707 struct printer_handle *Printer=NULL;
1710 if (!r->in.printername) {
1711 return WERR_INVALID_PARAM;
1714 if (r->in.level > 3) {
1715 return WERR_INVALID_PARAM;
1717 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1718 (r->in.level == 2 && !r->in.userlevel.level2) ||
1719 (r->in.level == 3 && !r->in.userlevel.level3)) {
1720 return WERR_INVALID_PARAM;
1723 /* some sanity check because you can open a printer or a print server */
1724 /* aka: \\server\printer or \\server */
1726 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1728 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1729 if (!W_ERROR_IS_OK(result)) {
1730 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1731 "for printer %s\n", r->in.printername));
1732 ZERO_STRUCTP(r->out.handle);
1736 Printer = find_printer_index_by_hnd(p, r->out.handle);
1738 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1739 "handle we created for printer %s\n", r->in.printername));
1740 close_printer_handle(p, r->out.handle);
1741 ZERO_STRUCTP(r->out.handle);
1742 return WERR_INVALID_PARAM;
1746 * First case: the user is opening the print server:
1748 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1749 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1751 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1752 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1753 * or if the user is listed in the smb.conf printer admin parameter.
1755 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1756 * client view printer folder, but does not show the MSAPW.
1758 * Note: this test needs code to check access rights here too. Jeremy
1759 * could you look at this?
1761 * Second case: the user is opening a printer:
1762 * NT doesn't let us connect to a printer if the connecting user
1763 * doesn't have print permission.
1765 * Third case: user is opening a Port Monitor
1766 * access checks same as opening a handle to the print server.
1769 switch (Printer->printer_type )
1772 case SPLHND_PORTMON_TCP:
1773 case SPLHND_PORTMON_LOCAL:
1774 /* Printserver handles use global struct... */
1778 /* Map standard access rights to object specific access rights */
1780 se_map_standard(&r->in.access_mask,
1781 &printserver_std_mapping);
1783 /* Deny any object specific bits that don't apply to print
1784 servers (i.e printer and job specific bits) */
1786 r->in.access_mask &= SEC_MASK_SPECIFIC;
1788 if (r->in.access_mask &
1789 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1790 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1791 close_printer_handle(p, r->out.handle);
1792 ZERO_STRUCTP(r->out.handle);
1793 return WERR_ACCESS_DENIED;
1796 /* Allow admin access */
1798 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1800 if (!lp_ms_add_printer_wizard()) {
1801 close_printer_handle(p, r->out.handle);
1802 ZERO_STRUCTP(r->out.handle);
1803 return WERR_ACCESS_DENIED;
1806 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1807 and not a printer admin, then fail */
1809 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1810 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1811 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1812 !token_contains_name_in_list(
1813 uidtoname(p->session_info->utok.uid),
1814 p->session_info->info3->base.domain.string,
1816 p->session_info->security_token,
1817 lp_printer_admin(snum))) {
1818 close_printer_handle(p, r->out.handle);
1819 ZERO_STRUCTP(r->out.handle);
1820 DEBUG(3,("access DENIED as user is not root, "
1821 "has no printoperator privilege, "
1822 "not a member of the printoperator builtin group and "
1823 "is not in printer admin list"));
1824 return WERR_ACCESS_DENIED;
1827 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1831 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1835 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1837 /* We fall through to return WERR_OK */
1840 case SPLHND_PRINTER:
1841 /* NT doesn't let us connect to a printer if the connecting user
1842 doesn't have print permission. */
1844 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1845 close_printer_handle(p, r->out.handle);
1846 ZERO_STRUCTP(r->out.handle);
1850 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1851 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1854 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1856 /* map an empty access mask to the minimum access mask */
1857 if (r->in.access_mask == 0x0)
1858 r->in.access_mask = PRINTER_ACCESS_USE;
1861 * If we are not serving the printer driver for this printer,
1862 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1863 * will keep NT clients happy --jerry
1866 if (lp_use_client_driver(snum)
1867 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1869 r->in.access_mask = PRINTER_ACCESS_USE;
1872 /* check smb.conf parameters and the the sec_desc */
1874 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1875 p->client_id->name, p->client_id->addr)) {
1876 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1877 ZERO_STRUCTP(r->out.handle);
1878 return WERR_ACCESS_DENIED;
1881 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1882 p->session_info->security_token, snum) ||
1883 !print_access_check(p->session_info,
1886 r->in.access_mask)) {
1887 DEBUG(3, ("access DENIED for printer open\n"));
1888 close_printer_handle(p, r->out.handle);
1889 ZERO_STRUCTP(r->out.handle);
1890 return WERR_ACCESS_DENIED;
1893 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1894 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1895 close_printer_handle(p, r->out.handle);
1896 ZERO_STRUCTP(r->out.handle);
1897 return WERR_ACCESS_DENIED;
1900 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1901 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1903 r->in.access_mask = PRINTER_ACCESS_USE;
1905 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1906 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1908 winreg_create_printer(p->mem_ctx,
1909 get_session_info_system(),
1911 lp_const_servicename(snum));
1916 /* sanity check to prevent programmer error */
1917 ZERO_STRUCTP(r->out.handle);
1921 Printer->access_granted = r->in.access_mask;
1924 * If the client sent a devmode in the OpenPrinter() call, then
1925 * save it here in case we get a job submission on this handle
1928 if ((Printer->printer_type != SPLHND_SERVER) &&
1929 r->in.devmode_ctr.devmode) {
1930 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1934 #if 0 /* JERRY -- I'm doubtful this is really effective */
1935 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1936 optimization in Windows 2000 clients --jerry */
1938 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1939 && (RA_WIN2K == get_remote_arch()) )
1941 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1942 sys_usleep( 500000 );
1949 /****************************************************************
1950 _spoolss_ClosePrinter
1951 ****************************************************************/
1953 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1954 struct spoolss_ClosePrinter *r)
1956 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1958 if (Printer && Printer->document_started) {
1959 struct spoolss_EndDocPrinter e;
1961 e.in.handle = r->in.handle;
1963 _spoolss_EndDocPrinter(p, &e);
1966 if (!close_printer_handle(p, r->in.handle))
1969 /* clear the returned printer handle. Observed behavior
1970 from Win2k server. Don't think this really matters.
1971 Previous code just copied the value of the closed
1974 ZERO_STRUCTP(r->out.handle);
1979 /****************************************************************
1980 _spoolss_DeletePrinter
1981 ****************************************************************/
1983 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1984 struct spoolss_DeletePrinter *r)
1986 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1990 if (Printer && Printer->document_started) {
1991 struct spoolss_EndDocPrinter e;
1993 e.in.handle = r->in.handle;
1995 _spoolss_EndDocPrinter(p, &e);
1998 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1999 winreg_delete_printer_key(p->mem_ctx,
2000 get_session_info_system(),
2002 lp_const_servicename(snum),
2006 result = delete_printer_handle(p, r->in.handle);
2011 /*******************************************************************
2012 * static function to lookup the version id corresponding to an
2013 * long architecture string
2014 ******************************************************************/
2016 static const struct print_architecture_table_node archi_table[]= {
2018 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2019 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2020 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2021 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2022 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2023 {"Windows IA64", SPL_ARCH_IA64, 3 },
2024 {"Windows x64", SPL_ARCH_X64, 3 },
2028 static int get_version_id(const char *arch)
2032 for (i=0; archi_table[i].long_archi != NULL; i++)
2034 if (strcmp(arch, archi_table[i].long_archi) == 0)
2035 return (archi_table[i].version);
2041 /****************************************************************
2042 _spoolss_DeletePrinterDriver
2043 ****************************************************************/
2045 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2046 struct spoolss_DeletePrinterDriver *r)
2049 struct spoolss_DriverInfo8 *info = NULL;
2050 struct spoolss_DriverInfo8 *info_win2k = NULL;
2054 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2055 and not a printer admin, then fail */
2057 if ( (p->session_info->utok.uid != sec_initial_uid())
2058 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2059 && !token_contains_name_in_list(
2060 uidtoname(p->session_info->utok.uid),
2061 p->session_info->info3->base.domain.string,
2063 p->session_info->security_token,
2064 lp_printer_admin(-1)) )
2066 return WERR_ACCESS_DENIED;
2069 /* check that we have a valid driver name first */
2071 if ((version = get_version_id(r->in.architecture)) == -1)
2072 return WERR_INVALID_ENVIRONMENT;
2074 status = winreg_get_driver(p->mem_ctx,
2075 get_session_info_system(),
2077 r->in.architecture, r->in.driver,
2079 if (!W_ERROR_IS_OK(status)) {
2080 /* try for Win2k driver if "Windows NT x86" */
2082 if ( version == 2 ) {
2085 status = winreg_get_driver(p->mem_ctx,
2086 get_session_info_system(),
2091 if (!W_ERROR_IS_OK(status)) {
2092 status = WERR_UNKNOWN_PRINTER_DRIVER;
2096 /* otherwise it was a failure */
2098 status = WERR_UNKNOWN_PRINTER_DRIVER;
2104 if (printer_driver_in_use(p->mem_ctx,
2105 get_session_info_system(),
2108 status = WERR_PRINTER_DRIVER_IN_USE;
2113 status = winreg_get_driver(p->mem_ctx,
2114 get_session_info_system(),
2117 r->in.driver, 3, &info_win2k);
2118 if (W_ERROR_IS_OK(status)) {
2119 /* if we get to here, we now have 2 driver info structures to remove */
2120 /* remove the Win2k driver first*/
2122 status = winreg_del_driver(p->mem_ctx,
2123 get_session_info_system(),
2126 talloc_free(info_win2k);
2128 /* this should not have failed---if it did, report to client */
2129 if (!W_ERROR_IS_OK(status)) {
2135 status = winreg_del_driver(p->mem_ctx,
2136 get_session_info_system(),
2146 /****************************************************************
2147 _spoolss_DeletePrinterDriverEx
2148 ****************************************************************/
2150 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2151 struct spoolss_DeletePrinterDriverEx *r)
2153 struct spoolss_DriverInfo8 *info = NULL;
2154 struct spoolss_DriverInfo8 *info_win2k = NULL;
2159 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2160 and not a printer admin, then fail */
2162 if ( (p->session_info->utok.uid != sec_initial_uid())
2163 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2164 && !token_contains_name_in_list(
2165 uidtoname(p->session_info->utok.uid),
2166 p->session_info->info3->base.domain.string,
2168 p->session_info->security_token, lp_printer_admin(-1)) )
2170 return WERR_ACCESS_DENIED;
2173 /* check that we have a valid driver name first */
2174 if ((version = get_version_id(r->in.architecture)) == -1) {
2175 /* this is what NT returns */
2176 return WERR_INVALID_ENVIRONMENT;
2179 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2180 version = r->in.version;
2182 status = winreg_get_driver(p->mem_ctx,
2183 get_session_info_system(),
2189 if (!W_ERROR_IS_OK(status)) {
2190 status = WERR_UNKNOWN_PRINTER_DRIVER;
2193 * if the client asked for a specific version,
2194 * or this is something other than Windows NT x86,
2198 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2201 /* try for Win2k driver if "Windows NT x86" */
2204 status = winreg_get_driver(info,
2205 get_session_info_system(),
2210 if (!W_ERROR_IS_OK(status)) {
2211 status = WERR_UNKNOWN_PRINTER_DRIVER;
2216 if (printer_driver_in_use(info,
2217 get_session_info_system(),
2220 status = WERR_PRINTER_DRIVER_IN_USE;
2225 * we have a couple of cases to consider.
2226 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2227 * then the delete should fail if **any** files overlap with
2229 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2230 * non-overlapping files
2231 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2232 * is set, the do not delete any files
2233 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2236 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2238 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2241 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2242 printer_driver_files_in_use(info,
2243 get_session_info_system(),
2246 /* no idea of the correct error here */
2247 status = WERR_ACCESS_DENIED;
2252 /* also check for W32X86/3 if necessary; maybe we already have? */
2254 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2255 status = winreg_get_driver(info,
2256 get_session_info_system(),
2259 r->in.driver, 3, &info_win2k);
2260 if (W_ERROR_IS_OK(status)) {
2263 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2264 printer_driver_files_in_use(info,
2265 get_session_info_system(),
2268 /* no idea of the correct error here */
2269 talloc_free(info_win2k);
2270 status = WERR_ACCESS_DENIED;
2274 /* if we get to here, we now have 2 driver info structures to remove */
2275 /* remove the Win2k driver first*/
2277 status = winreg_del_driver(info,
2278 get_session_info_system(),
2283 /* this should not have failed---if it did, report to client */
2285 if (!W_ERROR_IS_OK(status)) {
2290 * now delete any associated files if delete_files is
2291 * true. Even if this part failes, we return succes
2292 * because the driver doesn not exist any more
2295 delete_driver_files(get_session_info_system(),
2301 status = winreg_del_driver(info,
2302 get_session_info_system(),
2306 if (!W_ERROR_IS_OK(status)) {
2311 * now delete any associated files if delete_files is
2312 * true. Even if this part failes, we return succes
2313 * because the driver doesn not exist any more
2316 delete_driver_files(get_session_info_system(), info);
2325 /********************************************************************
2326 GetPrinterData on a printer server Handle.
2327 ********************************************************************/
2329 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2331 enum winreg_Type *type,
2332 union spoolss_PrinterData *data)
2334 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2336 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2342 if (!StrCaseCmp(value, "BeepEnabled")) {
2348 if (!StrCaseCmp(value, "EventLog")) {
2350 /* formally was 0x1b */
2355 if (!StrCaseCmp(value, "NetPopup")) {
2361 if (!StrCaseCmp(value, "MajorVersion")) {
2364 /* Windows NT 4.0 seems to not allow uploading of drivers
2365 to a server that reports 0x3 as the MajorVersion.
2366 need to investigate more how Win2k gets around this .
2369 if (RA_WINNT == get_remote_arch()) {
2378 if (!StrCaseCmp(value, "MinorVersion")) {
2385 * uint32_t size = 0x114
2386 * uint32_t major = 5
2387 * uint32_t minor = [0|1]
2388 * uint32_t build = [2195|2600]
2389 * extra unicode string = e.g. "Service Pack 3"
2391 if (!StrCaseCmp(value, "OSVersion")) {
2393 enum ndr_err_code ndr_err;
2394 struct spoolss_OSVersion os;
2396 os.major = 5; /* Windows 2000 == 5.0 */
2398 os.build = 2195; /* build */
2399 os.extra_string = ""; /* leave extra string empty */
2401 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2402 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2403 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2404 return WERR_GENERAL_FAILURE;
2408 data->binary = blob;
2414 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2417 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2418 W_ERROR_HAVE_NO_MEMORY(data->string);
2423 if (!StrCaseCmp(value, "Architecture")) {
2425 data->string = talloc_strdup(mem_ctx,
2426 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2427 W_ERROR_HAVE_NO_MEMORY(data->string);
2432 if (!StrCaseCmp(value, "DsPresent")) {
2435 /* only show the publish check box if we are a
2436 member of a AD domain */
2438 if (lp_security() == SEC_ADS) {
2446 if (!StrCaseCmp(value, "DNSMachineName")) {
2447 const char *hostname = get_mydnsfullname();
2450 return WERR_BADFILE;
2454 data->string = talloc_strdup(mem_ctx, hostname);
2455 W_ERROR_HAVE_NO_MEMORY(data->string);
2462 return WERR_INVALID_PARAM;
2465 /****************************************************************
2466 _spoolss_GetPrinterData
2467 ****************************************************************/
2469 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2470 struct spoolss_GetPrinterData *r)
2472 struct spoolss_GetPrinterDataEx r2;
2474 r2.in.handle = r->in.handle;
2475 r2.in.key_name = "PrinterDriverData";
2476 r2.in.value_name = r->in.value_name;
2477 r2.in.offered = r->in.offered;
2478 r2.out.type = r->out.type;
2479 r2.out.data = r->out.data;
2480 r2.out.needed = r->out.needed;
2482 return _spoolss_GetPrinterDataEx(p, &r2);
2485 /*********************************************************
2486 Connect to the client machine.
2487 **********************************************************/
2489 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2490 struct sockaddr_storage *client_ss, const char *remote_machine)
2493 struct cli_state *the_cli;
2494 struct sockaddr_storage rm_addr;
2495 char addr[INET6_ADDRSTRLEN];
2497 if ( is_zero_addr(client_ss) ) {
2498 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2500 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2501 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2504 print_sockaddr(addr, sizeof(addr), &rm_addr);
2506 rm_addr = *client_ss;
2507 print_sockaddr(addr, sizeof(addr), &rm_addr);
2508 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2512 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2513 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2518 /* setup the connection */
2519 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2520 &rm_addr, 0, "IPC$", "IPC",
2524 0, lp_client_signing());
2526 if ( !NT_STATUS_IS_OK( ret ) ) {
2527 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2532 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2533 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2534 cli_shutdown(the_cli);
2539 * Ok - we have an anonymous connection to the IPC$ share.
2540 * Now start the NT Domain stuff :-).
2543 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2544 if (!NT_STATUS_IS_OK(ret)) {
2545 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2546 remote_machine, nt_errstr(ret)));
2547 cli_shutdown(the_cli);
2554 /***************************************************************************
2555 Connect to the client.
2556 ****************************************************************************/
2558 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2559 uint32_t localprinter,
2560 enum winreg_Type type,
2561 struct policy_handle *handle,
2562 struct notify_back_channel **_chan,
2563 struct sockaddr_storage *client_ss,
2564 struct messaging_context *msg_ctx)
2568 struct notify_back_channel *chan;
2570 for (chan = back_channels; chan; chan = chan->next) {
2571 if (memcmp(&chan->client_address, client_ss,
2572 sizeof(struct sockaddr_storage)) == 0) {
2578 * If it's the first connection, contact the client
2579 * and connect to the IPC$ share anonymously
2582 fstring unix_printer;
2584 /* the +2 is to strip the leading 2 backslashs */
2585 fstrcpy(unix_printer, printer + 2);
2587 chan = talloc_zero(back_channels, struct notify_back_channel);
2591 chan->client_address = *client_ss;
2593 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2597 chan->binding_handle = chan->cli_pipe->binding_handle;
2599 DLIST_ADD(back_channels, chan);
2601 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2602 receive_notify2_message_list);
2603 /* Tell the connections db we're now interested in printer
2604 * notify messages. */
2605 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2606 true, FLAG_MSG_PRINT_NOTIFY);
2610 * Tell the specific printing tdb we want messages for this printer
2611 * by registering our PID.
2614 if (!print_notify_register_pid(snum)) {
2615 DEBUG(0, ("Failed to register our pid for printer %s\n",
2619 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2628 if (!NT_STATUS_IS_OK(status)) {
2629 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2630 result = ntstatus_to_werror(status);
2631 } else if (!W_ERROR_IS_OK(result)) {
2632 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2635 chan->active_connections++;
2638 return (W_ERROR_IS_OK(result));
2641 /****************************************************************
2642 ****************************************************************/
2644 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2645 const struct spoolss_NotifyOption *r)
2647 struct spoolss_NotifyOption *option;
2654 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2661 if (!option->count) {
2665 option->types = talloc_zero_array(option,
2666 struct spoolss_NotifyOptionType, option->count);
2667 if (!option->types) {
2668 talloc_free(option);
2672 for (i=0; i < option->count; i++) {
2673 option->types[i] = r->types[i];
2675 if (option->types[i].count) {
2676 option->types[i].fields = talloc_zero_array(option,
2677 union spoolss_Field, option->types[i].count);
2678 if (!option->types[i].fields) {
2679 talloc_free(option);
2682 for (k=0; k<option->types[i].count; k++) {
2683 option->types[i].fields[k] =
2684 r->types[i].fields[k];
2692 /****************************************************************
2693 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2695 * before replying OK: status=0 a rpc call is made to the workstation
2696 * asking ReplyOpenPrinter
2698 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2699 * called from api_spoolss_rffpcnex
2700 ****************************************************************/
2702 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2703 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2706 struct spoolss_NotifyOption *option = r->in.notify_options;
2707 struct sockaddr_storage client_ss;
2709 /* store the notify value in the printer struct */
2711 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2714 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2715 "Invalid handle (%s:%u:%u).\n",
2716 OUR_HANDLE(r->in.handle)));
2720 Printer->notify.flags = r->in.flags;
2721 Printer->notify.options = r->in.options;
2722 Printer->notify.printerlocal = r->in.printer_local;
2723 Printer->notify.msg_ctx = p->msg_ctx;
2725 TALLOC_FREE(Printer->notify.option);
2726 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2728 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2730 /* Connect to the client machine and send a ReplyOpenPrinter */
2732 if ( Printer->printer_type == SPLHND_SERVER)
2734 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2735 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2738 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2739 "client_address is %s\n", p->client_id->addr));
2741 if (!lp_print_notify_backchannel(snum)) {
2742 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2743 "backchannel disabled\n"));
2744 return WERR_SERVER_UNAVAILABLE;
2747 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2749 return WERR_SERVER_UNAVAILABLE;
2752 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2753 Printer->notify.printerlocal, REG_SZ,
2754 &Printer->notify.cli_hnd,
2755 &Printer->notify.cli_chan,
2756 &client_ss, p->msg_ctx)) {
2757 return WERR_SERVER_UNAVAILABLE;
2763 /*******************************************************************
2764 * fill a notify_info_data with the servername
2765 ********************************************************************/
2767 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2769 struct spoolss_Notify *data,
2770 print_queue_struct *queue,
2771 struct spoolss_PrinterInfo2 *pinfo2,
2772 TALLOC_CTX *mem_ctx)
2774 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2777 /*******************************************************************
2778 * fill a notify_info_data with the printername (not including the servername).
2779 ********************************************************************/
2781 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2783 struct spoolss_Notify *data,
2784 print_queue_struct *queue,
2785 struct spoolss_PrinterInfo2 *pinfo2,
2786 TALLOC_CTX *mem_ctx)
2788 /* the notify name should not contain the \\server\ part */
2789 const char *p = strrchr(pinfo2->printername, '\\');
2792 p = pinfo2->printername;
2797 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2800 /*******************************************************************
2801 * fill a notify_info_data with the servicename
2802 ********************************************************************/
2804 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2806 struct spoolss_Notify *data,
2807 print_queue_struct *queue,
2808 struct spoolss_PrinterInfo2 *pinfo2,
2809 TALLOC_CTX *mem_ctx)
2811 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2814 /*******************************************************************
2815 * fill a notify_info_data with the port name
2816 ********************************************************************/
2818 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2820 struct spoolss_Notify *data,
2821 print_queue_struct *queue,
2822 struct spoolss_PrinterInfo2 *pinfo2,
2823 TALLOC_CTX *mem_ctx)
2825 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2828 /*******************************************************************
2829 * fill a notify_info_data with the printername
2830 * but it doesn't exist, have to see what to do
2831 ********************************************************************/
2833 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2835 struct spoolss_Notify *data,
2836 print_queue_struct *queue,
2837 struct spoolss_PrinterInfo2 *pinfo2,
2838 TALLOC_CTX *mem_ctx)
2840 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2843 /*******************************************************************
2844 * fill a notify_info_data with the comment
2845 ********************************************************************/
2847 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2849 struct spoolss_Notify *data,
2850 print_queue_struct *queue,
2851 struct spoolss_PrinterInfo2 *pinfo2,
2852 TALLOC_CTX *mem_ctx)
2856 if (*pinfo2->comment == '\0') {
2857 p = lp_comment(snum);
2859 p = pinfo2->comment;
2862 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2865 /*******************************************************************
2866 * fill a notify_info_data with the comment
2867 * location = "Room 1, floor 2, building 3"
2868 ********************************************************************/
2870 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2872 struct spoolss_Notify *data,
2873 print_queue_struct *queue,
2874 struct spoolss_PrinterInfo2 *pinfo2,
2875 TALLOC_CTX *mem_ctx)
2877 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2880 /*******************************************************************
2881 * fill a notify_info_data with the device mode
2882 * jfm:xxxx don't to it for know but that's a real problem !!!
2883 ********************************************************************/
2885 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2887 struct spoolss_Notify *data,
2888 print_queue_struct *queue,
2889 struct spoolss_PrinterInfo2 *pinfo2,
2890 TALLOC_CTX *mem_ctx)
2892 /* for a dummy implementation we have to zero the fields */
2893 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2896 /*******************************************************************
2897 * fill a notify_info_data with the separator file name
2898 ********************************************************************/
2900 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2902 struct spoolss_Notify *data,
2903 print_queue_struct *queue,
2904 struct spoolss_PrinterInfo2 *pinfo2,
2905 TALLOC_CTX *mem_ctx)
2907 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2910 /*******************************************************************
2911 * fill a notify_info_data with the print processor
2912 * jfm:xxxx return always winprint to indicate we don't do anything to it
2913 ********************************************************************/
2915 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2917 struct spoolss_Notify *data,
2918 print_queue_struct *queue,
2919 struct spoolss_PrinterInfo2 *pinfo2,
2920 TALLOC_CTX *mem_ctx)
2922 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2925 /*******************************************************************
2926 * fill a notify_info_data with the print processor options
2927 * jfm:xxxx send an empty string
2928 ********************************************************************/
2930 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2932 struct spoolss_Notify *data,
2933 print_queue_struct *queue,
2934 struct spoolss_PrinterInfo2 *pinfo2,
2935 TALLOC_CTX *mem_ctx)
2937 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2940 /*******************************************************************
2941 * fill a notify_info_data with the data type
2942 * jfm:xxxx always send RAW as data type
2943 ********************************************************************/
2945 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2947 struct spoolss_Notify *data,
2948 print_queue_struct *queue,
2949 struct spoolss_PrinterInfo2 *pinfo2,
2950 TALLOC_CTX *mem_ctx)
2952 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2955 /*******************************************************************
2956 * fill a notify_info_data with the security descriptor
2957 * jfm:xxxx send an null pointer to say no security desc
2958 * have to implement security before !
2959 ********************************************************************/
2961 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2963 struct spoolss_Notify *data,
2964 print_queue_struct *queue,
2965 struct spoolss_PrinterInfo2 *pinfo2,
2966 TALLOC_CTX *mem_ctx)
2968 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2971 /*******************************************************************
2972 * fill a notify_info_data with the attributes
2973 * jfm:xxxx a samba printer is always shared
2974 ********************************************************************/
2976 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2978 struct spoolss_Notify *data,
2979 print_queue_struct *queue,
2980 struct spoolss_PrinterInfo2 *pinfo2,
2981 TALLOC_CTX *mem_ctx)
2983 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2986 /*******************************************************************
2987 * fill a notify_info_data with the priority
2988 ********************************************************************/
2990 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2992 struct spoolss_Notify *data,
2993 print_queue_struct *queue,
2994 struct spoolss_PrinterInfo2 *pinfo2,
2995 TALLOC_CTX *mem_ctx)
2997 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3000 /*******************************************************************
3001 * fill a notify_info_data with the default priority
3002 ********************************************************************/
3004 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3006 struct spoolss_Notify *data,
3007 print_queue_struct *queue,
3008 struct spoolss_PrinterInfo2 *pinfo2,
3009 TALLOC_CTX *mem_ctx)
3011 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3014 /*******************************************************************
3015 * fill a notify_info_data with the start time
3016 ********************************************************************/
3018 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3020 struct spoolss_Notify *data,
3021 print_queue_struct *queue,
3022 struct spoolss_PrinterInfo2 *pinfo2,
3023 TALLOC_CTX *mem_ctx)
3025 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3028 /*******************************************************************
3029 * fill a notify_info_data with the until time
3030 ********************************************************************/
3032 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3034 struct spoolss_Notify *data,
3035 print_queue_struct *queue,
3036 struct spoolss_PrinterInfo2 *pinfo2,
3037 TALLOC_CTX *mem_ctx)
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3042 /*******************************************************************
3043 * fill a notify_info_data with the status
3044 ********************************************************************/
3046 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3048 struct spoolss_Notify *data,
3049 print_queue_struct *queue,
3050 struct spoolss_PrinterInfo2 *pinfo2,
3051 TALLOC_CTX *mem_ctx)
3053 print_status_struct status;
3055 print_queue_length(msg_ctx, snum, &status);
3056 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3059 /*******************************************************************
3060 * fill a notify_info_data with the number of jobs queued
3061 ********************************************************************/
3063 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3065 struct spoolss_Notify *data,
3066 print_queue_struct *queue,
3067 struct spoolss_PrinterInfo2 *pinfo2,
3068 TALLOC_CTX *mem_ctx)
3070 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3071 data, print_queue_length(msg_ctx, snum, NULL));
3074 /*******************************************************************
3075 * fill a notify_info_data with the average ppm
3076 ********************************************************************/
3078 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3080 struct spoolss_Notify *data,
3081 print_queue_struct *queue,
3082 struct spoolss_PrinterInfo2 *pinfo2,
3083 TALLOC_CTX *mem_ctx)
3085 /* always respond 8 pages per minutes */
3086 /* a little hard ! */
3087 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3090 /*******************************************************************
3091 * fill a notify_info_data with username
3092 ********************************************************************/
3094 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3096 struct spoolss_Notify *data,
3097 print_queue_struct *queue,
3098 struct spoolss_PrinterInfo2 *pinfo2,
3099 TALLOC_CTX *mem_ctx)
3101 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3104 /*******************************************************************
3105 * fill a notify_info_data with job status
3106 ********************************************************************/
3108 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3110 struct spoolss_Notify *data,
3111 print_queue_struct *queue,
3112 struct spoolss_PrinterInfo2 *pinfo2,
3113 TALLOC_CTX *mem_ctx)
3115 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3118 /*******************************************************************
3119 * fill a notify_info_data with job name
3120 ********************************************************************/
3122 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3124 struct spoolss_Notify *data,
3125 print_queue_struct *queue,
3126 struct spoolss_PrinterInfo2 *pinfo2,
3127 TALLOC_CTX *mem_ctx)
3129 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3132 /*******************************************************************
3133 * fill a notify_info_data with job status
3134 ********************************************************************/
3136 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3138 struct spoolss_Notify *data,
3139 print_queue_struct *queue,
3140 struct spoolss_PrinterInfo2 *pinfo2,
3141 TALLOC_CTX *mem_ctx)
3144 * Now we're returning job status codes we just return a "" here. JRA.
3149 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3152 switch (queue->status) {
3157 p = ""; /* NT provides the paused string */
3166 #endif /* NO LONGER NEEDED. */
3168 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3171 /*******************************************************************
3172 * fill a notify_info_data with job time
3173 ********************************************************************/
3175 static void spoolss_notify_job_time(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_INTEGER(data, 0);
3185 /*******************************************************************
3186 * fill a notify_info_data with job size
3187 ********************************************************************/
3189 static void spoolss_notify_job_size(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)
3196 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3199 /*******************************************************************
3200 * fill a notify_info_data with page info
3201 ********************************************************************/
3202 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3204 struct spoolss_Notify *data,
3205 print_queue_struct *queue,
3206 struct spoolss_PrinterInfo2 *pinfo2,
3207 TALLOC_CTX *mem_ctx)
3209 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3212 /*******************************************************************
3213 * fill a notify_info_data with pages printed info.
3214 ********************************************************************/
3215 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3217 struct spoolss_Notify *data,
3218 print_queue_struct *queue,
3219 struct spoolss_PrinterInfo2 *pinfo2,
3220 TALLOC_CTX *mem_ctx)
3222 /* Add code when back-end tracks this */
3223 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3226 /*******************************************************************
3227 Fill a notify_info_data with job position.
3228 ********************************************************************/
3230 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3232 struct spoolss_Notify *data,
3233 print_queue_struct *queue,
3234 struct spoolss_PrinterInfo2 *pinfo2,
3235 TALLOC_CTX *mem_ctx)
3237 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3240 /*******************************************************************
3241 Fill a notify_info_data with submitted time.
3242 ********************************************************************/
3244 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3246 struct spoolss_Notify *data,
3247 print_queue_struct *queue,
3248 struct spoolss_PrinterInfo2 *pinfo2,
3249 TALLOC_CTX *mem_ctx)
3251 data->data.string.string = NULL;
3252 data->data.string.size = 0;
3254 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3255 &data->data.string.string,
3256 &data->data.string.size);
3260 struct s_notify_info_data_table
3262 enum spoolss_NotifyType type;
3265 enum spoolss_NotifyTable variable_type;
3266 void (*fn) (struct messaging_context *msg_ctx,
3267 int snum, struct spoolss_Notify *data,
3268 print_queue_struct *queue,
3269 struct spoolss_PrinterInfo2 *pinfo2,
3270 TALLOC_CTX *mem_ctx);
3273 /* A table describing the various print notification constants and
3274 whether the notification data is a pointer to a variable sized
3275 buffer, a one value uint32_t or a two value uint32_t. */
3277 static const struct s_notify_info_data_table notify_info_data_table[] =
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3330 /*******************************************************************
3331 Return the variable_type of info_data structure.
3332 ********************************************************************/
3334 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3339 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3340 if ( (notify_info_data_table[i].type == type) &&
3341 (notify_info_data_table[i].field == field) ) {
3342 return notify_info_data_table[i].variable_type;
3346 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3348 return (enum spoolss_NotifyTable) 0;
3351 /****************************************************************************
3352 ****************************************************************************/
3354 static bool search_notify(enum spoolss_NotifyType type,
3360 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3361 if (notify_info_data_table[i].type == type &&
3362 notify_info_data_table[i].field == field &&
3363 notify_info_data_table[i].fn != NULL) {
3372 /****************************************************************************
3373 ****************************************************************************/
3375 static void construct_info_data(struct spoolss_Notify *info_data,
3376 enum spoolss_NotifyType type,
3377 uint16_t field, int id)
3379 info_data->type = type;
3380 info_data->field.field = field;
3381 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3382 info_data->job_id = id;
3385 /*******************************************************************
3387 * fill a notify_info struct with info asked
3389 ********************************************************************/
3391 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3392 struct printer_handle *print_hnd,
3393 struct spoolss_NotifyInfo *info,
3394 struct spoolss_PrinterInfo2 *pinfo2,
3396 const struct spoolss_NotifyOptionType *option_type,
3398 TALLOC_CTX *mem_ctx)
3401 enum spoolss_NotifyType type;
3404 struct spoolss_Notify *current_data;
3405 print_queue_struct *queue=NULL;
3407 type = option_type->type;
3409 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3410 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3411 option_type->count, lp_servicename(snum)));
3413 for(field_num=0; field_num < option_type->count; field_num++) {
3414 field = option_type->fields[field_num].field;
3416 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3418 if (!search_notify(type, field, &j) )
3421 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3422 struct spoolss_Notify,
3424 if (info->notifies == NULL) {
3425 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3429 current_data = &info->notifies[info->count];
3431 construct_info_data(current_data, type, field, id);
3433 DEBUG(10, ("construct_notify_printer_info: "
3434 "calling [%s] snum=%d printername=[%s])\n",
3435 notify_info_data_table[j].name, snum,
3436 pinfo2->printername));
3438 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3439 queue, pinfo2, mem_ctx);
3447 /*******************************************************************
3449 * fill a notify_info struct with info asked
3451 ********************************************************************/
3453 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3454 print_queue_struct *queue,
3455 struct spoolss_NotifyInfo *info,
3456 struct spoolss_PrinterInfo2 *pinfo2,
3458 const struct spoolss_NotifyOptionType *option_type,
3460 TALLOC_CTX *mem_ctx)
3463 enum spoolss_NotifyType type;
3465 struct spoolss_Notify *current_data;
3467 DEBUG(4,("construct_notify_jobs_info\n"));
3469 type = option_type->type;
3471 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3472 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3473 option_type->count));
3475 for(field_num=0; field_num<option_type->count; field_num++) {
3476 field = option_type->fields[field_num].field;
3478 if (!search_notify(type, field, &j) )
3481 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3482 struct spoolss_Notify,
3484 if (info->notifies == NULL) {
3485 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3489 current_data=&(info->notifies[info->count]);
3491 construct_info_data(current_data, type, field, id);
3492 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3493 queue, pinfo2, mem_ctx);
3501 * JFM: The enumeration is not that simple, it's even non obvious.
3503 * let's take an example: I want to monitor the PRINTER SERVER for
3504 * the printer's name and the number of jobs currently queued.
3505 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3506 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3508 * I have 3 printers on the back of my server.
3510 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3513 * 1 printer 1 name 1
3514 * 2 printer 1 cjob 1
3515 * 3 printer 2 name 2
3516 * 4 printer 2 cjob 2
3517 * 5 printer 3 name 3
3518 * 6 printer 3 name 3
3520 * that's the print server case, the printer case is even worse.
3523 /*******************************************************************
3525 * enumerate all printers on the printserver
3526 * fill a notify_info struct with info asked
3528 ********************************************************************/
3530 static WERROR printserver_notify_info(struct pipes_struct *p,
3531 struct policy_handle *hnd,
3532 struct spoolss_NotifyInfo *info,
3533 TALLOC_CTX *mem_ctx)
3536 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3537 int n_services=lp_numservices();
3539 struct spoolss_NotifyOption *option;
3540 struct spoolss_NotifyOptionType option_type;
3541 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3544 DEBUG(4,("printserver_notify_info\n"));
3549 option = Printer->notify.option;
3552 info->notifies = NULL;
3555 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3556 sending a ffpcn() request first */
3561 for (i=0; i<option->count; i++) {
3562 option_type = option->types[i];
3564 if (option_type.type != PRINTER_NOTIFY_TYPE)
3567 for (snum = 0; snum < n_services; snum++) {
3568 if (!lp_browseable(snum) ||
3569 !lp_snum_ok(snum) ||
3570 !lp_print_ok(snum)) {
3571 continue; /* skip */
3574 /* Maybe we should use the SYSTEM session_info here... */
3575 result = winreg_get_printer(mem_ctx,
3576 get_session_info_system(),
3578 lp_servicename(snum),
3580 if (!W_ERROR_IS_OK(result)) {
3581 DEBUG(4, ("printserver_notify_info: "
3582 "Failed to get printer [%s]\n",
3583 lp_servicename(snum)));
3588 construct_notify_printer_info(p->msg_ctx,
3594 TALLOC_FREE(pinfo2);
3600 * Debugging information, don't delete.
3603 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3604 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3605 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3607 for (i=0; i<info->count; i++) {
3608 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3609 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3610 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3617 /*******************************************************************
3619 * fill a notify_info struct with info asked
3621 ********************************************************************/
3623 static WERROR printer_notify_info(struct pipes_struct *p,
3624 struct policy_handle *hnd,
3625 struct spoolss_NotifyInfo *info,
3626 TALLOC_CTX *mem_ctx)
3629 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3632 struct spoolss_NotifyOption *option;
3633 struct spoolss_NotifyOptionType option_type;
3635 print_queue_struct *queue=NULL;
3636 print_status_struct status;
3637 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3640 DEBUG(4,("printer_notify_info\n"));
3645 option = Printer->notify.option;
3649 info->notifies = NULL;
3652 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3653 sending a ffpcn() request first */
3658 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3662 /* Maybe we should use the SYSTEM session_info here... */
3663 result = winreg_get_printer(mem_ctx,
3664 get_session_info_system(),
3666 lp_servicename(snum), &pinfo2);
3667 if (!W_ERROR_IS_OK(result)) {
3671 for (i=0; i<option->count; i++) {
3672 option_type = option->types[i];
3674 switch (option_type.type) {
3675 case PRINTER_NOTIFY_TYPE:
3676 if (construct_notify_printer_info(p->msg_ctx,
3685 case JOB_NOTIFY_TYPE:
3687 count = print_queue_status(p->msg_ctx, snum, &queue,
3690 for (j=0; j<count; j++) {
3691 construct_notify_jobs_info(p->msg_ctx,
3705 * Debugging information, don't delete.
3708 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3709 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3710 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3712 for (i=0; i<info->count; i++) {
3713 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3714 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3715 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3719 talloc_free(pinfo2);
3723 /****************************************************************
3724 _spoolss_RouterRefreshPrinterChangeNotify
3725 ****************************************************************/
3727 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3728 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3730 struct spoolss_NotifyInfo *info;
3732 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3733 WERROR result = WERR_BADFID;
3735 /* we always have a spoolss_NotifyInfo struct */
3736 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3738 result = WERR_NOMEM;
3742 *r->out.info = info;
3745 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3746 "Invalid handle (%s:%u:%u).\n",
3747 OUR_HANDLE(r->in.handle)));
3751 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3754 * We are now using the change value, and
3755 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3756 * I don't have a global notification system, I'm sending back all the
3757 * information even when _NOTHING_ has changed.
3760 /* We need to keep track of the change value to send back in
3761 RRPCN replies otherwise our updates are ignored. */
3763 Printer->notify.fnpcn = true;
3765 if (Printer->notify.cli_chan != NULL &&
3766 Printer->notify.cli_chan->active_connections > 0) {
3767 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3768 "Saving change value in request [%x]\n",
3770 Printer->notify.change = r->in.change_low;
3773 /* just ignore the spoolss_NotifyOption */
3775 switch (Printer->printer_type) {
3777 result = printserver_notify_info(p, r->in.handle,
3781 case SPLHND_PRINTER:
3782 result = printer_notify_info(p, r->in.handle,
3787 Printer->notify.fnpcn = false;
3793 /********************************************************************
3794 ********************************************************************/
3796 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3797 const char *servername,
3798 const char *printername,
3799 const char **printername_p)
3801 /* FIXME: add lp_force_printername() */
3803 if (servername == NULL) {
3804 *printername_p = talloc_strdup(mem_ctx, printername);
3805 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3809 if (servername[0] == '\\' && servername[1] == '\\') {
3813 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3814 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3819 /********************************************************************
3820 ********************************************************************/
3822 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3823 const char *printername)
3829 dm->devicename = talloc_strndup(dm, printername,
3830 MIN(strlen(printername), 31));
3833 /********************************************************************
3834 * construct_printer_info_0
3835 * fill a printer_info_0 struct
3836 ********************************************************************/
3838 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3839 const struct auth_serversupplied_info *session_info,
3840 struct messaging_context *msg_ctx,
3841 struct spoolss_PrinterInfo2 *info2,
3842 const char *servername,
3843 struct spoolss_PrinterInfo0 *r,
3847 struct printer_session_counter *session_counter;
3848 struct timeval setuptime;
3849 print_status_struct status;
3852 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3853 if (!W_ERROR_IS_OK(result)) {
3858 r->servername = talloc_strdup(mem_ctx, servername);
3859 W_ERROR_HAVE_NO_MEMORY(r->servername);
3861 r->servername = NULL;
3864 count = print_queue_length(msg_ctx, snum, &status);
3866 /* check if we already have a counter for this printer */
3867 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3868 if (session_counter->snum == snum)
3872 /* it's the first time, add it to the list */
3873 if (session_counter == NULL) {
3874 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3875 W_ERROR_HAVE_NO_MEMORY(session_counter);
3876 session_counter->snum = snum;
3877 session_counter->counter = 0;
3878 DLIST_ADD(counter_list, session_counter);
3882 session_counter->counter++;
3888 get_startup_time(&setuptime);
3889 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3892 * the global_counter should be stored in a TDB as it's common to all the clients
3893 * and should be zeroed on samba startup
3895 r->global_counter = session_counter->counter;
3897 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3898 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3899 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3900 r->free_build = SPOOLSS_RELEASE_BUILD;
3902 r->max_spooling = 0;
3903 r->session_counter = session_counter->counter;
3904 r->num_error_out_of_paper = 0x0;
3905 r->num_error_not_ready = 0x0; /* number of print failure */
3907 r->number_of_processors = 0x1;
3908 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3909 r->high_part_total_bytes = 0x0;
3911 /* ChangeID in milliseconds*/
3912 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3913 info2->sharename, &r->change_id);
3915 r->last_error = WERR_OK;
3916 r->status = nt_printq_status(status.status);
3917 r->enumerate_network_printers = 0x0;
3918 r->c_setprinter = 0x0;
3919 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3920 r->processor_level = 0x6; /* 6 ???*/
3929 /********************************************************************
3930 * construct_printer_info1
3931 * fill a spoolss_PrinterInfo1 struct
3932 ********************************************************************/
3934 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3935 const struct spoolss_PrinterInfo2 *info2,
3937 const char *servername,
3938 struct spoolss_PrinterInfo1 *r,
3945 if (info2->comment == NULL || info2->comment[0] == '\0') {
3946 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3948 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3950 W_ERROR_HAVE_NO_MEMORY(r->comment);
3952 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3953 if (!W_ERROR_IS_OK(result)) {
3957 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3961 W_ERROR_HAVE_NO_MEMORY(r->description);
3966 /********************************************************************
3967 * construct_printer_info2
3968 * fill a spoolss_PrinterInfo2 struct
3969 ********************************************************************/
3971 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3972 struct messaging_context *msg_ctx,
3973 const struct spoolss_PrinterInfo2 *info2,
3974 const char *servername,
3975 struct spoolss_PrinterInfo2 *r,
3979 print_status_struct status;
3982 count = print_queue_length(msg_ctx, snum, &status);
3985 r->servername = talloc_strdup(mem_ctx, servername);
3986 W_ERROR_HAVE_NO_MEMORY(r->servername);
3988 r->servername = NULL;
3991 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3992 if (!W_ERROR_IS_OK(result)) {
3996 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3997 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3998 r->portname = talloc_strdup(mem_ctx, info2->portname);
3999 W_ERROR_HAVE_NO_MEMORY(r->portname);
4000 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4001 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4003 if (info2->comment[0] == '\0') {
4004 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4006 r->comment = talloc_strdup(mem_ctx, info2->comment);
4008 W_ERROR_HAVE_NO_MEMORY(r->comment);
4010 r->location = talloc_strdup(mem_ctx, info2->location);
4011 W_ERROR_HAVE_NO_MEMORY(r->location);
4012 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4013 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4014 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4015 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4016 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4017 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4018 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4019 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4021 r->attributes = info2->attributes;
4023 r->priority = info2->priority;
4024 r->defaultpriority = info2->defaultpriority;
4025 r->starttime = info2->starttime;
4026 r->untiltime = info2->untiltime;
4027 r->status = nt_printq_status(status.status);
4029 r->averageppm = info2->averageppm;
4031 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4033 DEBUG(8,("Returning NULL Devicemode!\n"));
4036 compose_devicemode_devicename(r->devmode, r->printername);
4040 if (info2->secdesc != NULL) {
4041 /* don't use talloc_steal() here unless you do a deep steal of all
4042 the SEC_DESC members */
4044 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4050 /********************************************************************
4051 * construct_printer_info3
4052 * fill a spoolss_PrinterInfo3 struct
4053 ********************************************************************/
4055 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4056 const struct spoolss_PrinterInfo2 *info2,
4057 const char *servername,
4058 struct spoolss_PrinterInfo3 *r,
4061 /* These are the components of the SD we are returning. */
4063 if (info2->secdesc != NULL) {
4064 /* don't use talloc_steal() here unless you do a deep steal of all
4065 the SEC_DESC members */
4067 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4068 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4074 /********************************************************************
4075 * construct_printer_info4
4076 * fill a spoolss_PrinterInfo4 struct
4077 ********************************************************************/
4079 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4080 const struct spoolss_PrinterInfo2 *info2,
4081 const char *servername,
4082 struct spoolss_PrinterInfo4 *r,
4087 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4088 if (!W_ERROR_IS_OK(result)) {
4093 r->servername = talloc_strdup(mem_ctx, servername);
4094 W_ERROR_HAVE_NO_MEMORY(r->servername);
4096 r->servername = NULL;
4099 r->attributes = info2->attributes;
4104 /********************************************************************
4105 * construct_printer_info5
4106 * fill a spoolss_PrinterInfo5 struct
4107 ********************************************************************/
4109 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4110 const struct spoolss_PrinterInfo2 *info2,
4111 const char *servername,
4112 struct spoolss_PrinterInfo5 *r,
4117 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4118 if (!W_ERROR_IS_OK(result)) {
4122 r->portname = talloc_strdup(mem_ctx, info2->portname);
4123 W_ERROR_HAVE_NO_MEMORY(r->portname);
4125 r->attributes = info2->attributes;
4127 /* these two are not used by NT+ according to MSDN */
4128 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4129 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4134 /********************************************************************
4135 * construct_printer_info_6
4136 * fill a spoolss_PrinterInfo6 struct
4137 ********************************************************************/
4139 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4140 struct messaging_context *msg_ctx,
4141 const struct spoolss_PrinterInfo2 *info2,
4142 const char *servername,
4143 struct spoolss_PrinterInfo6 *r,
4147 print_status_struct status;
4149 count = print_queue_length(msg_ctx, snum, &status);
4151 r->status = nt_printq_status(status.status);
4156 /********************************************************************
4157 * construct_printer_info7
4158 * fill a spoolss_PrinterInfo7 struct
4159 ********************************************************************/
4161 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4162 struct messaging_context *msg_ctx,
4163 const char *servername,
4164 struct spoolss_PrinterInfo7 *r,
4167 struct auth_serversupplied_info *session_info;
4171 status = make_session_info_system(mem_ctx, &session_info);
4172 if (!NT_STATUS_IS_OK(status)) {
4173 DEBUG(0, ("construct_printer_info7: "
4174 "Could not create system session_info\n"));
4178 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4180 lp_servicename(snum), &guid, NULL)) {
4181 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4182 r->action = DSPRINT_PUBLISH;
4184 r->guid = talloc_strdup(mem_ctx, "");
4185 r->action = DSPRINT_UNPUBLISH;
4187 W_ERROR_HAVE_NO_MEMORY(r->guid);
4189 TALLOC_FREE(session_info);
4193 /********************************************************************
4194 * construct_printer_info8
4195 * fill a spoolss_PrinterInfo8 struct
4196 ********************************************************************/
4198 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4199 const struct spoolss_PrinterInfo2 *info2,
4200 const char *servername,
4201 struct spoolss_DeviceModeInfo *r,
4205 const char *printername;
4207 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4208 if (!W_ERROR_IS_OK(result)) {
4212 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4214 DEBUG(8,("Returning NULL Devicemode!\n"));
4217 compose_devicemode_devicename(r->devmode, printername);
4223 /********************************************************************
4224 ********************************************************************/
4226 static bool snum_is_shared_printer(int snum)
4228 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4231 /********************************************************************
4232 Spoolss_enumprinters.
4233 ********************************************************************/
4235 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4236 const struct auth_serversupplied_info *session_info,
4237 struct messaging_context *msg_ctx,
4238 const char *servername,
4241 union spoolss_PrinterInfo **info_p,
4245 int n_services = lp_numservices();
4246 union spoolss_PrinterInfo *info = NULL;
4248 WERROR result = WERR_OK;
4253 for (snum = 0; snum < n_services; snum++) {
4255 const char *printer;
4256 struct spoolss_PrinterInfo2 *info2;
4258 if (!snum_is_shared_printer(snum)) {
4262 printer = lp_const_servicename(snum);
4264 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4267 result = winreg_create_printer(mem_ctx,
4271 if (!W_ERROR_IS_OK(result)) {
4275 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4276 union spoolss_PrinterInfo,
4279 result = WERR_NOMEM;
4283 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4285 if (!W_ERROR_IS_OK(result)) {
4291 result = construct_printer_info0(info, session_info,
4294 &info[count].info0, snum);
4297 result = construct_printer_info1(info, info2, flags,
4299 &info[count].info1, snum);
4302 result = construct_printer_info2(info, msg_ctx, info2,
4304 &info[count].info2, snum);
4307 result = construct_printer_info4(info, info2,
4309 &info[count].info4, snum);
4312 result = construct_printer_info5(info, info2,
4314 &info[count].info5, snum);
4318 result = WERR_UNKNOWN_LEVEL;
4322 if (!W_ERROR_IS_OK(result)) {
4333 if (!W_ERROR_IS_OK(result)) {
4343 /********************************************************************
4344 * handle enumeration of printers at level 0
4345 ********************************************************************/
4347 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4348 const struct auth_serversupplied_info *session_info,
4349 struct messaging_context *msg_ctx,
4351 const char *servername,
4352 union spoolss_PrinterInfo **info,
4355 DEBUG(4,("enum_all_printers_info_0\n"));
4357 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4358 servername, 0, flags, info, count);
4362 /********************************************************************
4363 ********************************************************************/
4365 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4366 const struct auth_serversupplied_info *session_info,
4367 struct messaging_context *msg_ctx,
4368 const char *servername,
4370 union spoolss_PrinterInfo **info,
4373 DEBUG(4,("enum_all_printers_info_1\n"));
4375 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4376 servername, 1, flags, info, count);
4379 /********************************************************************
4380 enum_all_printers_info_1_local.
4381 *********************************************************************/
4383 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4384 const struct auth_serversupplied_info *session_info,
4385 struct messaging_context *msg_ctx,
4386 const char *servername,
4387 union spoolss_PrinterInfo **info,
4390 DEBUG(4,("enum_all_printers_info_1_local\n"));
4392 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4393 servername, PRINTER_ENUM_ICON8, info, count);
4396 /********************************************************************
4397 enum_all_printers_info_1_name.
4398 *********************************************************************/
4400 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4401 const struct auth_serversupplied_info *session_info,
4402 struct messaging_context *msg_ctx,
4403 const char *servername,
4404 union spoolss_PrinterInfo **info,
4407 const char *s = servername;
4409 DEBUG(4,("enum_all_printers_info_1_name\n"));
4411 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4415 if (!is_myname_or_ipaddr(s)) {
4416 return WERR_INVALID_NAME;
4419 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4420 servername, PRINTER_ENUM_ICON8, info, count);
4423 /********************************************************************
4424 enum_all_printers_info_1_network.
4425 *********************************************************************/
4427 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4428 const struct auth_serversupplied_info *session_info,
4429 struct messaging_context *msg_ctx,
4430 const char *servername,
4431 union spoolss_PrinterInfo **info,
4434 const char *s = servername;
4436 DEBUG(4,("enum_all_printers_info_1_network\n"));
4438 /* If we respond to a enum_printers level 1 on our name with flags
4439 set to PRINTER_ENUM_REMOTE with a list of printers then these
4440 printers incorrectly appear in the APW browse list.
4441 Specifically the printers for the server appear at the workgroup
4442 level where all the other servers in the domain are
4443 listed. Windows responds to this call with a
4444 WERR_CAN_NOT_COMPLETE so we should do the same. */
4446 if (servername[0] == '\\' && servername[1] == '\\') {
4450 if (is_myname_or_ipaddr(s)) {
4451 return WERR_CAN_NOT_COMPLETE;
4454 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4455 servername, PRINTER_ENUM_NAME, info, count);
4458 /********************************************************************
4459 * api_spoolss_enumprinters
4461 * called from api_spoolss_enumprinters (see this to understand)
4462 ********************************************************************/
4464 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4465 const struct auth_serversupplied_info *session_info,
4466 struct messaging_context *msg_ctx,
4467 const char *servername,
4468 union spoolss_PrinterInfo **info,
4471 DEBUG(4,("enum_all_printers_info_2\n"));
4473 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4474 servername, 2, 0, info, count);
4477 /********************************************************************
4478 * handle enumeration of printers at level 1
4479 ********************************************************************/
4481 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4482 const struct auth_serversupplied_info *session_info,
4483 struct messaging_context *msg_ctx,
4485 const char *servername,
4486 union spoolss_PrinterInfo **info,
4489 /* Not all the flags are equals */
4491 if (flags & PRINTER_ENUM_LOCAL) {
4492 return enum_all_printers_info_1_local(mem_ctx, session_info,
4493 msg_ctx, servername, info, count);
4496 if (flags & PRINTER_ENUM_NAME) {
4497 return enum_all_printers_info_1_name(mem_ctx, session_info,
4498 msg_ctx, servername, info,
4502 if (flags & PRINTER_ENUM_NETWORK) {
4503 return enum_all_printers_info_1_network(mem_ctx, session_info,
4504 msg_ctx, servername, info,
4508 return WERR_OK; /* NT4sp5 does that */
4511 /********************************************************************
4512 * handle enumeration of printers at level 2
4513 ********************************************************************/
4515 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4516 const struct auth_serversupplied_info *session_info,
4517 struct messaging_context *msg_ctx,
4519 const char *servername,
4520 union spoolss_PrinterInfo **info,
4523 if (flags & PRINTER_ENUM_LOCAL) {
4525 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4530 if (flags & PRINTER_ENUM_NAME) {
4531 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4532 return WERR_INVALID_NAME;
4535 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4540 if (flags & PRINTER_ENUM_REMOTE) {
4541 return WERR_UNKNOWN_LEVEL;
4547 /********************************************************************
4548 * handle enumeration of printers at level 4
4549 ********************************************************************/
4551 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4552 const struct auth_serversupplied_info *session_info,
4553 struct messaging_context *msg_ctx,
4555 const char *servername,
4556 union spoolss_PrinterInfo **info,
4559 DEBUG(4,("enum_all_printers_info_4\n"));
4561 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4562 servername, 4, flags, info, count);
4566 /********************************************************************
4567 * handle enumeration of printers at level 5
4568 ********************************************************************/
4570 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4571 const struct auth_serversupplied_info *session_info,
4572 struct messaging_context *msg_ctx,
4574 const char *servername,
4575 union spoolss_PrinterInfo **info,
4578 DEBUG(4,("enum_all_printers_info_5\n"));
4580 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4581 servername, 5, flags, info, count);
4584 /****************************************************************
4585 _spoolss_EnumPrinters
4586 ****************************************************************/
4588 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4589 struct spoolss_EnumPrinters *r)
4591 const struct auth_serversupplied_info *session_info = get_session_info_system();
4594 /* that's an [in out] buffer */
4596 if (!r->in.buffer && (r->in.offered != 0)) {
4597 return WERR_INVALID_PARAM;
4600 DEBUG(4,("_spoolss_EnumPrinters\n"));
4604 *r->out.info = NULL;
4608 * flags==PRINTER_ENUM_NAME
4609 * if name=="" then enumerates all printers
4610 * if name!="" then enumerate the printer
4611 * flags==PRINTER_ENUM_REMOTE
4612 * name is NULL, enumerate printers
4613 * Level 2: name!="" enumerates printers, name can't be NULL
4614 * Level 3: doesn't exist
4615 * Level 4: does a local registry lookup
4616 * Level 5: same as Level 2
4619 if (r->in.server && r->in.server[0] == '\0') {
4620 r->in.server = NULL;
4623 switch (r->in.level) {
4625 result = enumprinters_level0(p->mem_ctx, session_info,
4626 p->msg_ctx, r->in.flags,
4628 r->out.info, r->out.count);
4631 result = enumprinters_level1(p->mem_ctx, session_info,
4632 p->msg_ctx, r->in.flags,
4634 r->out.info, r->out.count);
4637 result = enumprinters_level2(p->mem_ctx, session_info,
4638 p->msg_ctx, r->in.flags,
4640 r->out.info, r->out.count);
4643 result = enumprinters_level4(p->mem_ctx, session_info,
4644 p->msg_ctx, r->in.flags,
4646 r->out.info, r->out.count);
4649 result = enumprinters_level5(p->mem_ctx, session_info,
4650 p->msg_ctx, r->in.flags,
4652 r->out.info, r->out.count);
4655 return WERR_UNKNOWN_LEVEL;
4658 if (!W_ERROR_IS_OK(result)) {
4662 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4663 spoolss_EnumPrinters,
4664 *r->out.info, r->in.level,
4666 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4667 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4669 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4672 /****************************************************************
4674 ****************************************************************/
4676 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4677 struct spoolss_GetPrinter *r)
4679 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4680 struct spoolss_PrinterInfo2 *info2 = NULL;
4681 WERROR result = WERR_OK;
4684 /* that's an [in out] buffer */
4686 if (!r->in.buffer && (r->in.offered != 0)) {
4687 return WERR_INVALID_PARAM;
4692 if (Printer == NULL) {
4696 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4700 result = winreg_get_printer(p->mem_ctx,
4701 get_session_info_system(),
4703 lp_const_servicename(snum),
4705 if (!W_ERROR_IS_OK(result)) {
4709 switch (r->in.level) {
4711 result = construct_printer_info0(p->mem_ctx,
4712 get_session_info_system(),
4715 Printer->servername,
4716 &r->out.info->info0,
4720 result = construct_printer_info1(p->mem_ctx, info2,
4722 Printer->servername,
4723 &r->out.info->info1, snum);
4726 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4727 Printer->servername,
4728 &r->out.info->info2, snum);
4731 result = construct_printer_info3(p->mem_ctx, info2,
4732 Printer->servername,
4733 &r->out.info->info3, snum);
4736 result = construct_printer_info4(p->mem_ctx, info2,
4737 Printer->servername,
4738 &r->out.info->info4, snum);
4741 result = construct_printer_info5(p->mem_ctx, info2,
4742 Printer->servername,
4743 &r->out.info->info5, snum);
4746 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4747 Printer->servername,
4748 &r->out.info->info6, snum);
4751 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4752 Printer->servername,
4753 &r->out.info->info7, snum);
4756 result = construct_printer_info8(p->mem_ctx, info2,
4757 Printer->servername,
4758 &r->out.info->info8, snum);
4761 result = WERR_UNKNOWN_LEVEL;
4766 if (!W_ERROR_IS_OK(result)) {
4767 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4768 r->in.level, win_errstr(result)));
4769 TALLOC_FREE(r->out.info);
4773 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4774 r->out.info, r->in.level);
4775 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4777 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4780 /********************************************************************
4781 ********************************************************************/
4783 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4785 if (in && strlen(in)) { \
4786 out = talloc_strdup(mem_ctx, in); \
4788 out = talloc_strdup(mem_ctx, ""); \
4790 W_ERROR_HAVE_NO_MEMORY(out); \
4793 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4795 if (in && strlen(in)) { \
4796 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4798 out = talloc_strdup(mem_ctx, ""); \
4800 W_ERROR_HAVE_NO_MEMORY(out); \
4803 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4804 const char **string_array,
4805 const char ***presult,
4806 const char *cservername,
4810 int i, num_strings = 0;
4811 const char **array = NULL;
4813 if (string_array == NULL) {
4814 return WERR_INVALID_PARAMETER;
4817 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4818 const char *str = NULL;
4820 if (cservername == NULL || arch == NULL) {
4821 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4823 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4826 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4833 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4834 &array, &num_strings);
4844 /********************************************************************
4845 * fill a spoolss_DriverInfo1 struct
4846 ********************************************************************/
4848 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4849 struct spoolss_DriverInfo1 *r,
4850 const struct spoolss_DriverInfo8 *driver,
4851 const char *servername)
4853 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4854 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4859 /********************************************************************
4860 * fill a spoolss_DriverInfo2 struct
4861 ********************************************************************/
4863 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4864 struct spoolss_DriverInfo2 *r,
4865 const struct spoolss_DriverInfo8 *driver,
4866 const char *servername)
4869 const char *cservername = canon_servername(servername);
4871 r->version = driver->version;
4873 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4874 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4875 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4876 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4878 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4879 driver->architecture,
4881 driver->driver_path,
4884 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4885 driver->architecture,
4890 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4891 driver->architecture,
4893 driver->config_file,
4899 /********************************************************************
4900 * fill a spoolss_DriverInfo3 struct
4901 ********************************************************************/
4903 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4904 struct spoolss_DriverInfo3 *r,
4905 const struct spoolss_DriverInfo8 *driver,
4906 const char *servername)
4908 const char *cservername = canon_servername(servername);
4910 r->version = driver->version;
4912 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4913 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4914 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4915 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4917 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4918 driver->architecture,
4920 driver->driver_path,
4923 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4924 driver->architecture,
4929 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4930 driver->architecture,
4932 driver->config_file,
4935 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4936 driver->architecture,
4941 FILL_DRIVER_STRING(mem_ctx,
4942 driver->monitor_name,
4945 FILL_DRIVER_STRING(mem_ctx,
4946 driver->default_datatype,
4947 r->default_datatype);
4949 return string_array_from_driver_info(mem_ctx,
4950 driver->dependent_files,
4951 &r->dependent_files,
4953 driver->architecture,
4957 /********************************************************************
4958 * fill a spoolss_DriverInfo4 struct
4959 ********************************************************************/
4961 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4962 struct spoolss_DriverInfo4 *r,
4963 const struct spoolss_DriverInfo8 *driver,
4964 const char *servername)
4966 const char *cservername = canon_servername(servername);
4969 r->version = driver->version;
4971 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4972 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4973 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4974 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4976 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4977 driver->architecture,
4979 driver->driver_path,
4982 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4983 driver->architecture,
4988 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4989 driver->architecture,
4991 driver->config_file,
4994 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995 driver->architecture,
5000 result = string_array_from_driver_info(mem_ctx,
5001 driver->dependent_files,
5002 &r->dependent_files,
5004 driver->architecture,
5006 if (!W_ERROR_IS_OK(result)) {
5010 FILL_DRIVER_STRING(mem_ctx,
5011 driver->monitor_name,
5014 FILL_DRIVER_STRING(mem_ctx,
5015 driver->default_datatype,
5016 r->default_datatype);
5019 result = string_array_from_driver_info(mem_ctx,
5020 driver->previous_names,
5027 /********************************************************************
5028 * fill a spoolss_DriverInfo5 struct
5029 ********************************************************************/
5031 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5032 struct spoolss_DriverInfo5 *r,
5033 const struct spoolss_DriverInfo8 *driver,
5034 const char *servername)
5036 const char *cservername = canon_servername(servername);
5038 r->version = driver->version;
5040 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5041 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5042 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5043 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5045 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5046 driver->architecture,
5048 driver->driver_path,
5051 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5052 driver->architecture,
5057 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5058 driver->architecture,
5060 driver->config_file,
5063 r->driver_attributes = 0;
5064 r->config_version = 0;
5065 r->driver_version = 0;
5069 /********************************************************************
5070 * fill a spoolss_DriverInfo6 struct
5071 ********************************************************************/
5073 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5074 struct spoolss_DriverInfo6 *r,
5075 const struct spoolss_DriverInfo8 *driver,
5076 const char *servername)
5078 const char *cservername = canon_servername(servername);
5081 r->version = driver->version;
5083 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5084 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5085 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5086 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5088 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5089 driver->architecture,
5091 driver->driver_path,
5094 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5095 driver->architecture,
5100 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5101 driver->architecture,
5103 driver->config_file,
5106 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107 driver->architecture,
5112 FILL_DRIVER_STRING(mem_ctx,
5113 driver->monitor_name,
5116 FILL_DRIVER_STRING(mem_ctx,
5117 driver->default_datatype,
5118 r->default_datatype);
5120 result = string_array_from_driver_info(mem_ctx,
5121 driver->dependent_files,
5122 &r->dependent_files,
5124 driver->architecture,
5126 if (!W_ERROR_IS_OK(result)) {
5130 result = string_array_from_driver_info(mem_ctx,
5131 driver->previous_names,
5134 if (!W_ERROR_IS_OK(result)) {
5138 r->driver_date = driver->driver_date;
5139 r->driver_version = driver->driver_version;
5141 FILL_DRIVER_STRING(mem_ctx,
5142 driver->manufacturer_name,
5143 r->manufacturer_name);
5144 FILL_DRIVER_STRING(mem_ctx,
5145 driver->manufacturer_url,
5146 r->manufacturer_url);
5147 FILL_DRIVER_STRING(mem_ctx,
5148 driver->hardware_id,
5150 FILL_DRIVER_STRING(mem_ctx,
5157 /********************************************************************
5158 * fill a spoolss_DriverInfo8 struct
5159 ********************************************************************/
5161 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5162 struct spoolss_DriverInfo8 *r,
5163 const struct spoolss_DriverInfo8 *driver,
5164 const char *servername)
5166 const char *cservername = canon_servername(servername);
5169 r->version = driver->version;
5171 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5172 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5173 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5174 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5176 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177 driver->architecture,
5179 driver->driver_path,
5182 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5183 driver->architecture,
5188 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5189 driver->architecture,
5191 driver->config_file,
5194 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5195 driver->architecture,
5200 FILL_DRIVER_STRING(mem_ctx,
5201 driver->monitor_name,
5204 FILL_DRIVER_STRING(mem_ctx,
5205 driver->default_datatype,
5206 r->default_datatype);
5208 result = string_array_from_driver_info(mem_ctx,
5209 driver->dependent_files,
5210 &r->dependent_files,
5212 driver->architecture,
5214 if (!W_ERROR_IS_OK(result)) {
5218 result = string_array_from_driver_info(mem_ctx,
5219 driver->previous_names,
5222 if (!W_ERROR_IS_OK(result)) {
5226 r->driver_date = driver->driver_date;
5227 r->driver_version = driver->driver_version;
5229 FILL_DRIVER_STRING(mem_ctx,
5230 driver->manufacturer_name,
5231 r->manufacturer_name);
5232 FILL_DRIVER_STRING(mem_ctx,
5233 driver->manufacturer_url,
5234 r->manufacturer_url);
5235 FILL_DRIVER_STRING(mem_ctx,
5236 driver->hardware_id,
5238 FILL_DRIVER_STRING(mem_ctx,
5242 FILL_DRIVER_STRING(mem_ctx,
5243 driver->print_processor,
5244 r->print_processor);
5245 FILL_DRIVER_STRING(mem_ctx,
5246 driver->vendor_setup,
5249 result = string_array_from_driver_info(mem_ctx,
5250 driver->color_profiles,
5253 if (!W_ERROR_IS_OK(result)) {
5257 FILL_DRIVER_STRING(mem_ctx,
5261 r->printer_driver_attributes = driver->printer_driver_attributes;
5263 result = string_array_from_driver_info(mem_ctx,
5264 driver->core_driver_dependencies,
5265 &r->core_driver_dependencies,
5267 if (!W_ERROR_IS_OK(result)) {
5271 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5272 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5277 #if 0 /* disabled until marshalling issues are resolved - gd */
5278 /********************************************************************
5279 ********************************************************************/
5281 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5282 struct spoolss_DriverFileInfo *r,
5283 const char *cservername,
5284 const char *file_name,
5285 enum spoolss_DriverFileType file_type,
5286 uint32_t file_version)
5288 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5289 cservername, file_name);
5290 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5291 r->file_type = file_type;
5292 r->file_version = file_version;
5297 /********************************************************************
5298 ********************************************************************/
5300 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5301 const struct spoolss_DriverInfo8 *driver,
5302 const char *cservername,
5303 struct spoolss_DriverFileInfo **info_p,
5306 struct spoolss_DriverFileInfo *info = NULL;
5314 if (strlen(driver->driver_path)) {
5315 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5316 struct spoolss_DriverFileInfo,
5318 W_ERROR_HAVE_NO_MEMORY(info);
5319 result = fill_spoolss_DriverFileInfo(info,
5322 driver->driver_path,
5323 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5325 W_ERROR_NOT_OK_RETURN(result);
5329 if (strlen(driver->config_file)) {
5330 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5331 struct spoolss_DriverFileInfo,
5333 W_ERROR_HAVE_NO_MEMORY(info);
5334 result = fill_spoolss_DriverFileInfo(info,
5337 driver->config_file,
5338 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5340 W_ERROR_NOT_OK_RETURN(result);
5344 if (strlen(driver->data_file)) {
5345 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5346 struct spoolss_DriverFileInfo,
5348 W_ERROR_HAVE_NO_MEMORY(info);
5349 result = fill_spoolss_DriverFileInfo(info,
5353 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5355 W_ERROR_NOT_OK_RETURN(result);
5359 if (strlen(driver->help_file)) {
5360 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5361 struct spoolss_DriverFileInfo,
5363 W_ERROR_HAVE_NO_MEMORY(info);
5364 result = fill_spoolss_DriverFileInfo(info,
5368 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5370 W_ERROR_NOT_OK_RETURN(result);
5374 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5375 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5376 struct spoolss_DriverFileInfo,
5378 W_ERROR_HAVE_NO_MEMORY(info);
5379 result = fill_spoolss_DriverFileInfo(info,
5382 driver->dependent_files[i],
5383 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5385 W_ERROR_NOT_OK_RETURN(result);
5395 /********************************************************************
5396 * fill a spoolss_DriverInfo101 struct
5397 ********************************************************************/
5399 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5400 struct spoolss_DriverInfo101 *r,
5401 const struct spoolss_DriverInfo8 *driver,
5402 const char *servername)
5404 const char *cservername = canon_servername(servername);
5407 r->version = driver->version;
5409 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5410 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5411 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5412 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5414 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5418 if (!W_ERROR_IS_OK(result)) {
5422 FILL_DRIVER_STRING(mem_ctx,
5423 driver->monitor_name,
5426 FILL_DRIVER_STRING(mem_ctx,
5427 driver->default_datatype,
5428 r->default_datatype);
5430 result = string_array_from_driver_info(mem_ctx,
5431 driver->previous_names,
5434 if (!W_ERROR_IS_OK(result)) {
5438 r->driver_date = driver->driver_date;
5439 r->driver_version = driver->driver_version;
5441 FILL_DRIVER_STRING(mem_ctx,
5442 driver->manufacturer_name,
5443 r->manufacturer_name);
5444 FILL_DRIVER_STRING(mem_ctx,
5445 driver->manufacturer_url,
5446 r->manufacturer_url);
5447 FILL_DRIVER_STRING(mem_ctx,
5448 driver->hardware_id,
5450 FILL_DRIVER_STRING(mem_ctx,
5457 /********************************************************************
5458 ********************************************************************/
5460 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5461 const struct auth_serversupplied_info *session_info,
5462 struct messaging_context *msg_ctx,
5464 union spoolss_DriverInfo *r,
5466 const char *servername,
5467 const char *architecture,
5470 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5471 struct spoolss_DriverInfo8 *driver;
5475 return WERR_UNKNOWN_LEVEL;
5478 result = winreg_get_printer(mem_ctx,
5481 lp_const_servicename(snum),
5484 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5485 win_errstr(result)));
5487 if (!W_ERROR_IS_OK(result)) {
5488 return WERR_INVALID_PRINTER_NAME;
5491 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5493 pinfo2->drivername, version, &driver);
5495 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5496 win_errstr(result)));
5498 if (!W_ERROR_IS_OK(result)) {
5500 * Is this a W2k client ?
5504 talloc_free(pinfo2);
5505 return WERR_UNKNOWN_PRINTER_DRIVER;
5508 /* Yes - try again with a WinNT driver. */
5510 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5514 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5515 win_errstr(result)));
5516 if (!W_ERROR_IS_OK(result)) {
5517 talloc_free(pinfo2);
5518 return WERR_UNKNOWN_PRINTER_DRIVER;
5524 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5527 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5530 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5533 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5536 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5539 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5542 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5544 #if 0 /* disabled until marshalling issues are resolved - gd */
5546 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5550 result = WERR_UNKNOWN_LEVEL;
5554 talloc_free(pinfo2);
5555 talloc_free(driver);
5560 /****************************************************************
5561 _spoolss_GetPrinterDriver2
5562 ****************************************************************/
5564 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5565 struct spoolss_GetPrinterDriver2 *r)
5567 struct printer_handle *printer;
5572 /* that's an [in out] buffer */
5574 if (!r->in.buffer && (r->in.offered != 0)) {
5575 return WERR_INVALID_PARAM;
5578 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5580 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5581 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5582 return WERR_INVALID_PRINTER_NAME;
5586 *r->out.server_major_version = 0;
5587 *r->out.server_minor_version = 0;
5589 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5593 result = construct_printer_driver_info_level(p->mem_ctx,
5594 get_session_info_system(),
5596 r->in.level, r->out.info,
5597 snum, printer->servername,
5599 r->in.client_major_version);
5600 if (!W_ERROR_IS_OK(result)) {
5601 TALLOC_FREE(r->out.info);
5605 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5606 r->out.info, r->in.level);
5607 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5609 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5613 /****************************************************************
5614 _spoolss_StartPagePrinter
5615 ****************************************************************/
5617 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5618 struct spoolss_StartPagePrinter *r)
5620 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5623 DEBUG(3,("_spoolss_StartPagePrinter: "
5624 "Error in startpageprinter printer handle\n"));
5628 Printer->page_started = true;
5632 /****************************************************************
5633 _spoolss_EndPagePrinter
5634 ****************************************************************/
5636 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5637 struct spoolss_EndPagePrinter *r)
5641 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5644 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5645 OUR_HANDLE(r->in.handle)));
5649 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5652 Printer->page_started = false;
5653 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5658 /****************************************************************
5659 _spoolss_StartDocPrinter
5660 ****************************************************************/
5662 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5663 struct spoolss_StartDocPrinter *r)
5665 struct spoolss_DocumentInfo1 *info_1;
5667 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5671 DEBUG(2,("_spoolss_StartDocPrinter: "
5672 "Invalid handle (%s:%u:%u)\n",
5673 OUR_HANDLE(r->in.handle)));
5677 if (Printer->jobid) {
5678 DEBUG(2, ("_spoolss_StartDocPrinter: "
5679 "StartDocPrinter called twice! "
5680 "(existing jobid = %d)\n", Printer->jobid));
5681 return WERR_INVALID_HANDLE;
5684 if (r->in.level != 1) {
5685 return WERR_UNKNOWN_LEVEL;
5688 info_1 = r->in.info.info1;
5691 * a nice thing with NT is it doesn't listen to what you tell it.
5692 * when asked to send _only_ RAW datas, it tries to send datas
5695 * So I add checks like in NT Server ...
5698 if (info_1->datatype) {
5699 if (strcmp(info_1->datatype, "RAW") != 0) {
5701 return WERR_INVALID_DATATYPE;
5705 /* get the share number of the printer */
5706 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5710 werr = print_job_start(p->session_info,
5714 info_1->document_name,
5715 info_1->output_file,
5719 /* An error occured in print_job_start() so return an appropriate
5722 if (!W_ERROR_IS_OK(werr)) {
5726 Printer->document_started = true;
5727 *r->out.job_id = Printer->jobid;
5732 /****************************************************************
5733 _spoolss_EndDocPrinter
5734 ****************************************************************/
5736 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5737 struct spoolss_EndDocPrinter *r)
5739 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5744 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5745 OUR_HANDLE(r->in.handle)));
5749 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5753 Printer->document_started = false;
5754 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5755 if (!NT_STATUS_IS_OK(status)) {
5756 DEBUG(2, ("_spoolss_EndDocPrinter: "
5757 "print_job_end failed [%s]\n",
5758 nt_errstr(status)));
5762 return ntstatus_to_werror(status);
5765 /****************************************************************
5766 _spoolss_WritePrinter
5767 ****************************************************************/
5769 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5770 struct spoolss_WritePrinter *r)
5772 ssize_t buffer_written;
5774 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5777 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5778 OUR_HANDLE(r->in.handle)));
5779 *r->out.num_written = r->in._data_size;
5783 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5786 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5787 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5788 snum, Printer->jobid,
5789 (const char *)r->in.data.data,
5790 (size_t)r->in._data_size);
5791 if (buffer_written == (ssize_t)-1) {
5792 *r->out.num_written = 0;
5793 if (errno == ENOSPC)
5794 return WERR_NO_SPOOL_SPACE;
5796 return WERR_ACCESS_DENIED;
5799 *r->out.num_written = r->in._data_size;
5804 /********************************************************************
5805 * api_spoolss_getprinter
5806 * called from the spoolss dispatcher
5808 ********************************************************************/
5810 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5811 struct pipes_struct *p)
5813 const struct auth_serversupplied_info *session_info = p->session_info;
5815 WERROR errcode = WERR_BADFUNC;
5816 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5819 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5820 OUR_HANDLE(handle)));
5824 if (!get_printer_snum(p, handle, &snum, NULL))
5828 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5829 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5831 case SPOOLSS_PRINTER_CONTROL_RESUME:
5832 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5833 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5835 case SPOOLSS_PRINTER_CONTROL_PURGE:
5836 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5839 return WERR_UNKNOWN_LEVEL;
5846 /****************************************************************
5847 _spoolss_AbortPrinter
5848 * From MSDN: "Deletes printer's spool file if printer is configured
5850 ****************************************************************/
5852 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5853 struct spoolss_AbortPrinter *r)
5855 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5857 WERROR errcode = WERR_OK;
5860 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5861 OUR_HANDLE(r->in.handle)));
5865 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5868 if (!Printer->document_started) {
5869 return WERR_SPL_NO_STARTDOC;
5872 errcode = print_job_delete(p->session_info,
5880 /********************************************************************
5881 * called by spoolss_api_setprinter
5882 * when updating a printer description
5883 ********************************************************************/
5885 static WERROR update_printer_sec(struct policy_handle *handle,
5886 struct pipes_struct *p,
5887 struct sec_desc_buf *secdesc_ctr)
5889 struct spoolss_security_descriptor *new_secdesc = NULL;
5890 struct spoolss_security_descriptor *old_secdesc = NULL;
5891 const char *printer;
5895 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5897 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5898 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5899 OUR_HANDLE(handle)));
5901 result = WERR_BADFID;
5905 if (secdesc_ctr == NULL) {
5906 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5907 result = WERR_INVALID_PARAM;
5910 printer = lp_const_servicename(snum);
5912 /* Check the user has permissions to change the security
5913 descriptor. By experimentation with two NT machines, the user
5914 requires Full Access to the printer to change security
5917 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5918 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5919 result = WERR_ACCESS_DENIED;
5923 /* NT seems to like setting the security descriptor even though
5924 nothing may have actually changed. */
5925 result = winreg_get_printer_secdesc(p->mem_ctx,
5926 get_session_info_system(),
5930 if (!W_ERROR_IS_OK(result)) {
5931 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5932 result = WERR_BADFID;
5936 if (DEBUGLEVEL >= 10) {
5937 struct security_acl *the_acl;
5940 the_acl = old_secdesc->dacl;
5941 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5942 printer, the_acl->num_aces));
5944 for (i = 0; i < the_acl->num_aces; i++) {
5945 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5946 &the_acl->aces[i].trustee),
5947 the_acl->aces[i].access_mask));
5950 the_acl = secdesc_ctr->sd->dacl;
5953 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5954 printer, the_acl->num_aces));
5956 for (i = 0; i < the_acl->num_aces; i++) {
5957 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5958 &the_acl->aces[i].trustee),
5959 the_acl->aces[i].access_mask));
5962 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5966 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5967 if (new_secdesc == NULL) {
5968 result = WERR_NOMEM;
5972 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5977 result = winreg_set_printer_secdesc(p->mem_ctx,
5978 get_session_info_system(),
5987 /********************************************************************
5988 Canonicalize printer info from a client
5989 ********************************************************************/
5991 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5992 struct spoolss_SetPrinterInfo2 *info2,
5995 fstring printername;
5998 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5999 "portname=%s drivername=%s comment=%s location=%s\n",
6000 info2->servername, info2->printername, info2->sharename,
6001 info2->portname, info2->drivername, info2->comment,
6004 /* we force some elements to "correct" values */
6005 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6006 if (info2->servername == NULL) {
6009 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6010 if (info2->sharename == NULL) {
6014 /* check to see if we allow printername != sharename */
6015 if (lp_force_printername(snum)) {
6016 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6017 global_myname(), info2->sharename);
6019 /* make sure printername is in \\server\printername format */
6020 fstrcpy(printername, info2->printername);
6022 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6023 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6027 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6028 global_myname(), p);
6030 if (info2->printername == NULL) {
6034 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6035 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6040 /****************************************************************************
6041 ****************************************************************************/
6043 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6045 char *cmd = lp_addport_cmd();
6046 char *command = NULL;
6048 bool is_print_op = false;
6051 return WERR_ACCESS_DENIED;
6054 command = talloc_asprintf(ctx,
6055 "%s \"%s\" \"%s\"", cmd, portname, uri );
6061 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6063 DEBUG(10,("Running [%s]\n", command));
6065 /********* BEGIN SePrintOperatorPrivilege **********/
6070 ret = smbrun(command, NULL);
6075 /********* END SePrintOperatorPrivilege **********/
6077 DEBUGADD(10,("returned [%d]\n", ret));
6079 TALLOC_FREE(command);
6082 return WERR_ACCESS_DENIED;
6088 /****************************************************************************
6089 ****************************************************************************/
6091 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6092 struct spoolss_SetPrinterInfo2 *info2,
6093 const char *remote_machine,
6094 struct messaging_context *msg_ctx)
6096 char *cmd = lp_addprinter_cmd();
6098 char *command = NULL;
6102 bool is_print_op = false;
6104 if (!remote_machine) {
6108 command = talloc_asprintf(ctx,
6109 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6110 cmd, info2->printername, info2->sharename,
6111 info2->portname, info2->drivername,
6112 info2->location, info2->comment, remote_machine);
6118 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6120 DEBUG(10,("Running [%s]\n", command));
6122 /********* BEGIN SePrintOperatorPrivilege **********/
6127 if ( (ret = smbrun(command, &fd)) == 0 ) {
6128 /* Tell everyone we updated smb.conf. */
6129 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6135 /********* END SePrintOperatorPrivilege **********/
6137 DEBUGADD(10,("returned [%d]\n", ret));
6139 TALLOC_FREE(command);
6147 /* reload our services immediately */
6149 reload_services(msg_ctx, -1, false);
6153 /* Get lines and convert them back to dos-codepage */
6154 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6155 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6158 /* Set the portname to what the script says the portname should be. */
6159 /* but don't require anything to be return from the script exit a good error code */
6162 /* Set the portname to what the script says the portname should be. */
6163 info2->portname = talloc_strdup(ctx, qlines[0]);
6164 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6167 TALLOC_FREE(qlines);
6171 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6172 const struct auth_serversupplied_info *session_info,
6173 struct messaging_context *msg_ctx,
6175 struct spoolss_SetPrinterInfo2 *printer,
6176 struct spoolss_PrinterInfo2 *old_printer)
6178 bool force_update = (old_printer == NULL);
6179 const char *dnsdomname;
6180 const char *longname;
6181 const char *uncname;
6182 const char *spooling;
6184 WERROR result = WERR_OK;
6186 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6187 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6188 winreg_set_printer_dataex(mem_ctx,
6192 SPOOL_DSSPOOLER_KEY,
6193 SPOOL_REG_DRIVERNAME,
6198 if (!force_update) {
6199 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6200 printer->drivername));
6202 notify_printer_driver(server_event_context(), msg_ctx,
6203 snum, printer->drivername ?
6204 printer->drivername : "");
6208 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6209 push_reg_sz(mem_ctx, &buffer, printer->comment);
6210 winreg_set_printer_dataex(mem_ctx,
6214 SPOOL_DSSPOOLER_KEY,
6215 SPOOL_REG_DESCRIPTION,
6220 if (!force_update) {
6221 notify_printer_comment(server_event_context(), msg_ctx,
6222 snum, printer->comment ?
6223 printer->comment : "");
6227 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6228 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6229 winreg_set_printer_dataex(mem_ctx,
6233 SPOOL_DSSPOOLER_KEY,
6234 SPOOL_REG_PRINTSHARENAME,
6239 if (!force_update) {
6240 notify_printer_sharename(server_event_context(),
6242 snum, printer->sharename ?
6243 printer->sharename : "");
6247 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6250 p = strrchr(printer->printername, '\\' );
6254 p = printer->printername;
6257 push_reg_sz(mem_ctx, &buffer, p);
6258 winreg_set_printer_dataex(mem_ctx,
6262 SPOOL_DSSPOOLER_KEY,
6263 SPOOL_REG_PRINTERNAME,
6268 if (!force_update) {
6269 notify_printer_printername(server_event_context(),
6270 msg_ctx, snum, p ? p : "");
6274 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6275 push_reg_sz(mem_ctx, &buffer, printer->portname);
6276 winreg_set_printer_dataex(mem_ctx,
6280 SPOOL_DSSPOOLER_KEY,
6286 if (!force_update) {
6287 notify_printer_port(server_event_context(),
6288 msg_ctx, snum, printer->portname ?
6289 printer->portname : "");
6293 if (force_update || !strequal(printer->location, old_printer->location)) {
6294 push_reg_sz(mem_ctx, &buffer, printer->location);
6295 winreg_set_printer_dataex(mem_ctx,
6299 SPOOL_DSSPOOLER_KEY,
6305 if (!force_update) {
6306 notify_printer_location(server_event_context(),
6309 printer->location : "");
6313 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6314 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6315 winreg_set_printer_dataex(mem_ctx,
6319 SPOOL_DSSPOOLER_KEY,
6320 SPOOL_REG_PRINTSEPARATORFILE,
6325 if (!force_update) {
6326 notify_printer_sepfile(server_event_context(),
6329 printer->sepfile : "");
6333 if (force_update || printer->starttime != old_printer->starttime) {
6334 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6335 SIVAL(buffer.data, 0, printer->starttime);
6336 winreg_set_printer_dataex(mem_ctx,
6340 SPOOL_DSSPOOLER_KEY,
6341 SPOOL_REG_PRINTSTARTTIME,
6347 if (force_update || printer->untiltime != old_printer->untiltime) {
6348 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6349 SIVAL(buffer.data, 0, printer->untiltime);
6350 winreg_set_printer_dataex(mem_ctx,
6354 SPOOL_DSSPOOLER_KEY,
6355 SPOOL_REG_PRINTENDTIME,
6361 if (force_update || printer->priority != old_printer->priority) {
6362 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6363 SIVAL(buffer.data, 0, printer->priority);
6364 winreg_set_printer_dataex(mem_ctx,
6368 SPOOL_DSSPOOLER_KEY,
6375 if (force_update || printer->attributes != old_printer->attributes) {
6376 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6377 SIVAL(buffer.data, 0, (printer->attributes &
6378 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6379 winreg_set_printer_dataex(mem_ctx,
6383 SPOOL_DSSPOOLER_KEY,
6384 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6389 switch (printer->attributes & 0x3) {
6391 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6394 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6397 spooling = SPOOL_REGVAL_PRINTDIRECT;
6400 spooling = "unknown";
6402 push_reg_sz(mem_ctx, &buffer, spooling);
6403 winreg_set_printer_dataex(mem_ctx,
6407 SPOOL_DSSPOOLER_KEY,
6408 SPOOL_REG_PRINTSPOOLING,
6414 push_reg_sz(mem_ctx, &buffer, global_myname());
6415 winreg_set_printer_dataex(mem_ctx,
6419 SPOOL_DSSPOOLER_KEY,
6420 SPOOL_REG_SHORTSERVERNAME,
6425 dnsdomname = get_mydnsfullname();
6426 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6427 longname = talloc_strdup(mem_ctx, dnsdomname);
6429 longname = talloc_strdup(mem_ctx, global_myname());
6431 if (longname == NULL) {
6432 result = WERR_NOMEM;
6436 push_reg_sz(mem_ctx, &buffer, longname);
6437 winreg_set_printer_dataex(mem_ctx,
6441 SPOOL_DSSPOOLER_KEY,
6442 SPOOL_REG_SERVERNAME,
6447 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6448 global_myname(), printer->sharename);
6449 push_reg_sz(mem_ctx, &buffer, uncname);
6450 winreg_set_printer_dataex(mem_ctx,
6454 SPOOL_DSSPOOLER_KEY,
6464 /********************************************************************
6465 * Called by spoolss_api_setprinter
6466 * when updating a printer description.
6467 ********************************************************************/
6469 static WERROR update_printer(struct pipes_struct *p,
6470 struct policy_handle *handle,
6471 struct spoolss_SetPrinterInfoCtr *info_ctr,
6472 struct spoolss_DeviceMode *devmode)
6474 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6475 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6476 struct spoolss_PrinterInfo2 *old_printer;
6477 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6479 WERROR result = WERR_OK;
6480 TALLOC_CTX *tmp_ctx;
6482 DEBUG(8,("update_printer\n"));
6484 tmp_ctx = talloc_new(p->mem_ctx);
6485 if (tmp_ctx == NULL) {
6490 result = WERR_BADFID;
6494 if (!get_printer_snum(p, handle, &snum, NULL)) {
6495 result = WERR_BADFID;
6499 result = winreg_get_printer(tmp_ctx,
6500 get_session_info_system(),
6502 lp_const_servicename(snum),
6504 if (!W_ERROR_IS_OK(result)) {
6505 result = WERR_BADFID;
6509 /* Do sanity check on the requested changes for Samba */
6510 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6511 result = WERR_INVALID_PARAM;
6515 /* FIXME!!! If the driver has changed we really should verify that
6516 it is installed before doing much else --jerry */
6518 /* Check calling user has permission to update printer description */
6519 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6520 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6521 result = WERR_ACCESS_DENIED;
6525 /* Call addprinter hook */
6526 /* Check changes to see if this is really needed */
6528 if (*lp_addprinter_cmd() &&
6529 (!strequal(printer->drivername, old_printer->drivername) ||
6530 !strequal(printer->comment, old_printer->comment) ||
6531 !strequal(printer->portname, old_printer->portname) ||
6532 !strequal(printer->location, old_printer->location)) )
6534 /* add_printer_hook() will call reload_services() */
6535 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6536 printer, p->client_id->addr,
6538 result = WERR_ACCESS_DENIED;
6543 update_dsspooler(tmp_ctx,
6544 get_session_info_system(),
6550 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6552 if (devmode == NULL) {
6553 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6555 result = winreg_update_printer(tmp_ctx,
6556 get_session_info_system(),
6565 talloc_free(tmp_ctx);
6570 /****************************************************************************
6571 ****************************************************************************/
6572 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6573 struct policy_handle *handle,
6574 struct spoolss_SetPrinterInfo7 *info7)
6577 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6580 struct printer_handle *Printer;
6582 if ( lp_security() != SEC_ADS ) {
6583 return WERR_UNKNOWN_LEVEL;
6586 Printer = find_printer_index_by_hnd(p, handle);
6588 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6593 if (!get_printer_snum(p, handle, &snum, NULL))
6596 result = winreg_get_printer(p->mem_ctx,
6597 get_session_info_system(),
6599 lp_servicename(snum),
6601 if (!W_ERROR_IS_OK(result)) {
6605 nt_printer_publish(pinfo2,
6606 get_session_info_system(),
6611 TALLOC_FREE(pinfo2);
6614 return WERR_UNKNOWN_LEVEL;
6618 /********************************************************************
6619 ********************************************************************/
6621 static WERROR update_printer_devmode(struct pipes_struct *p,
6622 struct policy_handle *handle,
6623 struct spoolss_DeviceMode *devmode)
6626 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6627 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6629 DEBUG(8,("update_printer_devmode\n"));
6635 if (!get_printer_snum(p, handle, &snum, NULL)) {
6639 /* Check calling user has permission to update printer description */
6640 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6641 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6642 return WERR_ACCESS_DENIED;
6645 return winreg_update_printer(p->mem_ctx,
6646 get_session_info_system(),
6648 lp_const_servicename(snum),
6656 /****************************************************************
6658 ****************************************************************/
6660 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6661 struct spoolss_SetPrinter *r)
6665 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6668 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6669 OUR_HANDLE(r->in.handle)));
6673 /* check the level */
6674 switch (r->in.info_ctr->level) {
6676 return control_printer(r->in.handle, r->in.command, p);
6678 result = update_printer(p, r->in.handle,
6680 r->in.devmode_ctr->devmode);
6681 if (!W_ERROR_IS_OK(result))
6683 if (r->in.secdesc_ctr->sd)
6684 result = update_printer_sec(r->in.handle, p,
6688 return update_printer_sec(r->in.handle, p,
6691 return publish_or_unpublish_printer(p, r->in.handle,
6692 r->in.info_ctr->info.info7);
6694 return update_printer_devmode(p, r->in.handle,
6695 r->in.devmode_ctr->devmode);
6697 return WERR_UNKNOWN_LEVEL;
6701 /****************************************************************
6702 _spoolss_FindClosePrinterNotify
6703 ****************************************************************/
6705 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6706 struct spoolss_FindClosePrinterNotify *r)
6708 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6711 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6712 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6716 if (Printer->notify.cli_chan != NULL &&
6717 Printer->notify.cli_chan->active_connections > 0) {
6720 if (Printer->printer_type == SPLHND_PRINTER) {
6721 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6726 srv_spoolss_replycloseprinter(snum, Printer);
6729 Printer->notify.flags=0;
6730 Printer->notify.options=0;
6731 Printer->notify.localmachine[0]='\0';
6732 Printer->notify.printerlocal=0;
6733 TALLOC_FREE(Printer->notify.option);
6738 /****************************************************************
6740 ****************************************************************/
6742 WERROR _spoolss_AddJob(struct pipes_struct *p,
6743 struct spoolss_AddJob *r)
6745 if (!r->in.buffer && (r->in.offered != 0)) {
6746 return WERR_INVALID_PARAM;
6749 /* this is what a NT server returns for AddJob. AddJob must fail on
6750 * non-local printers */
6752 if (r->in.level != 1) {
6753 return WERR_UNKNOWN_LEVEL;
6756 return WERR_INVALID_PARAM;
6759 /****************************************************************************
6761 ****************************************************************************/
6763 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6764 struct spoolss_JobInfo1 *r,
6765 const print_queue_struct *queue,
6766 int position, int snum,
6767 struct spoolss_PrinterInfo2 *pinfo2)
6771 t = gmtime(&queue->time);
6773 r->job_id = queue->job;
6775 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6776 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6777 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6778 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6779 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6780 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6781 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6782 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6783 r->data_type = talloc_strdup(mem_ctx, "RAW");
6784 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6785 r->text_status = talloc_strdup(mem_ctx, "");
6786 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6788 r->status = nt_printj_status(queue->status);
6789 r->priority = queue->priority;
6790 r->position = position;
6791 r->total_pages = queue->page_count;
6792 r->pages_printed = 0; /* ??? */
6794 init_systemtime(&r->submitted, t);
6799 /****************************************************************************
6801 ****************************************************************************/
6803 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6804 struct spoolss_JobInfo2 *r,
6805 const print_queue_struct *queue,
6806 int position, int snum,
6807 struct spoolss_PrinterInfo2 *pinfo2,
6808 struct spoolss_DeviceMode *devmode)
6812 t = gmtime(&queue->time);
6814 r->job_id = queue->job;
6816 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6817 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6818 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6819 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6820 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6821 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6822 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6823 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6824 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6825 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6826 r->data_type = talloc_strdup(mem_ctx, "RAW");
6827 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6828 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6829 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6830 r->parameters = talloc_strdup(mem_ctx, "");
6831 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6832 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6833 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6835 r->devmode = devmode;
6837 r->text_status = talloc_strdup(mem_ctx, "");
6838 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6842 r->status = nt_printj_status(queue->status);
6843 r->priority = queue->priority;
6844 r->position = position;
6847 r->total_pages = queue->page_count;
6848 r->size = queue->size;
6849 init_systemtime(&r->submitted, t);
6851 r->pages_printed = 0; /* ??? */
6856 /****************************************************************************
6858 ****************************************************************************/
6860 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6861 struct spoolss_JobInfo3 *r,
6862 const print_queue_struct *queue,
6863 const print_queue_struct *next_queue,
6864 int position, int snum,
6865 struct spoolss_PrinterInfo2 *pinfo2)
6867 r->job_id = queue->job;
6870 r->next_job_id = next_queue->job;
6877 /****************************************************************************
6878 Enumjobs at level 1.
6879 ****************************************************************************/
6881 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6882 const print_queue_struct *queue,
6883 uint32_t num_queues, int snum,
6884 struct spoolss_PrinterInfo2 *pinfo2,
6885 union spoolss_JobInfo **info_p,
6888 union spoolss_JobInfo *info;
6890 WERROR result = WERR_OK;
6892 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6893 W_ERROR_HAVE_NO_MEMORY(info);
6895 *count = num_queues;
6897 for (i=0; i<*count; i++) {
6898 result = fill_job_info1(info,
6904 if (!W_ERROR_IS_OK(result)) {
6910 if (!W_ERROR_IS_OK(result)) {
6921 /****************************************************************************
6922 Enumjobs at level 2.
6923 ****************************************************************************/
6925 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6926 const print_queue_struct *queue,
6927 uint32_t num_queues, int snum,
6928 struct spoolss_PrinterInfo2 *pinfo2,
6929 union spoolss_JobInfo **info_p,
6932 union spoolss_JobInfo *info;
6934 WERROR result = WERR_OK;
6936 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6937 W_ERROR_HAVE_NO_MEMORY(info);
6939 *count = num_queues;
6941 for (i=0; i<*count; i++) {
6942 struct spoolss_DeviceMode *devmode;
6944 result = spoolss_create_default_devmode(info,
6945 pinfo2->printername,
6947 if (!W_ERROR_IS_OK(result)) {
6948 DEBUG(3, ("Can't proceed w/o a devmode!"));
6952 result = fill_job_info2(info,
6959 if (!W_ERROR_IS_OK(result)) {
6965 if (!W_ERROR_IS_OK(result)) {
6976 /****************************************************************************
6977 Enumjobs at level 3.
6978 ****************************************************************************/
6980 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6981 const print_queue_struct *queue,
6982 uint32_t num_queues, int snum,
6983 struct spoolss_PrinterInfo2 *pinfo2,
6984 union spoolss_JobInfo **info_p,
6987 union spoolss_JobInfo *info;
6989 WERROR result = WERR_OK;
6991 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6992 W_ERROR_HAVE_NO_MEMORY(info);
6994 *count = num_queues;
6996 for (i=0; i<*count; i++) {
6997 const print_queue_struct *next_queue = NULL;
7000 next_queue = &queue[i+1];
7003 result = fill_job_info3(info,
7010 if (!W_ERROR_IS_OK(result)) {
7016 if (!W_ERROR_IS_OK(result)) {
7027 /****************************************************************
7029 ****************************************************************/
7031 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7032 struct spoolss_EnumJobs *r)
7035 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7037 print_status_struct prt_status;
7038 print_queue_struct *queue = NULL;
7041 /* that's an [in out] buffer */
7043 if (!r->in.buffer && (r->in.offered != 0)) {
7044 return WERR_INVALID_PARAM;
7047 DEBUG(4,("_spoolss_EnumJobs\n"));
7051 *r->out.info = NULL;
7053 /* lookup the printer snum and tdb entry */
7055 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7059 result = winreg_get_printer(p->mem_ctx,
7060 get_session_info_system(),
7062 lp_const_servicename(snum),
7064 if (!W_ERROR_IS_OK(result)) {
7068 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7069 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7070 count, prt_status.status, prt_status.message));
7074 TALLOC_FREE(pinfo2);
7078 switch (r->in.level) {
7080 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7081 pinfo2, r->out.info, r->out.count);
7084 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7085 pinfo2, r->out.info, r->out.count);
7088 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7089 pinfo2, r->out.info, r->out.count);
7092 result = WERR_UNKNOWN_LEVEL;
7097 TALLOC_FREE(pinfo2);
7099 if (!W_ERROR_IS_OK(result)) {
7103 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7105 *r->out.info, r->in.level,
7107 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7108 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7110 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7113 /****************************************************************
7114 _spoolss_ScheduleJob
7115 ****************************************************************/
7117 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7118 struct spoolss_ScheduleJob *r)
7123 /****************************************************************
7124 ****************************************************************/
7126 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7127 struct messaging_context *msg_ctx,
7128 const char *printer_name,
7130 struct spoolss_SetJobInfo1 *r)
7134 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7138 if (strequal(old_doc_name, r->document_name)) {
7142 if (!print_job_set_name(server_event_context(), msg_ctx,
7143 printer_name, job_id, r->document_name)) {
7150 /****************************************************************
7152 ****************************************************************/
7154 WERROR _spoolss_SetJob(struct pipes_struct *p,
7155 struct spoolss_SetJob *r)
7157 const struct auth_serversupplied_info *session_info = p->session_info;
7159 WERROR errcode = WERR_BADFUNC;
7161 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7165 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7166 return WERR_INVALID_PRINTER_NAME;
7169 switch (r->in.command) {
7170 case SPOOLSS_JOB_CONTROL_CANCEL:
7171 case SPOOLSS_JOB_CONTROL_DELETE:
7172 errcode = print_job_delete(session_info, p->msg_ctx,
7173 snum, r->in.job_id);
7174 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7178 case SPOOLSS_JOB_CONTROL_PAUSE:
7179 if (print_job_pause(session_info, p->msg_ctx,
7180 snum, r->in.job_id, &errcode)) {
7184 case SPOOLSS_JOB_CONTROL_RESTART:
7185 case SPOOLSS_JOB_CONTROL_RESUME:
7186 if (print_job_resume(session_info, p->msg_ctx,
7187 snum, r->in.job_id, &errcode)) {
7195 return WERR_UNKNOWN_LEVEL;
7198 if (!W_ERROR_IS_OK(errcode)) {
7202 if (r->in.ctr == NULL) {
7206 switch (r->in.ctr->level) {
7208 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7209 lp_const_servicename(snum),
7211 r->in.ctr->info.info1);
7217 return WERR_UNKNOWN_LEVEL;
7223 /****************************************************************************
7224 Enumerates all printer drivers by level and architecture.
7225 ****************************************************************************/
7227 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7228 const struct auth_serversupplied_info *session_info,
7229 struct messaging_context *msg_ctx,
7230 const char *servername,
7231 const char *architecture,
7233 union spoolss_DriverInfo **info_p,
7238 struct spoolss_DriverInfo8 *driver;
7239 union spoolss_DriverInfo *info = NULL;
7241 WERROR result = WERR_OK;
7242 uint32_t num_drivers;
7243 const char **drivers;
7248 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7249 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7250 architecture, version,
7251 &num_drivers, &drivers);
7252 if (!W_ERROR_IS_OK(result)) {
7255 DEBUG(4, ("we have:[%d] drivers in environment"
7256 " [%s] and version [%d]\n",
7257 num_drivers, architecture, version));
7259 if (num_drivers != 0) {
7260 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7261 union spoolss_DriverInfo,
7262 count + num_drivers);
7264 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7265 "failed to enlarge driver info buffer!\n"));
7266 result = WERR_NOMEM;
7271 for (i = 0; i < num_drivers; i++) {
7272 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7274 result = winreg_get_driver(mem_ctx, session_info,
7276 architecture, drivers[i],
7278 if (!W_ERROR_IS_OK(result)) {
7284 result = fill_printer_driver_info1(info, &info[count+i].info1,
7285 driver, servername);
7288 result = fill_printer_driver_info2(info, &info[count+i].info2,
7289 driver, servername);
7292 result = fill_printer_driver_info3(info, &info[count+i].info3,
7293 driver, servername);
7296 result = fill_printer_driver_info4(info, &info[count+i].info4,
7297 driver, servername);
7300 result = fill_printer_driver_info5(info, &info[count+i].info5,
7301 driver, servername);
7304 result = fill_printer_driver_info6(info, &info[count+i].info6,
7305 driver, servername);
7308 result = fill_printer_driver_info8(info, &info[count+i].info8,
7309 driver, servername);
7312 result = WERR_UNKNOWN_LEVEL;
7316 TALLOC_FREE(driver);
7318 if (!W_ERROR_IS_OK(result)) {
7323 count += num_drivers;
7324 TALLOC_FREE(drivers);
7328 TALLOC_FREE(drivers);
7330 if (!W_ERROR_IS_OK(result)) {
7341 /****************************************************************************
7342 Enumerates all printer drivers by level.
7343 ****************************************************************************/
7345 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7346 const struct auth_serversupplied_info *session_info,
7347 struct messaging_context *msg_ctx,
7348 const char *servername,
7349 const char *architecture,
7351 union spoolss_DriverInfo **info_p,
7355 WERROR result = WERR_OK;
7357 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7359 for (a=0; archi_table[a].long_archi != NULL; a++) {
7361 union spoolss_DriverInfo *info = NULL;
7364 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7368 archi_table[a].long_archi,
7372 if (!W_ERROR_IS_OK(result)) {
7376 for (i=0; i < count; i++) {
7377 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7378 info[i], info_p, count_p);
7385 return enumprinterdrivers_level_by_architecture(mem_ctx,
7395 /****************************************************************
7396 _spoolss_EnumPrinterDrivers
7397 ****************************************************************/
7399 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7400 struct spoolss_EnumPrinterDrivers *r)
7402 const char *cservername;
7405 /* that's an [in out] buffer */
7407 if (!r->in.buffer && (r->in.offered != 0)) {
7408 return WERR_INVALID_PARAM;
7411 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7415 *r->out.info = NULL;
7417 cservername = canon_servername(r->in.server);
7419 if (!is_myname_or_ipaddr(cservername)) {
7420 return WERR_UNKNOWN_PRINTER_DRIVER;
7423 result = enumprinterdrivers_level(p->mem_ctx,
7424 get_session_info_system(),
7431 if (!W_ERROR_IS_OK(result)) {
7435 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7436 spoolss_EnumPrinterDrivers,
7437 *r->out.info, r->in.level,
7439 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7440 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7442 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7445 /****************************************************************
7447 ****************************************************************/
7449 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7450 struct spoolss_EnumForms *r)
7456 *r->out.info = NULL;
7458 /* that's an [in out] buffer */
7460 if (!r->in.buffer && (r->in.offered != 0) ) {
7461 return WERR_INVALID_PARAM;
7464 DEBUG(4,("_spoolss_EnumForms\n"));
7465 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7466 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7468 switch (r->in.level) {
7470 result = winreg_printer_enumforms1(p->mem_ctx,
7471 get_session_info_system(),
7477 result = WERR_UNKNOWN_LEVEL;
7481 if (!W_ERROR_IS_OK(result)) {
7485 if (*r->out.count == 0) {
7486 return WERR_NO_MORE_ITEMS;
7489 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7491 *r->out.info, r->in.level,
7493 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7494 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7496 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7499 /****************************************************************
7501 ****************************************************************/
7503 WERROR _spoolss_GetForm(struct pipes_struct *p,
7504 struct spoolss_GetForm *r)
7508 /* that's an [in out] buffer */
7510 if (!r->in.buffer && (r->in.offered != 0)) {
7511 return WERR_INVALID_PARAM;
7514 DEBUG(4,("_spoolss_GetForm\n"));
7515 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7516 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7518 switch (r->in.level) {
7520 result = winreg_printer_getform1(p->mem_ctx,
7521 get_session_info_system(),
7524 &r->out.info->info1);
7527 result = WERR_UNKNOWN_LEVEL;
7531 if (!W_ERROR_IS_OK(result)) {
7532 TALLOC_FREE(r->out.info);
7536 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7537 r->out.info, r->in.level);
7538 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7540 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7543 /****************************************************************************
7544 ****************************************************************************/
7546 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7547 struct spoolss_PortInfo1 *r,
7550 r->port_name = talloc_strdup(mem_ctx, name);
7551 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7556 /****************************************************************************
7557 TODO: This probably needs distinguish between TCP/IP and Local ports
7559 ****************************************************************************/
7561 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7562 struct spoolss_PortInfo2 *r,
7565 r->port_name = talloc_strdup(mem_ctx, name);
7566 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7568 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7569 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7571 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7572 W_ERROR_HAVE_NO_MEMORY(r->description);
7574 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7581 /****************************************************************************
7582 wrapper around the enumer ports command
7583 ****************************************************************************/
7585 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7587 char *cmd = lp_enumports_cmd();
7588 char **qlines = NULL;
7589 char *command = NULL;
7597 /* if no hook then just fill in the default port */
7600 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7603 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7604 TALLOC_FREE(qlines);
7611 /* we have a valid enumport command */
7613 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7618 DEBUG(10,("Running [%s]\n", command));
7619 ret = smbrun(command, &fd);
7620 DEBUG(10,("Returned [%d]\n", ret));
7621 TALLOC_FREE(command);
7626 return WERR_ACCESS_DENIED;
7630 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7631 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7641 /****************************************************************************
7643 ****************************************************************************/
7645 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7646 union spoolss_PortInfo **info_p,
7649 union spoolss_PortInfo *info = NULL;
7651 WERROR result = WERR_OK;
7652 char **qlines = NULL;
7655 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7656 if (!W_ERROR_IS_OK(result)) {
7661 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7663 DEBUG(10,("Returning WERR_NOMEM\n"));
7664 result = WERR_NOMEM;
7668 for (i=0; i<numlines; i++) {
7669 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7670 result = fill_port_1(info, &info[i].info1, qlines[i]);
7671 if (!W_ERROR_IS_OK(result)) {
7676 TALLOC_FREE(qlines);
7679 if (!W_ERROR_IS_OK(result)) {
7681 TALLOC_FREE(qlines);
7693 /****************************************************************************
7695 ****************************************************************************/
7697 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7698 union spoolss_PortInfo **info_p,
7701 union spoolss_PortInfo *info = NULL;
7703 WERROR result = WERR_OK;
7704 char **qlines = NULL;
7707 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7708 if (!W_ERROR_IS_OK(result)) {
7713 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7715 DEBUG(10,("Returning WERR_NOMEM\n"));
7716 result = WERR_NOMEM;
7720 for (i=0; i<numlines; i++) {
7721 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7722 result = fill_port_2(info, &info[i].info2, qlines[i]);
7723 if (!W_ERROR_IS_OK(result)) {
7728 TALLOC_FREE(qlines);
7731 if (!W_ERROR_IS_OK(result)) {
7733 TALLOC_FREE(qlines);
7745 /****************************************************************
7747 ****************************************************************/
7749 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7750 struct spoolss_EnumPorts *r)
7754 /* that's an [in out] buffer */
7756 if (!r->in.buffer && (r->in.offered != 0)) {
7757 return WERR_INVALID_PARAM;
7760 DEBUG(4,("_spoolss_EnumPorts\n"));
7764 *r->out.info = NULL;
7766 switch (r->in.level) {
7768 result = enumports_level_1(p->mem_ctx, r->out.info,
7772 result = enumports_level_2(p->mem_ctx, r->out.info,
7776 return WERR_UNKNOWN_LEVEL;
7779 if (!W_ERROR_IS_OK(result)) {
7783 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7785 *r->out.info, r->in.level,
7787 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7788 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7790 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7793 /****************************************************************************
7794 ****************************************************************************/
7796 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7798 struct spoolss_SetPrinterInfoCtr *info_ctr,
7799 struct spoolss_DeviceMode *devmode,
7800 struct security_descriptor *secdesc,
7801 struct spoolss_UserLevelCtr *user_ctr,
7802 struct policy_handle *handle)
7804 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7805 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7807 WERROR err = WERR_OK;
7809 /* samba does not have a concept of local, non-shared printers yet, so
7810 * make sure we always setup sharename - gd */
7811 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7812 (info2->printername != NULL && info2->printername[0] != '\0')) {
7813 DEBUG(5, ("spoolss_addprinterex_level_2: "
7814 "no sharename has been set, setting printername %s as sharename\n",
7815 info2->printername));
7816 info2->sharename = info2->printername;
7819 /* check to see if the printer already exists */
7820 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7821 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7823 return WERR_PRINTER_ALREADY_EXISTS;
7826 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7827 if ((snum = print_queue_snum(info2->printername)) != -1) {
7828 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7829 info2->printername));
7830 return WERR_PRINTER_ALREADY_EXISTS;
7834 /* validate printer info struct */
7835 if (!info2->printername || strlen(info2->printername) == 0) {
7836 return WERR_INVALID_PRINTER_NAME;
7838 if (!info2->portname || strlen(info2->portname) == 0) {
7839 return WERR_UNKNOWN_PORT;
7841 if (!info2->drivername || strlen(info2->drivername) == 0) {
7842 return WERR_UNKNOWN_PRINTER_DRIVER;
7844 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7845 return WERR_UNKNOWN_PRINTPROCESSOR;
7848 /* FIXME!!! smbd should check to see if the driver is installed before
7849 trying to add a printer like this --jerry */
7851 if (*lp_addprinter_cmd() ) {
7852 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7853 info2, p->client_id->addr,
7855 return WERR_ACCESS_DENIED;
7858 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7859 "smb.conf parameter \"addprinter command\" is defined. This"
7860 "parameter must exist for this call to succeed\n",
7861 info2->sharename ));
7864 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7865 return WERR_ACCESS_DENIED;
7868 /* you must be a printer admin to add a new printer */
7869 if (!print_access_check(p->session_info,
7872 PRINTER_ACCESS_ADMINISTER)) {
7873 return WERR_ACCESS_DENIED;
7877 * Do sanity check on the requested changes for Samba.
7880 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7881 return WERR_INVALID_PARAM;
7884 if (devmode == NULL) {
7885 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7888 update_dsspooler(p->mem_ctx,
7889 get_session_info_system(),
7895 err = winreg_update_printer(p->mem_ctx,
7896 get_session_info_system(),
7903 if (!W_ERROR_IS_OK(err)) {
7907 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7908 if (!W_ERROR_IS_OK(err)) {
7909 /* Handle open failed - remove addition. */
7910 ZERO_STRUCTP(handle);
7917 /****************************************************************
7918 _spoolss_AddPrinterEx
7919 ****************************************************************/
7921 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7922 struct spoolss_AddPrinterEx *r)
7924 switch (r->in.info_ctr->level) {
7926 /* we don't handle yet */
7927 /* but I know what to do ... */
7928 return WERR_UNKNOWN_LEVEL;
7930 return spoolss_addprinterex_level_2(p, r->in.server,
7932 r->in.devmode_ctr->devmode,
7933 r->in.secdesc_ctr->sd,
7934 r->in.userlevel_ctr,
7937 return WERR_UNKNOWN_LEVEL;
7941 /****************************************************************
7943 ****************************************************************/
7945 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7946 struct spoolss_AddPrinter *r)
7948 struct spoolss_AddPrinterEx a;
7949 struct spoolss_UserLevelCtr userlevel_ctr;
7951 ZERO_STRUCT(userlevel_ctr);
7953 userlevel_ctr.level = 1;
7955 a.in.server = r->in.server;
7956 a.in.info_ctr = r->in.info_ctr;
7957 a.in.devmode_ctr = r->in.devmode_ctr;
7958 a.in.secdesc_ctr = r->in.secdesc_ctr;
7959 a.in.userlevel_ctr = &userlevel_ctr;
7960 a.out.handle = r->out.handle;
7962 return _spoolss_AddPrinterEx(p, &a);
7965 /****************************************************************
7966 _spoolss_AddPrinterDriverEx
7967 ****************************************************************/
7969 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7970 struct spoolss_AddPrinterDriverEx *r)
7972 WERROR err = WERR_OK;
7973 const char *driver_name = NULL;
7978 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7979 fn = "_spoolss_AddPrinterDriver";
7981 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7982 fn = "_spoolss_AddPrinterDriverEx";
7985 return WERR_INVALID_PARAM;
7989 * we only support the semantics of AddPrinterDriver()
7990 * i.e. only copy files that are newer than existing ones
7993 if (r->in.flags == 0) {
7994 return WERR_INVALID_PARAM;
7997 if (r->in.flags != APD_COPY_NEW_FILES) {
7998 return WERR_ACCESS_DENIED;
8002 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8003 /* Clever hack from Martin Zielinski <mz@seh.de>
8004 * to allow downgrade from level 8 (Vista).
8006 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8007 r->in.info_ctr->level));
8008 return WERR_UNKNOWN_LEVEL;
8011 DEBUG(5,("Cleaning driver's information\n"));
8012 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8013 if (!W_ERROR_IS_OK(err))
8016 DEBUG(5,("Moving driver to final destination\n"));
8017 err = move_driver_to_download_area(p, r->in.info_ctr);
8018 if (!W_ERROR_IS_OK(err)) {
8022 err = winreg_add_driver(p->mem_ctx,
8023 get_session_info_system(),
8028 if (!W_ERROR_IS_OK(err)) {
8033 * I think this is where he DrvUpgradePrinter() hook would be
8034 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8035 * server. Right now, we just need to send ourselves a message
8036 * to update each printer bound to this driver. --jerry
8039 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8040 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8048 /****************************************************************
8049 _spoolss_AddPrinterDriver
8050 ****************************************************************/
8052 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8053 struct spoolss_AddPrinterDriver *r)
8055 struct spoolss_AddPrinterDriverEx a;
8057 switch (r->in.info_ctr->level) {
8064 return WERR_UNKNOWN_LEVEL;
8067 a.in.servername = r->in.servername;
8068 a.in.info_ctr = r->in.info_ctr;
8069 a.in.flags = APD_COPY_NEW_FILES;
8071 return _spoolss_AddPrinterDriverEx(p, &a);
8074 /****************************************************************************
8075 ****************************************************************************/
8077 struct _spoolss_paths {
8083 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8085 static const struct _spoolss_paths spoolss_paths[]= {
8086 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8087 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8090 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8091 const char *servername,
8092 const char *environment,
8096 const char *pservername = NULL;
8097 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8098 const char *short_archi;
8102 /* environment may be empty */
8103 if (environment && strlen(environment)) {
8104 long_archi = environment;
8107 /* servername may be empty */
8108 if (servername && strlen(servername)) {
8109 pservername = canon_servername(servername);
8111 if (!is_myname_or_ipaddr(pservername)) {
8112 return WERR_INVALID_PARAM;
8116 if (!(short_archi = get_short_archi(long_archi))) {
8117 return WERR_INVALID_ENVIRONMENT;
8120 switch (component) {
8121 case SPOOLSS_PRTPROCS_PATH:
8122 case SPOOLSS_DRIVER_PATH:
8124 *path = talloc_asprintf(mem_ctx,
8127 spoolss_paths[component].share,
8130 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8131 SPOOLSS_DEFAULT_SERVER_PATH,
8132 spoolss_paths[component].dir,
8137 return WERR_INVALID_PARAM;
8147 /****************************************************************************
8148 ****************************************************************************/
8150 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8151 const char *servername,
8152 const char *environment,
8153 struct spoolss_DriverDirectoryInfo1 *r)
8158 werr = compose_spoolss_server_path(mem_ctx,
8161 SPOOLSS_DRIVER_PATH,
8163 if (!W_ERROR_IS_OK(werr)) {
8167 DEBUG(4,("printer driver directory: [%s]\n", path));
8169 r->directory_name = path;
8174 /****************************************************************
8175 _spoolss_GetPrinterDriverDirectory
8176 ****************************************************************/
8178 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8179 struct spoolss_GetPrinterDriverDirectory *r)
8183 /* that's an [in out] buffer */
8185 if (!r->in.buffer && (r->in.offered != 0)) {
8186 return WERR_INVALID_PARAM;
8189 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8194 /* r->in.level is ignored */
8196 werror = getprinterdriverdir_level_1(p->mem_ctx,
8199 &r->out.info->info1);
8200 if (!W_ERROR_IS_OK(werror)) {
8201 TALLOC_FREE(r->out.info);
8205 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8206 r->out.info, r->in.level);
8207 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8209 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8212 /****************************************************************
8213 _spoolss_EnumPrinterData
8214 ****************************************************************/
8216 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8217 struct spoolss_EnumPrinterData *r)
8220 struct spoolss_EnumPrinterDataEx r2;
8222 struct spoolss_PrinterEnumValues *info, *val = NULL;
8225 r2.in.handle = r->in.handle;
8226 r2.in.key_name = "PrinterDriverData";
8228 r2.out.count = &count;
8229 r2.out.info = &info;
8230 r2.out.needed = &needed;
8232 result = _spoolss_EnumPrinterDataEx(p, &r2);
8233 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8234 r2.in.offered = needed;
8235 result = _spoolss_EnumPrinterDataEx(p, &r2);
8237 if (!W_ERROR_IS_OK(result)) {
8242 * The NT machine wants to know the biggest size of value and data
8244 * cf: MSDN EnumPrinterData remark section
8247 if (!r->in.value_offered && !r->in.data_offered) {
8248 uint32_t biggest_valuesize = 0;
8249 uint32_t biggest_datasize = 0;
8252 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8254 for (i=0; i<count; i++) {
8256 name_length = strlen(info[i].value_name);
8257 if (strlen(info[i].value_name) > biggest_valuesize) {
8258 biggest_valuesize = name_length;
8261 if (info[i].data_length > biggest_datasize) {
8262 biggest_datasize = info[i].data_length;
8265 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8269 /* the value is an UNICODE string but real_value_size is the length
8270 in bytes including the trailing 0 */
8272 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8273 *r->out.data_needed = biggest_datasize;
8275 DEBUG(6,("final values: [%d], [%d]\n",
8276 *r->out.value_needed, *r->out.data_needed));
8281 if (r->in.enum_index < count) {
8282 val = &info[r->in.enum_index];
8286 /* out_value should default to "" or else NT4 has
8287 problems unmarshalling the response */
8289 if (r->in.value_offered) {
8290 *r->out.value_needed = 1;
8291 r->out.value_name = talloc_strdup(r, "");
8292 if (!r->out.value_name) {
8296 r->out.value_name = NULL;
8297 *r->out.value_needed = 0;
8300 /* the data is counted in bytes */
8302 *r->out.data_needed = r->in.data_offered;
8304 result = WERR_NO_MORE_ITEMS;
8308 * - counted in bytes in the request
8309 * - counted in UNICODE chars in the max reply
8310 * - counted in bytes in the real size
8312 * take a pause *before* coding not *during* coding
8316 if (r->in.value_offered) {
8317 r->out.value_name = talloc_strdup(r, val->value_name);
8318 if (!r->out.value_name) {
8321 *r->out.value_needed = val->value_name_len;
8323 r->out.value_name = NULL;
8324 *r->out.value_needed = 0;
8329 *r->out.type = val->type;
8331 /* data - counted in bytes */
8334 * See the section "Dynamically Typed Query Parameters"
8338 if (r->out.data && val->data && val->data->data &&
8339 val->data_length && r->in.data_offered) {
8340 memcpy(r->out.data, val->data->data,
8341 MIN(val->data_length,r->in.data_offered));
8344 *r->out.data_needed = val->data_length;
8352 /****************************************************************
8353 _spoolss_SetPrinterData
8354 ****************************************************************/
8356 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8357 struct spoolss_SetPrinterData *r)
8359 struct spoolss_SetPrinterDataEx r2;
8361 r2.in.handle = r->in.handle;
8362 r2.in.key_name = "PrinterDriverData";
8363 r2.in.value_name = r->in.value_name;
8364 r2.in.type = r->in.type;
8365 r2.in.data = r->in.data;
8366 r2.in.offered = r->in.offered;
8368 return _spoolss_SetPrinterDataEx(p, &r2);
8371 /****************************************************************
8372 _spoolss_ResetPrinter
8373 ****************************************************************/
8375 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8376 struct spoolss_ResetPrinter *r)
8378 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8381 DEBUG(5,("_spoolss_ResetPrinter\n"));
8384 * All we do is to check to see if the handle and queue is valid.
8385 * This call really doesn't mean anything to us because we only
8386 * support RAW printing. --jerry
8390 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8391 OUR_HANDLE(r->in.handle)));
8395 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8399 /* blindly return success */
8403 /****************************************************************
8404 _spoolss_DeletePrinterData
8405 ****************************************************************/
8407 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8408 struct spoolss_DeletePrinterData *r)
8410 struct spoolss_DeletePrinterDataEx r2;
8412 r2.in.handle = r->in.handle;
8413 r2.in.key_name = "PrinterDriverData";
8414 r2.in.value_name = r->in.value_name;
8416 return _spoolss_DeletePrinterDataEx(p, &r2);
8419 /****************************************************************
8421 ****************************************************************/
8423 WERROR _spoolss_AddForm(struct pipes_struct *p,
8424 struct spoolss_AddForm *r)
8426 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8428 WERROR status = WERR_OK;
8430 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8432 DEBUG(5,("_spoolss_AddForm\n"));
8435 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8436 OUR_HANDLE(r->in.handle)));
8440 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8441 and not a printer admin, then fail */
8443 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8444 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8445 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8446 p->session_info->info3->base.domain.string,
8448 p->session_info->security_token,
8449 lp_printer_admin(snum))) {
8450 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8451 return WERR_ACCESS_DENIED;
8454 switch (form->flags) {
8455 case SPOOLSS_FORM_USER:
8456 case SPOOLSS_FORM_BUILTIN:
8457 case SPOOLSS_FORM_PRINTER:
8460 return WERR_INVALID_PARAM;
8463 status = winreg_printer_addform1(p->mem_ctx,
8464 get_session_info_system(),
8467 if (!W_ERROR_IS_OK(status)) {
8472 * ChangeID must always be set if this is a printer
8474 if (Printer->printer_type == SPLHND_PRINTER) {
8475 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8479 status = winreg_printer_update_changeid(p->mem_ctx,
8480 get_session_info_system(),
8482 lp_const_servicename(snum));
8483 if (!W_ERROR_IS_OK(status)) {
8491 /****************************************************************
8493 ****************************************************************/
8495 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8496 struct spoolss_DeleteForm *r)
8498 const char *form_name = r->in.form_name;
8499 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8501 WERROR status = WERR_OK;
8503 DEBUG(5,("_spoolss_DeleteForm\n"));
8506 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8507 OUR_HANDLE(r->in.handle)));
8511 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8512 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8513 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8514 p->session_info->info3->base.domain.string,
8516 p->session_info->security_token,
8517 lp_printer_admin(snum))) {
8518 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8519 return WERR_ACCESS_DENIED;
8522 status = winreg_printer_deleteform1(p->mem_ctx,
8523 get_session_info_system(),
8526 if (!W_ERROR_IS_OK(status)) {
8531 * ChangeID must always be set if this is a printer
8533 if (Printer->printer_type == SPLHND_PRINTER) {
8534 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8538 status = winreg_printer_update_changeid(p->mem_ctx,
8539 get_session_info_system(),
8541 lp_const_servicename(snum));
8542 if (!W_ERROR_IS_OK(status)) {
8550 /****************************************************************
8552 ****************************************************************/
8554 WERROR _spoolss_SetForm(struct pipes_struct *p,
8555 struct spoolss_SetForm *r)
8557 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8558 const char *form_name = r->in.form_name;
8560 WERROR status = WERR_OK;
8562 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8564 DEBUG(5,("_spoolss_SetForm\n"));
8567 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8568 OUR_HANDLE(r->in.handle)));
8572 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8573 and not a printer admin, then fail */
8575 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8576 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8577 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8578 p->session_info->info3->base.domain.string,
8580 p->session_info->security_token,
8581 lp_printer_admin(snum))) {
8582 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8583 return WERR_ACCESS_DENIED;
8586 status = winreg_printer_setform1(p->mem_ctx,
8587 get_session_info_system(),
8591 if (!W_ERROR_IS_OK(status)) {
8596 * ChangeID must always be set if this is a printer
8598 if (Printer->printer_type == SPLHND_PRINTER) {
8599 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8603 status = winreg_printer_update_changeid(p->mem_ctx,
8604 get_session_info_system(),
8606 lp_const_servicename(snum));
8607 if (!W_ERROR_IS_OK(status)) {
8615 /****************************************************************************
8616 fill_print_processor1
8617 ****************************************************************************/
8619 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8620 struct spoolss_PrintProcessorInfo1 *r,
8621 const char *print_processor_name)
8623 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8624 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8629 /****************************************************************************
8630 enumprintprocessors level 1.
8631 ****************************************************************************/
8633 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8634 union spoolss_PrintProcessorInfo **info_p,
8637 union spoolss_PrintProcessorInfo *info;
8640 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8641 W_ERROR_HAVE_NO_MEMORY(info);
8645 result = fill_print_processor1(info, &info[0].info1, "winprint");
8646 if (!W_ERROR_IS_OK(result)) {
8651 if (!W_ERROR_IS_OK(result)) {
8662 /****************************************************************
8663 _spoolss_EnumPrintProcessors
8664 ****************************************************************/
8666 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8667 struct spoolss_EnumPrintProcessors *r)
8671 /* that's an [in out] buffer */
8673 if (!r->in.buffer && (r->in.offered != 0)) {
8674 return WERR_INVALID_PARAM;
8677 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8680 * Enumerate the print processors ...
8682 * Just reply with "winprint", to keep NT happy
8683 * and I can use my nice printer checker.
8688 *r->out.info = NULL;
8690 if (!get_short_archi(r->in.environment)) {
8691 return WERR_INVALID_ENVIRONMENT;
8694 switch (r->in.level) {
8696 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8700 return WERR_UNKNOWN_LEVEL;
8703 if (!W_ERROR_IS_OK(result)) {
8707 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8708 spoolss_EnumPrintProcessors,
8709 *r->out.info, r->in.level,
8711 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8712 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8714 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8717 /****************************************************************************
8718 fill_printprocdatatype1
8719 ****************************************************************************/
8721 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8722 struct spoolss_PrintProcDataTypesInfo1 *r,
8723 const char *name_array)
8725 r->name_array = talloc_strdup(mem_ctx, name_array);
8726 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8731 /****************************************************************************
8732 enumprintprocdatatypes level 1.
8733 ****************************************************************************/
8735 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8736 union spoolss_PrintProcDataTypesInfo **info_p,
8740 union spoolss_PrintProcDataTypesInfo *info;
8742 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8743 W_ERROR_HAVE_NO_MEMORY(info);
8747 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8748 if (!W_ERROR_IS_OK(result)) {
8753 if (!W_ERROR_IS_OK(result)) {
8764 /****************************************************************
8765 _spoolss_EnumPrintProcDataTypes
8766 ****************************************************************/
8768 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8769 struct spoolss_EnumPrintProcDataTypes *r)
8773 /* that's an [in out] buffer */
8775 if (!r->in.buffer && (r->in.offered != 0)) {
8776 return WERR_INVALID_PARAM;
8779 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8783 *r->out.info = NULL;
8785 if (r->in.print_processor_name == NULL ||
8786 !strequal(r->in.print_processor_name, "winprint")) {
8787 return WERR_UNKNOWN_PRINTPROCESSOR;
8790 switch (r->in.level) {
8792 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8796 return WERR_UNKNOWN_LEVEL;
8799 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8800 spoolss_EnumPrintProcDataTypes,
8801 *r->out.info, r->in.level,
8803 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8804 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8806 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8809 /****************************************************************************
8811 ****************************************************************************/
8813 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8814 struct spoolss_MonitorInfo1 *r,
8815 const char *monitor_name)
8817 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8818 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8823 /****************************************************************************
8825 ****************************************************************************/
8827 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8828 struct spoolss_MonitorInfo2 *r,
8829 const char *monitor_name,
8830 const char *environment,
8831 const char *dll_name)
8833 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8834 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8835 r->environment = talloc_strdup(mem_ctx, environment);
8836 W_ERROR_HAVE_NO_MEMORY(r->environment);
8837 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8838 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8843 /****************************************************************************
8844 enumprintmonitors level 1.
8845 ****************************************************************************/
8847 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8848 union spoolss_MonitorInfo **info_p,
8851 union spoolss_MonitorInfo *info;
8852 WERROR result = WERR_OK;
8854 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8855 W_ERROR_HAVE_NO_MEMORY(info);
8859 result = fill_monitor_1(info, &info[0].info1,
8861 if (!W_ERROR_IS_OK(result)) {
8865 result = fill_monitor_1(info, &info[1].info1,
8867 if (!W_ERROR_IS_OK(result)) {
8872 if (!W_ERROR_IS_OK(result)) {
8883 /****************************************************************************
8884 enumprintmonitors level 2.
8885 ****************************************************************************/
8887 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8888 union spoolss_MonitorInfo **info_p,
8891 union spoolss_MonitorInfo *info;
8892 WERROR result = WERR_OK;
8894 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8895 W_ERROR_HAVE_NO_MEMORY(info);
8899 result = fill_monitor_2(info, &info[0].info2,
8901 "Windows NT X86", /* FIXME */
8903 if (!W_ERROR_IS_OK(result)) {
8907 result = fill_monitor_2(info, &info[1].info2,
8909 "Windows NT X86", /* FIXME */
8911 if (!W_ERROR_IS_OK(result)) {
8916 if (!W_ERROR_IS_OK(result)) {
8927 /****************************************************************
8928 _spoolss_EnumMonitors
8929 ****************************************************************/
8931 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8932 struct spoolss_EnumMonitors *r)
8936 /* that's an [in out] buffer */
8938 if (!r->in.buffer && (r->in.offered != 0)) {
8939 return WERR_INVALID_PARAM;
8942 DEBUG(5,("_spoolss_EnumMonitors\n"));
8945 * Enumerate the print monitors ...
8947 * Just reply with "Local Port", to keep NT happy
8948 * and I can use my nice printer checker.
8953 *r->out.info = NULL;
8955 switch (r->in.level) {
8957 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8961 result = enumprintmonitors_level_2(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_EnumMonitors,
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 /****************************************************************************
8983 ****************************************************************************/
8985 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8986 const print_queue_struct *queue,
8987 int count, int snum,
8988 struct spoolss_PrinterInfo2 *pinfo2,
8990 struct spoolss_JobInfo1 *r)
8995 for (i=0; i<count; i++) {
8996 if (queue[i].job == (int)jobid) {
9002 if (found == false) {
9003 /* NT treats not found as bad param... yet another bad choice */
9004 return WERR_INVALID_PARAM;
9007 return fill_job_info1(mem_ctx,
9015 /****************************************************************************
9016 ****************************************************************************/
9018 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9019 const print_queue_struct *queue,
9020 int count, int snum,
9021 struct spoolss_PrinterInfo2 *pinfo2,
9023 struct spoolss_JobInfo2 *r)
9027 struct spoolss_DeviceMode *devmode;
9030 for (i=0; i<count; i++) {
9031 if (queue[i].job == (int)jobid) {
9037 if (found == false) {
9038 /* NT treats not found as bad param... yet another bad
9040 return WERR_INVALID_PARAM;
9044 * if the print job does not have a DEVMODE associated with it,
9045 * just use the one for the printer. A NULL devicemode is not
9046 * a failure condition
9049 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9051 result = spoolss_create_default_devmode(mem_ctx,
9052 pinfo2->printername,
9054 if (!W_ERROR_IS_OK(result)) {
9055 DEBUG(3, ("Can't proceed w/o a devmode!"));
9060 return fill_job_info2(mem_ctx,
9069 /****************************************************************
9071 ****************************************************************/
9073 WERROR _spoolss_GetJob(struct pipes_struct *p,
9074 struct spoolss_GetJob *r)
9076 WERROR result = WERR_OK;
9077 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9080 print_queue_struct *queue = NULL;
9081 print_status_struct prt_status;
9083 /* that's an [in out] buffer */
9085 if (!r->in.buffer && (r->in.offered != 0)) {
9086 return WERR_INVALID_PARAM;
9089 DEBUG(5,("_spoolss_GetJob\n"));
9093 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9097 result = winreg_get_printer(p->mem_ctx,
9098 get_session_info_system(),
9100 lp_const_servicename(snum),
9102 if (!W_ERROR_IS_OK(result)) {
9106 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9108 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9109 count, prt_status.status, prt_status.message));
9111 switch (r->in.level) {
9113 result = getjob_level_1(p->mem_ctx,
9114 queue, count, snum, pinfo2,
9115 r->in.job_id, &r->out.info->info1);
9118 result = getjob_level_2(p->mem_ctx,
9119 queue, count, snum, pinfo2,
9120 r->in.job_id, &r->out.info->info2);
9123 result = WERR_UNKNOWN_LEVEL;
9128 TALLOC_FREE(pinfo2);
9130 if (!W_ERROR_IS_OK(result)) {
9131 TALLOC_FREE(r->out.info);
9135 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9137 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9139 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9142 /****************************************************************
9143 _spoolss_GetPrinterDataEx
9144 ****************************************************************/
9146 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9147 struct spoolss_GetPrinterDataEx *r)
9150 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9151 const char *printer;
9153 WERROR result = WERR_OK;
9155 enum winreg_Type val_type;
9160 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9162 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9163 r->in.key_name, r->in.value_name));
9165 /* in case of problem, return some default values */
9168 *r->out.type = REG_NONE;
9171 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9172 OUR_HANDLE(r->in.handle)));
9173 result = WERR_BADFID;
9177 /* Is the handle to a printer or to the server? */
9179 if (Printer->printer_type == SPLHND_SERVER) {
9181 union spoolss_PrinterData data;
9183 result = getprinterdata_printer_server(p->mem_ctx,
9187 if (!W_ERROR_IS_OK(result)) {
9191 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9192 *r->out.type, &data);
9193 if (!W_ERROR_IS_OK(result)) {
9197 *r->out.needed = blob.length;
9199 if (r->in.offered >= *r->out.needed) {
9200 memcpy(r->out.data, blob.data, blob.length);
9203 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9206 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9209 printer = lp_const_servicename(snum);
9211 /* check to see if the keyname is valid */
9212 if (!strlen(r->in.key_name)) {
9213 return WERR_INVALID_PARAM;
9216 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9217 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9218 strequal(r->in.value_name, "ChangeId")) {
9219 *r->out.type = REG_DWORD;
9221 if (r->in.offered >= *r->out.needed) {
9222 uint32_t changeid = 0;
9224 result = winreg_printer_get_changeid(p->mem_ctx,
9225 get_session_info_system(),
9229 if (!W_ERROR_IS_OK(result)) {
9233 SIVAL(r->out.data, 0, changeid);
9239 result = winreg_get_printer_dataex(p->mem_ctx,
9240 get_session_info_system(),
9248 if (!W_ERROR_IS_OK(result)) {
9252 *r->out.needed = val_size;
9253 *r->out.type = val_type;
9255 if (r->in.offered >= *r->out.needed) {
9256 memcpy(r->out.data, val_data, val_size);
9260 /* retain type when returning WERR_MORE_DATA */
9261 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9263 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9266 /****************************************************************
9267 _spoolss_SetPrinterDataEx
9268 ****************************************************************/
9270 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9271 struct spoolss_SetPrinterDataEx *r)
9273 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9275 WERROR result = WERR_OK;
9276 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9279 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9281 /* From MSDN documentation of SetPrinterDataEx: pass request to
9282 SetPrinterData if key is "PrinterDriverData" */
9285 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9286 OUR_HANDLE(r->in.handle)));
9290 if (Printer->printer_type == SPLHND_SERVER) {
9291 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9292 "Not implemented for server handles yet\n"));
9293 return WERR_INVALID_PARAM;
9296 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9301 * Access check : NT returns "access denied" if you make a
9302 * SetPrinterData call without the necessary privildge.
9303 * we were originally returning OK if nothing changed
9304 * which made Win2k issue **a lot** of SetPrinterData
9305 * when connecting to a printer --jerry
9308 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9309 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9310 "change denied by handle access permissions\n"));
9311 return WERR_ACCESS_DENIED;
9314 result = winreg_get_printer(Printer,
9315 get_session_info_system(),
9317 lp_servicename(snum),
9319 if (!W_ERROR_IS_OK(result)) {
9323 /* check for OID in valuename */
9325 oid_string = strchr(r->in.value_name, ',');
9331 /* save the registry data */
9333 result = winreg_set_printer_dataex(p->mem_ctx,
9334 get_session_info_system(),
9343 if (W_ERROR_IS_OK(result)) {
9344 /* save the OID if one was specified */
9346 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9347 r->in.key_name, SPOOL_OID_KEY);
9349 result = WERR_NOMEM;
9354 * I'm not checking the status here on purpose. Don't know
9355 * if this is right, but I'm returning the status from the
9356 * previous set_printer_dataex() call. I have no idea if
9357 * this is right. --jerry
9359 winreg_set_printer_dataex(p->mem_ctx,
9360 get_session_info_system(),
9366 (uint8_t *) oid_string,
9367 strlen(oid_string) + 1);
9370 result = winreg_printer_update_changeid(p->mem_ctx,
9371 get_session_info_system(),
9373 lp_const_servicename(snum));
9378 talloc_free(pinfo2);
9382 /****************************************************************
9383 _spoolss_DeletePrinterDataEx
9384 ****************************************************************/
9386 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9387 struct spoolss_DeletePrinterDataEx *r)
9389 const char *printer;
9391 WERROR status = WERR_OK;
9392 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9394 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9397 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9398 "Invalid handle (%s:%u:%u).\n",
9399 OUR_HANDLE(r->in.handle)));
9403 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9404 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9405 "printer properties change denied by handle\n"));
9406 return WERR_ACCESS_DENIED;
9409 if (!r->in.value_name || !r->in.key_name) {
9413 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9416 printer = lp_const_servicename(snum);
9418 status = winreg_delete_printer_dataex(p->mem_ctx,
9419 get_session_info_system(),
9424 if (W_ERROR_IS_OK(status)) {
9425 status = winreg_printer_update_changeid(p->mem_ctx,
9426 get_session_info_system(),
9434 /****************************************************************
9435 _spoolss_EnumPrinterKey
9436 ****************************************************************/
9438 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9439 struct spoolss_EnumPrinterKey *r)
9442 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9444 WERROR result = WERR_BADFILE;
9445 const char **array = NULL;
9448 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9451 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9452 OUR_HANDLE(r->in.handle)));
9456 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9460 result = winreg_enum_printer_key(p->mem_ctx,
9461 get_session_info_system(),
9463 lp_const_servicename(snum),
9467 if (!W_ERROR_IS_OK(result)) {
9471 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9472 result = WERR_NOMEM;
9476 *r->out._ndr_size = r->in.offered / 2;
9477 *r->out.needed = blob.length;
9479 if (r->in.offered < *r->out.needed) {
9480 result = WERR_MORE_DATA;
9483 r->out.key_buffer->string_array = array;
9487 if (!W_ERROR_IS_OK(result)) {
9489 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9497 /****************************************************************
9498 _spoolss_DeletePrinterKey
9499 ****************************************************************/
9501 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9502 struct spoolss_DeletePrinterKey *r)
9504 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9507 const char *printer;
9509 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9512 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9513 OUR_HANDLE(r->in.handle)));
9517 /* if keyname == NULL, return error */
9518 if ( !r->in.key_name )
9519 return WERR_INVALID_PARAM;
9521 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9525 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9526 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9527 "printer properties change denied by handle\n"));
9528 return WERR_ACCESS_DENIED;
9531 printer = lp_const_servicename(snum);
9533 /* delete the key and all subkeys */
9534 status = winreg_delete_printer_key(p->mem_ctx,
9535 get_session_info_system(),
9539 if (W_ERROR_IS_OK(status)) {
9540 status = winreg_printer_update_changeid(p->mem_ctx,
9541 get_session_info_system(),
9549 /****************************************************************
9550 _spoolss_EnumPrinterDataEx
9551 ****************************************************************/
9553 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9554 struct spoolss_EnumPrinterDataEx *r)
9557 struct spoolss_PrinterEnumValues *info = NULL;
9558 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9562 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9566 *r->out.info = NULL;
9569 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9570 OUR_HANDLE(r->in.handle)));
9575 * first check for a keyname of NULL or "". Win2k seems to send
9576 * this a lot and we should send back WERR_INVALID_PARAM
9577 * no need to spend time looking up the printer in this case.
9581 if (!strlen(r->in.key_name)) {
9582 result = WERR_INVALID_PARAM;
9586 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9590 /* now look for a match on the key name */
9591 result = winreg_enum_printer_dataex(p->mem_ctx,
9592 get_session_info_system(),
9594 lp_const_servicename(snum),
9598 if (!W_ERROR_IS_OK(result)) {
9602 #if 0 /* FIXME - gd */
9603 /* housekeeping information in the reply */
9605 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9606 * the hand marshalled container size is a multiple
9607 * of 4 bytes for RPC alignment.
9611 needed += 4-(needed % 4);
9614 *r->out.count = count;
9615 *r->out.info = info;
9618 if (!W_ERROR_IS_OK(result)) {
9622 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9623 spoolss_EnumPrinterDataEx,
9626 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9627 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9629 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9632 /****************************************************************************
9633 ****************************************************************************/
9635 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9636 const char *servername,
9637 const char *environment,
9638 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9643 werr = compose_spoolss_server_path(mem_ctx,
9646 SPOOLSS_PRTPROCS_PATH,
9648 if (!W_ERROR_IS_OK(werr)) {
9652 DEBUG(4,("print processor directory: [%s]\n", path));
9654 r->directory_name = path;
9659 /****************************************************************
9660 _spoolss_GetPrintProcessorDirectory
9661 ****************************************************************/
9663 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9664 struct spoolss_GetPrintProcessorDirectory *r)
9667 char *prnproc_share = NULL;
9668 bool prnproc_share_exists = false;
9671 /* that's an [in out] buffer */
9673 if (!r->in.buffer && (r->in.offered != 0)) {
9674 return WERR_INVALID_PARAM;
9677 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9682 /* r->in.level is ignored */
9684 /* We always should reply with a local print processor directory so that
9685 * users are not forced to have a [prnproc$] share on the Samba spoolss
9686 * server, if users decide to do so, lets announce it though - Guenther */
9688 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9689 if (!prnproc_share) {
9693 prnproc_share_exists = true;
9696 result = getprintprocessordirectory_level_1(p->mem_ctx,
9697 prnproc_share_exists ? r->in.server : NULL,
9699 &r->out.info->info1);
9700 if (!W_ERROR_IS_OK(result)) {
9701 TALLOC_FREE(r->out.info);
9705 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9706 r->out.info, r->in.level);
9707 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9709 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9712 /*******************************************************************
9713 ********************************************************************/
9715 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9716 const char *dllname)
9718 enum ndr_err_code ndr_err;
9719 struct spoolss_MonitorUi ui;
9721 ui.dll_name = dllname;
9723 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9724 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9725 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9726 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9728 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9731 /*******************************************************************
9732 Streams the monitor UI DLL name in UNICODE
9733 *******************************************************************/
9735 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9736 struct security_token *token, DATA_BLOB *in,
9737 DATA_BLOB *out, uint32_t *needed)
9739 const char *dllname = "tcpmonui.dll";
9741 *needed = (strlen(dllname)+1) * 2;
9743 if (out->length < *needed) {
9744 return WERR_INSUFFICIENT_BUFFER;
9747 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9754 /*******************************************************************
9755 ********************************************************************/
9757 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9758 struct spoolss_PortData1 *port1,
9759 const DATA_BLOB *buf)
9761 enum ndr_err_code ndr_err;
9762 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9763 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9764 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9765 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9767 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9770 /*******************************************************************
9771 ********************************************************************/
9773 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9774 struct spoolss_PortData2 *port2,
9775 const DATA_BLOB *buf)
9777 enum ndr_err_code ndr_err;
9778 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9779 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9780 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9781 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9783 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9786 /*******************************************************************
9787 Create a new TCP/IP port
9788 *******************************************************************/
9790 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9791 struct security_token *token, DATA_BLOB *in,
9792 DATA_BLOB *out, uint32_t *needed)
9794 struct spoolss_PortData1 port1;
9795 struct spoolss_PortData2 port2;
9796 char *device_uri = NULL;
9799 const char *portname;
9800 const char *hostaddress;
9802 uint32_t port_number;
9805 /* peek for spoolss_PortData version */
9807 if (!in || (in->length < (128 + 4))) {
9808 return WERR_GENERAL_FAILURE;
9811 version = IVAL(in->data, 128);
9817 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9821 portname = port1.portname;
9822 hostaddress = port1.hostaddress;
9823 queue = port1.queue;
9824 protocol = port1.protocol;
9825 port_number = port1.port_number;
9831 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9835 portname = port2.portname;
9836 hostaddress = port2.hostaddress;
9837 queue = port2.queue;
9838 protocol = port2.protocol;
9839 port_number = port2.port_number;
9843 DEBUG(1,("xcvtcp_addport: "
9844 "unknown version of port_data: %d\n", version));
9845 return WERR_UNKNOWN_PORT;
9848 /* create the device URI and call the add_port_hook() */
9851 case PROTOCOL_RAWTCP_TYPE:
9852 device_uri = talloc_asprintf(mem_ctx,
9853 "socket://%s:%d/", hostaddress,
9857 case PROTOCOL_LPR_TYPE:
9858 device_uri = talloc_asprintf(mem_ctx,
9859 "lpr://%s/%s", hostaddress, queue );
9863 return WERR_UNKNOWN_PORT;
9870 return add_port_hook(mem_ctx, token, portname, device_uri);
9873 /*******************************************************************
9874 *******************************************************************/
9876 struct xcv_api_table xcvtcp_cmds[] = {
9877 { "MonitorUI", xcvtcp_monitorui },
9878 { "AddPort", xcvtcp_addport},
9882 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9883 struct security_token *token, const char *command,
9890 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9892 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9893 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9894 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9897 return WERR_BADFUNC;
9900 /*******************************************************************
9901 *******************************************************************/
9902 #if 0 /* don't support management using the "Local Port" monitor */
9904 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9905 struct security_token *token, DATA_BLOB *in,
9906 DATA_BLOB *out, uint32_t *needed)
9908 const char *dllname = "localui.dll";
9910 *needed = (strlen(dllname)+1) * 2;
9912 if (out->length < *needed) {
9913 return WERR_INSUFFICIENT_BUFFER;
9916 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9923 /*******************************************************************
9924 *******************************************************************/
9926 struct xcv_api_table xcvlocal_cmds[] = {
9927 { "MonitorUI", xcvlocal_monitorui },
9931 struct xcv_api_table xcvlocal_cmds[] = {
9938 /*******************************************************************
9939 *******************************************************************/
9941 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9942 struct security_token *token, const char *command,
9943 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9948 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9950 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9951 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9952 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9954 return WERR_BADFUNC;
9957 /****************************************************************
9959 ****************************************************************/
9961 WERROR _spoolss_XcvData(struct pipes_struct *p,
9962 struct spoolss_XcvData *r)
9964 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9965 DATA_BLOB out_data = data_blob_null;
9969 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9970 OUR_HANDLE(r->in.handle)));
9974 /* Has to be a handle to the TCP/IP port monitor */
9976 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9977 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9981 /* requires administrative access to the server */
9983 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9984 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9985 return WERR_ACCESS_DENIED;
9988 /* Allocate the outgoing buffer */
9990 if (r->in.out_data_size) {
9991 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9992 if (out_data.data == NULL) {
9997 switch ( Printer->printer_type ) {
9998 case SPLHND_PORTMON_TCP:
9999 werror = process_xcvtcp_command(p->mem_ctx,
10000 p->session_info->security_token,
10001 r->in.function_name,
10002 &r->in.in_data, &out_data,
10005 case SPLHND_PORTMON_LOCAL:
10006 werror = process_xcvlocal_command(p->mem_ctx,
10007 p->session_info->security_token,
10008 r->in.function_name,
10009 &r->in.in_data, &out_data,
10013 werror = WERR_INVALID_PRINT_MONITOR;
10016 if (!W_ERROR_IS_OK(werror)) {
10020 *r->out.status_code = 0;
10022 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10023 memcpy(r->out.out_data, out_data.data,
10024 MIN(r->in.out_data_size, out_data.length));
10030 /****************************************************************
10031 _spoolss_AddPrintProcessor
10032 ****************************************************************/
10034 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10035 struct spoolss_AddPrintProcessor *r)
10037 /* for now, just indicate success and ignore the add. We'll
10038 automatically set the winprint processor for printer
10039 entries later. Used to debug the LexMark Optra S 1855 PCL
10045 /****************************************************************
10047 ****************************************************************/
10049 WERROR _spoolss_AddPort(struct pipes_struct *p,
10050 struct spoolss_AddPort *r)
10052 /* do what w2k3 does */
10054 return WERR_NOT_SUPPORTED;
10057 /****************************************************************
10058 _spoolss_GetPrinterDriver
10059 ****************************************************************/
10061 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10062 struct spoolss_GetPrinterDriver *r)
10064 p->rng_fault_state = true;
10065 return WERR_NOT_SUPPORTED;
10068 /****************************************************************
10069 _spoolss_ReadPrinter
10070 ****************************************************************/
10072 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10073 struct spoolss_ReadPrinter *r)
10075 p->rng_fault_state = true;
10076 return WERR_NOT_SUPPORTED;
10079 /****************************************************************
10080 _spoolss_WaitForPrinterChange
10081 ****************************************************************/
10083 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10084 struct spoolss_WaitForPrinterChange *r)
10086 p->rng_fault_state = true;
10087 return WERR_NOT_SUPPORTED;
10090 /****************************************************************
10091 _spoolss_ConfigurePort
10092 ****************************************************************/
10094 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10095 struct spoolss_ConfigurePort *r)
10097 p->rng_fault_state = true;
10098 return WERR_NOT_SUPPORTED;
10101 /****************************************************************
10102 _spoolss_DeletePort
10103 ****************************************************************/
10105 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10106 struct spoolss_DeletePort *r)
10108 p->rng_fault_state = true;
10109 return WERR_NOT_SUPPORTED;
10112 /****************************************************************
10113 _spoolss_CreatePrinterIC
10114 ****************************************************************/
10116 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10117 struct spoolss_CreatePrinterIC *r)
10119 p->rng_fault_state = true;
10120 return WERR_NOT_SUPPORTED;
10123 /****************************************************************
10124 _spoolss_PlayGDIScriptOnPrinterIC
10125 ****************************************************************/
10127 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10128 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10130 p->rng_fault_state = true;
10131 return WERR_NOT_SUPPORTED;
10134 /****************************************************************
10135 _spoolss_DeletePrinterIC
10136 ****************************************************************/
10138 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10139 struct spoolss_DeletePrinterIC *r)
10141 p->rng_fault_state = true;
10142 return WERR_NOT_SUPPORTED;
10145 /****************************************************************
10146 _spoolss_AddPrinterConnection
10147 ****************************************************************/
10149 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10150 struct spoolss_AddPrinterConnection *r)
10152 p->rng_fault_state = true;
10153 return WERR_NOT_SUPPORTED;
10156 /****************************************************************
10157 _spoolss_DeletePrinterConnection
10158 ****************************************************************/
10160 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10161 struct spoolss_DeletePrinterConnection *r)
10163 p->rng_fault_state = true;
10164 return WERR_NOT_SUPPORTED;
10167 /****************************************************************
10168 _spoolss_PrinterMessageBox
10169 ****************************************************************/
10171 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10172 struct spoolss_PrinterMessageBox *r)
10174 p->rng_fault_state = true;
10175 return WERR_NOT_SUPPORTED;
10178 /****************************************************************
10179 _spoolss_AddMonitor
10180 ****************************************************************/
10182 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10183 struct spoolss_AddMonitor *r)
10185 p->rng_fault_state = true;
10186 return WERR_NOT_SUPPORTED;
10189 /****************************************************************
10190 _spoolss_DeleteMonitor
10191 ****************************************************************/
10193 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10194 struct spoolss_DeleteMonitor *r)
10196 p->rng_fault_state = true;
10197 return WERR_NOT_SUPPORTED;
10200 /****************************************************************
10201 _spoolss_DeletePrintProcessor
10202 ****************************************************************/
10204 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10205 struct spoolss_DeletePrintProcessor *r)
10207 p->rng_fault_state = true;
10208 return WERR_NOT_SUPPORTED;
10211 /****************************************************************
10212 _spoolss_AddPrintProvidor
10213 ****************************************************************/
10215 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10216 struct spoolss_AddPrintProvidor *r)
10218 p->rng_fault_state = true;
10219 return WERR_NOT_SUPPORTED;
10222 /****************************************************************
10223 _spoolss_DeletePrintProvidor
10224 ****************************************************************/
10226 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10227 struct spoolss_DeletePrintProvidor *r)
10229 p->rng_fault_state = true;
10230 return WERR_NOT_SUPPORTED;
10233 /****************************************************************
10234 _spoolss_FindFirstPrinterChangeNotification
10235 ****************************************************************/
10237 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10238 struct spoolss_FindFirstPrinterChangeNotification *r)
10240 p->rng_fault_state = true;
10241 return WERR_NOT_SUPPORTED;
10244 /****************************************************************
10245 _spoolss_FindNextPrinterChangeNotification
10246 ****************************************************************/
10248 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10249 struct spoolss_FindNextPrinterChangeNotification *r)
10251 p->rng_fault_state = true;
10252 return WERR_NOT_SUPPORTED;
10255 /****************************************************************
10256 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10257 ****************************************************************/
10259 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10260 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10262 p->rng_fault_state = true;
10263 return WERR_NOT_SUPPORTED;
10266 /****************************************************************
10267 _spoolss_ReplyOpenPrinter
10268 ****************************************************************/
10270 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10271 struct spoolss_ReplyOpenPrinter *r)
10273 p->rng_fault_state = true;
10274 return WERR_NOT_SUPPORTED;
10277 /****************************************************************
10278 _spoolss_RouterReplyPrinter
10279 ****************************************************************/
10281 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10282 struct spoolss_RouterReplyPrinter *r)
10284 p->rng_fault_state = true;
10285 return WERR_NOT_SUPPORTED;
10288 /****************************************************************
10289 _spoolss_ReplyClosePrinter
10290 ****************************************************************/
10292 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10293 struct spoolss_ReplyClosePrinter *r)
10295 p->rng_fault_state = true;
10296 return WERR_NOT_SUPPORTED;
10299 /****************************************************************
10301 ****************************************************************/
10303 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10304 struct spoolss_AddPortEx *r)
10306 p->rng_fault_state = true;
10307 return WERR_NOT_SUPPORTED;
10310 /****************************************************************
10311 _spoolss_RouterFindFirstPrinterChangeNotification
10312 ****************************************************************/
10314 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10315 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10317 p->rng_fault_state = true;
10318 return WERR_NOT_SUPPORTED;
10321 /****************************************************************
10322 _spoolss_SpoolerInit
10323 ****************************************************************/
10325 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10326 struct spoolss_SpoolerInit *r)
10328 p->rng_fault_state = true;
10329 return WERR_NOT_SUPPORTED;
10332 /****************************************************************
10333 _spoolss_ResetPrinterEx
10334 ****************************************************************/
10336 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10337 struct spoolss_ResetPrinterEx *r)
10339 p->rng_fault_state = true;
10340 return WERR_NOT_SUPPORTED;
10343 /****************************************************************
10344 _spoolss_RouterReplyPrinterEx
10345 ****************************************************************/
10347 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10348 struct spoolss_RouterReplyPrinterEx *r)
10350 p->rng_fault_state = true;
10351 return WERR_NOT_SUPPORTED;
10354 /****************************************************************
10356 ****************************************************************/
10358 WERROR _spoolss_44(struct pipes_struct *p,
10359 struct spoolss_44 *r)
10361 p->rng_fault_state = true;
10362 return WERR_NOT_SUPPORTED;
10365 /****************************************************************
10367 ****************************************************************/
10369 WERROR _spoolss_SetPort(struct pipes_struct *p,
10370 struct spoolss_SetPort *r)
10372 p->rng_fault_state = true;
10373 return WERR_NOT_SUPPORTED;
10376 /****************************************************************
10378 ****************************************************************/
10380 WERROR _spoolss_4a(struct pipes_struct *p,
10381 struct spoolss_4a *r)
10383 p->rng_fault_state = true;
10384 return WERR_NOT_SUPPORTED;
10387 /****************************************************************
10389 ****************************************************************/
10391 WERROR _spoolss_4b(struct pipes_struct *p,
10392 struct spoolss_4b *r)
10394 p->rng_fault_state = true;
10395 return WERR_NOT_SUPPORTED;
10398 /****************************************************************
10400 ****************************************************************/
10402 WERROR _spoolss_4c(struct pipes_struct *p,
10403 struct spoolss_4c *r)
10405 p->rng_fault_state = true;
10406 return WERR_NOT_SUPPORTED;
10409 /****************************************************************
10411 ****************************************************************/
10413 WERROR _spoolss_53(struct pipes_struct *p,
10414 struct spoolss_53 *r)
10416 p->rng_fault_state = true;
10417 return WERR_NOT_SUPPORTED;
10420 /****************************************************************
10421 _spoolss_AddPerMachineConnection
10422 ****************************************************************/
10424 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10425 struct spoolss_AddPerMachineConnection *r)
10427 p->rng_fault_state = true;
10428 return WERR_NOT_SUPPORTED;
10431 /****************************************************************
10432 _spoolss_DeletePerMachineConnection
10433 ****************************************************************/
10435 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10436 struct spoolss_DeletePerMachineConnection *r)
10438 p->rng_fault_state = true;
10439 return WERR_NOT_SUPPORTED;
10442 /****************************************************************
10443 _spoolss_EnumPerMachineConnections
10444 ****************************************************************/
10446 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10447 struct spoolss_EnumPerMachineConnections *r)
10449 p->rng_fault_state = true;
10450 return WERR_NOT_SUPPORTED;
10453 /****************************************************************
10455 ****************************************************************/
10457 WERROR _spoolss_5a(struct pipes_struct *p,
10458 struct spoolss_5a *r)
10460 p->rng_fault_state = true;
10461 return WERR_NOT_SUPPORTED;
10464 /****************************************************************
10466 ****************************************************************/
10468 WERROR _spoolss_5b(struct pipes_struct *p,
10469 struct spoolss_5b *r)
10471 p->rng_fault_state = true;
10472 return WERR_NOT_SUPPORTED;
10475 /****************************************************************
10477 ****************************************************************/
10479 WERROR _spoolss_5c(struct pipes_struct *p,
10480 struct spoolss_5c *r)
10482 p->rng_fault_state = true;
10483 return WERR_NOT_SUPPORTED;
10486 /****************************************************************
10488 ****************************************************************/
10490 WERROR _spoolss_5d(struct pipes_struct *p,
10491 struct spoolss_5d *r)
10493 p->rng_fault_state = true;
10494 return WERR_NOT_SUPPORTED;
10497 /****************************************************************
10499 ****************************************************************/
10501 WERROR _spoolss_5e(struct pipes_struct *p,
10502 struct spoolss_5e *r)
10504 p->rng_fault_state = true;
10505 return WERR_NOT_SUPPORTED;
10508 /****************************************************************
10510 ****************************************************************/
10512 WERROR _spoolss_5f(struct pipes_struct *p,
10513 struct spoolss_5f *r)
10515 p->rng_fault_state = true;
10516 return WERR_NOT_SUPPORTED;
10519 /****************************************************************
10521 ****************************************************************/
10523 WERROR _spoolss_60(struct pipes_struct *p,
10524 struct spoolss_60 *r)
10526 p->rng_fault_state = true;
10527 return WERR_NOT_SUPPORTED;
10530 /****************************************************************
10532 ****************************************************************/
10534 WERROR _spoolss_61(struct pipes_struct *p,
10535 struct spoolss_61 *r)
10537 p->rng_fault_state = true;
10538 return WERR_NOT_SUPPORTED;
10541 /****************************************************************
10543 ****************************************************************/
10545 WERROR _spoolss_62(struct pipes_struct *p,
10546 struct spoolss_62 *r)
10548 p->rng_fault_state = true;
10549 return WERR_NOT_SUPPORTED;
10552 /****************************************************************
10554 ****************************************************************/
10556 WERROR _spoolss_63(struct pipes_struct *p,
10557 struct spoolss_63 *r)
10559 p->rng_fault_state = true;
10560 return WERR_NOT_SUPPORTED;
10563 /****************************************************************
10565 ****************************************************************/
10567 WERROR _spoolss_64(struct pipes_struct *p,
10568 struct spoolss_64 *r)
10570 p->rng_fault_state = true;
10571 return WERR_NOT_SUPPORTED;
10574 /****************************************************************
10576 ****************************************************************/
10578 WERROR _spoolss_65(struct pipes_struct *p,
10579 struct spoolss_65 *r)
10581 p->rng_fault_state = true;
10582 return WERR_NOT_SUPPORTED;
10585 /****************************************************************
10586 _spoolss_GetCorePrinterDrivers
10587 ****************************************************************/
10589 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10590 struct spoolss_GetCorePrinterDrivers *r)
10592 p->rng_fault_state = true;
10593 return WERR_NOT_SUPPORTED;
10596 /****************************************************************
10598 ****************************************************************/
10600 WERROR _spoolss_67(struct pipes_struct *p,
10601 struct spoolss_67 *r)
10603 p->rng_fault_state = true;
10604 return WERR_NOT_SUPPORTED;
10607 /****************************************************************
10608 _spoolss_GetPrinterDriverPackagePath
10609 ****************************************************************/
10611 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10612 struct spoolss_GetPrinterDriverPackagePath *r)
10614 p->rng_fault_state = true;
10615 return WERR_NOT_SUPPORTED;
10618 /****************************************************************
10620 ****************************************************************/
10622 WERROR _spoolss_69(struct pipes_struct *p,
10623 struct spoolss_69 *r)
10625 p->rng_fault_state = true;
10626 return WERR_NOT_SUPPORTED;
10629 /****************************************************************
10631 ****************************************************************/
10633 WERROR _spoolss_6a(struct pipes_struct *p,
10634 struct spoolss_6a *r)
10636 p->rng_fault_state = true;
10637 return WERR_NOT_SUPPORTED;
10640 /****************************************************************
10642 ****************************************************************/
10644 WERROR _spoolss_6b(struct pipes_struct *p,
10645 struct spoolss_6b *r)
10647 p->rng_fault_state = true;
10648 return WERR_NOT_SUPPORTED;
10651 /****************************************************************
10653 ****************************************************************/
10655 WERROR _spoolss_6c(struct pipes_struct *p,
10656 struct spoolss_6c *r)
10658 p->rng_fault_state = true;
10659 return WERR_NOT_SUPPORTED;
10662 /****************************************************************
10664 ****************************************************************/
10666 WERROR _spoolss_6d(struct pipes_struct *p,
10667 struct spoolss_6d *r)
10669 p->rng_fault_state = true;
10670 return WERR_NOT_SUPPORTED;