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"
49 /* macros stolen from s4 spoolss server */
50 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
51 ((info)?ndr_size_##fn(info, level, 0):0)
53 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
54 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
56 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
57 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
59 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
62 #define DBGC_CLASS DBGC_RPC_SRV
64 #ifndef MAX_OPEN_PRINTER_EXS
65 #define MAX_OPEN_PRINTER_EXS 50
68 struct notify_back_channel;
70 /* structure to store the printer handles */
71 /* and a reference to what it's pointing to */
72 /* and the notify info asked about */
73 /* that's the central struct */
74 struct printer_handle {
75 struct printer_handle *prev, *next;
76 bool document_started;
78 uint32 jobid; /* jobid in printing backend */
80 const char *servername;
83 uint32 access_granted;
89 struct spoolss_NotifyOption *option;
90 struct policy_handle cli_hnd;
91 struct notify_back_channel *cli_chan;
93 /* are we in a FindNextPrinterChangeNotify() call? */
95 struct messaging_context *msg_ctx;
102 /* devmode sent in the OpenPrinter() call */
103 struct spoolss_DeviceMode *devmode;
105 /* TODO cache the printer info2 structure */
106 struct spoolss_PrinterInfo2 *info2;
110 static struct printer_handle *printers_list;
112 struct printer_session_counter {
113 struct printer_session_counter *next;
114 struct printer_session_counter *prev;
120 static struct printer_session_counter *counter_list;
122 struct notify_back_channel {
123 struct notify_back_channel *prev, *next;
125 /* associated client */
126 struct sockaddr_storage client_address;
128 /* print notify back-channel pipe handle*/
129 struct rpc_pipe_client *cli_pipe;
130 struct dcerpc_binding_handle *binding_handle;
131 uint32_t active_connections;
134 static struct notify_back_channel *back_channels;
136 /* Map generic permissions to printer object specific permissions */
138 const struct standard_mapping printer_std_mapping = {
145 /* Map generic permissions to print server object specific permissions */
147 const struct standard_mapping printserver_std_mapping = {
154 /* API table for Xcv Monitor functions */
156 struct xcv_api_table {
158 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
161 static void prune_printername_cache(void);
163 /********************************************************************
164 * Canonicalize servername.
165 ********************************************************************/
167 static const char *canon_servername(const char *servername)
169 const char *pservername = servername;
170 while (*pservername == '\\') {
176 /* translate between internal status numbers and NT status numbers */
177 static int nt_printj_status(int v)
183 return JOB_STATUS_PAUSED;
185 return JOB_STATUS_SPOOLING;
187 return JOB_STATUS_PRINTING;
189 return JOB_STATUS_ERROR;
191 return JOB_STATUS_DELETING;
193 return JOB_STATUS_OFFLINE;
195 return JOB_STATUS_PAPEROUT;
197 return JOB_STATUS_PRINTED;
199 return JOB_STATUS_DELETED;
201 return JOB_STATUS_BLOCKED_DEVQ;
202 case LPQ_USER_INTERVENTION:
203 return JOB_STATUS_USER_INTERVENTION;
208 static int nt_printq_status(int v)
212 return PRINTER_STATUS_PAUSED;
221 /***************************************************************************
222 Disconnect from the client
223 ****************************************************************************/
225 static void srv_spoolss_replycloseprinter(int snum,
226 struct printer_handle *prn_hnd)
232 * Tell the specific printing tdb we no longer want messages for this printer
233 * by deregistering our PID.
236 if (!print_notify_deregister_pid(snum)) {
237 DEBUG(0, ("Failed to register our pid for printer %s\n",
238 lp_const_servicename(snum)));
241 /* weird if the test succeeds !!! */
242 if (prn_hnd->notify.cli_chan == NULL ||
243 prn_hnd->notify.cli_chan->active_connections == 0) {
244 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
245 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
246 TALLOC_FREE(prn_hnd->notify.cli_chan);
250 status = dcerpc_spoolss_ReplyClosePrinter(
251 prn_hnd->notify.cli_chan->binding_handle,
253 &prn_hnd->notify.cli_hnd,
255 if (!NT_STATUS_IS_OK(status)) {
256 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
258 result = ntstatus_to_werror(status);
259 } else if (!W_ERROR_IS_OK(result)) {
260 DEBUG(0, ("reply_close_printer failed [%s].\n",
261 win_errstr(result)));
264 /* if it's the last connection, deconnect the IPC$ share */
265 if (prn_hnd->notify.cli_chan->active_connections == 1) {
267 prn_hnd->notify.cli_chan->binding_handle = NULL;
268 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
269 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
270 TALLOC_FREE(prn_hnd->notify.cli_chan);
272 if (prn_hnd->notify.msg_ctx != NULL) {
273 messaging_deregister(prn_hnd->notify.msg_ctx,
274 MSG_PRINTER_NOTIFY2, NULL);
277 * Tell the serverid.tdb we're no longer
278 * interested in printer notify messages.
281 serverid_register_msg_flags(
282 messaging_server_id(prn_hnd->notify.msg_ctx),
283 false, FLAG_MSG_PRINT_NOTIFY);
287 if (prn_hnd->notify.cli_chan) {
288 prn_hnd->notify.cli_chan->active_connections--;
292 /****************************************************************************
293 Functions to free a printer entry datastruct.
294 ****************************************************************************/
296 static int printer_entry_destructor(struct printer_handle *Printer)
298 if (Printer->notify.cli_chan != NULL &&
299 Printer->notify.cli_chan->active_connections > 0) {
302 switch(Printer->printer_type) {
304 srv_spoolss_replycloseprinter(snum, Printer);
308 snum = print_queue_snum(Printer->sharename);
310 srv_spoolss_replycloseprinter(snum, Printer);
318 Printer->notify.flags=0;
319 Printer->notify.options=0;
320 Printer->notify.localmachine[0]='\0';
321 Printer->notify.printerlocal=0;
322 TALLOC_FREE(Printer->notify.option);
323 TALLOC_FREE(Printer->devmode);
325 /* Remove from the internal list. */
326 DLIST_REMOVE(printers_list, Printer);
330 /****************************************************************************
331 find printer index by handle
332 ****************************************************************************/
334 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
335 struct policy_handle *hnd)
337 struct printer_handle *find_printer = NULL;
339 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
340 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
347 /****************************************************************************
348 Close printer index by handle.
349 ****************************************************************************/
351 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
353 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
356 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
361 close_policy_hnd(p, hnd);
366 /****************************************************************************
367 Delete a printer given a handle.
368 ****************************************************************************/
370 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
371 const char *sharename,
372 struct messaging_context *msg_ctx)
374 char *cmd = lp_deleteprinter_cmd();
375 char *command = NULL;
377 bool is_print_op = false;
379 /* can't fail if we don't try */
384 command = talloc_asprintf(ctx,
391 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
393 DEBUG(10,("Running [%s]\n", command));
395 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
400 if ( (ret = smbrun(command, NULL)) == 0 ) {
401 /* Tell everyone we updated smb.conf. */
402 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
408 /********** END SePrintOperatorPrivlege BLOCK **********/
410 DEBUGADD(10,("returned [%d]\n", ret));
412 TALLOC_FREE(command);
415 return WERR_BADFID; /* What to return here? */
417 /* go ahead and re-read the services immediately */
419 reload_services(msg_ctx, -1, false);
422 if ( lp_servicenumber( sharename ) >= 0 )
423 return WERR_ACCESS_DENIED;
428 /****************************************************************************
429 Delete a printer given a handle.
430 ****************************************************************************/
432 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
434 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
438 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
444 * It turns out that Windows allows delete printer on a handle
445 * opened by an admin user, then used on a pipe handle created
446 * by an anonymous user..... but they're working on security.... riiight !
450 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
451 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
452 return WERR_ACCESS_DENIED;
455 /* this does not need a become root since the access check has been
456 done on the handle already */
458 result = winreg_delete_printer_key(p->mem_ctx,
459 get_session_info_system(),
463 if (!W_ERROR_IS_OK(result)) {
464 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
468 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
469 Printer->sharename, p->msg_ctx);
470 if (!W_ERROR_IS_OK(result)) {
473 prune_printername_cache();
477 /****************************************************************************
478 Return the snum of a printer corresponding to an handle.
479 ****************************************************************************/
481 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
482 int *number, struct share_params **params)
484 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
487 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
492 switch (Printer->printer_type) {
494 DEBUG(4,("short name:%s\n", Printer->sharename));
495 *number = print_queue_snum(Printer->sharename);
496 return (*number != -1);
504 /****************************************************************************
505 Set printer handle type.
506 Check if it's \\server or \\server\printer
507 ****************************************************************************/
509 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
511 DEBUG(3,("Setting printer type=%s\n", handlename));
513 /* it's a print server */
514 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
515 DEBUGADD(4,("Printer is a print server\n"));
516 Printer->printer_type = SPLHND_SERVER;
518 /* it's a printer (set_printer_hnd_name() will handle port monitors */
520 DEBUGADD(4,("Printer is a printer\n"));
521 Printer->printer_type = SPLHND_PRINTER;
527 static void prune_printername_cache_fn(const char *key, const char *value,
528 time_t timeout, void *private_data)
533 static void prune_printername_cache(void)
535 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
538 /****************************************************************************
539 Set printer handle name.. Accept names like \\server, \\server\printer,
540 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
541 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
542 XcvDataPort() interface.
543 ****************************************************************************/
545 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
546 const struct auth_serversupplied_info *session_info,
547 struct messaging_context *msg_ctx,
548 struct printer_handle *Printer,
549 const char *handlename)
552 int n_services=lp_numservices();
554 const char *printername;
555 const char *servername = NULL;
558 struct spoolss_PrinterInfo2 *info2 = NULL;
563 * Hopefully nobody names his printers like this. Maybe \ or ,
564 * are illegal in printer names even?
566 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
570 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
571 (unsigned long)strlen(handlename)));
573 aprinter = CONST_DISCARD(char *, handlename);
574 if ( *handlename == '\\' ) {
575 servername = canon_servername(handlename);
576 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
580 if (!is_myname_or_ipaddr(servername)) {
581 return WERR_INVALID_PRINTER_NAME;
583 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
584 if (Printer->servername == NULL) {
589 if (Printer->printer_type == SPLHND_SERVER) {
593 if (Printer->printer_type != SPLHND_PRINTER) {
594 return WERR_INVALID_HANDLE;
597 DEBUGADD(5, ("searching for [%s]\n", aprinter));
599 p = strchr(aprinter, ',');
606 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
608 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
614 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
617 /* check for the Port Monitor Interface */
618 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
619 Printer->printer_type = SPLHND_PORTMON_TCP;
620 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
623 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
624 Printer->printer_type = SPLHND_PORTMON_LOCAL;
625 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
630 * With hundreds of printers, the "for" loop iterating all
631 * shares can be quite expensive, as it is done on every
632 * OpenPrinter. The loop maps "aprinter" to "sname", the
633 * result of which we cache in gencache.
636 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
638 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
640 found = (strcmp(tmp, printer_not_found) != 0);
642 DEBUG(4, ("Printer %s not found\n", aprinter));
644 return WERR_INVALID_PRINTER_NAME;
650 /* Search all sharenames first as this is easier than pulling
651 the printer_info_2 off of disk. Don't use find_service() since
652 that calls out to map_username() */
654 /* do another loop to look for printernames */
655 for (snum = 0; !found && snum < n_services; snum++) {
656 const char *printer = lp_const_servicename(snum);
658 /* no point going on if this is not a printer */
659 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
663 /* ignore [printers] share */
664 if (strequal(printer, "printers")) {
668 fstrcpy(sname, printer);
669 if (strequal(aprinter, printer)) {
674 /* no point looking up the printer object if
675 we aren't allowing printername != sharename */
676 if (lp_force_printername(snum)) {
680 result = winreg_get_printer(mem_ctx,
685 if ( !W_ERROR_IS_OK(result) ) {
686 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
687 sname, win_errstr(result)));
691 printername = strrchr(info2->printername, '\\');
692 if (printername == NULL) {
693 printername = info2->printername;
698 if (strequal(printername, aprinter)) {
703 DEBUGADD(10, ("printername: %s\n", printername));
709 if (cache_key != NULL) {
710 gencache_set(cache_key, printer_not_found,
712 TALLOC_FREE(cache_key);
714 DEBUGADD(4,("Printer not found\n"));
715 return WERR_INVALID_PRINTER_NAME;
718 if (cache_key != NULL) {
719 gencache_set(cache_key, sname, time(NULL)+300);
720 TALLOC_FREE(cache_key);
723 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
725 fstrcpy(Printer->sharename, sname);
730 /****************************************************************************
731 Find first available printer slot. creates a printer handle for you.
732 ****************************************************************************/
734 static WERROR open_printer_hnd(struct pipes_struct *p,
735 struct policy_handle *hnd,
737 uint32_t access_granted)
739 struct printer_handle *new_printer;
742 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
744 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
745 if (new_printer == NULL) {
748 talloc_set_destructor(new_printer, printer_entry_destructor);
750 /* This also steals the printer_handle on the policy_handle */
751 if (!create_policy_hnd(p, hnd, new_printer)) {
752 TALLOC_FREE(new_printer);
753 return WERR_INVALID_HANDLE;
756 /* Add to the internal list. */
757 DLIST_ADD(printers_list, new_printer);
759 new_printer->notify.option=NULL;
761 if (!set_printer_hnd_printertype(new_printer, name)) {
762 close_printer_handle(p, hnd);
763 return WERR_INVALID_HANDLE;
766 result = set_printer_hnd_name(p->mem_ctx,
767 get_session_info_system(),
770 if (!W_ERROR_IS_OK(result)) {
771 close_printer_handle(p, hnd);
775 new_printer->access_granted = access_granted;
777 DEBUG(5, ("%d printer handles active\n",
778 (int)num_pipe_handles(p)));
783 /***************************************************************************
784 check to see if the client motify handle is monitoring the notification
785 given by (notify_type, notify_field).
786 **************************************************************************/
788 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
789 uint16_t notify_field)
794 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
795 uint16_t notify_field)
797 struct spoolss_NotifyOption *option = p->notify.option;
801 * Flags should always be zero when the change notify
802 * is registered by the client's spooler. A user Win32 app
803 * might use the flags though instead of the NOTIFY_OPTION_INFO
812 return is_monitoring_event_flags(
813 p->notify.flags, notify_type, notify_field);
815 for (i = 0; i < option->count; i++) {
817 /* Check match for notify_type */
819 if (option->types[i].type != notify_type)
822 /* Check match for field */
824 for (j = 0; j < option->types[i].count; j++) {
825 if (option->types[i].fields[j].field == notify_field) {
831 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
832 p->servername, p->sharename, notify_type, notify_field));
837 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
838 _data->data.integer[0] = _integer; \
839 _data->data.integer[1] = 0;
842 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
843 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
844 if (!_data->data.string.string) {\
845 _data->data.string.size = 0; \
847 _data->data.string.size = strlen_m_term(_p) * 2;
849 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
850 _data->data.devmode.devmode = _devmode;
852 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
853 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
854 if (!_data->data.sd.sd) { \
855 _data->data.sd.sd_size = 0; \
857 _data->data.sd.sd_size = \
858 ndr_size_security_descriptor(_data->data.sd.sd, 0);
860 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
865 struct spoolss_Time st;
869 if (!init_systemtime(&st, t)) {
873 p = talloc_array(mem_ctx, char, len);
879 * Systemtime must be linearized as a set of UINT16's.
880 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
883 SSVAL(p, 0, st.year);
884 SSVAL(p, 2, st.month);
885 SSVAL(p, 4, st.day_of_week);
887 SSVAL(p, 8, st.hour);
888 SSVAL(p, 10, st.minute);
889 SSVAL(p, 12, st.second);
890 SSVAL(p, 14, st.millisecond);
896 /* Convert a notification message to a struct spoolss_Notify */
898 static void notify_one_value(struct spoolss_notify_msg *msg,
899 struct spoolss_Notify *data,
902 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
905 static void notify_string(struct spoolss_notify_msg *msg,
906 struct spoolss_Notify *data,
909 /* The length of the message includes the trailing \0 */
911 data->data.string.size = msg->len * 2;
912 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
913 if (!data->data.string.string) {
914 data->data.string.size = 0;
919 static void notify_system_time(struct spoolss_notify_msg *msg,
920 struct spoolss_Notify *data,
923 data->data.string.string = NULL;
924 data->data.string.size = 0;
926 if (msg->len != sizeof(time_t)) {
927 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
932 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
933 &data->data.string.string,
934 &data->data.string.size);
937 struct notify2_message_table {
939 void (*fn)(struct spoolss_notify_msg *msg,
940 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
943 static struct notify2_message_table printer_notify_table[] = {
944 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
945 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
946 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
947 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
948 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
949 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
950 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
951 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
952 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
953 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
954 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
955 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
956 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
957 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
958 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
959 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
960 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
961 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
962 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
965 static struct notify2_message_table job_notify_table[] = {
966 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
967 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
968 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
969 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
970 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
971 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
972 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
973 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
974 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
975 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
976 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
977 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
978 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
979 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
980 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
981 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
982 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
983 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
984 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
985 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
986 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
987 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
988 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
989 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
993 /***********************************************************************
994 Allocate talloc context for container object
995 **********************************************************************/
997 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1002 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1007 /***********************************************************************
1008 release all allocated memory and zero out structure
1009 **********************************************************************/
1011 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1017 talloc_destroy(ctr->ctx);
1024 /***********************************************************************
1025 **********************************************************************/
1027 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1035 /***********************************************************************
1036 **********************************************************************/
1038 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1040 if ( !ctr || !ctr->msg_groups )
1043 if ( idx >= ctr->num_groups )
1046 return &ctr->msg_groups[idx];
1050 /***********************************************************************
1051 How many groups of change messages do we have ?
1052 **********************************************************************/
1054 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1059 return ctr->num_groups;
1062 /***********************************************************************
1063 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1064 **********************************************************************/
1066 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1068 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1069 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1070 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1076 /* loop over all groups looking for a matching printer name */
1078 for ( i=0; i<ctr->num_groups; i++ ) {
1079 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1083 /* add a new group? */
1085 if ( i == ctr->num_groups ) {
1088 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1089 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1092 ctr->msg_groups = groups;
1094 /* clear the new entry and set the printer name */
1096 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1097 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1100 /* add the change messages; 'i' is the correct index now regardless */
1102 msg_grp = &ctr->msg_groups[i];
1104 msg_grp->num_msgs++;
1106 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1107 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1110 msg_grp->msgs = msg_list;
1112 new_slot = msg_grp->num_msgs-1;
1113 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1115 /* need to allocate own copy of data */
1117 if ( msg->len != 0 )
1118 msg_grp->msgs[new_slot].notify.data = (char *)
1119 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1121 return ctr->num_groups;
1124 static void construct_info_data(struct spoolss_Notify *info_data,
1125 enum spoolss_NotifyType type,
1126 uint16_t field, int id);
1128 /***********************************************************************
1129 Send a change notication message on all handles which have a call
1131 **********************************************************************/
1133 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1134 struct printer_handle *prn_hnd,
1135 SPOOLSS_NOTIFY_MSG *messages,
1137 struct spoolss_Notify **_notifies,
1140 struct spoolss_Notify *notifies;
1141 SPOOLSS_NOTIFY_MSG *msg;
1146 notifies = talloc_zero_array(mem_ctx,
1147 struct spoolss_Notify, num_msgs);
1152 for (i = 0; i < num_msgs; i++) {
1156 /* Are we monitoring this event? */
1158 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1162 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1163 "for printer [%s]\n",
1164 msg->type, msg->field, prn_hnd->sharename));
1167 * if the is a printer notification handle and not a job
1168 * notification type, then set the id to 0.
1169 * Otherwise just use what was specified in the message.
1171 * When registering change notification on a print server
1172 * handle we always need to send back the id (snum) matching
1173 * the printer for which the change took place.
1174 * For change notify registered on a printer handle,
1175 * this does not matter and the id should be 0.
1180 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1181 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1187 /* Convert unix jobid to smb jobid */
1189 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1190 id = sysjob_to_jobid(msg->id);
1193 DEBUG(3, ("no such unix jobid %d\n",
1199 construct_info_data(¬ifies[count],
1200 msg->type, msg->field, id);
1203 case PRINTER_NOTIFY_TYPE:
1204 if (printer_notify_table[msg->field].fn) {
1205 printer_notify_table[msg->field].fn(msg,
1206 ¬ifies[count], mem_ctx);
1210 case JOB_NOTIFY_TYPE:
1211 if (job_notify_table[msg->field].fn) {
1212 job_notify_table[msg->field].fn(msg,
1213 ¬ifies[count], mem_ctx);
1218 DEBUG(5, ("Unknown notification type %d\n",
1226 *_notifies = notifies;
1232 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1233 struct printer_handle *prn_hnd,
1234 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1236 struct spoolss_Notify *notifies;
1238 union spoolss_ReplyPrinterInfo info;
1239 struct spoolss_NotifyInfo info0;
1240 uint32_t reply_result;
1245 /* Is there notification on this handle? */
1246 if (prn_hnd->notify.cli_chan == NULL ||
1247 prn_hnd->notify.cli_chan->active_connections == 0) {
1251 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1252 prn_hnd->servername, prn_hnd->sharename));
1254 /* For this printer? Print servers always receive notifications. */
1255 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1256 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1260 DEBUG(10,("Our printer\n"));
1262 /* build the array of change notifications */
1263 ret = build_notify2_messages(mem_ctx, prn_hnd,
1265 msg_group->num_msgs,
1271 info0.version = 0x2;
1272 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1273 info0.count = count;
1274 info0.notifies = notifies;
1276 info.info0 = &info0;
1278 status = dcerpc_spoolss_RouterReplyPrinterEx(
1279 prn_hnd->notify.cli_chan->binding_handle,
1281 &prn_hnd->notify.cli_hnd,
1282 prn_hnd->notify.change, /* color */
1283 prn_hnd->notify.flags,
1285 0, /* reply_type, must be 0 */
1287 if (!NT_STATUS_IS_OK(status)) {
1288 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1290 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1291 nt_errstr(status)));
1292 werr = ntstatus_to_werror(status);
1293 } else if (!W_ERROR_IS_OK(werr)) {
1294 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1296 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1299 switch (reply_result) {
1302 case PRINTER_NOTIFY_INFO_DISCARDED:
1303 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1304 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1313 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1315 struct printer_handle *p;
1316 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1317 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1321 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1325 if (!msg_group->msgs) {
1326 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1330 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1332 /* loop over all printers */
1334 for (p = printers_list; p; p = p->next) {
1335 ret = send_notify2_printer(mem_ctx, p, msg_group);
1342 DEBUG(8,("send_notify2_changes: Exit...\n"));
1346 /***********************************************************************
1347 **********************************************************************/
1349 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1352 uint32_t tv_sec, tv_usec;
1355 /* Unpack message */
1357 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1360 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1362 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1365 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1366 &msg->notify.value[0], &msg->notify.value[1]);
1368 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1369 &msg->len, &msg->notify.data);
1371 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1372 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1374 tv->tv_sec = tv_sec;
1375 tv->tv_usec = tv_usec;
1378 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1379 msg->notify.value[1]));
1381 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1386 /********************************************************************
1387 Receive a notify2 message list
1388 ********************************************************************/
1390 static void receive_notify2_message_list(struct messaging_context *msg,
1393 struct server_id server_id,
1396 size_t msg_count, i;
1397 char *buf = (char *)data->data;
1400 SPOOLSS_NOTIFY_MSG notify;
1401 SPOOLSS_NOTIFY_MSG_CTR messages;
1404 if (data->length < 4) {
1405 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1409 msg_count = IVAL(buf, 0);
1412 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1414 if (msg_count == 0) {
1415 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1419 /* initialize the container */
1421 ZERO_STRUCT( messages );
1422 notify_msg_ctr_init( &messages );
1425 * build message groups for each printer identified
1426 * in a change_notify msg. Remember that a PCN message
1427 * includes the handle returned for the srv_spoolss_replyopenprinter()
1428 * call. Therefore messages are grouped according to printer handle.
1431 for ( i=0; i<msg_count; i++ ) {
1432 struct timeval msg_tv;
1434 if (msg_ptr + 4 - buf > data->length) {
1435 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1439 msg_len = IVAL(msg_ptr,0);
1442 if (msg_ptr + msg_len - buf > data->length) {
1443 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1447 /* unpack messages */
1449 ZERO_STRUCT( notify );
1450 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1453 /* add to correct list in container */
1455 notify_msg_ctr_addmsg( &messages, ¬ify );
1457 /* free memory that might have been allocated by notify2_unpack_msg() */
1459 if ( notify.len != 0 )
1460 SAFE_FREE( notify.notify.data );
1463 /* process each group of messages */
1465 num_groups = notify_msg_ctr_numgroups( &messages );
1466 for ( i=0; i<num_groups; i++ )
1467 send_notify2_changes( &messages, i );
1472 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1473 (uint32_t)msg_count ));
1475 notify_msg_ctr_destroy( &messages );
1480 /********************************************************************
1481 Send a message to ourself about new driver being installed
1482 so we can upgrade the information for each printer bound to this
1484 ********************************************************************/
1486 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1487 struct messaging_context *msg_ctx)
1489 int len = strlen(drivername);
1494 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1497 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1498 MSG_PRINTER_DRVUPGRADE,
1499 (uint8_t *)drivername, len+1);
1504 void srv_spoolss_cleanup(void)
1506 struct printer_session_counter *session_counter;
1508 for (session_counter = counter_list;
1509 session_counter != NULL;
1510 session_counter = counter_list) {
1511 DLIST_REMOVE(counter_list, session_counter);
1512 TALLOC_FREE(session_counter);
1516 /**********************************************************************
1517 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1518 over all printers, upgrading ones as necessary
1519 **********************************************************************/
1521 void do_drv_upgrade_printer(struct messaging_context *msg,
1524 struct server_id server_id,
1527 TALLOC_CTX *tmp_ctx;
1528 struct auth_serversupplied_info *session_info = NULL;
1529 struct spoolss_PrinterInfo2 *pinfo2;
1532 const char *drivername;
1534 int n_services = lp_numservices();
1536 tmp_ctx = talloc_new(NULL);
1537 if (!tmp_ctx) return;
1539 status = make_session_info_system(tmp_ctx, &session_info);
1540 if (!NT_STATUS_IS_OK(status)) {
1541 DEBUG(0, ("do_drv_upgrade_printer: "
1542 "Could not create system session_info\n"));
1546 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1548 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1552 DEBUG(10, ("do_drv_upgrade_printer: "
1553 "Got message for new driver [%s]\n", drivername));
1555 /* Iterate the printer list */
1557 for (snum = 0; snum < n_services; snum++) {
1558 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1562 /* ignore [printers] share */
1563 if (strequal(lp_const_servicename(snum), "printers")) {
1567 result = winreg_get_printer(tmp_ctx, session_info, msg,
1568 lp_const_servicename(snum),
1571 if (!W_ERROR_IS_OK(result)) {
1575 if (!pinfo2->drivername) {
1579 if (strcmp(drivername, pinfo2->drivername) != 0) {
1583 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1585 /* all we care about currently is the change_id */
1586 result = winreg_printer_update_changeid(tmp_ctx,
1589 pinfo2->printername);
1591 if (!W_ERROR_IS_OK(result)) {
1592 DEBUG(3, ("do_drv_upgrade_printer: "
1593 "Failed to update changeid [%s]\n",
1594 win_errstr(result)));
1600 talloc_free(tmp_ctx);
1603 /********************************************************************
1604 Update the cache for all printq's with a registered client
1606 ********************************************************************/
1608 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1610 struct printer_handle *printer = printers_list;
1613 /* loop through all printers and update the cache where
1614 a client is connected */
1616 if ((printer->printer_type == SPLHND_PRINTER) &&
1617 ((printer->notify.cli_chan != NULL) &&
1618 (printer->notify.cli_chan->active_connections > 0))) {
1619 snum = print_queue_snum(printer->sharename);
1620 print_queue_status(msg_ctx, snum, NULL, NULL);
1623 printer = printer->next;
1629 /****************************************************************
1630 _spoolss_OpenPrinter
1631 ****************************************************************/
1633 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1634 struct spoolss_OpenPrinter *r)
1636 struct spoolss_OpenPrinterEx e;
1639 ZERO_STRUCT(e.in.userlevel);
1641 e.in.printername = r->in.printername;
1642 e.in.datatype = r->in.datatype;
1643 e.in.devmode_ctr = r->in.devmode_ctr;
1644 e.in.access_mask = r->in.access_mask;
1647 e.out.handle = r->out.handle;
1649 werr = _spoolss_OpenPrinterEx(p, &e);
1651 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1652 /* OpenPrinterEx returns this for a bad
1653 * printer name. We must return WERR_INVALID_PRINTER_NAME
1656 werr = WERR_INVALID_PRINTER_NAME;
1662 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1663 struct spoolss_DeviceMode *orig,
1664 struct spoolss_DeviceMode **dest)
1666 struct spoolss_DeviceMode *dm;
1668 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1673 /* copy all values, then duplicate strings and structs */
1676 dm->devicename = talloc_strdup(dm, orig->devicename);
1677 if (!dm->devicename) {
1680 dm->formname = talloc_strdup(dm, orig->formname);
1681 if (!dm->formname) {
1684 if (orig->driverextra_data.data) {
1685 dm->driverextra_data.data =
1686 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1687 orig->driverextra_data.length);
1688 if (!dm->driverextra_data.data) {
1697 /****************************************************************
1698 _spoolss_OpenPrinterEx
1699 ****************************************************************/
1701 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1702 struct spoolss_OpenPrinterEx *r)
1705 struct printer_handle *Printer=NULL;
1708 if (!r->in.printername) {
1709 return WERR_INVALID_PARAM;
1712 if (r->in.level > 3) {
1713 return WERR_INVALID_PARAM;
1715 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1716 (r->in.level == 2 && !r->in.userlevel.level2) ||
1717 (r->in.level == 3 && !r->in.userlevel.level3)) {
1718 return WERR_INVALID_PARAM;
1721 /* some sanity check because you can open a printer or a print server */
1722 /* aka: \\server\printer or \\server */
1724 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1726 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1727 if (!W_ERROR_IS_OK(result)) {
1728 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1729 "for printer %s\n", r->in.printername));
1730 ZERO_STRUCTP(r->out.handle);
1734 Printer = find_printer_index_by_hnd(p, r->out.handle);
1736 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1737 "handle we created for printer %s\n", r->in.printername));
1738 close_printer_handle(p, r->out.handle);
1739 ZERO_STRUCTP(r->out.handle);
1740 return WERR_INVALID_PARAM;
1744 * First case: the user is opening the print server:
1746 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1747 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1749 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1750 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1751 * or if the user is listed in the smb.conf printer admin parameter.
1753 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1754 * client view printer folder, but does not show the MSAPW.
1756 * Note: this test needs code to check access rights here too. Jeremy
1757 * could you look at this?
1759 * Second case: the user is opening a printer:
1760 * NT doesn't let us connect to a printer if the connecting user
1761 * doesn't have print permission.
1763 * Third case: user is opening a Port Monitor
1764 * access checks same as opening a handle to the print server.
1767 switch (Printer->printer_type )
1770 case SPLHND_PORTMON_TCP:
1771 case SPLHND_PORTMON_LOCAL:
1772 /* Printserver handles use global struct... */
1776 /* Map standard access rights to object specific access rights */
1778 se_map_standard(&r->in.access_mask,
1779 &printserver_std_mapping);
1781 /* Deny any object specific bits that don't apply to print
1782 servers (i.e printer and job specific bits) */
1784 r->in.access_mask &= SEC_MASK_SPECIFIC;
1786 if (r->in.access_mask &
1787 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1788 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1789 close_printer_handle(p, r->out.handle);
1790 ZERO_STRUCTP(r->out.handle);
1791 return WERR_ACCESS_DENIED;
1794 /* Allow admin access */
1796 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1798 if (!lp_ms_add_printer_wizard()) {
1799 close_printer_handle(p, r->out.handle);
1800 ZERO_STRUCTP(r->out.handle);
1801 return WERR_ACCESS_DENIED;
1804 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1805 and not a printer admin, then fail */
1807 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1808 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1809 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1810 !token_contains_name_in_list(
1811 uidtoname(p->session_info->utok.uid),
1812 p->session_info->info3->base.domain.string,
1814 p->session_info->security_token,
1815 lp_printer_admin(snum))) {
1816 close_printer_handle(p, r->out.handle);
1817 ZERO_STRUCTP(r->out.handle);
1818 DEBUG(3,("access DENIED as user is not root, "
1819 "has no printoperator privilege, "
1820 "not a member of the printoperator builtin group and "
1821 "is not in printer admin list"));
1822 return WERR_ACCESS_DENIED;
1825 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1829 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1832 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1835 /* We fall through to return WERR_OK */
1838 case SPLHND_PRINTER:
1839 /* NT doesn't let us connect to a printer if the connecting user
1840 doesn't have print permission. */
1842 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843 close_printer_handle(p, r->out.handle);
1844 ZERO_STRUCTP(r->out.handle);
1848 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1852 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1854 /* map an empty access mask to the minimum access mask */
1855 if (r->in.access_mask == 0x0)
1856 r->in.access_mask = PRINTER_ACCESS_USE;
1859 * If we are not serving the printer driver for this printer,
1860 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1861 * will keep NT clients happy --jerry
1864 if (lp_use_client_driver(snum)
1865 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1867 r->in.access_mask = PRINTER_ACCESS_USE;
1870 /* check smb.conf parameters and the the sec_desc */
1872 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1873 p->client_id->name, p->client_id->addr)) {
1874 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1875 ZERO_STRUCTP(r->out.handle);
1876 return WERR_ACCESS_DENIED;
1879 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1880 p->session_info->security_token, snum) ||
1881 !print_access_check(p->session_info,
1884 r->in.access_mask)) {
1885 DEBUG(3, ("access DENIED for printer open\n"));
1886 close_printer_handle(p, r->out.handle);
1887 ZERO_STRUCTP(r->out.handle);
1888 return WERR_ACCESS_DENIED;
1891 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1892 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1893 close_printer_handle(p, r->out.handle);
1894 ZERO_STRUCTP(r->out.handle);
1895 return WERR_ACCESS_DENIED;
1898 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1899 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1901 r->in.access_mask = PRINTER_ACCESS_USE;
1903 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1904 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1906 winreg_create_printer(p->mem_ctx,
1907 get_session_info_system(),
1909 lp_const_servicename(snum));
1914 /* sanity check to prevent programmer error */
1915 ZERO_STRUCTP(r->out.handle);
1919 Printer->access_granted = r->in.access_mask;
1922 * If the client sent a devmode in the OpenPrinter() call, then
1923 * save it here in case we get a job submission on this handle
1926 if ((Printer->printer_type != SPLHND_SERVER) &&
1927 r->in.devmode_ctr.devmode) {
1928 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1932 #if 0 /* JERRY -- I'm doubtful this is really effective */
1933 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1934 optimization in Windows 2000 clients --jerry */
1936 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1937 && (RA_WIN2K == get_remote_arch()) )
1939 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1940 sys_usleep( 500000 );
1947 /****************************************************************
1948 _spoolss_ClosePrinter
1949 ****************************************************************/
1951 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1952 struct spoolss_ClosePrinter *r)
1954 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1956 if (Printer && Printer->document_started) {
1957 struct spoolss_EndDocPrinter e;
1959 e.in.handle = r->in.handle;
1961 _spoolss_EndDocPrinter(p, &e);
1964 if (!close_printer_handle(p, r->in.handle))
1967 /* clear the returned printer handle. Observed behavior
1968 from Win2k server. Don't think this really matters.
1969 Previous code just copied the value of the closed
1972 ZERO_STRUCTP(r->out.handle);
1977 /****************************************************************
1978 _spoolss_DeletePrinter
1979 ****************************************************************/
1981 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1982 struct spoolss_DeletePrinter *r)
1984 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1988 if (Printer && Printer->document_started) {
1989 struct spoolss_EndDocPrinter e;
1991 e.in.handle = r->in.handle;
1993 _spoolss_EndDocPrinter(p, &e);
1996 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1997 winreg_delete_printer_key(p->mem_ctx,
1998 get_session_info_system(),
2000 lp_const_servicename(snum),
2004 result = delete_printer_handle(p, r->in.handle);
2009 /*******************************************************************
2010 * static function to lookup the version id corresponding to an
2011 * long architecture string
2012 ******************************************************************/
2014 static const struct print_architecture_table_node archi_table[]= {
2016 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2017 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2018 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2019 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2020 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2021 {"Windows IA64", SPL_ARCH_IA64, 3 },
2022 {"Windows x64", SPL_ARCH_X64, 3 },
2026 static int get_version_id(const char *arch)
2030 for (i=0; archi_table[i].long_archi != NULL; i++)
2032 if (strcmp(arch, archi_table[i].long_archi) == 0)
2033 return (archi_table[i].version);
2039 /****************************************************************
2040 _spoolss_DeletePrinterDriver
2041 ****************************************************************/
2043 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2044 struct spoolss_DeletePrinterDriver *r)
2047 struct spoolss_DriverInfo8 *info = NULL;
2048 struct spoolss_DriverInfo8 *info_win2k = NULL;
2052 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2053 and not a printer admin, then fail */
2055 if ( (p->session_info->utok.uid != sec_initial_uid())
2056 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2057 && !token_contains_name_in_list(
2058 uidtoname(p->session_info->utok.uid),
2059 p->session_info->info3->base.domain.string,
2061 p->session_info->security_token,
2062 lp_printer_admin(-1)) )
2064 return WERR_ACCESS_DENIED;
2067 /* check that we have a valid driver name first */
2069 if ((version = get_version_id(r->in.architecture)) == -1)
2070 return WERR_INVALID_ENVIRONMENT;
2072 status = winreg_get_driver(p->mem_ctx,
2073 get_session_info_system(),
2075 r->in.architecture, r->in.driver,
2077 if (!W_ERROR_IS_OK(status)) {
2078 /* try for Win2k driver if "Windows NT x86" */
2080 if ( version == 2 ) {
2083 status = winreg_get_driver(p->mem_ctx,
2084 get_session_info_system(),
2089 if (!W_ERROR_IS_OK(status)) {
2090 status = WERR_UNKNOWN_PRINTER_DRIVER;
2094 /* otherwise it was a failure */
2096 status = WERR_UNKNOWN_PRINTER_DRIVER;
2102 if (printer_driver_in_use(p->mem_ctx,
2103 get_session_info_system(),
2106 status = WERR_PRINTER_DRIVER_IN_USE;
2111 status = winreg_get_driver(p->mem_ctx,
2112 get_session_info_system(),
2115 r->in.driver, 3, &info_win2k);
2116 if (W_ERROR_IS_OK(status)) {
2117 /* if we get to here, we now have 2 driver info structures to remove */
2118 /* remove the Win2k driver first*/
2120 status = winreg_del_driver(p->mem_ctx,
2121 get_session_info_system(),
2124 talloc_free(info_win2k);
2126 /* this should not have failed---if it did, report to client */
2127 if (!W_ERROR_IS_OK(status)) {
2133 status = winreg_del_driver(p->mem_ctx,
2134 get_session_info_system(),
2144 /****************************************************************
2145 _spoolss_DeletePrinterDriverEx
2146 ****************************************************************/
2148 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2149 struct spoolss_DeletePrinterDriverEx *r)
2151 struct spoolss_DriverInfo8 *info = NULL;
2152 struct spoolss_DriverInfo8 *info_win2k = NULL;
2157 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2158 and not a printer admin, then fail */
2160 if ( (p->session_info->utok.uid != sec_initial_uid())
2161 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2162 && !token_contains_name_in_list(
2163 uidtoname(p->session_info->utok.uid),
2164 p->session_info->info3->base.domain.string,
2166 p->session_info->security_token, lp_printer_admin(-1)) )
2168 return WERR_ACCESS_DENIED;
2171 /* check that we have a valid driver name first */
2172 if ((version = get_version_id(r->in.architecture)) == -1) {
2173 /* this is what NT returns */
2174 return WERR_INVALID_ENVIRONMENT;
2177 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2178 version = r->in.version;
2180 status = winreg_get_driver(p->mem_ctx,
2181 get_session_info_system(),
2187 if (!W_ERROR_IS_OK(status)) {
2188 status = WERR_UNKNOWN_PRINTER_DRIVER;
2191 * if the client asked for a specific version,
2192 * or this is something other than Windows NT x86,
2196 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2199 /* try for Win2k driver if "Windows NT x86" */
2202 status = winreg_get_driver(info,
2203 get_session_info_system(),
2208 if (!W_ERROR_IS_OK(status)) {
2209 status = WERR_UNKNOWN_PRINTER_DRIVER;
2214 if (printer_driver_in_use(info,
2215 get_session_info_system(),
2218 status = WERR_PRINTER_DRIVER_IN_USE;
2223 * we have a couple of cases to consider.
2224 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2225 * then the delete should fail if **any** files overlap with
2227 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2228 * non-overlapping files
2229 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2230 * is set, the do not delete any files
2231 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2234 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2236 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2239 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2240 printer_driver_files_in_use(info,
2241 get_session_info_system(),
2244 /* no idea of the correct error here */
2245 status = WERR_ACCESS_DENIED;
2250 /* also check for W32X86/3 if necessary; maybe we already have? */
2252 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2253 status = winreg_get_driver(info,
2254 get_session_info_system(),
2257 r->in.driver, 3, &info_win2k);
2258 if (W_ERROR_IS_OK(status)) {
2261 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2262 printer_driver_files_in_use(info,
2263 get_session_info_system(),
2266 /* no idea of the correct error here */
2267 talloc_free(info_win2k);
2268 status = WERR_ACCESS_DENIED;
2272 /* if we get to here, we now have 2 driver info structures to remove */
2273 /* remove the Win2k driver first*/
2275 status = winreg_del_driver(info,
2276 get_session_info_system(),
2281 /* this should not have failed---if it did, report to client */
2283 if (!W_ERROR_IS_OK(status)) {
2288 * now delete any associated files if delete_files is
2289 * true. Even if this part failes, we return succes
2290 * because the driver doesn not exist any more
2293 delete_driver_files(get_session_info_system(),
2299 status = winreg_del_driver(info,
2300 get_session_info_system(),
2304 if (!W_ERROR_IS_OK(status)) {
2309 * now delete any associated files if delete_files is
2310 * true. Even if this part failes, we return succes
2311 * because the driver doesn not exist any more
2314 delete_driver_files(get_session_info_system(), info);
2323 /********************************************************************
2324 GetPrinterData on a printer server Handle.
2325 ********************************************************************/
2327 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2329 enum winreg_Type *type,
2330 union spoolss_PrinterData *data)
2332 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2334 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2340 if (!StrCaseCmp(value, "BeepEnabled")) {
2346 if (!StrCaseCmp(value, "EventLog")) {
2348 /* formally was 0x1b */
2353 if (!StrCaseCmp(value, "NetPopup")) {
2359 if (!StrCaseCmp(value, "MajorVersion")) {
2362 /* Windows NT 4.0 seems to not allow uploading of drivers
2363 to a server that reports 0x3 as the MajorVersion.
2364 need to investigate more how Win2k gets around this .
2367 if (RA_WINNT == get_remote_arch()) {
2376 if (!StrCaseCmp(value, "MinorVersion")) {
2383 * uint32_t size = 0x114
2384 * uint32_t major = 5
2385 * uint32_t minor = [0|1]
2386 * uint32_t build = [2195|2600]
2387 * extra unicode string = e.g. "Service Pack 3"
2389 if (!StrCaseCmp(value, "OSVersion")) {
2391 enum ndr_err_code ndr_err;
2392 struct spoolss_OSVersion os;
2394 os.major = 5; /* Windows 2000 == 5.0 */
2396 os.build = 2195; /* build */
2397 os.extra_string = ""; /* leave extra string empty */
2399 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2400 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2401 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2402 return WERR_GENERAL_FAILURE;
2406 data->binary = blob;
2412 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2415 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2416 W_ERROR_HAVE_NO_MEMORY(data->string);
2421 if (!StrCaseCmp(value, "Architecture")) {
2423 data->string = talloc_strdup(mem_ctx,
2424 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2425 W_ERROR_HAVE_NO_MEMORY(data->string);
2430 if (!StrCaseCmp(value, "DsPresent")) {
2433 /* only show the publish check box if we are a
2434 member of a AD domain */
2436 if (lp_security() == SEC_ADS) {
2444 if (!StrCaseCmp(value, "DNSMachineName")) {
2445 const char *hostname = get_mydnsfullname();
2448 return WERR_BADFILE;
2452 data->string = talloc_strdup(mem_ctx, hostname);
2453 W_ERROR_HAVE_NO_MEMORY(data->string);
2460 return WERR_INVALID_PARAM;
2463 /****************************************************************
2464 _spoolss_GetPrinterData
2465 ****************************************************************/
2467 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2468 struct spoolss_GetPrinterData *r)
2470 struct spoolss_GetPrinterDataEx r2;
2472 r2.in.handle = r->in.handle;
2473 r2.in.key_name = "PrinterDriverData";
2474 r2.in.value_name = r->in.value_name;
2475 r2.in.offered = r->in.offered;
2476 r2.out.type = r->out.type;
2477 r2.out.data = r->out.data;
2478 r2.out.needed = r->out.needed;
2480 return _spoolss_GetPrinterDataEx(p, &r2);
2483 /*********************************************************
2484 Connect to the client machine.
2485 **********************************************************/
2487 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2488 struct sockaddr_storage *client_ss, const char *remote_machine)
2491 struct cli_state *the_cli;
2492 struct sockaddr_storage rm_addr;
2493 char addr[INET6_ADDRSTRLEN];
2495 if ( is_zero_addr(client_ss) ) {
2496 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2498 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2499 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2502 print_sockaddr(addr, sizeof(addr), &rm_addr);
2504 rm_addr = *client_ss;
2505 print_sockaddr(addr, sizeof(addr), &rm_addr);
2506 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2510 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2511 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2516 /* setup the connection */
2517 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2518 &rm_addr, 0, "IPC$", "IPC",
2522 0, lp_client_signing());
2524 if ( !NT_STATUS_IS_OK( ret ) ) {
2525 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2530 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2531 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2532 cli_shutdown(the_cli);
2537 * Ok - we have an anonymous connection to the IPC$ share.
2538 * Now start the NT Domain stuff :-).
2541 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2542 if (!NT_STATUS_IS_OK(ret)) {
2543 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2544 remote_machine, nt_errstr(ret)));
2545 cli_shutdown(the_cli);
2552 /***************************************************************************
2553 Connect to the client.
2554 ****************************************************************************/
2556 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2557 uint32_t localprinter,
2558 enum winreg_Type type,
2559 struct policy_handle *handle,
2560 struct notify_back_channel **_chan,
2561 struct sockaddr_storage *client_ss,
2562 struct messaging_context *msg_ctx)
2566 struct notify_back_channel *chan;
2568 for (chan = back_channels; chan; chan = chan->next) {
2569 if (memcmp(&chan->client_address, client_ss,
2570 sizeof(struct sockaddr_storage)) == 0) {
2576 * If it's the first connection, contact the client
2577 * and connect to the IPC$ share anonymously
2580 fstring unix_printer;
2582 /* the +2 is to strip the leading 2 backslashs */
2583 fstrcpy(unix_printer, printer + 2);
2585 chan = talloc_zero(back_channels, struct notify_back_channel);
2589 chan->client_address = *client_ss;
2591 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2595 chan->binding_handle = chan->cli_pipe->binding_handle;
2597 DLIST_ADD(back_channels, chan);
2599 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2600 receive_notify2_message_list);
2601 /* Tell the connections db we're now interested in printer
2602 * notify messages. */
2603 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2604 true, FLAG_MSG_PRINT_NOTIFY);
2608 * Tell the specific printing tdb we want messages for this printer
2609 * by registering our PID.
2612 if (!print_notify_register_pid(snum)) {
2613 DEBUG(0, ("Failed to register our pid for printer %s\n",
2617 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2626 if (!NT_STATUS_IS_OK(status)) {
2627 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2628 result = ntstatus_to_werror(status);
2629 } else if (!W_ERROR_IS_OK(result)) {
2630 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2633 chan->active_connections++;
2636 return (W_ERROR_IS_OK(result));
2639 /****************************************************************
2640 ****************************************************************/
2642 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2643 const struct spoolss_NotifyOption *r)
2645 struct spoolss_NotifyOption *option;
2652 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2659 if (!option->count) {
2663 option->types = talloc_zero_array(option,
2664 struct spoolss_NotifyOptionType, option->count);
2665 if (!option->types) {
2666 talloc_free(option);
2670 for (i=0; i < option->count; i++) {
2671 option->types[i] = r->types[i];
2673 if (option->types[i].count) {
2674 option->types[i].fields = talloc_zero_array(option,
2675 union spoolss_Field, option->types[i].count);
2676 if (!option->types[i].fields) {
2677 talloc_free(option);
2680 for (k=0; k<option->types[i].count; k++) {
2681 option->types[i].fields[k] =
2682 r->types[i].fields[k];
2690 /****************************************************************
2691 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2693 * before replying OK: status=0 a rpc call is made to the workstation
2694 * asking ReplyOpenPrinter
2696 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2697 * called from api_spoolss_rffpcnex
2698 ****************************************************************/
2700 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2701 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2704 struct spoolss_NotifyOption *option = r->in.notify_options;
2705 struct sockaddr_storage client_ss;
2707 /* store the notify value in the printer struct */
2709 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2712 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2713 "Invalid handle (%s:%u:%u).\n",
2714 OUR_HANDLE(r->in.handle)));
2718 Printer->notify.flags = r->in.flags;
2719 Printer->notify.options = r->in.options;
2720 Printer->notify.printerlocal = r->in.printer_local;
2721 Printer->notify.msg_ctx = p->msg_ctx;
2723 TALLOC_FREE(Printer->notify.option);
2724 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2726 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2728 /* Connect to the client machine and send a ReplyOpenPrinter */
2730 if ( Printer->printer_type == SPLHND_SERVER)
2732 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2733 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2736 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2737 "client_address is %s\n", p->client_id->addr));
2739 if (!lp_print_notify_backchannel(snum)) {
2740 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2741 "backchannel disabled\n"));
2742 return WERR_SERVER_UNAVAILABLE;
2745 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2747 return WERR_SERVER_UNAVAILABLE;
2750 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2751 Printer->notify.printerlocal, REG_SZ,
2752 &Printer->notify.cli_hnd,
2753 &Printer->notify.cli_chan,
2754 &client_ss, p->msg_ctx)) {
2755 return WERR_SERVER_UNAVAILABLE;
2761 /*******************************************************************
2762 * fill a notify_info_data with the servername
2763 ********************************************************************/
2765 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2767 struct spoolss_Notify *data,
2768 print_queue_struct *queue,
2769 struct spoolss_PrinterInfo2 *pinfo2,
2770 TALLOC_CTX *mem_ctx)
2772 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2775 /*******************************************************************
2776 * fill a notify_info_data with the printername (not including the servername).
2777 ********************************************************************/
2779 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2781 struct spoolss_Notify *data,
2782 print_queue_struct *queue,
2783 struct spoolss_PrinterInfo2 *pinfo2,
2784 TALLOC_CTX *mem_ctx)
2786 /* the notify name should not contain the \\server\ part */
2787 const char *p = strrchr(pinfo2->printername, '\\');
2790 p = pinfo2->printername;
2795 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2798 /*******************************************************************
2799 * fill a notify_info_data with the servicename
2800 ********************************************************************/
2802 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2804 struct spoolss_Notify *data,
2805 print_queue_struct *queue,
2806 struct spoolss_PrinterInfo2 *pinfo2,
2807 TALLOC_CTX *mem_ctx)
2809 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2812 /*******************************************************************
2813 * fill a notify_info_data with the port name
2814 ********************************************************************/
2816 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2818 struct spoolss_Notify *data,
2819 print_queue_struct *queue,
2820 struct spoolss_PrinterInfo2 *pinfo2,
2821 TALLOC_CTX *mem_ctx)
2823 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2826 /*******************************************************************
2827 * fill a notify_info_data with the printername
2828 * but it doesn't exist, have to see what to do
2829 ********************************************************************/
2831 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2833 struct spoolss_Notify *data,
2834 print_queue_struct *queue,
2835 struct spoolss_PrinterInfo2 *pinfo2,
2836 TALLOC_CTX *mem_ctx)
2838 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2841 /*******************************************************************
2842 * fill a notify_info_data with the comment
2843 ********************************************************************/
2845 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2847 struct spoolss_Notify *data,
2848 print_queue_struct *queue,
2849 struct spoolss_PrinterInfo2 *pinfo2,
2850 TALLOC_CTX *mem_ctx)
2854 if (*pinfo2->comment == '\0') {
2855 p = lp_comment(snum);
2857 p = pinfo2->comment;
2860 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2863 /*******************************************************************
2864 * fill a notify_info_data with the comment
2865 * location = "Room 1, floor 2, building 3"
2866 ********************************************************************/
2868 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2870 struct spoolss_Notify *data,
2871 print_queue_struct *queue,
2872 struct spoolss_PrinterInfo2 *pinfo2,
2873 TALLOC_CTX *mem_ctx)
2875 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2878 /*******************************************************************
2879 * fill a notify_info_data with the device mode
2880 * jfm:xxxx don't to it for know but that's a real problem !!!
2881 ********************************************************************/
2883 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2885 struct spoolss_Notify *data,
2886 print_queue_struct *queue,
2887 struct spoolss_PrinterInfo2 *pinfo2,
2888 TALLOC_CTX *mem_ctx)
2890 /* for a dummy implementation we have to zero the fields */
2891 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2894 /*******************************************************************
2895 * fill a notify_info_data with the separator file name
2896 ********************************************************************/
2898 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2900 struct spoolss_Notify *data,
2901 print_queue_struct *queue,
2902 struct spoolss_PrinterInfo2 *pinfo2,
2903 TALLOC_CTX *mem_ctx)
2905 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2908 /*******************************************************************
2909 * fill a notify_info_data with the print processor
2910 * jfm:xxxx return always winprint to indicate we don't do anything to it
2911 ********************************************************************/
2913 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2915 struct spoolss_Notify *data,
2916 print_queue_struct *queue,
2917 struct spoolss_PrinterInfo2 *pinfo2,
2918 TALLOC_CTX *mem_ctx)
2920 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2923 /*******************************************************************
2924 * fill a notify_info_data with the print processor options
2925 * jfm:xxxx send an empty string
2926 ********************************************************************/
2928 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2930 struct spoolss_Notify *data,
2931 print_queue_struct *queue,
2932 struct spoolss_PrinterInfo2 *pinfo2,
2933 TALLOC_CTX *mem_ctx)
2935 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2938 /*******************************************************************
2939 * fill a notify_info_data with the data type
2940 * jfm:xxxx always send RAW as data type
2941 ********************************************************************/
2943 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2945 struct spoolss_Notify *data,
2946 print_queue_struct *queue,
2947 struct spoolss_PrinterInfo2 *pinfo2,
2948 TALLOC_CTX *mem_ctx)
2950 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2953 /*******************************************************************
2954 * fill a notify_info_data with the security descriptor
2955 * jfm:xxxx send an null pointer to say no security desc
2956 * have to implement security before !
2957 ********************************************************************/
2959 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2961 struct spoolss_Notify *data,
2962 print_queue_struct *queue,
2963 struct spoolss_PrinterInfo2 *pinfo2,
2964 TALLOC_CTX *mem_ctx)
2966 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2969 /*******************************************************************
2970 * fill a notify_info_data with the attributes
2971 * jfm:xxxx a samba printer is always shared
2972 ********************************************************************/
2974 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2976 struct spoolss_Notify *data,
2977 print_queue_struct *queue,
2978 struct spoolss_PrinterInfo2 *pinfo2,
2979 TALLOC_CTX *mem_ctx)
2981 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2984 /*******************************************************************
2985 * fill a notify_info_data with the priority
2986 ********************************************************************/
2988 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2990 struct spoolss_Notify *data,
2991 print_queue_struct *queue,
2992 struct spoolss_PrinterInfo2 *pinfo2,
2993 TALLOC_CTX *mem_ctx)
2995 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2998 /*******************************************************************
2999 * fill a notify_info_data with the default priority
3000 ********************************************************************/
3002 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3004 struct spoolss_Notify *data,
3005 print_queue_struct *queue,
3006 struct spoolss_PrinterInfo2 *pinfo2,
3007 TALLOC_CTX *mem_ctx)
3009 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3012 /*******************************************************************
3013 * fill a notify_info_data with the start time
3014 ********************************************************************/
3016 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3018 struct spoolss_Notify *data,
3019 print_queue_struct *queue,
3020 struct spoolss_PrinterInfo2 *pinfo2,
3021 TALLOC_CTX *mem_ctx)
3023 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3026 /*******************************************************************
3027 * fill a notify_info_data with the until time
3028 ********************************************************************/
3030 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3032 struct spoolss_Notify *data,
3033 print_queue_struct *queue,
3034 struct spoolss_PrinterInfo2 *pinfo2,
3035 TALLOC_CTX *mem_ctx)
3037 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3040 /*******************************************************************
3041 * fill a notify_info_data with the status
3042 ********************************************************************/
3044 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3046 struct spoolss_Notify *data,
3047 print_queue_struct *queue,
3048 struct spoolss_PrinterInfo2 *pinfo2,
3049 TALLOC_CTX *mem_ctx)
3051 print_status_struct status;
3053 print_queue_length(msg_ctx, snum, &status);
3054 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3057 /*******************************************************************
3058 * fill a notify_info_data with the number of jobs queued
3059 ********************************************************************/
3061 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3063 struct spoolss_Notify *data,
3064 print_queue_struct *queue,
3065 struct spoolss_PrinterInfo2 *pinfo2,
3066 TALLOC_CTX *mem_ctx)
3068 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3069 data, print_queue_length(msg_ctx, snum, NULL));
3072 /*******************************************************************
3073 * fill a notify_info_data with the average ppm
3074 ********************************************************************/
3076 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3078 struct spoolss_Notify *data,
3079 print_queue_struct *queue,
3080 struct spoolss_PrinterInfo2 *pinfo2,
3081 TALLOC_CTX *mem_ctx)
3083 /* always respond 8 pages per minutes */
3084 /* a little hard ! */
3085 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3088 /*******************************************************************
3089 * fill a notify_info_data with username
3090 ********************************************************************/
3092 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3094 struct spoolss_Notify *data,
3095 print_queue_struct *queue,
3096 struct spoolss_PrinterInfo2 *pinfo2,
3097 TALLOC_CTX *mem_ctx)
3099 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3102 /*******************************************************************
3103 * fill a notify_info_data with job status
3104 ********************************************************************/
3106 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3108 struct spoolss_Notify *data,
3109 print_queue_struct *queue,
3110 struct spoolss_PrinterInfo2 *pinfo2,
3111 TALLOC_CTX *mem_ctx)
3113 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3116 /*******************************************************************
3117 * fill a notify_info_data with job name
3118 ********************************************************************/
3120 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3122 struct spoolss_Notify *data,
3123 print_queue_struct *queue,
3124 struct spoolss_PrinterInfo2 *pinfo2,
3125 TALLOC_CTX *mem_ctx)
3127 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3130 /*******************************************************************
3131 * fill a notify_info_data with job status
3132 ********************************************************************/
3134 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3136 struct spoolss_Notify *data,
3137 print_queue_struct *queue,
3138 struct spoolss_PrinterInfo2 *pinfo2,
3139 TALLOC_CTX *mem_ctx)
3142 * Now we're returning job status codes we just return a "" here. JRA.
3147 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3150 switch (queue->status) {
3155 p = ""; /* NT provides the paused string */
3164 #endif /* NO LONGER NEEDED. */
3166 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3169 /*******************************************************************
3170 * fill a notify_info_data with job time
3171 ********************************************************************/
3173 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3175 struct spoolss_Notify *data,
3176 print_queue_struct *queue,
3177 struct spoolss_PrinterInfo2 *pinfo2,
3178 TALLOC_CTX *mem_ctx)
3180 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3183 /*******************************************************************
3184 * fill a notify_info_data with job size
3185 ********************************************************************/
3187 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3189 struct spoolss_Notify *data,
3190 print_queue_struct *queue,
3191 struct spoolss_PrinterInfo2 *pinfo2,
3192 TALLOC_CTX *mem_ctx)
3194 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3197 /*******************************************************************
3198 * fill a notify_info_data with page info
3199 ********************************************************************/
3200 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3202 struct spoolss_Notify *data,
3203 print_queue_struct *queue,
3204 struct spoolss_PrinterInfo2 *pinfo2,
3205 TALLOC_CTX *mem_ctx)
3207 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3210 /*******************************************************************
3211 * fill a notify_info_data with pages printed info.
3212 ********************************************************************/
3213 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3215 struct spoolss_Notify *data,
3216 print_queue_struct *queue,
3217 struct spoolss_PrinterInfo2 *pinfo2,
3218 TALLOC_CTX *mem_ctx)
3220 /* Add code when back-end tracks this */
3221 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3224 /*******************************************************************
3225 Fill a notify_info_data with job position.
3226 ********************************************************************/
3228 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3230 struct spoolss_Notify *data,
3231 print_queue_struct *queue,
3232 struct spoolss_PrinterInfo2 *pinfo2,
3233 TALLOC_CTX *mem_ctx)
3235 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3238 /*******************************************************************
3239 Fill a notify_info_data with submitted time.
3240 ********************************************************************/
3242 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3244 struct spoolss_Notify *data,
3245 print_queue_struct *queue,
3246 struct spoolss_PrinterInfo2 *pinfo2,
3247 TALLOC_CTX *mem_ctx)
3249 data->data.string.string = NULL;
3250 data->data.string.size = 0;
3252 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3253 &data->data.string.string,
3254 &data->data.string.size);
3258 struct s_notify_info_data_table
3260 enum spoolss_NotifyType type;
3263 enum spoolss_NotifyTable variable_type;
3264 void (*fn) (struct messaging_context *msg_ctx,
3265 int snum, struct spoolss_Notify *data,
3266 print_queue_struct *queue,
3267 struct spoolss_PrinterInfo2 *pinfo2,
3268 TALLOC_CTX *mem_ctx);
3271 /* A table describing the various print notification constants and
3272 whether the notification data is a pointer to a variable sized
3273 buffer, a one value uint32_t or a two value uint32_t. */
3275 static const struct s_notify_info_data_table notify_info_data_table[] =
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3328 /*******************************************************************
3329 Return the variable_type of info_data structure.
3330 ********************************************************************/
3332 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3337 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3338 if ( (notify_info_data_table[i].type == type) &&
3339 (notify_info_data_table[i].field == field) ) {
3340 return notify_info_data_table[i].variable_type;
3344 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3346 return (enum spoolss_NotifyTable) 0;
3349 /****************************************************************************
3350 ****************************************************************************/
3352 static bool search_notify(enum spoolss_NotifyType type,
3358 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3359 if (notify_info_data_table[i].type == type &&
3360 notify_info_data_table[i].field == field &&
3361 notify_info_data_table[i].fn != NULL) {
3370 /****************************************************************************
3371 ****************************************************************************/
3373 static void construct_info_data(struct spoolss_Notify *info_data,
3374 enum spoolss_NotifyType type,
3375 uint16_t field, int id)
3377 info_data->type = type;
3378 info_data->field.field = field;
3379 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3380 info_data->job_id = id;
3383 /*******************************************************************
3385 * fill a notify_info struct with info asked
3387 ********************************************************************/
3389 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3390 struct printer_handle *print_hnd,
3391 struct spoolss_NotifyInfo *info,
3392 struct spoolss_PrinterInfo2 *pinfo2,
3394 const struct spoolss_NotifyOptionType *option_type,
3396 TALLOC_CTX *mem_ctx)
3399 enum spoolss_NotifyType type;
3402 struct spoolss_Notify *current_data;
3403 print_queue_struct *queue=NULL;
3405 type = option_type->type;
3407 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3408 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3409 option_type->count, lp_servicename(snum)));
3411 for(field_num=0; field_num < option_type->count; field_num++) {
3412 field = option_type->fields[field_num].field;
3414 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3416 if (!search_notify(type, field, &j) )
3419 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3420 struct spoolss_Notify,
3422 if (info->notifies == NULL) {
3423 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3427 current_data = &info->notifies[info->count];
3429 construct_info_data(current_data, type, field, id);
3431 DEBUG(10, ("construct_notify_printer_info: "
3432 "calling [%s] snum=%d printername=[%s])\n",
3433 notify_info_data_table[j].name, snum,
3434 pinfo2->printername));
3436 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3437 queue, pinfo2, mem_ctx);
3445 /*******************************************************************
3447 * fill a notify_info struct with info asked
3449 ********************************************************************/
3451 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3452 print_queue_struct *queue,
3453 struct spoolss_NotifyInfo *info,
3454 struct spoolss_PrinterInfo2 *pinfo2,
3456 const struct spoolss_NotifyOptionType *option_type,
3458 TALLOC_CTX *mem_ctx)
3461 enum spoolss_NotifyType type;
3463 struct spoolss_Notify *current_data;
3465 DEBUG(4,("construct_notify_jobs_info\n"));
3467 type = option_type->type;
3469 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3470 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3471 option_type->count));
3473 for(field_num=0; field_num<option_type->count; field_num++) {
3474 field = option_type->fields[field_num].field;
3476 if (!search_notify(type, field, &j) )
3479 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3480 struct spoolss_Notify,
3482 if (info->notifies == NULL) {
3483 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3487 current_data=&(info->notifies[info->count]);
3489 construct_info_data(current_data, type, field, id);
3490 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3491 queue, pinfo2, mem_ctx);
3499 * JFM: The enumeration is not that simple, it's even non obvious.
3501 * let's take an example: I want to monitor the PRINTER SERVER for
3502 * the printer's name and the number of jobs currently queued.
3503 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3504 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3506 * I have 3 printers on the back of my server.
3508 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3511 * 1 printer 1 name 1
3512 * 2 printer 1 cjob 1
3513 * 3 printer 2 name 2
3514 * 4 printer 2 cjob 2
3515 * 5 printer 3 name 3
3516 * 6 printer 3 name 3
3518 * that's the print server case, the printer case is even worse.
3521 /*******************************************************************
3523 * enumerate all printers on the printserver
3524 * fill a notify_info struct with info asked
3526 ********************************************************************/
3528 static WERROR printserver_notify_info(struct pipes_struct *p,
3529 struct policy_handle *hnd,
3530 struct spoolss_NotifyInfo *info,
3531 TALLOC_CTX *mem_ctx)
3534 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3535 int n_services=lp_numservices();
3537 struct spoolss_NotifyOption *option;
3538 struct spoolss_NotifyOptionType option_type;
3539 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3542 DEBUG(4,("printserver_notify_info\n"));
3547 option = Printer->notify.option;
3550 info->notifies = NULL;
3553 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3554 sending a ffpcn() request first */
3559 for (i=0; i<option->count; i++) {
3560 option_type = option->types[i];
3562 if (option_type.type != PRINTER_NOTIFY_TYPE)
3565 for (snum = 0; snum < n_services; snum++) {
3566 if (!lp_browseable(snum) ||
3567 !lp_snum_ok(snum) ||
3568 !lp_print_ok(snum)) {
3569 continue; /* skip */
3572 /* Maybe we should use the SYSTEM session_info here... */
3573 result = winreg_get_printer(mem_ctx,
3574 get_session_info_system(),
3576 lp_servicename(snum),
3578 if (!W_ERROR_IS_OK(result)) {
3579 DEBUG(4, ("printserver_notify_info: "
3580 "Failed to get printer [%s]\n",
3581 lp_servicename(snum)));
3586 construct_notify_printer_info(p->msg_ctx,
3592 TALLOC_FREE(pinfo2);
3598 * Debugging information, don't delete.
3601 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3602 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3603 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3605 for (i=0; i<info->count; i++) {
3606 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3607 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3608 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3615 /*******************************************************************
3617 * fill a notify_info struct with info asked
3619 ********************************************************************/
3621 static WERROR printer_notify_info(struct pipes_struct *p,
3622 struct policy_handle *hnd,
3623 struct spoolss_NotifyInfo *info,
3624 TALLOC_CTX *mem_ctx)
3627 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3630 struct spoolss_NotifyOption *option;
3631 struct spoolss_NotifyOptionType option_type;
3633 print_queue_struct *queue=NULL;
3634 print_status_struct status;
3635 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3638 DEBUG(4,("printer_notify_info\n"));
3643 option = Printer->notify.option;
3647 info->notifies = NULL;
3650 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3651 sending a ffpcn() request first */
3656 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3660 /* Maybe we should use the SYSTEM session_info here... */
3661 result = winreg_get_printer(mem_ctx,
3662 get_session_info_system(),
3664 lp_servicename(snum), &pinfo2);
3665 if (!W_ERROR_IS_OK(result)) {
3669 for (i=0; i<option->count; i++) {
3670 option_type = option->types[i];
3672 switch (option_type.type) {
3673 case PRINTER_NOTIFY_TYPE:
3674 if (construct_notify_printer_info(p->msg_ctx,
3683 case JOB_NOTIFY_TYPE:
3685 count = print_queue_status(p->msg_ctx, snum, &queue,
3688 for (j=0; j<count; j++) {
3689 construct_notify_jobs_info(p->msg_ctx,
3703 * Debugging information, don't delete.
3706 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3707 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3708 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3710 for (i=0; i<info->count; i++) {
3711 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3712 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3713 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3717 talloc_free(pinfo2);
3721 /****************************************************************
3722 _spoolss_RouterRefreshPrinterChangeNotify
3723 ****************************************************************/
3725 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3726 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3728 struct spoolss_NotifyInfo *info;
3730 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3731 WERROR result = WERR_BADFID;
3733 /* we always have a spoolss_NotifyInfo struct */
3734 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3736 result = WERR_NOMEM;
3740 *r->out.info = info;
3743 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3744 "Invalid handle (%s:%u:%u).\n",
3745 OUR_HANDLE(r->in.handle)));
3749 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3752 * We are now using the change value, and
3753 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3754 * I don't have a global notification system, I'm sending back all the
3755 * information even when _NOTHING_ has changed.
3758 /* We need to keep track of the change value to send back in
3759 RRPCN replies otherwise our updates are ignored. */
3761 Printer->notify.fnpcn = true;
3763 if (Printer->notify.cli_chan != NULL &&
3764 Printer->notify.cli_chan->active_connections > 0) {
3765 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3766 "Saving change value in request [%x]\n",
3768 Printer->notify.change = r->in.change_low;
3771 /* just ignore the spoolss_NotifyOption */
3773 switch (Printer->printer_type) {
3775 result = printserver_notify_info(p, r->in.handle,
3779 case SPLHND_PRINTER:
3780 result = printer_notify_info(p, r->in.handle,
3785 Printer->notify.fnpcn = false;
3791 /********************************************************************
3792 ********************************************************************/
3794 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3795 const char *servername,
3796 const char *printername,
3797 const char **printername_p)
3799 /* FIXME: add lp_force_printername() */
3801 if (servername == NULL) {
3802 *printername_p = talloc_strdup(mem_ctx, printername);
3803 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3807 if (servername[0] == '\\' && servername[1] == '\\') {
3811 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3812 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3817 /********************************************************************
3818 ********************************************************************/
3820 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3821 const char *printername)
3827 dm->devicename = talloc_strndup(dm, printername,
3828 MIN(strlen(printername), 31));
3831 /********************************************************************
3832 * construct_printer_info_0
3833 * fill a printer_info_0 struct
3834 ********************************************************************/
3836 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3837 const struct auth_serversupplied_info *session_info,
3838 struct messaging_context *msg_ctx,
3839 struct spoolss_PrinterInfo2 *info2,
3840 const char *servername,
3841 struct spoolss_PrinterInfo0 *r,
3845 struct printer_session_counter *session_counter;
3846 struct timeval setuptime;
3847 print_status_struct status;
3850 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3851 if (!W_ERROR_IS_OK(result)) {
3856 r->servername = talloc_strdup(mem_ctx, servername);
3857 W_ERROR_HAVE_NO_MEMORY(r->servername);
3859 r->servername = NULL;
3862 count = print_queue_length(msg_ctx, snum, &status);
3864 /* check if we already have a counter for this printer */
3865 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3866 if (session_counter->snum == snum)
3870 /* it's the first time, add it to the list */
3871 if (session_counter == NULL) {
3872 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3873 W_ERROR_HAVE_NO_MEMORY(session_counter);
3874 session_counter->snum = snum;
3875 session_counter->counter = 0;
3876 DLIST_ADD(counter_list, session_counter);
3880 session_counter->counter++;
3886 get_startup_time(&setuptime);
3887 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3890 * the global_counter should be stored in a TDB as it's common to all the clients
3891 * and should be zeroed on samba startup
3893 r->global_counter = session_counter->counter;
3895 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3896 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3897 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3898 r->free_build = SPOOLSS_RELEASE_BUILD;
3900 r->max_spooling = 0;
3901 r->session_counter = session_counter->counter;
3902 r->num_error_out_of_paper = 0x0;
3903 r->num_error_not_ready = 0x0; /* number of print failure */
3905 r->number_of_processors = 0x1;
3906 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3907 r->high_part_total_bytes = 0x0;
3909 /* ChangeID in milliseconds*/
3910 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3911 info2->sharename, &r->change_id);
3913 r->last_error = WERR_OK;
3914 r->status = nt_printq_status(status.status);
3915 r->enumerate_network_printers = 0x0;
3916 r->c_setprinter = 0x0;
3917 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3918 r->processor_level = 0x6; /* 6 ???*/
3927 /********************************************************************
3928 * construct_printer_info1
3929 * fill a spoolss_PrinterInfo1 struct
3930 ********************************************************************/
3932 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3933 const struct spoolss_PrinterInfo2 *info2,
3935 const char *servername,
3936 struct spoolss_PrinterInfo1 *r,
3943 if (info2->comment == NULL || info2->comment[0] == '\0') {
3944 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3946 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3948 W_ERROR_HAVE_NO_MEMORY(r->comment);
3950 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3951 if (!W_ERROR_IS_OK(result)) {
3955 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3959 W_ERROR_HAVE_NO_MEMORY(r->description);
3964 /********************************************************************
3965 * construct_printer_info2
3966 * fill a spoolss_PrinterInfo2 struct
3967 ********************************************************************/
3969 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3970 struct messaging_context *msg_ctx,
3971 const struct spoolss_PrinterInfo2 *info2,
3972 const char *servername,
3973 struct spoolss_PrinterInfo2 *r,
3977 print_status_struct status;
3980 count = print_queue_length(msg_ctx, snum, &status);
3983 r->servername = talloc_strdup(mem_ctx, servername);
3984 W_ERROR_HAVE_NO_MEMORY(r->servername);
3986 r->servername = NULL;
3989 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3990 if (!W_ERROR_IS_OK(result)) {
3994 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3995 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3996 r->portname = talloc_strdup(mem_ctx, info2->portname);
3997 W_ERROR_HAVE_NO_MEMORY(r->portname);
3998 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3999 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4001 if (info2->comment[0] == '\0') {
4002 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4004 r->comment = talloc_strdup(mem_ctx, info2->comment);
4006 W_ERROR_HAVE_NO_MEMORY(r->comment);
4008 r->location = talloc_strdup(mem_ctx, info2->location);
4009 W_ERROR_HAVE_NO_MEMORY(r->location);
4010 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4011 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4012 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4013 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4014 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4015 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4016 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4017 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4019 r->attributes = info2->attributes;
4021 r->priority = info2->priority;
4022 r->defaultpriority = info2->defaultpriority;
4023 r->starttime = info2->starttime;
4024 r->untiltime = info2->untiltime;
4025 r->status = nt_printq_status(status.status);
4027 r->averageppm = info2->averageppm;
4029 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4031 DEBUG(8,("Returning NULL Devicemode!\n"));
4034 compose_devicemode_devicename(r->devmode, r->printername);
4038 if (info2->secdesc != NULL) {
4039 /* don't use talloc_steal() here unless you do a deep steal of all
4040 the SEC_DESC members */
4042 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4048 /********************************************************************
4049 * construct_printer_info3
4050 * fill a spoolss_PrinterInfo3 struct
4051 ********************************************************************/
4053 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4054 const struct spoolss_PrinterInfo2 *info2,
4055 const char *servername,
4056 struct spoolss_PrinterInfo3 *r,
4059 /* These are the components of the SD we are returning. */
4061 if (info2->secdesc != NULL) {
4062 /* don't use talloc_steal() here unless you do a deep steal of all
4063 the SEC_DESC members */
4065 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4066 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4072 /********************************************************************
4073 * construct_printer_info4
4074 * fill a spoolss_PrinterInfo4 struct
4075 ********************************************************************/
4077 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4078 const struct spoolss_PrinterInfo2 *info2,
4079 const char *servername,
4080 struct spoolss_PrinterInfo4 *r,
4085 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4086 if (!W_ERROR_IS_OK(result)) {
4091 r->servername = talloc_strdup(mem_ctx, servername);
4092 W_ERROR_HAVE_NO_MEMORY(r->servername);
4094 r->servername = NULL;
4097 r->attributes = info2->attributes;
4102 /********************************************************************
4103 * construct_printer_info5
4104 * fill a spoolss_PrinterInfo5 struct
4105 ********************************************************************/
4107 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4108 const struct spoolss_PrinterInfo2 *info2,
4109 const char *servername,
4110 struct spoolss_PrinterInfo5 *r,
4115 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4116 if (!W_ERROR_IS_OK(result)) {
4120 r->portname = talloc_strdup(mem_ctx, info2->portname);
4121 W_ERROR_HAVE_NO_MEMORY(r->portname);
4123 r->attributes = info2->attributes;
4125 /* these two are not used by NT+ according to MSDN */
4126 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4127 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4132 /********************************************************************
4133 * construct_printer_info_6
4134 * fill a spoolss_PrinterInfo6 struct
4135 ********************************************************************/
4137 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4138 struct messaging_context *msg_ctx,
4139 const struct spoolss_PrinterInfo2 *info2,
4140 const char *servername,
4141 struct spoolss_PrinterInfo6 *r,
4145 print_status_struct status;
4147 count = print_queue_length(msg_ctx, snum, &status);
4149 r->status = nt_printq_status(status.status);
4154 /********************************************************************
4155 * construct_printer_info7
4156 * fill a spoolss_PrinterInfo7 struct
4157 ********************************************************************/
4159 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4160 struct messaging_context *msg_ctx,
4161 const char *servername,
4162 struct spoolss_PrinterInfo7 *r,
4165 struct auth_serversupplied_info *session_info;
4169 status = make_session_info_system(mem_ctx, &session_info);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 DEBUG(0, ("construct_printer_info7: "
4172 "Could not create system session_info\n"));
4176 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4178 lp_servicename(snum), &guid, NULL)) {
4179 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4180 r->action = DSPRINT_PUBLISH;
4182 r->guid = talloc_strdup(mem_ctx, "");
4183 r->action = DSPRINT_UNPUBLISH;
4185 W_ERROR_HAVE_NO_MEMORY(r->guid);
4187 TALLOC_FREE(session_info);
4191 /********************************************************************
4192 * construct_printer_info8
4193 * fill a spoolss_PrinterInfo8 struct
4194 ********************************************************************/
4196 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4197 const struct spoolss_PrinterInfo2 *info2,
4198 const char *servername,
4199 struct spoolss_DeviceModeInfo *r,
4203 const char *printername;
4205 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4206 if (!W_ERROR_IS_OK(result)) {
4210 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4212 DEBUG(8,("Returning NULL Devicemode!\n"));
4215 compose_devicemode_devicename(r->devmode, printername);
4221 /********************************************************************
4222 ********************************************************************/
4224 static bool snum_is_shared_printer(int snum)
4226 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4229 /********************************************************************
4230 Spoolss_enumprinters.
4231 ********************************************************************/
4233 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4234 const struct auth_serversupplied_info *session_info,
4235 struct messaging_context *msg_ctx,
4236 const char *servername,
4239 union spoolss_PrinterInfo **info_p,
4243 int n_services = lp_numservices();
4244 union spoolss_PrinterInfo *info = NULL;
4246 WERROR result = WERR_OK;
4251 for (snum = 0; snum < n_services; snum++) {
4253 const char *printer;
4254 struct spoolss_PrinterInfo2 *info2;
4256 if (!snum_is_shared_printer(snum)) {
4260 printer = lp_const_servicename(snum);
4262 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4265 result = winreg_create_printer(mem_ctx,
4269 if (!W_ERROR_IS_OK(result)) {
4273 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4274 union spoolss_PrinterInfo,
4277 result = WERR_NOMEM;
4281 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4283 if (!W_ERROR_IS_OK(result)) {
4289 result = construct_printer_info0(info, session_info,
4292 &info[count].info0, snum);
4295 result = construct_printer_info1(info, info2, flags,
4297 &info[count].info1, snum);
4300 result = construct_printer_info2(info, msg_ctx, info2,
4302 &info[count].info2, snum);
4305 result = construct_printer_info4(info, info2,
4307 &info[count].info4, snum);
4310 result = construct_printer_info5(info, info2,
4312 &info[count].info5, snum);
4316 result = WERR_UNKNOWN_LEVEL;
4320 if (!W_ERROR_IS_OK(result)) {
4331 if (!W_ERROR_IS_OK(result)) {
4341 /********************************************************************
4342 * handle enumeration of printers at level 0
4343 ********************************************************************/
4345 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4346 const struct auth_serversupplied_info *session_info,
4347 struct messaging_context *msg_ctx,
4349 const char *servername,
4350 union spoolss_PrinterInfo **info,
4353 DEBUG(4,("enum_all_printers_info_0\n"));
4355 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4356 servername, 0, flags, info, count);
4360 /********************************************************************
4361 ********************************************************************/
4363 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4364 const struct auth_serversupplied_info *session_info,
4365 struct messaging_context *msg_ctx,
4366 const char *servername,
4368 union spoolss_PrinterInfo **info,
4371 DEBUG(4,("enum_all_printers_info_1\n"));
4373 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4374 servername, 1, flags, info, count);
4377 /********************************************************************
4378 enum_all_printers_info_1_local.
4379 *********************************************************************/
4381 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4382 const struct auth_serversupplied_info *session_info,
4383 struct messaging_context *msg_ctx,
4384 const char *servername,
4385 union spoolss_PrinterInfo **info,
4388 DEBUG(4,("enum_all_printers_info_1_local\n"));
4390 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4391 servername, PRINTER_ENUM_ICON8, info, count);
4394 /********************************************************************
4395 enum_all_printers_info_1_name.
4396 *********************************************************************/
4398 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4399 const struct auth_serversupplied_info *session_info,
4400 struct messaging_context *msg_ctx,
4401 const char *servername,
4402 union spoolss_PrinterInfo **info,
4405 const char *s = servername;
4407 DEBUG(4,("enum_all_printers_info_1_name\n"));
4409 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4413 if (!is_myname_or_ipaddr(s)) {
4414 return WERR_INVALID_NAME;
4417 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4418 servername, PRINTER_ENUM_ICON8, info, count);
4421 /********************************************************************
4422 enum_all_printers_info_1_network.
4423 *********************************************************************/
4425 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4426 const struct auth_serversupplied_info *session_info,
4427 struct messaging_context *msg_ctx,
4428 const char *servername,
4429 union spoolss_PrinterInfo **info,
4432 const char *s = servername;
4434 DEBUG(4,("enum_all_printers_info_1_network\n"));
4436 /* If we respond to a enum_printers level 1 on our name with flags
4437 set to PRINTER_ENUM_REMOTE with a list of printers then these
4438 printers incorrectly appear in the APW browse list.
4439 Specifically the printers for the server appear at the workgroup
4440 level where all the other servers in the domain are
4441 listed. Windows responds to this call with a
4442 WERR_CAN_NOT_COMPLETE so we should do the same. */
4444 if (servername[0] == '\\' && servername[1] == '\\') {
4448 if (is_myname_or_ipaddr(s)) {
4449 return WERR_CAN_NOT_COMPLETE;
4452 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4453 servername, PRINTER_ENUM_NAME, info, count);
4456 /********************************************************************
4457 * api_spoolss_enumprinters
4459 * called from api_spoolss_enumprinters (see this to understand)
4460 ********************************************************************/
4462 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4463 const struct auth_serversupplied_info *session_info,
4464 struct messaging_context *msg_ctx,
4465 const char *servername,
4466 union spoolss_PrinterInfo **info,
4469 DEBUG(4,("enum_all_printers_info_2\n"));
4471 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4472 servername, 2, 0, info, count);
4475 /********************************************************************
4476 * handle enumeration of printers at level 1
4477 ********************************************************************/
4479 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4480 const struct auth_serversupplied_info *session_info,
4481 struct messaging_context *msg_ctx,
4483 const char *servername,
4484 union spoolss_PrinterInfo **info,
4487 /* Not all the flags are equals */
4489 if (flags & PRINTER_ENUM_LOCAL) {
4490 return enum_all_printers_info_1_local(mem_ctx, session_info,
4491 msg_ctx, servername, info, count);
4494 if (flags & PRINTER_ENUM_NAME) {
4495 return enum_all_printers_info_1_name(mem_ctx, session_info,
4496 msg_ctx, servername, info,
4500 if (flags & PRINTER_ENUM_NETWORK) {
4501 return enum_all_printers_info_1_network(mem_ctx, session_info,
4502 msg_ctx, servername, info,
4506 return WERR_OK; /* NT4sp5 does that */
4509 /********************************************************************
4510 * handle enumeration of printers at level 2
4511 ********************************************************************/
4513 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4514 const struct auth_serversupplied_info *session_info,
4515 struct messaging_context *msg_ctx,
4517 const char *servername,
4518 union spoolss_PrinterInfo **info,
4521 if (flags & PRINTER_ENUM_LOCAL) {
4523 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4528 if (flags & PRINTER_ENUM_NAME) {
4529 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4530 return WERR_INVALID_NAME;
4533 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4538 if (flags & PRINTER_ENUM_REMOTE) {
4539 return WERR_UNKNOWN_LEVEL;
4545 /********************************************************************
4546 * handle enumeration of printers at level 4
4547 ********************************************************************/
4549 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4550 const struct auth_serversupplied_info *session_info,
4551 struct messaging_context *msg_ctx,
4553 const char *servername,
4554 union spoolss_PrinterInfo **info,
4557 DEBUG(4,("enum_all_printers_info_4\n"));
4559 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4560 servername, 4, flags, info, count);
4564 /********************************************************************
4565 * handle enumeration of printers at level 5
4566 ********************************************************************/
4568 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4569 const struct auth_serversupplied_info *session_info,
4570 struct messaging_context *msg_ctx,
4572 const char *servername,
4573 union spoolss_PrinterInfo **info,
4576 DEBUG(4,("enum_all_printers_info_5\n"));
4578 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4579 servername, 5, flags, info, count);
4582 /****************************************************************
4583 _spoolss_EnumPrinters
4584 ****************************************************************/
4586 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4587 struct spoolss_EnumPrinters *r)
4589 const struct auth_serversupplied_info *session_info = get_session_info_system();
4592 /* that's an [in out] buffer */
4594 if (!r->in.buffer && (r->in.offered != 0)) {
4595 return WERR_INVALID_PARAM;
4598 DEBUG(4,("_spoolss_EnumPrinters\n"));
4602 *r->out.info = NULL;
4606 * flags==PRINTER_ENUM_NAME
4607 * if name=="" then enumerates all printers
4608 * if name!="" then enumerate the printer
4609 * flags==PRINTER_ENUM_REMOTE
4610 * name is NULL, enumerate printers
4611 * Level 2: name!="" enumerates printers, name can't be NULL
4612 * Level 3: doesn't exist
4613 * Level 4: does a local registry lookup
4614 * Level 5: same as Level 2
4617 if (r->in.server && r->in.server[0] == '\0') {
4618 r->in.server = NULL;
4621 switch (r->in.level) {
4623 result = enumprinters_level0(p->mem_ctx, session_info,
4624 p->msg_ctx, r->in.flags,
4626 r->out.info, r->out.count);
4629 result = enumprinters_level1(p->mem_ctx, session_info,
4630 p->msg_ctx, r->in.flags,
4632 r->out.info, r->out.count);
4635 result = enumprinters_level2(p->mem_ctx, session_info,
4636 p->msg_ctx, r->in.flags,
4638 r->out.info, r->out.count);
4641 result = enumprinters_level4(p->mem_ctx, session_info,
4642 p->msg_ctx, r->in.flags,
4644 r->out.info, r->out.count);
4647 result = enumprinters_level5(p->mem_ctx, session_info,
4648 p->msg_ctx, r->in.flags,
4650 r->out.info, r->out.count);
4653 return WERR_UNKNOWN_LEVEL;
4656 if (!W_ERROR_IS_OK(result)) {
4660 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4661 spoolss_EnumPrinters,
4662 *r->out.info, r->in.level,
4664 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4665 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4667 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4670 /****************************************************************
4672 ****************************************************************/
4674 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4675 struct spoolss_GetPrinter *r)
4677 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4678 struct spoolss_PrinterInfo2 *info2 = NULL;
4679 WERROR result = WERR_OK;
4682 /* that's an [in out] buffer */
4684 if (!r->in.buffer && (r->in.offered != 0)) {
4685 return WERR_INVALID_PARAM;
4690 if (Printer == NULL) {
4694 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4698 result = winreg_get_printer(p->mem_ctx,
4699 get_session_info_system(),
4701 lp_const_servicename(snum),
4703 if (!W_ERROR_IS_OK(result)) {
4707 switch (r->in.level) {
4709 result = construct_printer_info0(p->mem_ctx,
4710 get_session_info_system(),
4713 Printer->servername,
4714 &r->out.info->info0,
4718 result = construct_printer_info1(p->mem_ctx, info2,
4720 Printer->servername,
4721 &r->out.info->info1, snum);
4724 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4725 Printer->servername,
4726 &r->out.info->info2, snum);
4729 result = construct_printer_info3(p->mem_ctx, info2,
4730 Printer->servername,
4731 &r->out.info->info3, snum);
4734 result = construct_printer_info4(p->mem_ctx, info2,
4735 Printer->servername,
4736 &r->out.info->info4, snum);
4739 result = construct_printer_info5(p->mem_ctx, info2,
4740 Printer->servername,
4741 &r->out.info->info5, snum);
4744 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4745 Printer->servername,
4746 &r->out.info->info6, snum);
4749 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4750 Printer->servername,
4751 &r->out.info->info7, snum);
4754 result = construct_printer_info8(p->mem_ctx, info2,
4755 Printer->servername,
4756 &r->out.info->info8, snum);
4759 result = WERR_UNKNOWN_LEVEL;
4764 if (!W_ERROR_IS_OK(result)) {
4765 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4766 r->in.level, win_errstr(result)));
4767 TALLOC_FREE(r->out.info);
4771 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4772 r->out.info, r->in.level);
4773 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4775 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4778 /********************************************************************
4779 ********************************************************************/
4781 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4783 if (in && strlen(in)) { \
4784 out = talloc_strdup(mem_ctx, in); \
4786 out = talloc_strdup(mem_ctx, ""); \
4788 W_ERROR_HAVE_NO_MEMORY(out); \
4791 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4793 if (in && strlen(in)) { \
4794 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4796 out = talloc_strdup(mem_ctx, ""); \
4798 W_ERROR_HAVE_NO_MEMORY(out); \
4801 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4802 const char **string_array,
4803 const char ***presult,
4804 const char *cservername,
4808 int i, num_strings = 0;
4809 const char **array = NULL;
4811 if (string_array == NULL) {
4812 return WERR_INVALID_PARAMETER;
4815 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4816 const char *str = NULL;
4818 if (cservername == NULL || arch == NULL) {
4819 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4821 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4824 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4831 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4832 &array, &num_strings);
4842 /********************************************************************
4843 * fill a spoolss_DriverInfo1 struct
4844 ********************************************************************/
4846 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4847 struct spoolss_DriverInfo1 *r,
4848 const struct spoolss_DriverInfo8 *driver,
4849 const char *servername)
4851 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4852 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4857 /********************************************************************
4858 * fill a spoolss_DriverInfo2 struct
4859 ********************************************************************/
4861 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4862 struct spoolss_DriverInfo2 *r,
4863 const struct spoolss_DriverInfo8 *driver,
4864 const char *servername)
4867 const char *cservername = canon_servername(servername);
4869 r->version = driver->version;
4871 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4872 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4873 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4874 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4876 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4877 driver->architecture,
4879 driver->driver_path,
4882 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4883 driver->architecture,
4888 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4889 driver->architecture,
4891 driver->config_file,
4897 /********************************************************************
4898 * fill a spoolss_DriverInfo3 struct
4899 ********************************************************************/
4901 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4902 struct spoolss_DriverInfo3 *r,
4903 const struct spoolss_DriverInfo8 *driver,
4904 const char *servername)
4906 const char *cservername = canon_servername(servername);
4908 r->version = driver->version;
4910 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4911 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4912 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4913 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4915 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4916 driver->architecture,
4918 driver->driver_path,
4921 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4922 driver->architecture,
4927 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4928 driver->architecture,
4930 driver->config_file,
4933 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4934 driver->architecture,
4939 FILL_DRIVER_STRING(mem_ctx,
4940 driver->monitor_name,
4943 FILL_DRIVER_STRING(mem_ctx,
4944 driver->default_datatype,
4945 r->default_datatype);
4947 return string_array_from_driver_info(mem_ctx,
4948 driver->dependent_files,
4949 &r->dependent_files,
4951 driver->architecture,
4955 /********************************************************************
4956 * fill a spoolss_DriverInfo4 struct
4957 ********************************************************************/
4959 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4960 struct spoolss_DriverInfo4 *r,
4961 const struct spoolss_DriverInfo8 *driver,
4962 const char *servername)
4964 const char *cservername = canon_servername(servername);
4967 r->version = driver->version;
4969 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4970 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4971 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4972 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4974 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4975 driver->architecture,
4977 driver->driver_path,
4980 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4981 driver->architecture,
4986 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4987 driver->architecture,
4989 driver->config_file,
4992 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4993 driver->architecture,
4998 result = string_array_from_driver_info(mem_ctx,
4999 driver->dependent_files,
5000 &r->dependent_files,
5002 driver->architecture,
5004 if (!W_ERROR_IS_OK(result)) {
5008 FILL_DRIVER_STRING(mem_ctx,
5009 driver->monitor_name,
5012 FILL_DRIVER_STRING(mem_ctx,
5013 driver->default_datatype,
5014 r->default_datatype);
5017 result = string_array_from_driver_info(mem_ctx,
5018 driver->previous_names,
5025 /********************************************************************
5026 * fill a spoolss_DriverInfo5 struct
5027 ********************************************************************/
5029 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5030 struct spoolss_DriverInfo5 *r,
5031 const struct spoolss_DriverInfo8 *driver,
5032 const char *servername)
5034 const char *cservername = canon_servername(servername);
5036 r->version = driver->version;
5038 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5039 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5040 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5041 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5043 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5044 driver->architecture,
5046 driver->driver_path,
5049 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050 driver->architecture,
5055 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056 driver->architecture,
5058 driver->config_file,
5061 r->driver_attributes = 0;
5062 r->config_version = 0;
5063 r->driver_version = 0;
5067 /********************************************************************
5068 * fill a spoolss_DriverInfo6 struct
5069 ********************************************************************/
5071 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5072 struct spoolss_DriverInfo6 *r,
5073 const struct spoolss_DriverInfo8 *driver,
5074 const char *servername)
5076 const char *cservername = canon_servername(servername);
5079 r->version = driver->version;
5081 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5082 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5083 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5084 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5086 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5087 driver->architecture,
5089 driver->driver_path,
5092 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093 driver->architecture,
5098 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5099 driver->architecture,
5101 driver->config_file,
5104 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105 driver->architecture,
5110 FILL_DRIVER_STRING(mem_ctx,
5111 driver->monitor_name,
5114 FILL_DRIVER_STRING(mem_ctx,
5115 driver->default_datatype,
5116 r->default_datatype);
5118 result = string_array_from_driver_info(mem_ctx,
5119 driver->dependent_files,
5120 &r->dependent_files,
5122 driver->architecture,
5124 if (!W_ERROR_IS_OK(result)) {
5128 result = string_array_from_driver_info(mem_ctx,
5129 driver->previous_names,
5132 if (!W_ERROR_IS_OK(result)) {
5136 r->driver_date = driver->driver_date;
5137 r->driver_version = driver->driver_version;
5139 FILL_DRIVER_STRING(mem_ctx,
5140 driver->manufacturer_name,
5141 r->manufacturer_name);
5142 FILL_DRIVER_STRING(mem_ctx,
5143 driver->manufacturer_url,
5144 r->manufacturer_url);
5145 FILL_DRIVER_STRING(mem_ctx,
5146 driver->hardware_id,
5148 FILL_DRIVER_STRING(mem_ctx,
5155 /********************************************************************
5156 * fill a spoolss_DriverInfo8 struct
5157 ********************************************************************/
5159 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5160 struct spoolss_DriverInfo8 *r,
5161 const struct spoolss_DriverInfo8 *driver,
5162 const char *servername)
5164 const char *cservername = canon_servername(servername);
5167 r->version = driver->version;
5169 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5170 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5171 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5172 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5174 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5175 driver->architecture,
5177 driver->driver_path,
5180 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181 driver->architecture,
5186 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187 driver->architecture,
5189 driver->config_file,
5192 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5193 driver->architecture,
5198 FILL_DRIVER_STRING(mem_ctx,
5199 driver->monitor_name,
5202 FILL_DRIVER_STRING(mem_ctx,
5203 driver->default_datatype,
5204 r->default_datatype);
5206 result = string_array_from_driver_info(mem_ctx,
5207 driver->dependent_files,
5208 &r->dependent_files,
5210 driver->architecture,
5212 if (!W_ERROR_IS_OK(result)) {
5216 result = string_array_from_driver_info(mem_ctx,
5217 driver->previous_names,
5220 if (!W_ERROR_IS_OK(result)) {
5224 r->driver_date = driver->driver_date;
5225 r->driver_version = driver->driver_version;
5227 FILL_DRIVER_STRING(mem_ctx,
5228 driver->manufacturer_name,
5229 r->manufacturer_name);
5230 FILL_DRIVER_STRING(mem_ctx,
5231 driver->manufacturer_url,
5232 r->manufacturer_url);
5233 FILL_DRIVER_STRING(mem_ctx,
5234 driver->hardware_id,
5236 FILL_DRIVER_STRING(mem_ctx,
5240 FILL_DRIVER_STRING(mem_ctx,
5241 driver->print_processor,
5242 r->print_processor);
5243 FILL_DRIVER_STRING(mem_ctx,
5244 driver->vendor_setup,
5247 result = string_array_from_driver_info(mem_ctx,
5248 driver->color_profiles,
5251 if (!W_ERROR_IS_OK(result)) {
5255 FILL_DRIVER_STRING(mem_ctx,
5259 r->printer_driver_attributes = driver->printer_driver_attributes;
5261 result = string_array_from_driver_info(mem_ctx,
5262 driver->core_driver_dependencies,
5263 &r->core_driver_dependencies,
5265 if (!W_ERROR_IS_OK(result)) {
5269 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5270 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5275 #if 0 /* disabled until marshalling issues are resolved - gd */
5276 /********************************************************************
5277 ********************************************************************/
5279 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5280 struct spoolss_DriverFileInfo *r,
5281 const char *cservername,
5282 const char *file_name,
5283 enum spoolss_DriverFileType file_type,
5284 uint32_t file_version)
5286 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5287 cservername, file_name);
5288 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5289 r->file_type = file_type;
5290 r->file_version = file_version;
5295 /********************************************************************
5296 ********************************************************************/
5298 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5299 const struct spoolss_DriverInfo8 *driver,
5300 const char *cservername,
5301 struct spoolss_DriverFileInfo **info_p,
5304 struct spoolss_DriverFileInfo *info = NULL;
5312 if (strlen(driver->driver_path)) {
5313 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5314 struct spoolss_DriverFileInfo,
5316 W_ERROR_HAVE_NO_MEMORY(info);
5317 result = fill_spoolss_DriverFileInfo(info,
5320 driver->driver_path,
5321 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5323 W_ERROR_NOT_OK_RETURN(result);
5327 if (strlen(driver->config_file)) {
5328 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5329 struct spoolss_DriverFileInfo,
5331 W_ERROR_HAVE_NO_MEMORY(info);
5332 result = fill_spoolss_DriverFileInfo(info,
5335 driver->config_file,
5336 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5338 W_ERROR_NOT_OK_RETURN(result);
5342 if (strlen(driver->data_file)) {
5343 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5344 struct spoolss_DriverFileInfo,
5346 W_ERROR_HAVE_NO_MEMORY(info);
5347 result = fill_spoolss_DriverFileInfo(info,
5351 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5353 W_ERROR_NOT_OK_RETURN(result);
5357 if (strlen(driver->help_file)) {
5358 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5359 struct spoolss_DriverFileInfo,
5361 W_ERROR_HAVE_NO_MEMORY(info);
5362 result = fill_spoolss_DriverFileInfo(info,
5366 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5368 W_ERROR_NOT_OK_RETURN(result);
5372 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5373 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5374 struct spoolss_DriverFileInfo,
5376 W_ERROR_HAVE_NO_MEMORY(info);
5377 result = fill_spoolss_DriverFileInfo(info,
5380 driver->dependent_files[i],
5381 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5383 W_ERROR_NOT_OK_RETURN(result);
5393 /********************************************************************
5394 * fill a spoolss_DriverInfo101 struct
5395 ********************************************************************/
5397 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5398 struct spoolss_DriverInfo101 *r,
5399 const struct spoolss_DriverInfo8 *driver,
5400 const char *servername)
5402 const char *cservername = canon_servername(servername);
5405 r->version = driver->version;
5407 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5408 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5409 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5410 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5412 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5416 if (!W_ERROR_IS_OK(result)) {
5420 FILL_DRIVER_STRING(mem_ctx,
5421 driver->monitor_name,
5424 FILL_DRIVER_STRING(mem_ctx,
5425 driver->default_datatype,
5426 r->default_datatype);
5428 result = string_array_from_driver_info(mem_ctx,
5429 driver->previous_names,
5432 if (!W_ERROR_IS_OK(result)) {
5436 r->driver_date = driver->driver_date;
5437 r->driver_version = driver->driver_version;
5439 FILL_DRIVER_STRING(mem_ctx,
5440 driver->manufacturer_name,
5441 r->manufacturer_name);
5442 FILL_DRIVER_STRING(mem_ctx,
5443 driver->manufacturer_url,
5444 r->manufacturer_url);
5445 FILL_DRIVER_STRING(mem_ctx,
5446 driver->hardware_id,
5448 FILL_DRIVER_STRING(mem_ctx,
5455 /********************************************************************
5456 ********************************************************************/
5458 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5459 const struct auth_serversupplied_info *session_info,
5460 struct messaging_context *msg_ctx,
5462 union spoolss_DriverInfo *r,
5464 const char *servername,
5465 const char *architecture,
5468 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5469 struct spoolss_DriverInfo8 *driver;
5473 return WERR_UNKNOWN_LEVEL;
5476 result = winreg_get_printer(mem_ctx,
5479 lp_const_servicename(snum),
5482 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5483 win_errstr(result)));
5485 if (!W_ERROR_IS_OK(result)) {
5486 return WERR_INVALID_PRINTER_NAME;
5489 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5491 pinfo2->drivername, version, &driver);
5493 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5494 win_errstr(result)));
5496 if (!W_ERROR_IS_OK(result)) {
5498 * Is this a W2k client ?
5502 talloc_free(pinfo2);
5503 return WERR_UNKNOWN_PRINTER_DRIVER;
5506 /* Yes - try again with a WinNT driver. */
5508 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5512 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5513 win_errstr(result)));
5514 if (!W_ERROR_IS_OK(result)) {
5515 talloc_free(pinfo2);
5516 return WERR_UNKNOWN_PRINTER_DRIVER;
5522 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5525 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5528 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5531 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5534 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5537 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5540 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5542 #if 0 /* disabled until marshalling issues are resolved - gd */
5544 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5548 result = WERR_UNKNOWN_LEVEL;
5552 talloc_free(pinfo2);
5553 talloc_free(driver);
5558 /****************************************************************
5559 _spoolss_GetPrinterDriver2
5560 ****************************************************************/
5562 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5563 struct spoolss_GetPrinterDriver2 *r)
5565 struct printer_handle *printer;
5570 /* that's an [in out] buffer */
5572 if (!r->in.buffer && (r->in.offered != 0)) {
5573 return WERR_INVALID_PARAM;
5576 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5578 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5579 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5580 return WERR_INVALID_PRINTER_NAME;
5584 *r->out.server_major_version = 0;
5585 *r->out.server_minor_version = 0;
5587 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5591 result = construct_printer_driver_info_level(p->mem_ctx,
5592 get_session_info_system(),
5594 r->in.level, r->out.info,
5595 snum, printer->servername,
5597 r->in.client_major_version);
5598 if (!W_ERROR_IS_OK(result)) {
5599 TALLOC_FREE(r->out.info);
5603 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5604 r->out.info, r->in.level);
5605 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5607 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5611 /****************************************************************
5612 _spoolss_StartPagePrinter
5613 ****************************************************************/
5615 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5616 struct spoolss_StartPagePrinter *r)
5618 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5621 DEBUG(3,("_spoolss_StartPagePrinter: "
5622 "Error in startpageprinter printer handle\n"));
5626 Printer->page_started = true;
5630 /****************************************************************
5631 _spoolss_EndPagePrinter
5632 ****************************************************************/
5634 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5635 struct spoolss_EndPagePrinter *r)
5639 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5642 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5643 OUR_HANDLE(r->in.handle)));
5647 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5650 Printer->page_started = false;
5651 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5656 /****************************************************************
5657 _spoolss_StartDocPrinter
5658 ****************************************************************/
5660 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5661 struct spoolss_StartDocPrinter *r)
5663 struct spoolss_DocumentInfo1 *info_1;
5665 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5669 DEBUG(2,("_spoolss_StartDocPrinter: "
5670 "Invalid handle (%s:%u:%u)\n",
5671 OUR_HANDLE(r->in.handle)));
5675 if (Printer->jobid) {
5676 DEBUG(2, ("_spoolss_StartDocPrinter: "
5677 "StartDocPrinter called twice! "
5678 "(existing jobid = %d)\n", Printer->jobid));
5679 return WERR_INVALID_HANDLE;
5682 if (r->in.level != 1) {
5683 return WERR_UNKNOWN_LEVEL;
5686 info_1 = r->in.info.info1;
5689 * a nice thing with NT is it doesn't listen to what you tell it.
5690 * when asked to send _only_ RAW datas, it tries to send datas
5693 * So I add checks like in NT Server ...
5696 if (info_1->datatype) {
5697 if (strcmp(info_1->datatype, "RAW") != 0) {
5699 return WERR_INVALID_DATATYPE;
5703 /* get the share number of the printer */
5704 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5708 werr = print_job_start(p->session_info,
5712 info_1->document_name,
5713 info_1->output_file,
5717 /* An error occured in print_job_start() so return an appropriate
5720 if (!W_ERROR_IS_OK(werr)) {
5724 Printer->document_started = true;
5725 *r->out.job_id = Printer->jobid;
5730 /****************************************************************
5731 _spoolss_EndDocPrinter
5732 ****************************************************************/
5734 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5735 struct spoolss_EndDocPrinter *r)
5737 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5742 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5743 OUR_HANDLE(r->in.handle)));
5747 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5751 Printer->document_started = false;
5752 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5753 if (!NT_STATUS_IS_OK(status)) {
5754 DEBUG(2, ("_spoolss_EndDocPrinter: "
5755 "print_job_end failed [%s]\n",
5756 nt_errstr(status)));
5760 return ntstatus_to_werror(status);
5763 /****************************************************************
5764 _spoolss_WritePrinter
5765 ****************************************************************/
5767 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5768 struct spoolss_WritePrinter *r)
5770 ssize_t buffer_written;
5772 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5775 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5776 OUR_HANDLE(r->in.handle)));
5777 *r->out.num_written = r->in._data_size;
5781 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5784 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5785 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5786 snum, Printer->jobid,
5787 (const char *)r->in.data.data,
5788 (size_t)r->in._data_size);
5789 if (buffer_written == (ssize_t)-1) {
5790 *r->out.num_written = 0;
5791 if (errno == ENOSPC)
5792 return WERR_NO_SPOOL_SPACE;
5794 return WERR_ACCESS_DENIED;
5797 *r->out.num_written = r->in._data_size;
5802 /********************************************************************
5803 * api_spoolss_getprinter
5804 * called from the spoolss dispatcher
5806 ********************************************************************/
5808 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5809 struct pipes_struct *p)
5811 const struct auth_serversupplied_info *session_info = p->session_info;
5813 WERROR errcode = WERR_BADFUNC;
5814 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5817 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5818 OUR_HANDLE(handle)));
5822 if (!get_printer_snum(p, handle, &snum, NULL))
5826 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5827 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5829 case SPOOLSS_PRINTER_CONTROL_RESUME:
5830 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5831 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5833 case SPOOLSS_PRINTER_CONTROL_PURGE:
5834 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5837 return WERR_UNKNOWN_LEVEL;
5844 /****************************************************************
5845 _spoolss_AbortPrinter
5846 * From MSDN: "Deletes printer's spool file if printer is configured
5848 ****************************************************************/
5850 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5851 struct spoolss_AbortPrinter *r)
5853 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5855 WERROR errcode = WERR_OK;
5858 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5859 OUR_HANDLE(r->in.handle)));
5863 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5866 if (!Printer->document_started) {
5867 return WERR_SPL_NO_STARTDOC;
5870 errcode = print_job_delete(p->session_info,
5878 /********************************************************************
5879 * called by spoolss_api_setprinter
5880 * when updating a printer description
5881 ********************************************************************/
5883 static WERROR update_printer_sec(struct policy_handle *handle,
5884 struct pipes_struct *p,
5885 struct sec_desc_buf *secdesc_ctr)
5887 struct spoolss_security_descriptor *new_secdesc = NULL;
5888 struct spoolss_security_descriptor *old_secdesc = NULL;
5889 const char *printer;
5893 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5895 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5896 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5897 OUR_HANDLE(handle)));
5899 result = WERR_BADFID;
5903 if (secdesc_ctr == NULL) {
5904 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5905 result = WERR_INVALID_PARAM;
5908 printer = lp_const_servicename(snum);
5910 /* Check the user has permissions to change the security
5911 descriptor. By experimentation with two NT machines, the user
5912 requires Full Access to the printer to change security
5915 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5916 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5917 result = WERR_ACCESS_DENIED;
5921 /* NT seems to like setting the security descriptor even though
5922 nothing may have actually changed. */
5923 result = winreg_get_printer_secdesc(p->mem_ctx,
5924 get_session_info_system(),
5928 if (!W_ERROR_IS_OK(result)) {
5929 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5930 result = WERR_BADFID;
5934 if (DEBUGLEVEL >= 10) {
5935 struct security_acl *the_acl;
5938 the_acl = old_secdesc->dacl;
5939 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5940 printer, the_acl->num_aces));
5942 for (i = 0; i < the_acl->num_aces; i++) {
5943 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5944 &the_acl->aces[i].trustee),
5945 the_acl->aces[i].access_mask));
5948 the_acl = secdesc_ctr->sd->dacl;
5951 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5952 printer, the_acl->num_aces));
5954 for (i = 0; i < the_acl->num_aces; i++) {
5955 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5956 &the_acl->aces[i].trustee),
5957 the_acl->aces[i].access_mask));
5960 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5964 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5965 if (new_secdesc == NULL) {
5966 result = WERR_NOMEM;
5970 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5975 result = winreg_set_printer_secdesc(p->mem_ctx,
5976 get_session_info_system(),
5985 /********************************************************************
5986 Canonicalize printer info from a client
5987 ********************************************************************/
5989 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5990 struct spoolss_SetPrinterInfo2 *info2,
5993 fstring printername;
5996 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5997 "portname=%s drivername=%s comment=%s location=%s\n",
5998 info2->servername, info2->printername, info2->sharename,
5999 info2->portname, info2->drivername, info2->comment,
6002 /* we force some elements to "correct" values */
6003 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6004 if (info2->servername == NULL) {
6007 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6008 if (info2->sharename == NULL) {
6012 /* check to see if we allow printername != sharename */
6013 if (lp_force_printername(snum)) {
6014 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6015 global_myname(), info2->sharename);
6017 /* make sure printername is in \\server\printername format */
6018 fstrcpy(printername, info2->printername);
6020 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6021 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6025 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6026 global_myname(), p);
6028 if (info2->printername == NULL) {
6032 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6033 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6038 /****************************************************************************
6039 ****************************************************************************/
6041 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6043 char *cmd = lp_addport_cmd();
6044 char *command = NULL;
6046 bool is_print_op = false;
6049 return WERR_ACCESS_DENIED;
6052 command = talloc_asprintf(ctx,
6053 "%s \"%s\" \"%s\"", cmd, portname, uri );
6059 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6061 DEBUG(10,("Running [%s]\n", command));
6063 /********* BEGIN SePrintOperatorPrivilege **********/
6068 ret = smbrun(command, NULL);
6073 /********* END SePrintOperatorPrivilege **********/
6075 DEBUGADD(10,("returned [%d]\n", ret));
6077 TALLOC_FREE(command);
6080 return WERR_ACCESS_DENIED;
6086 /****************************************************************************
6087 ****************************************************************************/
6089 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6090 struct spoolss_SetPrinterInfo2 *info2,
6091 const char *remote_machine,
6092 struct messaging_context *msg_ctx)
6094 char *cmd = lp_addprinter_cmd();
6096 char *command = NULL;
6100 bool is_print_op = false;
6102 if (!remote_machine) {
6106 command = talloc_asprintf(ctx,
6107 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6108 cmd, info2->printername, info2->sharename,
6109 info2->portname, info2->drivername,
6110 info2->location, info2->comment, remote_machine);
6116 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6118 DEBUG(10,("Running [%s]\n", command));
6120 /********* BEGIN SePrintOperatorPrivilege **********/
6125 if ( (ret = smbrun(command, &fd)) == 0 ) {
6126 /* Tell everyone we updated smb.conf. */
6127 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6133 /********* END SePrintOperatorPrivilege **********/
6135 DEBUGADD(10,("returned [%d]\n", ret));
6137 TALLOC_FREE(command);
6145 /* reload our services immediately */
6147 reload_services(msg_ctx, -1, false);
6151 /* Get lines and convert them back to dos-codepage */
6152 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6153 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6156 /* Set the portname to what the script says the portname should be. */
6157 /* but don't require anything to be return from the script exit a good error code */
6160 /* Set the portname to what the script says the portname should be. */
6161 info2->portname = talloc_strdup(ctx, qlines[0]);
6162 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6165 TALLOC_FREE(qlines);
6169 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6170 const struct auth_serversupplied_info *session_info,
6171 struct messaging_context *msg_ctx,
6173 struct spoolss_SetPrinterInfo2 *printer,
6174 struct spoolss_PrinterInfo2 *old_printer)
6176 bool force_update = (old_printer == NULL);
6177 const char *dnsdomname;
6178 const char *longname;
6179 const char *uncname;
6180 const char *spooling;
6182 WERROR result = WERR_OK;
6184 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6185 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6186 winreg_set_printer_dataex(mem_ctx,
6190 SPOOL_DSSPOOLER_KEY,
6191 SPOOL_REG_DRIVERNAME,
6196 if (!force_update) {
6197 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6198 printer->drivername));
6200 notify_printer_driver(server_event_context(), msg_ctx,
6201 snum, printer->drivername ?
6202 printer->drivername : "");
6206 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6207 push_reg_sz(mem_ctx, &buffer, printer->comment);
6208 winreg_set_printer_dataex(mem_ctx,
6212 SPOOL_DSSPOOLER_KEY,
6213 SPOOL_REG_DESCRIPTION,
6218 if (!force_update) {
6219 notify_printer_comment(server_event_context(), msg_ctx,
6220 snum, printer->comment ?
6221 printer->comment : "");
6225 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6226 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6227 winreg_set_printer_dataex(mem_ctx,
6231 SPOOL_DSSPOOLER_KEY,
6232 SPOOL_REG_PRINTSHARENAME,
6237 if (!force_update) {
6238 notify_printer_sharename(server_event_context(),
6240 snum, printer->sharename ?
6241 printer->sharename : "");
6245 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6248 p = strrchr(printer->printername, '\\' );
6252 p = printer->printername;
6255 push_reg_sz(mem_ctx, &buffer, p);
6256 winreg_set_printer_dataex(mem_ctx,
6260 SPOOL_DSSPOOLER_KEY,
6261 SPOOL_REG_PRINTERNAME,
6266 if (!force_update) {
6267 notify_printer_printername(server_event_context(),
6268 msg_ctx, snum, p ? p : "");
6272 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6273 push_reg_sz(mem_ctx, &buffer, printer->portname);
6274 winreg_set_printer_dataex(mem_ctx,
6278 SPOOL_DSSPOOLER_KEY,
6284 if (!force_update) {
6285 notify_printer_port(server_event_context(),
6286 msg_ctx, snum, printer->portname ?
6287 printer->portname : "");
6291 if (force_update || !strequal(printer->location, old_printer->location)) {
6292 push_reg_sz(mem_ctx, &buffer, printer->location);
6293 winreg_set_printer_dataex(mem_ctx,
6297 SPOOL_DSSPOOLER_KEY,
6303 if (!force_update) {
6304 notify_printer_location(server_event_context(),
6307 printer->location : "");
6311 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6312 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6313 winreg_set_printer_dataex(mem_ctx,
6317 SPOOL_DSSPOOLER_KEY,
6318 SPOOL_REG_PRINTSEPARATORFILE,
6323 if (!force_update) {
6324 notify_printer_sepfile(server_event_context(),
6327 printer->sepfile : "");
6331 if (force_update || printer->starttime != old_printer->starttime) {
6332 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6333 SIVAL(buffer.data, 0, printer->starttime);
6334 winreg_set_printer_dataex(mem_ctx,
6338 SPOOL_DSSPOOLER_KEY,
6339 SPOOL_REG_PRINTSTARTTIME,
6345 if (force_update || printer->untiltime != old_printer->untiltime) {
6346 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6347 SIVAL(buffer.data, 0, printer->untiltime);
6348 winreg_set_printer_dataex(mem_ctx,
6352 SPOOL_DSSPOOLER_KEY,
6353 SPOOL_REG_PRINTENDTIME,
6359 if (force_update || printer->priority != old_printer->priority) {
6360 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6361 SIVAL(buffer.data, 0, printer->priority);
6362 winreg_set_printer_dataex(mem_ctx,
6366 SPOOL_DSSPOOLER_KEY,
6373 if (force_update || printer->attributes != old_printer->attributes) {
6374 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6375 SIVAL(buffer.data, 0, (printer->attributes &
6376 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6377 winreg_set_printer_dataex(mem_ctx,
6381 SPOOL_DSSPOOLER_KEY,
6382 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6387 switch (printer->attributes & 0x3) {
6389 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6392 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6395 spooling = SPOOL_REGVAL_PRINTDIRECT;
6398 spooling = "unknown";
6400 push_reg_sz(mem_ctx, &buffer, spooling);
6401 winreg_set_printer_dataex(mem_ctx,
6405 SPOOL_DSSPOOLER_KEY,
6406 SPOOL_REG_PRINTSPOOLING,
6412 push_reg_sz(mem_ctx, &buffer, global_myname());
6413 winreg_set_printer_dataex(mem_ctx,
6417 SPOOL_DSSPOOLER_KEY,
6418 SPOOL_REG_SHORTSERVERNAME,
6423 dnsdomname = get_mydnsfullname();
6424 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6425 longname = talloc_strdup(mem_ctx, dnsdomname);
6427 longname = talloc_strdup(mem_ctx, global_myname());
6429 if (longname == NULL) {
6430 result = WERR_NOMEM;
6434 push_reg_sz(mem_ctx, &buffer, longname);
6435 winreg_set_printer_dataex(mem_ctx,
6439 SPOOL_DSSPOOLER_KEY,
6440 SPOOL_REG_SERVERNAME,
6445 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6446 global_myname(), printer->sharename);
6447 push_reg_sz(mem_ctx, &buffer, uncname);
6448 winreg_set_printer_dataex(mem_ctx,
6452 SPOOL_DSSPOOLER_KEY,
6462 /********************************************************************
6463 * Called by spoolss_api_setprinter
6464 * when updating a printer description.
6465 ********************************************************************/
6467 static WERROR update_printer(struct pipes_struct *p,
6468 struct policy_handle *handle,
6469 struct spoolss_SetPrinterInfoCtr *info_ctr,
6470 struct spoolss_DeviceMode *devmode)
6472 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6473 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6474 struct spoolss_PrinterInfo2 *old_printer;
6475 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6477 WERROR result = WERR_OK;
6478 TALLOC_CTX *tmp_ctx;
6480 DEBUG(8,("update_printer\n"));
6482 tmp_ctx = talloc_new(p->mem_ctx);
6483 if (tmp_ctx == NULL) {
6488 result = WERR_BADFID;
6492 if (!get_printer_snum(p, handle, &snum, NULL)) {
6493 result = WERR_BADFID;
6497 result = winreg_get_printer(tmp_ctx,
6498 get_session_info_system(),
6500 lp_const_servicename(snum),
6502 if (!W_ERROR_IS_OK(result)) {
6503 result = WERR_BADFID;
6507 /* Do sanity check on the requested changes for Samba */
6508 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6509 result = WERR_INVALID_PARAM;
6513 /* FIXME!!! If the driver has changed we really should verify that
6514 it is installed before doing much else --jerry */
6516 /* Check calling user has permission to update printer description */
6517 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6518 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6519 result = WERR_ACCESS_DENIED;
6523 /* Call addprinter hook */
6524 /* Check changes to see if this is really needed */
6526 if (*lp_addprinter_cmd() &&
6527 (!strequal(printer->drivername, old_printer->drivername) ||
6528 !strequal(printer->comment, old_printer->comment) ||
6529 !strequal(printer->portname, old_printer->portname) ||
6530 !strequal(printer->location, old_printer->location)) )
6532 /* add_printer_hook() will call reload_services() */
6533 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6534 printer, p->client_id->addr,
6536 result = WERR_ACCESS_DENIED;
6541 update_dsspooler(tmp_ctx,
6542 get_session_info_system(),
6548 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6550 if (devmode == NULL) {
6551 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6553 result = winreg_update_printer(tmp_ctx,
6554 get_session_info_system(),
6563 talloc_free(tmp_ctx);
6568 /****************************************************************************
6569 ****************************************************************************/
6570 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6571 struct policy_handle *handle,
6572 struct spoolss_SetPrinterInfo7 *info7)
6575 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6578 struct printer_handle *Printer;
6580 if ( lp_security() != SEC_ADS ) {
6581 return WERR_UNKNOWN_LEVEL;
6584 Printer = find_printer_index_by_hnd(p, handle);
6586 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6591 if (!get_printer_snum(p, handle, &snum, NULL))
6594 result = winreg_get_printer(p->mem_ctx,
6595 get_session_info_system(),
6597 lp_servicename(snum),
6599 if (!W_ERROR_IS_OK(result)) {
6603 nt_printer_publish(pinfo2,
6604 get_session_info_system(),
6609 TALLOC_FREE(pinfo2);
6612 return WERR_UNKNOWN_LEVEL;
6616 /********************************************************************
6617 ********************************************************************/
6619 static WERROR update_printer_devmode(struct pipes_struct *p,
6620 struct policy_handle *handle,
6621 struct spoolss_DeviceMode *devmode)
6624 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6625 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6627 DEBUG(8,("update_printer_devmode\n"));
6633 if (!get_printer_snum(p, handle, &snum, NULL)) {
6637 /* Check calling user has permission to update printer description */
6638 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6639 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6640 return WERR_ACCESS_DENIED;
6643 return winreg_update_printer(p->mem_ctx,
6644 get_session_info_system(),
6646 lp_const_servicename(snum),
6654 /****************************************************************
6656 ****************************************************************/
6658 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6659 struct spoolss_SetPrinter *r)
6663 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6666 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6667 OUR_HANDLE(r->in.handle)));
6671 /* check the level */
6672 switch (r->in.info_ctr->level) {
6674 return control_printer(r->in.handle, r->in.command, p);
6676 result = update_printer(p, r->in.handle,
6678 r->in.devmode_ctr->devmode);
6679 if (!W_ERROR_IS_OK(result))
6681 if (r->in.secdesc_ctr->sd)
6682 result = update_printer_sec(r->in.handle, p,
6686 return update_printer_sec(r->in.handle, p,
6689 return publish_or_unpublish_printer(p, r->in.handle,
6690 r->in.info_ctr->info.info7);
6692 return update_printer_devmode(p, r->in.handle,
6693 r->in.devmode_ctr->devmode);
6695 return WERR_UNKNOWN_LEVEL;
6699 /****************************************************************
6700 _spoolss_FindClosePrinterNotify
6701 ****************************************************************/
6703 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6704 struct spoolss_FindClosePrinterNotify *r)
6706 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6709 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6710 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6714 if (Printer->notify.cli_chan != NULL &&
6715 Printer->notify.cli_chan->active_connections > 0) {
6718 if (Printer->printer_type == SPLHND_PRINTER) {
6719 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6724 srv_spoolss_replycloseprinter(snum, Printer);
6727 Printer->notify.flags=0;
6728 Printer->notify.options=0;
6729 Printer->notify.localmachine[0]='\0';
6730 Printer->notify.printerlocal=0;
6731 TALLOC_FREE(Printer->notify.option);
6736 /****************************************************************
6738 ****************************************************************/
6740 WERROR _spoolss_AddJob(struct pipes_struct *p,
6741 struct spoolss_AddJob *r)
6743 if (!r->in.buffer && (r->in.offered != 0)) {
6744 return WERR_INVALID_PARAM;
6747 /* this is what a NT server returns for AddJob. AddJob must fail on
6748 * non-local printers */
6750 if (r->in.level != 1) {
6751 return WERR_UNKNOWN_LEVEL;
6754 return WERR_INVALID_PARAM;
6757 /****************************************************************************
6759 ****************************************************************************/
6761 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6762 struct spoolss_JobInfo1 *r,
6763 const print_queue_struct *queue,
6764 int position, int snum,
6765 struct spoolss_PrinterInfo2 *pinfo2)
6769 t = gmtime(&queue->time);
6771 r->job_id = queue->job;
6773 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6774 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6775 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6776 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6777 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6778 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6779 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6780 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6781 r->data_type = talloc_strdup(mem_ctx, "RAW");
6782 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6783 r->text_status = talloc_strdup(mem_ctx, "");
6784 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6786 r->status = nt_printj_status(queue->status);
6787 r->priority = queue->priority;
6788 r->position = position;
6789 r->total_pages = queue->page_count;
6790 r->pages_printed = 0; /* ??? */
6792 init_systemtime(&r->submitted, t);
6797 /****************************************************************************
6799 ****************************************************************************/
6801 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6802 struct spoolss_JobInfo2 *r,
6803 const print_queue_struct *queue,
6804 int position, int snum,
6805 struct spoolss_PrinterInfo2 *pinfo2,
6806 struct spoolss_DeviceMode *devmode)
6810 t = gmtime(&queue->time);
6812 r->job_id = queue->job;
6814 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6815 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6816 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6817 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6818 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6819 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6820 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6821 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6822 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6823 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6824 r->data_type = talloc_strdup(mem_ctx, "RAW");
6825 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6826 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6827 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6828 r->parameters = talloc_strdup(mem_ctx, "");
6829 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6830 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6831 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6833 r->devmode = devmode;
6835 r->text_status = talloc_strdup(mem_ctx, "");
6836 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6840 r->status = nt_printj_status(queue->status);
6841 r->priority = queue->priority;
6842 r->position = position;
6845 r->total_pages = queue->page_count;
6846 r->size = queue->size;
6847 init_systemtime(&r->submitted, t);
6849 r->pages_printed = 0; /* ??? */
6854 /****************************************************************************
6856 ****************************************************************************/
6858 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6859 struct spoolss_JobInfo3 *r,
6860 const print_queue_struct *queue,
6861 const print_queue_struct *next_queue,
6862 int position, int snum,
6863 struct spoolss_PrinterInfo2 *pinfo2)
6865 r->job_id = queue->job;
6868 r->next_job_id = next_queue->job;
6875 /****************************************************************************
6876 Enumjobs at level 1.
6877 ****************************************************************************/
6879 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6880 const print_queue_struct *queue,
6881 uint32_t num_queues, int snum,
6882 struct spoolss_PrinterInfo2 *pinfo2,
6883 union spoolss_JobInfo **info_p,
6886 union spoolss_JobInfo *info;
6888 WERROR result = WERR_OK;
6890 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6891 W_ERROR_HAVE_NO_MEMORY(info);
6893 *count = num_queues;
6895 for (i=0; i<*count; i++) {
6896 result = fill_job_info1(info,
6902 if (!W_ERROR_IS_OK(result)) {
6908 if (!W_ERROR_IS_OK(result)) {
6919 /****************************************************************************
6920 Enumjobs at level 2.
6921 ****************************************************************************/
6923 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6924 const print_queue_struct *queue,
6925 uint32_t num_queues, int snum,
6926 struct spoolss_PrinterInfo2 *pinfo2,
6927 union spoolss_JobInfo **info_p,
6930 union spoolss_JobInfo *info;
6932 WERROR result = WERR_OK;
6934 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6935 W_ERROR_HAVE_NO_MEMORY(info);
6937 *count = num_queues;
6939 for (i=0; i<*count; i++) {
6940 struct spoolss_DeviceMode *devmode;
6942 result = spoolss_create_default_devmode(info,
6943 pinfo2->printername,
6945 if (!W_ERROR_IS_OK(result)) {
6946 DEBUG(3, ("Can't proceed w/o a devmode!"));
6950 result = fill_job_info2(info,
6957 if (!W_ERROR_IS_OK(result)) {
6963 if (!W_ERROR_IS_OK(result)) {
6974 /****************************************************************************
6975 Enumjobs at level 3.
6976 ****************************************************************************/
6978 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6979 const print_queue_struct *queue,
6980 uint32_t num_queues, int snum,
6981 struct spoolss_PrinterInfo2 *pinfo2,
6982 union spoolss_JobInfo **info_p,
6985 union spoolss_JobInfo *info;
6987 WERROR result = WERR_OK;
6989 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6990 W_ERROR_HAVE_NO_MEMORY(info);
6992 *count = num_queues;
6994 for (i=0; i<*count; i++) {
6995 const print_queue_struct *next_queue = NULL;
6998 next_queue = &queue[i+1];
7001 result = fill_job_info3(info,
7008 if (!W_ERROR_IS_OK(result)) {
7014 if (!W_ERROR_IS_OK(result)) {
7025 /****************************************************************
7027 ****************************************************************/
7029 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7030 struct spoolss_EnumJobs *r)
7033 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7035 print_status_struct prt_status;
7036 print_queue_struct *queue = NULL;
7039 /* that's an [in out] buffer */
7041 if (!r->in.buffer && (r->in.offered != 0)) {
7042 return WERR_INVALID_PARAM;
7045 DEBUG(4,("_spoolss_EnumJobs\n"));
7049 *r->out.info = NULL;
7051 /* lookup the printer snum and tdb entry */
7053 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7057 result = winreg_get_printer(p->mem_ctx,
7058 get_session_info_system(),
7060 lp_const_servicename(snum),
7062 if (!W_ERROR_IS_OK(result)) {
7066 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7067 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7068 count, prt_status.status, prt_status.message));
7072 TALLOC_FREE(pinfo2);
7076 switch (r->in.level) {
7078 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7079 pinfo2, r->out.info, r->out.count);
7082 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7083 pinfo2, r->out.info, r->out.count);
7086 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7087 pinfo2, r->out.info, r->out.count);
7090 result = WERR_UNKNOWN_LEVEL;
7095 TALLOC_FREE(pinfo2);
7097 if (!W_ERROR_IS_OK(result)) {
7101 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7103 *r->out.info, r->in.level,
7105 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7106 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7108 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7111 /****************************************************************
7112 _spoolss_ScheduleJob
7113 ****************************************************************/
7115 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7116 struct spoolss_ScheduleJob *r)
7121 /****************************************************************
7122 ****************************************************************/
7124 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7125 struct messaging_context *msg_ctx,
7126 const char *printer_name,
7128 struct spoolss_SetJobInfo1 *r)
7132 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7136 if (strequal(old_doc_name, r->document_name)) {
7140 if (!print_job_set_name(server_event_context(), msg_ctx,
7141 printer_name, job_id, r->document_name)) {
7148 /****************************************************************
7150 ****************************************************************/
7152 WERROR _spoolss_SetJob(struct pipes_struct *p,
7153 struct spoolss_SetJob *r)
7155 const struct auth_serversupplied_info *session_info = p->session_info;
7157 WERROR errcode = WERR_BADFUNC;
7159 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7163 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7164 return WERR_INVALID_PRINTER_NAME;
7167 switch (r->in.command) {
7168 case SPOOLSS_JOB_CONTROL_CANCEL:
7169 case SPOOLSS_JOB_CONTROL_DELETE:
7170 errcode = print_job_delete(session_info, p->msg_ctx,
7171 snum, r->in.job_id);
7172 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7176 case SPOOLSS_JOB_CONTROL_PAUSE:
7177 if (print_job_pause(session_info, p->msg_ctx,
7178 snum, r->in.job_id, &errcode)) {
7182 case SPOOLSS_JOB_CONTROL_RESTART:
7183 case SPOOLSS_JOB_CONTROL_RESUME:
7184 if (print_job_resume(session_info, p->msg_ctx,
7185 snum, r->in.job_id, &errcode)) {
7193 return WERR_UNKNOWN_LEVEL;
7196 if (!W_ERROR_IS_OK(errcode)) {
7200 if (r->in.ctr == NULL) {
7204 switch (r->in.ctr->level) {
7206 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7207 lp_const_servicename(snum),
7209 r->in.ctr->info.info1);
7215 return WERR_UNKNOWN_LEVEL;
7221 /****************************************************************************
7222 Enumerates all printer drivers by level and architecture.
7223 ****************************************************************************/
7225 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7226 const struct auth_serversupplied_info *session_info,
7227 struct messaging_context *msg_ctx,
7228 const char *servername,
7229 const char *architecture,
7231 union spoolss_DriverInfo **info_p,
7236 struct spoolss_DriverInfo8 *driver;
7237 union spoolss_DriverInfo *info = NULL;
7239 WERROR result = WERR_OK;
7240 uint32_t num_drivers;
7241 const char **drivers;
7246 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7247 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7248 architecture, version,
7249 &num_drivers, &drivers);
7250 if (!W_ERROR_IS_OK(result)) {
7253 DEBUG(4, ("we have:[%d] drivers in environment"
7254 " [%s] and version [%d]\n",
7255 num_drivers, architecture, version));
7257 if (num_drivers != 0) {
7258 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7259 union spoolss_DriverInfo,
7260 count + num_drivers);
7262 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7263 "failed to enlarge driver info buffer!\n"));
7264 result = WERR_NOMEM;
7269 for (i = 0; i < num_drivers; i++) {
7270 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7272 result = winreg_get_driver(mem_ctx, session_info,
7274 architecture, drivers[i],
7276 if (!W_ERROR_IS_OK(result)) {
7282 result = fill_printer_driver_info1(info, &info[count+i].info1,
7283 driver, servername);
7286 result = fill_printer_driver_info2(info, &info[count+i].info2,
7287 driver, servername);
7290 result = fill_printer_driver_info3(info, &info[count+i].info3,
7291 driver, servername);
7294 result = fill_printer_driver_info4(info, &info[count+i].info4,
7295 driver, servername);
7298 result = fill_printer_driver_info5(info, &info[count+i].info5,
7299 driver, servername);
7302 result = fill_printer_driver_info6(info, &info[count+i].info6,
7303 driver, servername);
7306 result = fill_printer_driver_info8(info, &info[count+i].info8,
7307 driver, servername);
7310 result = WERR_UNKNOWN_LEVEL;
7314 TALLOC_FREE(driver);
7316 if (!W_ERROR_IS_OK(result)) {
7321 count += num_drivers;
7322 TALLOC_FREE(drivers);
7326 TALLOC_FREE(drivers);
7328 if (!W_ERROR_IS_OK(result)) {
7339 /****************************************************************************
7340 Enumerates all printer drivers by level.
7341 ****************************************************************************/
7343 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7344 const struct auth_serversupplied_info *session_info,
7345 struct messaging_context *msg_ctx,
7346 const char *servername,
7347 const char *architecture,
7349 union spoolss_DriverInfo **info_p,
7353 WERROR result = WERR_OK;
7355 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7357 for (a=0; archi_table[a].long_archi != NULL; a++) {
7359 union spoolss_DriverInfo *info = NULL;
7362 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7366 archi_table[a].long_archi,
7370 if (!W_ERROR_IS_OK(result)) {
7374 for (i=0; i < count; i++) {
7375 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7376 info[i], info_p, count_p);
7383 return enumprinterdrivers_level_by_architecture(mem_ctx,
7393 /****************************************************************
7394 _spoolss_EnumPrinterDrivers
7395 ****************************************************************/
7397 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7398 struct spoolss_EnumPrinterDrivers *r)
7400 const char *cservername;
7403 /* that's an [in out] buffer */
7405 if (!r->in.buffer && (r->in.offered != 0)) {
7406 return WERR_INVALID_PARAM;
7409 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7413 *r->out.info = NULL;
7415 cservername = canon_servername(r->in.server);
7417 if (!is_myname_or_ipaddr(cservername)) {
7418 return WERR_UNKNOWN_PRINTER_DRIVER;
7421 result = enumprinterdrivers_level(p->mem_ctx,
7422 get_session_info_system(),
7429 if (!W_ERROR_IS_OK(result)) {
7433 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7434 spoolss_EnumPrinterDrivers,
7435 *r->out.info, r->in.level,
7437 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7438 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7440 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7443 /****************************************************************
7445 ****************************************************************/
7447 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7448 struct spoolss_EnumForms *r)
7454 *r->out.info = NULL;
7456 /* that's an [in out] buffer */
7458 if (!r->in.buffer && (r->in.offered != 0) ) {
7459 return WERR_INVALID_PARAM;
7462 DEBUG(4,("_spoolss_EnumForms\n"));
7463 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7464 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7466 switch (r->in.level) {
7468 result = winreg_printer_enumforms1(p->mem_ctx,
7469 get_session_info_system(),
7475 result = WERR_UNKNOWN_LEVEL;
7479 if (!W_ERROR_IS_OK(result)) {
7483 if (*r->out.count == 0) {
7484 return WERR_NO_MORE_ITEMS;
7487 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7489 *r->out.info, r->in.level,
7491 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7492 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7494 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7497 /****************************************************************
7499 ****************************************************************/
7501 WERROR _spoolss_GetForm(struct pipes_struct *p,
7502 struct spoolss_GetForm *r)
7506 /* that's an [in out] buffer */
7508 if (!r->in.buffer && (r->in.offered != 0)) {
7509 return WERR_INVALID_PARAM;
7512 DEBUG(4,("_spoolss_GetForm\n"));
7513 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7514 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7516 switch (r->in.level) {
7518 result = winreg_printer_getform1(p->mem_ctx,
7519 get_session_info_system(),
7522 &r->out.info->info1);
7525 result = WERR_UNKNOWN_LEVEL;
7529 if (!W_ERROR_IS_OK(result)) {
7530 TALLOC_FREE(r->out.info);
7534 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7535 r->out.info, r->in.level);
7536 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7538 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7541 /****************************************************************************
7542 ****************************************************************************/
7544 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7545 struct spoolss_PortInfo1 *r,
7548 r->port_name = talloc_strdup(mem_ctx, name);
7549 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7554 /****************************************************************************
7555 TODO: This probably needs distinguish between TCP/IP and Local ports
7557 ****************************************************************************/
7559 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7560 struct spoolss_PortInfo2 *r,
7563 r->port_name = talloc_strdup(mem_ctx, name);
7564 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7566 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7567 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7569 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7570 W_ERROR_HAVE_NO_MEMORY(r->description);
7572 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7579 /****************************************************************************
7580 wrapper around the enumer ports command
7581 ****************************************************************************/
7583 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7585 char *cmd = lp_enumports_cmd();
7586 char **qlines = NULL;
7587 char *command = NULL;
7595 /* if no hook then just fill in the default port */
7598 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7601 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7602 TALLOC_FREE(qlines);
7609 /* we have a valid enumport command */
7611 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7616 DEBUG(10,("Running [%s]\n", command));
7617 ret = smbrun(command, &fd);
7618 DEBUG(10,("Returned [%d]\n", ret));
7619 TALLOC_FREE(command);
7624 return WERR_ACCESS_DENIED;
7628 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7629 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7639 /****************************************************************************
7641 ****************************************************************************/
7643 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7644 union spoolss_PortInfo **info_p,
7647 union spoolss_PortInfo *info = NULL;
7649 WERROR result = WERR_OK;
7650 char **qlines = NULL;
7653 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7654 if (!W_ERROR_IS_OK(result)) {
7659 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7661 DEBUG(10,("Returning WERR_NOMEM\n"));
7662 result = WERR_NOMEM;
7666 for (i=0; i<numlines; i++) {
7667 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7668 result = fill_port_1(info, &info[i].info1, qlines[i]);
7669 if (!W_ERROR_IS_OK(result)) {
7674 TALLOC_FREE(qlines);
7677 if (!W_ERROR_IS_OK(result)) {
7679 TALLOC_FREE(qlines);
7691 /****************************************************************************
7693 ****************************************************************************/
7695 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7696 union spoolss_PortInfo **info_p,
7699 union spoolss_PortInfo *info = NULL;
7701 WERROR result = WERR_OK;
7702 char **qlines = NULL;
7705 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7706 if (!W_ERROR_IS_OK(result)) {
7711 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7713 DEBUG(10,("Returning WERR_NOMEM\n"));
7714 result = WERR_NOMEM;
7718 for (i=0; i<numlines; i++) {
7719 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7720 result = fill_port_2(info, &info[i].info2, qlines[i]);
7721 if (!W_ERROR_IS_OK(result)) {
7726 TALLOC_FREE(qlines);
7729 if (!W_ERROR_IS_OK(result)) {
7731 TALLOC_FREE(qlines);
7743 /****************************************************************
7745 ****************************************************************/
7747 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7748 struct spoolss_EnumPorts *r)
7752 /* that's an [in out] buffer */
7754 if (!r->in.buffer && (r->in.offered != 0)) {
7755 return WERR_INVALID_PARAM;
7758 DEBUG(4,("_spoolss_EnumPorts\n"));
7762 *r->out.info = NULL;
7764 switch (r->in.level) {
7766 result = enumports_level_1(p->mem_ctx, r->out.info,
7770 result = enumports_level_2(p->mem_ctx, r->out.info,
7774 return WERR_UNKNOWN_LEVEL;
7777 if (!W_ERROR_IS_OK(result)) {
7781 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7783 *r->out.info, r->in.level,
7785 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7786 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7788 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7791 /****************************************************************************
7792 ****************************************************************************/
7794 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7796 struct spoolss_SetPrinterInfoCtr *info_ctr,
7797 struct spoolss_DeviceMode *devmode,
7798 struct security_descriptor *secdesc,
7799 struct spoolss_UserLevelCtr *user_ctr,
7800 struct policy_handle *handle)
7802 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7803 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7805 WERROR err = WERR_OK;
7807 /* samba does not have a concept of local, non-shared printers yet, so
7808 * make sure we always setup sharename - gd */
7809 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7810 (info2->printername != NULL && info2->printername[0] != '\0')) {
7811 DEBUG(5, ("spoolss_addprinterex_level_2: "
7812 "no sharename has been set, setting printername %s as sharename\n",
7813 info2->printername));
7814 info2->sharename = info2->printername;
7817 /* check to see if the printer already exists */
7818 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7819 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7821 return WERR_PRINTER_ALREADY_EXISTS;
7824 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7825 if ((snum = print_queue_snum(info2->printername)) != -1) {
7826 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7827 info2->printername));
7828 return WERR_PRINTER_ALREADY_EXISTS;
7832 /* validate printer info struct */
7833 if (!info2->printername || strlen(info2->printername) == 0) {
7834 return WERR_INVALID_PRINTER_NAME;
7836 if (!info2->portname || strlen(info2->portname) == 0) {
7837 return WERR_UNKNOWN_PORT;
7839 if (!info2->drivername || strlen(info2->drivername) == 0) {
7840 return WERR_UNKNOWN_PRINTER_DRIVER;
7842 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7843 return WERR_UNKNOWN_PRINTPROCESSOR;
7846 /* FIXME!!! smbd should check to see if the driver is installed before
7847 trying to add a printer like this --jerry */
7849 if (*lp_addprinter_cmd() ) {
7850 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7851 info2, p->client_id->addr,
7853 return WERR_ACCESS_DENIED;
7856 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7857 "smb.conf parameter \"addprinter command\" is defined. This"
7858 "parameter must exist for this call to succeed\n",
7859 info2->sharename ));
7862 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7863 return WERR_ACCESS_DENIED;
7866 /* you must be a printer admin to add a new printer */
7867 if (!print_access_check(p->session_info,
7870 PRINTER_ACCESS_ADMINISTER)) {
7871 return WERR_ACCESS_DENIED;
7875 * Do sanity check on the requested changes for Samba.
7878 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7879 return WERR_INVALID_PARAM;
7882 if (devmode == NULL) {
7883 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7886 update_dsspooler(p->mem_ctx,
7887 get_session_info_system(),
7893 err = winreg_update_printer(p->mem_ctx,
7894 get_session_info_system(),
7901 if (!W_ERROR_IS_OK(err)) {
7905 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7906 if (!W_ERROR_IS_OK(err)) {
7907 /* Handle open failed - remove addition. */
7908 ZERO_STRUCTP(handle);
7915 /****************************************************************
7916 _spoolss_AddPrinterEx
7917 ****************************************************************/
7919 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7920 struct spoolss_AddPrinterEx *r)
7922 switch (r->in.info_ctr->level) {
7924 /* we don't handle yet */
7925 /* but I know what to do ... */
7926 return WERR_UNKNOWN_LEVEL;
7928 return spoolss_addprinterex_level_2(p, r->in.server,
7930 r->in.devmode_ctr->devmode,
7931 r->in.secdesc_ctr->sd,
7932 r->in.userlevel_ctr,
7935 return WERR_UNKNOWN_LEVEL;
7939 /****************************************************************
7941 ****************************************************************/
7943 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7944 struct spoolss_AddPrinter *r)
7946 struct spoolss_AddPrinterEx a;
7947 struct spoolss_UserLevelCtr userlevel_ctr;
7949 ZERO_STRUCT(userlevel_ctr);
7951 userlevel_ctr.level = 1;
7953 a.in.server = r->in.server;
7954 a.in.info_ctr = r->in.info_ctr;
7955 a.in.devmode_ctr = r->in.devmode_ctr;
7956 a.in.secdesc_ctr = r->in.secdesc_ctr;
7957 a.in.userlevel_ctr = &userlevel_ctr;
7958 a.out.handle = r->out.handle;
7960 return _spoolss_AddPrinterEx(p, &a);
7963 /****************************************************************
7964 _spoolss_AddPrinterDriverEx
7965 ****************************************************************/
7967 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7968 struct spoolss_AddPrinterDriverEx *r)
7970 WERROR err = WERR_OK;
7971 const char *driver_name = NULL;
7976 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7977 fn = "_spoolss_AddPrinterDriver";
7979 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7980 fn = "_spoolss_AddPrinterDriverEx";
7983 return WERR_INVALID_PARAM;
7987 * we only support the semantics of AddPrinterDriver()
7988 * i.e. only copy files that are newer than existing ones
7991 if (r->in.flags == 0) {
7992 return WERR_INVALID_PARAM;
7995 if (r->in.flags != APD_COPY_NEW_FILES) {
7996 return WERR_ACCESS_DENIED;
8000 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8001 /* Clever hack from Martin Zielinski <mz@seh.de>
8002 * to allow downgrade from level 8 (Vista).
8004 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8005 r->in.info_ctr->level));
8006 return WERR_UNKNOWN_LEVEL;
8009 DEBUG(5,("Cleaning driver's information\n"));
8010 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8011 if (!W_ERROR_IS_OK(err))
8014 DEBUG(5,("Moving driver to final destination\n"));
8015 err = move_driver_to_download_area(p, r->in.info_ctr);
8016 if (!W_ERROR_IS_OK(err)) {
8020 err = winreg_add_driver(p->mem_ctx,
8021 get_session_info_system(),
8026 if (!W_ERROR_IS_OK(err)) {
8031 * I think this is where he DrvUpgradePrinter() hook would be
8032 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8033 * server. Right now, we just need to send ourselves a message
8034 * to update each printer bound to this driver. --jerry
8037 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8038 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8046 /****************************************************************
8047 _spoolss_AddPrinterDriver
8048 ****************************************************************/
8050 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8051 struct spoolss_AddPrinterDriver *r)
8053 struct spoolss_AddPrinterDriverEx a;
8055 switch (r->in.info_ctr->level) {
8062 return WERR_UNKNOWN_LEVEL;
8065 a.in.servername = r->in.servername;
8066 a.in.info_ctr = r->in.info_ctr;
8067 a.in.flags = APD_COPY_NEW_FILES;
8069 return _spoolss_AddPrinterDriverEx(p, &a);
8072 /****************************************************************************
8073 ****************************************************************************/
8075 struct _spoolss_paths {
8081 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8083 static const struct _spoolss_paths spoolss_paths[]= {
8084 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8085 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8088 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8089 const char *servername,
8090 const char *environment,
8094 const char *pservername = NULL;
8095 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8096 const char *short_archi;
8100 /* environment may be empty */
8101 if (environment && strlen(environment)) {
8102 long_archi = environment;
8105 /* servername may be empty */
8106 if (servername && strlen(servername)) {
8107 pservername = canon_servername(servername);
8109 if (!is_myname_or_ipaddr(pservername)) {
8110 return WERR_INVALID_PARAM;
8114 if (!(short_archi = get_short_archi(long_archi))) {
8115 return WERR_INVALID_ENVIRONMENT;
8118 switch (component) {
8119 case SPOOLSS_PRTPROCS_PATH:
8120 case SPOOLSS_DRIVER_PATH:
8122 *path = talloc_asprintf(mem_ctx,
8125 spoolss_paths[component].share,
8128 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8129 SPOOLSS_DEFAULT_SERVER_PATH,
8130 spoolss_paths[component].dir,
8135 return WERR_INVALID_PARAM;
8145 /****************************************************************************
8146 ****************************************************************************/
8148 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8149 const char *servername,
8150 const char *environment,
8151 struct spoolss_DriverDirectoryInfo1 *r)
8156 werr = compose_spoolss_server_path(mem_ctx,
8159 SPOOLSS_DRIVER_PATH,
8161 if (!W_ERROR_IS_OK(werr)) {
8165 DEBUG(4,("printer driver directory: [%s]\n", path));
8167 r->directory_name = path;
8172 /****************************************************************
8173 _spoolss_GetPrinterDriverDirectory
8174 ****************************************************************/
8176 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8177 struct spoolss_GetPrinterDriverDirectory *r)
8181 /* that's an [in out] buffer */
8183 if (!r->in.buffer && (r->in.offered != 0)) {
8184 return WERR_INVALID_PARAM;
8187 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8192 /* r->in.level is ignored */
8194 werror = getprinterdriverdir_level_1(p->mem_ctx,
8197 &r->out.info->info1);
8198 if (!W_ERROR_IS_OK(werror)) {
8199 TALLOC_FREE(r->out.info);
8203 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8204 r->out.info, r->in.level);
8205 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8207 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8210 /****************************************************************
8211 _spoolss_EnumPrinterData
8212 ****************************************************************/
8214 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8215 struct spoolss_EnumPrinterData *r)
8218 struct spoolss_EnumPrinterDataEx r2;
8220 struct spoolss_PrinterEnumValues *info, *val = NULL;
8223 r2.in.handle = r->in.handle;
8224 r2.in.key_name = "PrinterDriverData";
8226 r2.out.count = &count;
8227 r2.out.info = &info;
8228 r2.out.needed = &needed;
8230 result = _spoolss_EnumPrinterDataEx(p, &r2);
8231 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8232 r2.in.offered = needed;
8233 result = _spoolss_EnumPrinterDataEx(p, &r2);
8235 if (!W_ERROR_IS_OK(result)) {
8240 * The NT machine wants to know the biggest size of value and data
8242 * cf: MSDN EnumPrinterData remark section
8245 if (!r->in.value_offered && !r->in.data_offered) {
8246 uint32_t biggest_valuesize = 0;
8247 uint32_t biggest_datasize = 0;
8250 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8252 for (i=0; i<count; i++) {
8254 name_length = strlen(info[i].value_name);
8255 if (strlen(info[i].value_name) > biggest_valuesize) {
8256 biggest_valuesize = name_length;
8259 if (info[i].data_length > biggest_datasize) {
8260 biggest_datasize = info[i].data_length;
8263 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8267 /* the value is an UNICODE string but real_value_size is the length
8268 in bytes including the trailing 0 */
8270 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8271 *r->out.data_needed = biggest_datasize;
8273 DEBUG(6,("final values: [%d], [%d]\n",
8274 *r->out.value_needed, *r->out.data_needed));
8279 if (r->in.enum_index < count) {
8280 val = &info[r->in.enum_index];
8284 /* out_value should default to "" or else NT4 has
8285 problems unmarshalling the response */
8287 if (r->in.value_offered) {
8288 *r->out.value_needed = 1;
8289 r->out.value_name = talloc_strdup(r, "");
8290 if (!r->out.value_name) {
8294 r->out.value_name = NULL;
8295 *r->out.value_needed = 0;
8298 /* the data is counted in bytes */
8300 *r->out.data_needed = r->in.data_offered;
8302 result = WERR_NO_MORE_ITEMS;
8306 * - counted in bytes in the request
8307 * - counted in UNICODE chars in the max reply
8308 * - counted in bytes in the real size
8310 * take a pause *before* coding not *during* coding
8314 if (r->in.value_offered) {
8315 r->out.value_name = talloc_strdup(r, val->value_name);
8316 if (!r->out.value_name) {
8319 *r->out.value_needed = val->value_name_len;
8321 r->out.value_name = NULL;
8322 *r->out.value_needed = 0;
8327 *r->out.type = val->type;
8329 /* data - counted in bytes */
8332 * See the section "Dynamically Typed Query Parameters"
8336 if (r->out.data && val->data && val->data->data &&
8337 val->data_length && r->in.data_offered) {
8338 memcpy(r->out.data, val->data->data,
8339 MIN(val->data_length,r->in.data_offered));
8342 *r->out.data_needed = val->data_length;
8350 /****************************************************************
8351 _spoolss_SetPrinterData
8352 ****************************************************************/
8354 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8355 struct spoolss_SetPrinterData *r)
8357 struct spoolss_SetPrinterDataEx r2;
8359 r2.in.handle = r->in.handle;
8360 r2.in.key_name = "PrinterDriverData";
8361 r2.in.value_name = r->in.value_name;
8362 r2.in.type = r->in.type;
8363 r2.in.data = r->in.data;
8364 r2.in.offered = r->in.offered;
8366 return _spoolss_SetPrinterDataEx(p, &r2);
8369 /****************************************************************
8370 _spoolss_ResetPrinter
8371 ****************************************************************/
8373 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8374 struct spoolss_ResetPrinter *r)
8376 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8379 DEBUG(5,("_spoolss_ResetPrinter\n"));
8382 * All we do is to check to see if the handle and queue is valid.
8383 * This call really doesn't mean anything to us because we only
8384 * support RAW printing. --jerry
8388 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8389 OUR_HANDLE(r->in.handle)));
8393 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8397 /* blindly return success */
8401 /****************************************************************
8402 _spoolss_DeletePrinterData
8403 ****************************************************************/
8405 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8406 struct spoolss_DeletePrinterData *r)
8408 struct spoolss_DeletePrinterDataEx r2;
8410 r2.in.handle = r->in.handle;
8411 r2.in.key_name = "PrinterDriverData";
8412 r2.in.value_name = r->in.value_name;
8414 return _spoolss_DeletePrinterDataEx(p, &r2);
8417 /****************************************************************
8419 ****************************************************************/
8421 WERROR _spoolss_AddForm(struct pipes_struct *p,
8422 struct spoolss_AddForm *r)
8424 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8426 WERROR status = WERR_OK;
8428 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8430 DEBUG(5,("_spoolss_AddForm\n"));
8433 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8434 OUR_HANDLE(r->in.handle)));
8438 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8439 and not a printer admin, then fail */
8441 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8442 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8443 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8444 p->session_info->info3->base.domain.string,
8446 p->session_info->security_token,
8447 lp_printer_admin(snum))) {
8448 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8449 return WERR_ACCESS_DENIED;
8452 switch (form->flags) {
8453 case SPOOLSS_FORM_USER:
8454 case SPOOLSS_FORM_BUILTIN:
8455 case SPOOLSS_FORM_PRINTER:
8458 return WERR_INVALID_PARAM;
8461 status = winreg_printer_addform1(p->mem_ctx,
8462 get_session_info_system(),
8465 if (!W_ERROR_IS_OK(status)) {
8470 * ChangeID must always be set if this is a printer
8472 if (Printer->printer_type == SPLHND_PRINTER) {
8473 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8477 status = winreg_printer_update_changeid(p->mem_ctx,
8478 get_session_info_system(),
8480 lp_const_servicename(snum));
8481 if (!W_ERROR_IS_OK(status)) {
8489 /****************************************************************
8491 ****************************************************************/
8493 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8494 struct spoolss_DeleteForm *r)
8496 const char *form_name = r->in.form_name;
8497 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8499 WERROR status = WERR_OK;
8501 DEBUG(5,("_spoolss_DeleteForm\n"));
8504 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8505 OUR_HANDLE(r->in.handle)));
8509 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8510 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8511 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8512 p->session_info->info3->base.domain.string,
8514 p->session_info->security_token,
8515 lp_printer_admin(snum))) {
8516 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8517 return WERR_ACCESS_DENIED;
8520 status = winreg_printer_deleteform1(p->mem_ctx,
8521 get_session_info_system(),
8524 if (!W_ERROR_IS_OK(status)) {
8529 * ChangeID must always be set if this is a printer
8531 if (Printer->printer_type == SPLHND_PRINTER) {
8532 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8536 status = winreg_printer_update_changeid(p->mem_ctx,
8537 get_session_info_system(),
8539 lp_const_servicename(snum));
8540 if (!W_ERROR_IS_OK(status)) {
8548 /****************************************************************
8550 ****************************************************************/
8552 WERROR _spoolss_SetForm(struct pipes_struct *p,
8553 struct spoolss_SetForm *r)
8555 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8556 const char *form_name = r->in.form_name;
8558 WERROR status = WERR_OK;
8560 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8562 DEBUG(5,("_spoolss_SetForm\n"));
8565 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8566 OUR_HANDLE(r->in.handle)));
8570 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8571 and not a printer admin, then fail */
8573 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8574 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8575 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8576 p->session_info->info3->base.domain.string,
8578 p->session_info->security_token,
8579 lp_printer_admin(snum))) {
8580 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8581 return WERR_ACCESS_DENIED;
8584 status = winreg_printer_setform1(p->mem_ctx,
8585 get_session_info_system(),
8589 if (!W_ERROR_IS_OK(status)) {
8594 * ChangeID must always be set if this is a printer
8596 if (Printer->printer_type == SPLHND_PRINTER) {
8597 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8601 status = winreg_printer_update_changeid(p->mem_ctx,
8602 get_session_info_system(),
8604 lp_const_servicename(snum));
8605 if (!W_ERROR_IS_OK(status)) {
8613 /****************************************************************************
8614 fill_print_processor1
8615 ****************************************************************************/
8617 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8618 struct spoolss_PrintProcessorInfo1 *r,
8619 const char *print_processor_name)
8621 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8622 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8627 /****************************************************************************
8628 enumprintprocessors level 1.
8629 ****************************************************************************/
8631 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8632 union spoolss_PrintProcessorInfo **info_p,
8635 union spoolss_PrintProcessorInfo *info;
8638 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8639 W_ERROR_HAVE_NO_MEMORY(info);
8643 result = fill_print_processor1(info, &info[0].info1, "winprint");
8644 if (!W_ERROR_IS_OK(result)) {
8649 if (!W_ERROR_IS_OK(result)) {
8660 /****************************************************************
8661 _spoolss_EnumPrintProcessors
8662 ****************************************************************/
8664 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8665 struct spoolss_EnumPrintProcessors *r)
8669 /* that's an [in out] buffer */
8671 if (!r->in.buffer && (r->in.offered != 0)) {
8672 return WERR_INVALID_PARAM;
8675 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8678 * Enumerate the print processors ...
8680 * Just reply with "winprint", to keep NT happy
8681 * and I can use my nice printer checker.
8686 *r->out.info = NULL;
8688 if (!get_short_archi(r->in.environment)) {
8689 return WERR_INVALID_ENVIRONMENT;
8692 switch (r->in.level) {
8694 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8698 return WERR_UNKNOWN_LEVEL;
8701 if (!W_ERROR_IS_OK(result)) {
8705 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8706 spoolss_EnumPrintProcessors,
8707 *r->out.info, r->in.level,
8709 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8710 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8712 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8715 /****************************************************************************
8716 fill_printprocdatatype1
8717 ****************************************************************************/
8719 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8720 struct spoolss_PrintProcDataTypesInfo1 *r,
8721 const char *name_array)
8723 r->name_array = talloc_strdup(mem_ctx, name_array);
8724 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8729 /****************************************************************************
8730 enumprintprocdatatypes level 1.
8731 ****************************************************************************/
8733 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8734 union spoolss_PrintProcDataTypesInfo **info_p,
8738 union spoolss_PrintProcDataTypesInfo *info;
8740 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8741 W_ERROR_HAVE_NO_MEMORY(info);
8745 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8746 if (!W_ERROR_IS_OK(result)) {
8751 if (!W_ERROR_IS_OK(result)) {
8762 /****************************************************************
8763 _spoolss_EnumPrintProcDataTypes
8764 ****************************************************************/
8766 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8767 struct spoolss_EnumPrintProcDataTypes *r)
8771 /* that's an [in out] buffer */
8773 if (!r->in.buffer && (r->in.offered != 0)) {
8774 return WERR_INVALID_PARAM;
8777 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8781 *r->out.info = NULL;
8783 if (r->in.print_processor_name == NULL ||
8784 !strequal(r->in.print_processor_name, "winprint")) {
8785 return WERR_UNKNOWN_PRINTPROCESSOR;
8788 switch (r->in.level) {
8790 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8794 return WERR_UNKNOWN_LEVEL;
8797 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8798 spoolss_EnumPrintProcDataTypes,
8799 *r->out.info, r->in.level,
8801 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8802 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8804 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8807 /****************************************************************************
8809 ****************************************************************************/
8811 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8812 struct spoolss_MonitorInfo1 *r,
8813 const char *monitor_name)
8815 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8816 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8821 /****************************************************************************
8823 ****************************************************************************/
8825 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8826 struct spoolss_MonitorInfo2 *r,
8827 const char *monitor_name,
8828 const char *environment,
8829 const char *dll_name)
8831 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8832 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8833 r->environment = talloc_strdup(mem_ctx, environment);
8834 W_ERROR_HAVE_NO_MEMORY(r->environment);
8835 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8836 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8841 /****************************************************************************
8842 enumprintmonitors level 1.
8843 ****************************************************************************/
8845 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8846 union spoolss_MonitorInfo **info_p,
8849 union spoolss_MonitorInfo *info;
8850 WERROR result = WERR_OK;
8852 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8853 W_ERROR_HAVE_NO_MEMORY(info);
8857 result = fill_monitor_1(info, &info[0].info1,
8859 if (!W_ERROR_IS_OK(result)) {
8863 result = fill_monitor_1(info, &info[1].info1,
8865 if (!W_ERROR_IS_OK(result)) {
8870 if (!W_ERROR_IS_OK(result)) {
8881 /****************************************************************************
8882 enumprintmonitors level 2.
8883 ****************************************************************************/
8885 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8886 union spoolss_MonitorInfo **info_p,
8889 union spoolss_MonitorInfo *info;
8890 WERROR result = WERR_OK;
8892 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8893 W_ERROR_HAVE_NO_MEMORY(info);
8897 result = fill_monitor_2(info, &info[0].info2,
8899 "Windows NT X86", /* FIXME */
8901 if (!W_ERROR_IS_OK(result)) {
8905 result = fill_monitor_2(info, &info[1].info2,
8907 "Windows NT X86", /* FIXME */
8909 if (!W_ERROR_IS_OK(result)) {
8914 if (!W_ERROR_IS_OK(result)) {
8925 /****************************************************************
8926 _spoolss_EnumMonitors
8927 ****************************************************************/
8929 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8930 struct spoolss_EnumMonitors *r)
8934 /* that's an [in out] buffer */
8936 if (!r->in.buffer && (r->in.offered != 0)) {
8937 return WERR_INVALID_PARAM;
8940 DEBUG(5,("_spoolss_EnumMonitors\n"));
8943 * Enumerate the print monitors ...
8945 * Just reply with "Local Port", to keep NT happy
8946 * and I can use my nice printer checker.
8951 *r->out.info = NULL;
8953 switch (r->in.level) {
8955 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8959 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8963 return WERR_UNKNOWN_LEVEL;
8966 if (!W_ERROR_IS_OK(result)) {
8970 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8971 spoolss_EnumMonitors,
8972 *r->out.info, r->in.level,
8974 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8975 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8977 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8980 /****************************************************************************
8981 ****************************************************************************/
8983 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8984 const print_queue_struct *queue,
8985 int count, int snum,
8986 struct spoolss_PrinterInfo2 *pinfo2,
8988 struct spoolss_JobInfo1 *r)
8993 for (i=0; i<count; i++) {
8994 if (queue[i].job == (int)jobid) {
9000 if (found == false) {
9001 /* NT treats not found as bad param... yet another bad choice */
9002 return WERR_INVALID_PARAM;
9005 return fill_job_info1(mem_ctx,
9013 /****************************************************************************
9014 ****************************************************************************/
9016 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9017 const print_queue_struct *queue,
9018 int count, int snum,
9019 struct spoolss_PrinterInfo2 *pinfo2,
9021 struct spoolss_JobInfo2 *r)
9025 struct spoolss_DeviceMode *devmode;
9028 for (i=0; i<count; i++) {
9029 if (queue[i].job == (int)jobid) {
9035 if (found == false) {
9036 /* NT treats not found as bad param... yet another bad
9038 return WERR_INVALID_PARAM;
9042 * if the print job does not have a DEVMODE associated with it,
9043 * just use the one for the printer. A NULL devicemode is not
9044 * a failure condition
9047 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9049 result = spoolss_create_default_devmode(mem_ctx,
9050 pinfo2->printername,
9052 if (!W_ERROR_IS_OK(result)) {
9053 DEBUG(3, ("Can't proceed w/o a devmode!"));
9058 return fill_job_info2(mem_ctx,
9067 /****************************************************************
9069 ****************************************************************/
9071 WERROR _spoolss_GetJob(struct pipes_struct *p,
9072 struct spoolss_GetJob *r)
9074 WERROR result = WERR_OK;
9075 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9078 print_queue_struct *queue = NULL;
9079 print_status_struct prt_status;
9081 /* that's an [in out] buffer */
9083 if (!r->in.buffer && (r->in.offered != 0)) {
9084 return WERR_INVALID_PARAM;
9087 DEBUG(5,("_spoolss_GetJob\n"));
9091 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9095 result = winreg_get_printer(p->mem_ctx,
9096 get_session_info_system(),
9098 lp_const_servicename(snum),
9100 if (!W_ERROR_IS_OK(result)) {
9104 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9106 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9107 count, prt_status.status, prt_status.message));
9109 switch (r->in.level) {
9111 result = getjob_level_1(p->mem_ctx,
9112 queue, count, snum, pinfo2,
9113 r->in.job_id, &r->out.info->info1);
9116 result = getjob_level_2(p->mem_ctx,
9117 queue, count, snum, pinfo2,
9118 r->in.job_id, &r->out.info->info2);
9121 result = WERR_UNKNOWN_LEVEL;
9126 TALLOC_FREE(pinfo2);
9128 if (!W_ERROR_IS_OK(result)) {
9129 TALLOC_FREE(r->out.info);
9133 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9135 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9137 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9140 /****************************************************************
9141 _spoolss_GetPrinterDataEx
9142 ****************************************************************/
9144 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9145 struct spoolss_GetPrinterDataEx *r)
9148 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9149 const char *printer;
9151 WERROR result = WERR_OK;
9153 enum winreg_Type val_type;
9158 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9160 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9161 r->in.key_name, r->in.value_name));
9163 /* in case of problem, return some default values */
9166 *r->out.type = REG_NONE;
9169 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9170 OUR_HANDLE(r->in.handle)));
9171 result = WERR_BADFID;
9175 /* Is the handle to a printer or to the server? */
9177 if (Printer->printer_type == SPLHND_SERVER) {
9179 union spoolss_PrinterData data;
9181 result = getprinterdata_printer_server(p->mem_ctx,
9185 if (!W_ERROR_IS_OK(result)) {
9189 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9190 *r->out.type, &data);
9191 if (!W_ERROR_IS_OK(result)) {
9195 *r->out.needed = blob.length;
9197 if (r->in.offered >= *r->out.needed) {
9198 memcpy(r->out.data, blob.data, blob.length);
9201 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9204 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9207 printer = lp_const_servicename(snum);
9209 /* check to see if the keyname is valid */
9210 if (!strlen(r->in.key_name)) {
9211 return WERR_INVALID_PARAM;
9214 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9215 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9216 strequal(r->in.value_name, "ChangeId")) {
9217 *r->out.type = REG_DWORD;
9219 if (r->in.offered >= *r->out.needed) {
9220 uint32_t changeid = 0;
9222 result = winreg_printer_get_changeid(p->mem_ctx,
9223 get_session_info_system(),
9227 if (!W_ERROR_IS_OK(result)) {
9231 SIVAL(r->out.data, 0, changeid);
9237 result = winreg_get_printer_dataex(p->mem_ctx,
9238 get_session_info_system(),
9246 if (!W_ERROR_IS_OK(result)) {
9250 *r->out.needed = val_size;
9251 *r->out.type = val_type;
9253 if (r->in.offered >= *r->out.needed) {
9254 memcpy(r->out.data, val_data, val_size);
9258 /* retain type when returning WERR_MORE_DATA */
9259 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9261 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9264 /****************************************************************
9265 _spoolss_SetPrinterDataEx
9266 ****************************************************************/
9268 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9269 struct spoolss_SetPrinterDataEx *r)
9271 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9273 WERROR result = WERR_OK;
9274 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9277 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9279 /* From MSDN documentation of SetPrinterDataEx: pass request to
9280 SetPrinterData if key is "PrinterDriverData" */
9283 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9284 OUR_HANDLE(r->in.handle)));
9288 if (Printer->printer_type == SPLHND_SERVER) {
9289 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9290 "Not implemented for server handles yet\n"));
9291 return WERR_INVALID_PARAM;
9294 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9299 * Access check : NT returns "access denied" if you make a
9300 * SetPrinterData call without the necessary privildge.
9301 * we were originally returning OK if nothing changed
9302 * which made Win2k issue **a lot** of SetPrinterData
9303 * when connecting to a printer --jerry
9306 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9307 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9308 "change denied by handle access permissions\n"));
9309 return WERR_ACCESS_DENIED;
9312 result = winreg_get_printer(Printer,
9313 get_session_info_system(),
9315 lp_servicename(snum),
9317 if (!W_ERROR_IS_OK(result)) {
9321 /* check for OID in valuename */
9323 oid_string = strchr(r->in.value_name, ',');
9329 /* save the registry data */
9331 result = winreg_set_printer_dataex(p->mem_ctx,
9332 get_session_info_system(),
9341 if (W_ERROR_IS_OK(result)) {
9342 /* save the OID if one was specified */
9344 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9345 r->in.key_name, SPOOL_OID_KEY);
9347 result = WERR_NOMEM;
9352 * I'm not checking the status here on purpose. Don't know
9353 * if this is right, but I'm returning the status from the
9354 * previous set_printer_dataex() call. I have no idea if
9355 * this is right. --jerry
9357 winreg_set_printer_dataex(p->mem_ctx,
9358 get_session_info_system(),
9364 (uint8_t *) oid_string,
9365 strlen(oid_string) + 1);
9368 result = winreg_printer_update_changeid(p->mem_ctx,
9369 get_session_info_system(),
9371 lp_const_servicename(snum));
9376 talloc_free(pinfo2);
9380 /****************************************************************
9381 _spoolss_DeletePrinterDataEx
9382 ****************************************************************/
9384 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9385 struct spoolss_DeletePrinterDataEx *r)
9387 const char *printer;
9389 WERROR status = WERR_OK;
9390 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9392 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9395 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9396 "Invalid handle (%s:%u:%u).\n",
9397 OUR_HANDLE(r->in.handle)));
9401 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9402 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9403 "printer properties change denied by handle\n"));
9404 return WERR_ACCESS_DENIED;
9407 if (!r->in.value_name || !r->in.key_name) {
9411 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9414 printer = lp_const_servicename(snum);
9416 status = winreg_delete_printer_dataex(p->mem_ctx,
9417 get_session_info_system(),
9422 if (W_ERROR_IS_OK(status)) {
9423 status = winreg_printer_update_changeid(p->mem_ctx,
9424 get_session_info_system(),
9432 /****************************************************************
9433 _spoolss_EnumPrinterKey
9434 ****************************************************************/
9436 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9437 struct spoolss_EnumPrinterKey *r)
9440 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9442 WERROR result = WERR_BADFILE;
9443 const char **array = NULL;
9446 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9449 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9450 OUR_HANDLE(r->in.handle)));
9454 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9458 result = winreg_enum_printer_key(p->mem_ctx,
9459 get_session_info_system(),
9461 lp_const_servicename(snum),
9465 if (!W_ERROR_IS_OK(result)) {
9469 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9470 result = WERR_NOMEM;
9474 *r->out._ndr_size = r->in.offered / 2;
9475 *r->out.needed = blob.length;
9477 if (r->in.offered < *r->out.needed) {
9478 result = WERR_MORE_DATA;
9481 r->out.key_buffer->string_array = array;
9485 if (!W_ERROR_IS_OK(result)) {
9487 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9495 /****************************************************************
9496 _spoolss_DeletePrinterKey
9497 ****************************************************************/
9499 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9500 struct spoolss_DeletePrinterKey *r)
9502 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9505 const char *printer;
9507 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9510 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9511 OUR_HANDLE(r->in.handle)));
9515 /* if keyname == NULL, return error */
9516 if ( !r->in.key_name )
9517 return WERR_INVALID_PARAM;
9519 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9523 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9524 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9525 "printer properties change denied by handle\n"));
9526 return WERR_ACCESS_DENIED;
9529 printer = lp_const_servicename(snum);
9531 /* delete the key and all subkeys */
9532 status = winreg_delete_printer_key(p->mem_ctx,
9533 get_session_info_system(),
9537 if (W_ERROR_IS_OK(status)) {
9538 status = winreg_printer_update_changeid(p->mem_ctx,
9539 get_session_info_system(),
9547 /****************************************************************
9548 _spoolss_EnumPrinterDataEx
9549 ****************************************************************/
9551 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9552 struct spoolss_EnumPrinterDataEx *r)
9555 struct spoolss_PrinterEnumValues *info = NULL;
9556 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9560 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9564 *r->out.info = NULL;
9567 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9568 OUR_HANDLE(r->in.handle)));
9573 * first check for a keyname of NULL or "". Win2k seems to send
9574 * this a lot and we should send back WERR_INVALID_PARAM
9575 * no need to spend time looking up the printer in this case.
9579 if (!strlen(r->in.key_name)) {
9580 result = WERR_INVALID_PARAM;
9584 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9588 /* now look for a match on the key name */
9589 result = winreg_enum_printer_dataex(p->mem_ctx,
9590 get_session_info_system(),
9592 lp_const_servicename(snum),
9596 if (!W_ERROR_IS_OK(result)) {
9600 #if 0 /* FIXME - gd */
9601 /* housekeeping information in the reply */
9603 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9604 * the hand marshalled container size is a multiple
9605 * of 4 bytes for RPC alignment.
9609 needed += 4-(needed % 4);
9612 *r->out.count = count;
9613 *r->out.info = info;
9616 if (!W_ERROR_IS_OK(result)) {
9620 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9621 spoolss_EnumPrinterDataEx,
9624 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9625 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9627 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9630 /****************************************************************************
9631 ****************************************************************************/
9633 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9634 const char *servername,
9635 const char *environment,
9636 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9641 werr = compose_spoolss_server_path(mem_ctx,
9644 SPOOLSS_PRTPROCS_PATH,
9646 if (!W_ERROR_IS_OK(werr)) {
9650 DEBUG(4,("print processor directory: [%s]\n", path));
9652 r->directory_name = path;
9657 /****************************************************************
9658 _spoolss_GetPrintProcessorDirectory
9659 ****************************************************************/
9661 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9662 struct spoolss_GetPrintProcessorDirectory *r)
9665 char *prnproc_share = NULL;
9666 bool prnproc_share_exists = false;
9669 /* that's an [in out] buffer */
9671 if (!r->in.buffer && (r->in.offered != 0)) {
9672 return WERR_INVALID_PARAM;
9675 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9680 /* r->in.level is ignored */
9682 /* We always should reply with a local print processor directory so that
9683 * users are not forced to have a [prnproc$] share on the Samba spoolss
9684 * server, if users decide to do so, lets announce it though - Guenther */
9686 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9687 if (!prnproc_share) {
9691 prnproc_share_exists = true;
9694 result = getprintprocessordirectory_level_1(p->mem_ctx,
9695 prnproc_share_exists ? r->in.server : NULL,
9697 &r->out.info->info1);
9698 if (!W_ERROR_IS_OK(result)) {
9699 TALLOC_FREE(r->out.info);
9703 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9704 r->out.info, r->in.level);
9705 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9707 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9710 /*******************************************************************
9711 ********************************************************************/
9713 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9714 const char *dllname)
9716 enum ndr_err_code ndr_err;
9717 struct spoolss_MonitorUi ui;
9719 ui.dll_name = dllname;
9721 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9722 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9723 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9724 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9726 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9729 /*******************************************************************
9730 Streams the monitor UI DLL name in UNICODE
9731 *******************************************************************/
9733 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9734 struct security_token *token, DATA_BLOB *in,
9735 DATA_BLOB *out, uint32_t *needed)
9737 const char *dllname = "tcpmonui.dll";
9739 *needed = (strlen(dllname)+1) * 2;
9741 if (out->length < *needed) {
9742 return WERR_INSUFFICIENT_BUFFER;
9745 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9752 /*******************************************************************
9753 ********************************************************************/
9755 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9756 struct spoolss_PortData1 *port1,
9757 const DATA_BLOB *buf)
9759 enum ndr_err_code ndr_err;
9760 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9761 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9762 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9763 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9765 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9768 /*******************************************************************
9769 ********************************************************************/
9771 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9772 struct spoolss_PortData2 *port2,
9773 const DATA_BLOB *buf)
9775 enum ndr_err_code ndr_err;
9776 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9777 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9778 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9779 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9781 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9784 /*******************************************************************
9785 Create a new TCP/IP port
9786 *******************************************************************/
9788 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9789 struct security_token *token, DATA_BLOB *in,
9790 DATA_BLOB *out, uint32_t *needed)
9792 struct spoolss_PortData1 port1;
9793 struct spoolss_PortData2 port2;
9794 char *device_uri = NULL;
9797 const char *portname;
9798 const char *hostaddress;
9800 uint32_t port_number;
9803 /* peek for spoolss_PortData version */
9805 if (!in || (in->length < (128 + 4))) {
9806 return WERR_GENERAL_FAILURE;
9809 version = IVAL(in->data, 128);
9815 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9819 portname = port1.portname;
9820 hostaddress = port1.hostaddress;
9821 queue = port1.queue;
9822 protocol = port1.protocol;
9823 port_number = port1.port_number;
9829 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9833 portname = port2.portname;
9834 hostaddress = port2.hostaddress;
9835 queue = port2.queue;
9836 protocol = port2.protocol;
9837 port_number = port2.port_number;
9841 DEBUG(1,("xcvtcp_addport: "
9842 "unknown version of port_data: %d\n", version));
9843 return WERR_UNKNOWN_PORT;
9846 /* create the device URI and call the add_port_hook() */
9849 case PROTOCOL_RAWTCP_TYPE:
9850 device_uri = talloc_asprintf(mem_ctx,
9851 "socket://%s:%d/", hostaddress,
9855 case PROTOCOL_LPR_TYPE:
9856 device_uri = talloc_asprintf(mem_ctx,
9857 "lpr://%s/%s", hostaddress, queue );
9861 return WERR_UNKNOWN_PORT;
9868 return add_port_hook(mem_ctx, token, portname, device_uri);
9871 /*******************************************************************
9872 *******************************************************************/
9874 struct xcv_api_table xcvtcp_cmds[] = {
9875 { "MonitorUI", xcvtcp_monitorui },
9876 { "AddPort", xcvtcp_addport},
9880 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9881 struct security_token *token, const char *command,
9888 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9890 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9891 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9892 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9895 return WERR_BADFUNC;
9898 /*******************************************************************
9899 *******************************************************************/
9900 #if 0 /* don't support management using the "Local Port" monitor */
9902 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9903 struct security_token *token, DATA_BLOB *in,
9904 DATA_BLOB *out, uint32_t *needed)
9906 const char *dllname = "localui.dll";
9908 *needed = (strlen(dllname)+1) * 2;
9910 if (out->length < *needed) {
9911 return WERR_INSUFFICIENT_BUFFER;
9914 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9921 /*******************************************************************
9922 *******************************************************************/
9924 struct xcv_api_table xcvlocal_cmds[] = {
9925 { "MonitorUI", xcvlocal_monitorui },
9929 struct xcv_api_table xcvlocal_cmds[] = {
9936 /*******************************************************************
9937 *******************************************************************/
9939 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9940 struct security_token *token, const char *command,
9941 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9946 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9948 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9949 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9950 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9952 return WERR_BADFUNC;
9955 /****************************************************************
9957 ****************************************************************/
9959 WERROR _spoolss_XcvData(struct pipes_struct *p,
9960 struct spoolss_XcvData *r)
9962 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9963 DATA_BLOB out_data = data_blob_null;
9967 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9968 OUR_HANDLE(r->in.handle)));
9972 /* Has to be a handle to the TCP/IP port monitor */
9974 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9975 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9979 /* requires administrative access to the server */
9981 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9982 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9983 return WERR_ACCESS_DENIED;
9986 /* Allocate the outgoing buffer */
9988 if (r->in.out_data_size) {
9989 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9990 if (out_data.data == NULL) {
9995 switch ( Printer->printer_type ) {
9996 case SPLHND_PORTMON_TCP:
9997 werror = process_xcvtcp_command(p->mem_ctx,
9998 p->session_info->security_token,
9999 r->in.function_name,
10000 &r->in.in_data, &out_data,
10003 case SPLHND_PORTMON_LOCAL:
10004 werror = process_xcvlocal_command(p->mem_ctx,
10005 p->session_info->security_token,
10006 r->in.function_name,
10007 &r->in.in_data, &out_data,
10011 werror = WERR_INVALID_PRINT_MONITOR;
10014 if (!W_ERROR_IS_OK(werror)) {
10018 *r->out.status_code = 0;
10020 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10021 memcpy(r->out.out_data, out_data.data,
10022 MIN(r->in.out_data_size, out_data.length));
10028 /****************************************************************
10029 _spoolss_AddPrintProcessor
10030 ****************************************************************/
10032 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10033 struct spoolss_AddPrintProcessor *r)
10035 /* for now, just indicate success and ignore the add. We'll
10036 automatically set the winprint processor for printer
10037 entries later. Used to debug the LexMark Optra S 1855 PCL
10043 /****************************************************************
10045 ****************************************************************/
10047 WERROR _spoolss_AddPort(struct pipes_struct *p,
10048 struct spoolss_AddPort *r)
10050 /* do what w2k3 does */
10052 return WERR_NOT_SUPPORTED;
10055 /****************************************************************
10056 _spoolss_GetPrinterDriver
10057 ****************************************************************/
10059 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10060 struct spoolss_GetPrinterDriver *r)
10062 p->rng_fault_state = true;
10063 return WERR_NOT_SUPPORTED;
10066 /****************************************************************
10067 _spoolss_ReadPrinter
10068 ****************************************************************/
10070 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10071 struct spoolss_ReadPrinter *r)
10073 p->rng_fault_state = true;
10074 return WERR_NOT_SUPPORTED;
10077 /****************************************************************
10078 _spoolss_WaitForPrinterChange
10079 ****************************************************************/
10081 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10082 struct spoolss_WaitForPrinterChange *r)
10084 p->rng_fault_state = true;
10085 return WERR_NOT_SUPPORTED;
10088 /****************************************************************
10089 _spoolss_ConfigurePort
10090 ****************************************************************/
10092 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10093 struct spoolss_ConfigurePort *r)
10095 p->rng_fault_state = true;
10096 return WERR_NOT_SUPPORTED;
10099 /****************************************************************
10100 _spoolss_DeletePort
10101 ****************************************************************/
10103 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10104 struct spoolss_DeletePort *r)
10106 p->rng_fault_state = true;
10107 return WERR_NOT_SUPPORTED;
10110 /****************************************************************
10111 _spoolss_CreatePrinterIC
10112 ****************************************************************/
10114 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10115 struct spoolss_CreatePrinterIC *r)
10117 p->rng_fault_state = true;
10118 return WERR_NOT_SUPPORTED;
10121 /****************************************************************
10122 _spoolss_PlayGDIScriptOnPrinterIC
10123 ****************************************************************/
10125 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10126 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10128 p->rng_fault_state = true;
10129 return WERR_NOT_SUPPORTED;
10132 /****************************************************************
10133 _spoolss_DeletePrinterIC
10134 ****************************************************************/
10136 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10137 struct spoolss_DeletePrinterIC *r)
10139 p->rng_fault_state = true;
10140 return WERR_NOT_SUPPORTED;
10143 /****************************************************************
10144 _spoolss_AddPrinterConnection
10145 ****************************************************************/
10147 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10148 struct spoolss_AddPrinterConnection *r)
10150 p->rng_fault_state = true;
10151 return WERR_NOT_SUPPORTED;
10154 /****************************************************************
10155 _spoolss_DeletePrinterConnection
10156 ****************************************************************/
10158 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10159 struct spoolss_DeletePrinterConnection *r)
10161 p->rng_fault_state = true;
10162 return WERR_NOT_SUPPORTED;
10165 /****************************************************************
10166 _spoolss_PrinterMessageBox
10167 ****************************************************************/
10169 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10170 struct spoolss_PrinterMessageBox *r)
10172 p->rng_fault_state = true;
10173 return WERR_NOT_SUPPORTED;
10176 /****************************************************************
10177 _spoolss_AddMonitor
10178 ****************************************************************/
10180 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10181 struct spoolss_AddMonitor *r)
10183 p->rng_fault_state = true;
10184 return WERR_NOT_SUPPORTED;
10187 /****************************************************************
10188 _spoolss_DeleteMonitor
10189 ****************************************************************/
10191 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10192 struct spoolss_DeleteMonitor *r)
10194 p->rng_fault_state = true;
10195 return WERR_NOT_SUPPORTED;
10198 /****************************************************************
10199 _spoolss_DeletePrintProcessor
10200 ****************************************************************/
10202 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10203 struct spoolss_DeletePrintProcessor *r)
10205 p->rng_fault_state = true;
10206 return WERR_NOT_SUPPORTED;
10209 /****************************************************************
10210 _spoolss_AddPrintProvidor
10211 ****************************************************************/
10213 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10214 struct spoolss_AddPrintProvidor *r)
10216 p->rng_fault_state = true;
10217 return WERR_NOT_SUPPORTED;
10220 /****************************************************************
10221 _spoolss_DeletePrintProvidor
10222 ****************************************************************/
10224 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10225 struct spoolss_DeletePrintProvidor *r)
10227 p->rng_fault_state = true;
10228 return WERR_NOT_SUPPORTED;
10231 /****************************************************************
10232 _spoolss_FindFirstPrinterChangeNotification
10233 ****************************************************************/
10235 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10236 struct spoolss_FindFirstPrinterChangeNotification *r)
10238 p->rng_fault_state = true;
10239 return WERR_NOT_SUPPORTED;
10242 /****************************************************************
10243 _spoolss_FindNextPrinterChangeNotification
10244 ****************************************************************/
10246 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10247 struct spoolss_FindNextPrinterChangeNotification *r)
10249 p->rng_fault_state = true;
10250 return WERR_NOT_SUPPORTED;
10253 /****************************************************************
10254 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10255 ****************************************************************/
10257 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10258 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10260 p->rng_fault_state = true;
10261 return WERR_NOT_SUPPORTED;
10264 /****************************************************************
10265 _spoolss_ReplyOpenPrinter
10266 ****************************************************************/
10268 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10269 struct spoolss_ReplyOpenPrinter *r)
10271 p->rng_fault_state = true;
10272 return WERR_NOT_SUPPORTED;
10275 /****************************************************************
10276 _spoolss_RouterReplyPrinter
10277 ****************************************************************/
10279 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10280 struct spoolss_RouterReplyPrinter *r)
10282 p->rng_fault_state = true;
10283 return WERR_NOT_SUPPORTED;
10286 /****************************************************************
10287 _spoolss_ReplyClosePrinter
10288 ****************************************************************/
10290 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10291 struct spoolss_ReplyClosePrinter *r)
10293 p->rng_fault_state = true;
10294 return WERR_NOT_SUPPORTED;
10297 /****************************************************************
10299 ****************************************************************/
10301 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10302 struct spoolss_AddPortEx *r)
10304 p->rng_fault_state = true;
10305 return WERR_NOT_SUPPORTED;
10308 /****************************************************************
10309 _spoolss_RouterFindFirstPrinterChangeNotification
10310 ****************************************************************/
10312 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10313 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10315 p->rng_fault_state = true;
10316 return WERR_NOT_SUPPORTED;
10319 /****************************************************************
10320 _spoolss_SpoolerInit
10321 ****************************************************************/
10323 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10324 struct spoolss_SpoolerInit *r)
10326 p->rng_fault_state = true;
10327 return WERR_NOT_SUPPORTED;
10330 /****************************************************************
10331 _spoolss_ResetPrinterEx
10332 ****************************************************************/
10334 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10335 struct spoolss_ResetPrinterEx *r)
10337 p->rng_fault_state = true;
10338 return WERR_NOT_SUPPORTED;
10341 /****************************************************************
10342 _spoolss_RouterReplyPrinterEx
10343 ****************************************************************/
10345 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10346 struct spoolss_RouterReplyPrinterEx *r)
10348 p->rng_fault_state = true;
10349 return WERR_NOT_SUPPORTED;
10352 /****************************************************************
10354 ****************************************************************/
10356 WERROR _spoolss_44(struct pipes_struct *p,
10357 struct spoolss_44 *r)
10359 p->rng_fault_state = true;
10360 return WERR_NOT_SUPPORTED;
10363 /****************************************************************
10365 ****************************************************************/
10367 WERROR _spoolss_SetPort(struct pipes_struct *p,
10368 struct spoolss_SetPort *r)
10370 p->rng_fault_state = true;
10371 return WERR_NOT_SUPPORTED;
10374 /****************************************************************
10376 ****************************************************************/
10378 WERROR _spoolss_4a(struct pipes_struct *p,
10379 struct spoolss_4a *r)
10381 p->rng_fault_state = true;
10382 return WERR_NOT_SUPPORTED;
10385 /****************************************************************
10387 ****************************************************************/
10389 WERROR _spoolss_4b(struct pipes_struct *p,
10390 struct spoolss_4b *r)
10392 p->rng_fault_state = true;
10393 return WERR_NOT_SUPPORTED;
10396 /****************************************************************
10398 ****************************************************************/
10400 WERROR _spoolss_4c(struct pipes_struct *p,
10401 struct spoolss_4c *r)
10403 p->rng_fault_state = true;
10404 return WERR_NOT_SUPPORTED;
10407 /****************************************************************
10409 ****************************************************************/
10411 WERROR _spoolss_53(struct pipes_struct *p,
10412 struct spoolss_53 *r)
10414 p->rng_fault_state = true;
10415 return WERR_NOT_SUPPORTED;
10418 /****************************************************************
10419 _spoolss_AddPerMachineConnection
10420 ****************************************************************/
10422 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10423 struct spoolss_AddPerMachineConnection *r)
10425 p->rng_fault_state = true;
10426 return WERR_NOT_SUPPORTED;
10429 /****************************************************************
10430 _spoolss_DeletePerMachineConnection
10431 ****************************************************************/
10433 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10434 struct spoolss_DeletePerMachineConnection *r)
10436 p->rng_fault_state = true;
10437 return WERR_NOT_SUPPORTED;
10440 /****************************************************************
10441 _spoolss_EnumPerMachineConnections
10442 ****************************************************************/
10444 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10445 struct spoolss_EnumPerMachineConnections *r)
10447 p->rng_fault_state = true;
10448 return WERR_NOT_SUPPORTED;
10451 /****************************************************************
10453 ****************************************************************/
10455 WERROR _spoolss_5a(struct pipes_struct *p,
10456 struct spoolss_5a *r)
10458 p->rng_fault_state = true;
10459 return WERR_NOT_SUPPORTED;
10462 /****************************************************************
10464 ****************************************************************/
10466 WERROR _spoolss_5b(struct pipes_struct *p,
10467 struct spoolss_5b *r)
10469 p->rng_fault_state = true;
10470 return WERR_NOT_SUPPORTED;
10473 /****************************************************************
10475 ****************************************************************/
10477 WERROR _spoolss_5c(struct pipes_struct *p,
10478 struct spoolss_5c *r)
10480 p->rng_fault_state = true;
10481 return WERR_NOT_SUPPORTED;
10484 /****************************************************************
10486 ****************************************************************/
10488 WERROR _spoolss_5d(struct pipes_struct *p,
10489 struct spoolss_5d *r)
10491 p->rng_fault_state = true;
10492 return WERR_NOT_SUPPORTED;
10495 /****************************************************************
10497 ****************************************************************/
10499 WERROR _spoolss_5e(struct pipes_struct *p,
10500 struct spoolss_5e *r)
10502 p->rng_fault_state = true;
10503 return WERR_NOT_SUPPORTED;
10506 /****************************************************************
10508 ****************************************************************/
10510 WERROR _spoolss_5f(struct pipes_struct *p,
10511 struct spoolss_5f *r)
10513 p->rng_fault_state = true;
10514 return WERR_NOT_SUPPORTED;
10517 /****************************************************************
10519 ****************************************************************/
10521 WERROR _spoolss_60(struct pipes_struct *p,
10522 struct spoolss_60 *r)
10524 p->rng_fault_state = true;
10525 return WERR_NOT_SUPPORTED;
10528 /****************************************************************
10530 ****************************************************************/
10532 WERROR _spoolss_61(struct pipes_struct *p,
10533 struct spoolss_61 *r)
10535 p->rng_fault_state = true;
10536 return WERR_NOT_SUPPORTED;
10539 /****************************************************************
10541 ****************************************************************/
10543 WERROR _spoolss_62(struct pipes_struct *p,
10544 struct spoolss_62 *r)
10546 p->rng_fault_state = true;
10547 return WERR_NOT_SUPPORTED;
10550 /****************************************************************
10552 ****************************************************************/
10554 WERROR _spoolss_63(struct pipes_struct *p,
10555 struct spoolss_63 *r)
10557 p->rng_fault_state = true;
10558 return WERR_NOT_SUPPORTED;
10561 /****************************************************************
10563 ****************************************************************/
10565 WERROR _spoolss_64(struct pipes_struct *p,
10566 struct spoolss_64 *r)
10568 p->rng_fault_state = true;
10569 return WERR_NOT_SUPPORTED;
10572 /****************************************************************
10574 ****************************************************************/
10576 WERROR _spoolss_65(struct pipes_struct *p,
10577 struct spoolss_65 *r)
10579 p->rng_fault_state = true;
10580 return WERR_NOT_SUPPORTED;
10583 /****************************************************************
10584 _spoolss_GetCorePrinterDrivers
10585 ****************************************************************/
10587 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10588 struct spoolss_GetCorePrinterDrivers *r)
10590 p->rng_fault_state = true;
10591 return WERR_NOT_SUPPORTED;
10594 /****************************************************************
10596 ****************************************************************/
10598 WERROR _spoolss_67(struct pipes_struct *p,
10599 struct spoolss_67 *r)
10601 p->rng_fault_state = true;
10602 return WERR_NOT_SUPPORTED;
10605 /****************************************************************
10606 _spoolss_GetPrinterDriverPackagePath
10607 ****************************************************************/
10609 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10610 struct spoolss_GetPrinterDriverPackagePath *r)
10612 p->rng_fault_state = true;
10613 return WERR_NOT_SUPPORTED;
10616 /****************************************************************
10618 ****************************************************************/
10620 WERROR _spoolss_69(struct pipes_struct *p,
10621 struct spoolss_69 *r)
10623 p->rng_fault_state = true;
10624 return WERR_NOT_SUPPORTED;
10627 /****************************************************************
10629 ****************************************************************/
10631 WERROR _spoolss_6a(struct pipes_struct *p,
10632 struct spoolss_6a *r)
10634 p->rng_fault_state = true;
10635 return WERR_NOT_SUPPORTED;
10638 /****************************************************************
10640 ****************************************************************/
10642 WERROR _spoolss_6b(struct pipes_struct *p,
10643 struct spoolss_6b *r)
10645 p->rng_fault_state = true;
10646 return WERR_NOT_SUPPORTED;
10649 /****************************************************************
10651 ****************************************************************/
10653 WERROR _spoolss_6c(struct pipes_struct *p,
10654 struct spoolss_6c *r)
10656 p->rng_fault_state = true;
10657 return WERR_NOT_SUPPORTED;
10660 /****************************************************************
10662 ****************************************************************/
10664 WERROR _spoolss_6d(struct pipes_struct *p,
10665 struct spoolss_6d *r)
10667 p->rng_fault_state = true;
10668 return WERR_NOT_SUPPORTED;