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 < 0 || 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 (!interpret_string_addr(&client_ss, p->client_id->addr,
2741 return WERR_SERVER_UNAVAILABLE;
2744 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2745 Printer->notify.printerlocal, REG_SZ,
2746 &Printer->notify.cli_hnd,
2747 &Printer->notify.cli_chan,
2748 &client_ss, p->msg_ctx)) {
2749 return WERR_SERVER_UNAVAILABLE;
2755 /*******************************************************************
2756 * fill a notify_info_data with the servername
2757 ********************************************************************/
2759 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2761 struct spoolss_Notify *data,
2762 print_queue_struct *queue,
2763 struct spoolss_PrinterInfo2 *pinfo2,
2764 TALLOC_CTX *mem_ctx)
2766 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2769 /*******************************************************************
2770 * fill a notify_info_data with the printername (not including the servername).
2771 ********************************************************************/
2773 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2775 struct spoolss_Notify *data,
2776 print_queue_struct *queue,
2777 struct spoolss_PrinterInfo2 *pinfo2,
2778 TALLOC_CTX *mem_ctx)
2780 /* the notify name should not contain the \\server\ part */
2781 const char *p = strrchr(pinfo2->printername, '\\');
2784 p = pinfo2->printername;
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2792 /*******************************************************************
2793 * fill a notify_info_data with the servicename
2794 ********************************************************************/
2796 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2798 struct spoolss_Notify *data,
2799 print_queue_struct *queue,
2800 struct spoolss_PrinterInfo2 *pinfo2,
2801 TALLOC_CTX *mem_ctx)
2803 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2806 /*******************************************************************
2807 * fill a notify_info_data with the port name
2808 ********************************************************************/
2810 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2812 struct spoolss_Notify *data,
2813 print_queue_struct *queue,
2814 struct spoolss_PrinterInfo2 *pinfo2,
2815 TALLOC_CTX *mem_ctx)
2817 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2820 /*******************************************************************
2821 * fill a notify_info_data with the printername
2822 * but it doesn't exist, have to see what to do
2823 ********************************************************************/
2825 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2827 struct spoolss_Notify *data,
2828 print_queue_struct *queue,
2829 struct spoolss_PrinterInfo2 *pinfo2,
2830 TALLOC_CTX *mem_ctx)
2832 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2835 /*******************************************************************
2836 * fill a notify_info_data with the comment
2837 ********************************************************************/
2839 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2841 struct spoolss_Notify *data,
2842 print_queue_struct *queue,
2843 struct spoolss_PrinterInfo2 *pinfo2,
2844 TALLOC_CTX *mem_ctx)
2848 if (*pinfo2->comment == '\0') {
2849 p = lp_comment(snum);
2851 p = pinfo2->comment;
2854 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2857 /*******************************************************************
2858 * fill a notify_info_data with the comment
2859 * location = "Room 1, floor 2, building 3"
2860 ********************************************************************/
2862 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2864 struct spoolss_Notify *data,
2865 print_queue_struct *queue,
2866 struct spoolss_PrinterInfo2 *pinfo2,
2867 TALLOC_CTX *mem_ctx)
2869 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2872 /*******************************************************************
2873 * fill a notify_info_data with the device mode
2874 * jfm:xxxx don't to it for know but that's a real problem !!!
2875 ********************************************************************/
2877 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2879 struct spoolss_Notify *data,
2880 print_queue_struct *queue,
2881 struct spoolss_PrinterInfo2 *pinfo2,
2882 TALLOC_CTX *mem_ctx)
2884 /* for a dummy implementation we have to zero the fields */
2885 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2888 /*******************************************************************
2889 * fill a notify_info_data with the separator file name
2890 ********************************************************************/
2892 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2894 struct spoolss_Notify *data,
2895 print_queue_struct *queue,
2896 struct spoolss_PrinterInfo2 *pinfo2,
2897 TALLOC_CTX *mem_ctx)
2899 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2902 /*******************************************************************
2903 * fill a notify_info_data with the print processor
2904 * jfm:xxxx return always winprint to indicate we don't do anything to it
2905 ********************************************************************/
2907 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2909 struct spoolss_Notify *data,
2910 print_queue_struct *queue,
2911 struct spoolss_PrinterInfo2 *pinfo2,
2912 TALLOC_CTX *mem_ctx)
2914 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2917 /*******************************************************************
2918 * fill a notify_info_data with the print processor options
2919 * jfm:xxxx send an empty string
2920 ********************************************************************/
2922 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2924 struct spoolss_Notify *data,
2925 print_queue_struct *queue,
2926 struct spoolss_PrinterInfo2 *pinfo2,
2927 TALLOC_CTX *mem_ctx)
2929 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2932 /*******************************************************************
2933 * fill a notify_info_data with the data type
2934 * jfm:xxxx always send RAW as data type
2935 ********************************************************************/
2937 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2939 struct spoolss_Notify *data,
2940 print_queue_struct *queue,
2941 struct spoolss_PrinterInfo2 *pinfo2,
2942 TALLOC_CTX *mem_ctx)
2944 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2947 /*******************************************************************
2948 * fill a notify_info_data with the security descriptor
2949 * jfm:xxxx send an null pointer to say no security desc
2950 * have to implement security before !
2951 ********************************************************************/
2953 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2955 struct spoolss_Notify *data,
2956 print_queue_struct *queue,
2957 struct spoolss_PrinterInfo2 *pinfo2,
2958 TALLOC_CTX *mem_ctx)
2960 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2963 /*******************************************************************
2964 * fill a notify_info_data with the attributes
2965 * jfm:xxxx a samba printer is always shared
2966 ********************************************************************/
2968 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2970 struct spoolss_Notify *data,
2971 print_queue_struct *queue,
2972 struct spoolss_PrinterInfo2 *pinfo2,
2973 TALLOC_CTX *mem_ctx)
2975 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2978 /*******************************************************************
2979 * fill a notify_info_data with the priority
2980 ********************************************************************/
2982 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2984 struct spoolss_Notify *data,
2985 print_queue_struct *queue,
2986 struct spoolss_PrinterInfo2 *pinfo2,
2987 TALLOC_CTX *mem_ctx)
2989 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2992 /*******************************************************************
2993 * fill a notify_info_data with the default priority
2994 ********************************************************************/
2996 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2998 struct spoolss_Notify *data,
2999 print_queue_struct *queue,
3000 struct spoolss_PrinterInfo2 *pinfo2,
3001 TALLOC_CTX *mem_ctx)
3003 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3006 /*******************************************************************
3007 * fill a notify_info_data with the start time
3008 ********************************************************************/
3010 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3012 struct spoolss_Notify *data,
3013 print_queue_struct *queue,
3014 struct spoolss_PrinterInfo2 *pinfo2,
3015 TALLOC_CTX *mem_ctx)
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3020 /*******************************************************************
3021 * fill a notify_info_data with the until time
3022 ********************************************************************/
3024 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3026 struct spoolss_Notify *data,
3027 print_queue_struct *queue,
3028 struct spoolss_PrinterInfo2 *pinfo2,
3029 TALLOC_CTX *mem_ctx)
3031 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3034 /*******************************************************************
3035 * fill a notify_info_data with the status
3036 ********************************************************************/
3038 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3040 struct spoolss_Notify *data,
3041 print_queue_struct *queue,
3042 struct spoolss_PrinterInfo2 *pinfo2,
3043 TALLOC_CTX *mem_ctx)
3045 print_status_struct status;
3047 print_queue_length(msg_ctx, snum, &status);
3048 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3051 /*******************************************************************
3052 * fill a notify_info_data with the number of jobs queued
3053 ********************************************************************/
3055 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3057 struct spoolss_Notify *data,
3058 print_queue_struct *queue,
3059 struct spoolss_PrinterInfo2 *pinfo2,
3060 TALLOC_CTX *mem_ctx)
3062 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3063 data, print_queue_length(msg_ctx, snum, NULL));
3066 /*******************************************************************
3067 * fill a notify_info_data with the average ppm
3068 ********************************************************************/
3070 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3072 struct spoolss_Notify *data,
3073 print_queue_struct *queue,
3074 struct spoolss_PrinterInfo2 *pinfo2,
3075 TALLOC_CTX *mem_ctx)
3077 /* always respond 8 pages per minutes */
3078 /* a little hard ! */
3079 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3082 /*******************************************************************
3083 * fill a notify_info_data with username
3084 ********************************************************************/
3086 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3088 struct spoolss_Notify *data,
3089 print_queue_struct *queue,
3090 struct spoolss_PrinterInfo2 *pinfo2,
3091 TALLOC_CTX *mem_ctx)
3093 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3096 /*******************************************************************
3097 * fill a notify_info_data with job status
3098 ********************************************************************/
3100 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3102 struct spoolss_Notify *data,
3103 print_queue_struct *queue,
3104 struct spoolss_PrinterInfo2 *pinfo2,
3105 TALLOC_CTX *mem_ctx)
3107 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3110 /*******************************************************************
3111 * fill a notify_info_data with job name
3112 ********************************************************************/
3114 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3116 struct spoolss_Notify *data,
3117 print_queue_struct *queue,
3118 struct spoolss_PrinterInfo2 *pinfo2,
3119 TALLOC_CTX *mem_ctx)
3121 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3124 /*******************************************************************
3125 * fill a notify_info_data with job status
3126 ********************************************************************/
3128 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3130 struct spoolss_Notify *data,
3131 print_queue_struct *queue,
3132 struct spoolss_PrinterInfo2 *pinfo2,
3133 TALLOC_CTX *mem_ctx)
3136 * Now we're returning job status codes we just return a "" here. JRA.
3141 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3144 switch (queue->status) {
3149 p = ""; /* NT provides the paused string */
3158 #endif /* NO LONGER NEEDED. */
3160 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3163 /*******************************************************************
3164 * fill a notify_info_data with job time
3165 ********************************************************************/
3167 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3169 struct spoolss_Notify *data,
3170 print_queue_struct *queue,
3171 struct spoolss_PrinterInfo2 *pinfo2,
3172 TALLOC_CTX *mem_ctx)
3174 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3177 /*******************************************************************
3178 * fill a notify_info_data with job size
3179 ********************************************************************/
3181 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3183 struct spoolss_Notify *data,
3184 print_queue_struct *queue,
3185 struct spoolss_PrinterInfo2 *pinfo2,
3186 TALLOC_CTX *mem_ctx)
3188 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3191 /*******************************************************************
3192 * fill a notify_info_data with page info
3193 ********************************************************************/
3194 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3196 struct spoolss_Notify *data,
3197 print_queue_struct *queue,
3198 struct spoolss_PrinterInfo2 *pinfo2,
3199 TALLOC_CTX *mem_ctx)
3201 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3204 /*******************************************************************
3205 * fill a notify_info_data with pages printed info.
3206 ********************************************************************/
3207 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3209 struct spoolss_Notify *data,
3210 print_queue_struct *queue,
3211 struct spoolss_PrinterInfo2 *pinfo2,
3212 TALLOC_CTX *mem_ctx)
3214 /* Add code when back-end tracks this */
3215 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3218 /*******************************************************************
3219 Fill a notify_info_data with job position.
3220 ********************************************************************/
3222 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3224 struct spoolss_Notify *data,
3225 print_queue_struct *queue,
3226 struct spoolss_PrinterInfo2 *pinfo2,
3227 TALLOC_CTX *mem_ctx)
3229 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3232 /*******************************************************************
3233 Fill a notify_info_data with submitted time.
3234 ********************************************************************/
3236 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3238 struct spoolss_Notify *data,
3239 print_queue_struct *queue,
3240 struct spoolss_PrinterInfo2 *pinfo2,
3241 TALLOC_CTX *mem_ctx)
3243 data->data.string.string = NULL;
3244 data->data.string.size = 0;
3246 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3247 &data->data.string.string,
3248 &data->data.string.size);
3252 struct s_notify_info_data_table
3254 enum spoolss_NotifyType type;
3257 enum spoolss_NotifyTable variable_type;
3258 void (*fn) (struct messaging_context *msg_ctx,
3259 int snum, struct spoolss_Notify *data,
3260 print_queue_struct *queue,
3261 struct spoolss_PrinterInfo2 *pinfo2,
3262 TALLOC_CTX *mem_ctx);
3265 /* A table describing the various print notification constants and
3266 whether the notification data is a pointer to a variable sized
3267 buffer, a one value uint32_t or a two value uint32_t. */
3269 static const struct s_notify_info_data_table notify_info_data_table[] =
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3322 /*******************************************************************
3323 Return the variable_type of info_data structure.
3324 ********************************************************************/
3326 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3331 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3332 if ( (notify_info_data_table[i].type == type) &&
3333 (notify_info_data_table[i].field == field) ) {
3334 return notify_info_data_table[i].variable_type;
3338 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3340 return (enum spoolss_NotifyTable) 0;
3343 /****************************************************************************
3344 ****************************************************************************/
3346 static bool search_notify(enum spoolss_NotifyType type,
3352 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3353 if (notify_info_data_table[i].type == type &&
3354 notify_info_data_table[i].field == field &&
3355 notify_info_data_table[i].fn != NULL) {
3364 /****************************************************************************
3365 ****************************************************************************/
3367 static void construct_info_data(struct spoolss_Notify *info_data,
3368 enum spoolss_NotifyType type,
3369 uint16_t field, int id)
3371 info_data->type = type;
3372 info_data->field.field = field;
3373 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3374 info_data->job_id = id;
3377 /*******************************************************************
3379 * fill a notify_info struct with info asked
3381 ********************************************************************/
3383 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3384 struct printer_handle *print_hnd,
3385 struct spoolss_NotifyInfo *info,
3386 struct spoolss_PrinterInfo2 *pinfo2,
3388 const struct spoolss_NotifyOptionType *option_type,
3390 TALLOC_CTX *mem_ctx)
3393 enum spoolss_NotifyType type;
3396 struct spoolss_Notify *current_data;
3397 print_queue_struct *queue=NULL;
3399 type = option_type->type;
3401 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3402 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3403 option_type->count, lp_servicename(snum)));
3405 for(field_num=0; field_num < option_type->count; field_num++) {
3406 field = option_type->fields[field_num].field;
3408 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3410 if (!search_notify(type, field, &j) )
3413 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3414 struct spoolss_Notify,
3416 if (info->notifies == NULL) {
3417 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3421 current_data = &info->notifies[info->count];
3423 construct_info_data(current_data, type, field, id);
3425 DEBUG(10, ("construct_notify_printer_info: "
3426 "calling [%s] snum=%d printername=[%s])\n",
3427 notify_info_data_table[j].name, snum,
3428 pinfo2->printername));
3430 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3431 queue, pinfo2, mem_ctx);
3439 /*******************************************************************
3441 * fill a notify_info struct with info asked
3443 ********************************************************************/
3445 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3446 print_queue_struct *queue,
3447 struct spoolss_NotifyInfo *info,
3448 struct spoolss_PrinterInfo2 *pinfo2,
3450 const struct spoolss_NotifyOptionType *option_type,
3452 TALLOC_CTX *mem_ctx)
3455 enum spoolss_NotifyType type;
3457 struct spoolss_Notify *current_data;
3459 DEBUG(4,("construct_notify_jobs_info\n"));
3461 type = option_type->type;
3463 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3464 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3465 option_type->count));
3467 for(field_num=0; field_num<option_type->count; field_num++) {
3468 field = option_type->fields[field_num].field;
3470 if (!search_notify(type, field, &j) )
3473 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3474 struct spoolss_Notify,
3476 if (info->notifies == NULL) {
3477 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3481 current_data=&(info->notifies[info->count]);
3483 construct_info_data(current_data, type, field, id);
3484 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3485 queue, pinfo2, mem_ctx);
3493 * JFM: The enumeration is not that simple, it's even non obvious.
3495 * let's take an example: I want to monitor the PRINTER SERVER for
3496 * the printer's name and the number of jobs currently queued.
3497 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3498 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3500 * I have 3 printers on the back of my server.
3502 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3505 * 1 printer 1 name 1
3506 * 2 printer 1 cjob 1
3507 * 3 printer 2 name 2
3508 * 4 printer 2 cjob 2
3509 * 5 printer 3 name 3
3510 * 6 printer 3 name 3
3512 * that's the print server case, the printer case is even worse.
3515 /*******************************************************************
3517 * enumerate all printers on the printserver
3518 * fill a notify_info struct with info asked
3520 ********************************************************************/
3522 static WERROR printserver_notify_info(struct pipes_struct *p,
3523 struct policy_handle *hnd,
3524 struct spoolss_NotifyInfo *info,
3525 TALLOC_CTX *mem_ctx)
3528 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3529 int n_services=lp_numservices();
3531 struct spoolss_NotifyOption *option;
3532 struct spoolss_NotifyOptionType option_type;
3533 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3536 DEBUG(4,("printserver_notify_info\n"));
3541 option = Printer->notify.option;
3544 info->notifies = NULL;
3547 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3548 sending a ffpcn() request first */
3553 for (i=0; i<option->count; i++) {
3554 option_type = option->types[i];
3556 if (option_type.type != PRINTER_NOTIFY_TYPE)
3559 for (snum = 0; snum < n_services; snum++) {
3560 if (!lp_browseable(snum) ||
3561 !lp_snum_ok(snum) ||
3562 !lp_print_ok(snum)) {
3563 continue; /* skip */
3566 /* Maybe we should use the SYSTEM session_info here... */
3567 result = winreg_get_printer(mem_ctx,
3568 get_session_info_system(),
3570 lp_servicename(snum),
3572 if (!W_ERROR_IS_OK(result)) {
3573 DEBUG(4, ("printserver_notify_info: "
3574 "Failed to get printer [%s]\n",
3575 lp_servicename(snum)));
3580 construct_notify_printer_info(p->msg_ctx,
3586 TALLOC_FREE(pinfo2);
3592 * Debugging information, don't delete.
3595 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3596 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3597 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3599 for (i=0; i<info->count; i++) {
3600 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3601 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3602 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3609 /*******************************************************************
3611 * fill a notify_info struct with info asked
3613 ********************************************************************/
3615 static WERROR printer_notify_info(struct pipes_struct *p,
3616 struct policy_handle *hnd,
3617 struct spoolss_NotifyInfo *info,
3618 TALLOC_CTX *mem_ctx)
3621 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3624 struct spoolss_NotifyOption *option;
3625 struct spoolss_NotifyOptionType option_type;
3627 print_queue_struct *queue=NULL;
3628 print_status_struct status;
3629 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3632 DEBUG(4,("printer_notify_info\n"));
3637 option = Printer->notify.option;
3641 info->notifies = NULL;
3644 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3645 sending a ffpcn() request first */
3650 get_printer_snum(p, hnd, &snum, NULL);
3652 /* Maybe we should use the SYSTEM session_info here... */
3653 result = winreg_get_printer(mem_ctx,
3654 get_session_info_system(),
3656 lp_servicename(snum), &pinfo2);
3657 if (!W_ERROR_IS_OK(result)) {
3661 for (i=0; i<option->count; i++) {
3662 option_type = option->types[i];
3664 switch (option_type.type) {
3665 case PRINTER_NOTIFY_TYPE:
3666 if (construct_notify_printer_info(p->msg_ctx,
3675 case JOB_NOTIFY_TYPE:
3677 count = print_queue_status(p->msg_ctx, snum, &queue,
3680 for (j=0; j<count; j++) {
3681 construct_notify_jobs_info(p->msg_ctx,
3695 * Debugging information, don't delete.
3698 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3699 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3700 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3702 for (i=0; i<info->count; i++) {
3703 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3704 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3705 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3709 talloc_free(pinfo2);
3713 /****************************************************************
3714 _spoolss_RouterRefreshPrinterChangeNotify
3715 ****************************************************************/
3717 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3718 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3720 struct spoolss_NotifyInfo *info;
3722 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3723 WERROR result = WERR_BADFID;
3725 /* we always have a spoolss_NotifyInfo struct */
3726 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3728 result = WERR_NOMEM;
3732 *r->out.info = info;
3735 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3736 "Invalid handle (%s:%u:%u).\n",
3737 OUR_HANDLE(r->in.handle)));
3741 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3744 * We are now using the change value, and
3745 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3746 * I don't have a global notification system, I'm sending back all the
3747 * information even when _NOTHING_ has changed.
3750 /* We need to keep track of the change value to send back in
3751 RRPCN replies otherwise our updates are ignored. */
3753 Printer->notify.fnpcn = true;
3755 if (Printer->notify.cli_chan != NULL &&
3756 Printer->notify.cli_chan->active_connections > 0) {
3757 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3758 "Saving change value in request [%x]\n",
3760 Printer->notify.change = r->in.change_low;
3763 /* just ignore the spoolss_NotifyOption */
3765 switch (Printer->printer_type) {
3767 result = printserver_notify_info(p, r->in.handle,
3771 case SPLHND_PRINTER:
3772 result = printer_notify_info(p, r->in.handle,
3777 Printer->notify.fnpcn = false;
3783 /********************************************************************
3784 ********************************************************************/
3786 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3787 const char *servername,
3788 const char *printername,
3789 const char **printername_p)
3791 /* FIXME: add lp_force_printername() */
3793 if (servername == NULL) {
3794 *printername_p = talloc_strdup(mem_ctx, printername);
3795 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3799 if (servername[0] == '\\' && servername[1] == '\\') {
3803 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3804 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3809 /********************************************************************
3810 ********************************************************************/
3812 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3813 const char *printername)
3819 dm->devicename = talloc_strndup(dm, printername,
3820 MIN(strlen(printername), 31));
3823 /********************************************************************
3824 * construct_printer_info_0
3825 * fill a printer_info_0 struct
3826 ********************************************************************/
3828 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3829 const struct auth_serversupplied_info *session_info,
3830 struct messaging_context *msg_ctx,
3831 struct spoolss_PrinterInfo2 *info2,
3832 const char *servername,
3833 struct spoolss_PrinterInfo0 *r,
3837 struct printer_session_counter *session_counter;
3838 struct timeval setuptime;
3839 print_status_struct status;
3842 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3843 if (!W_ERROR_IS_OK(result)) {
3848 r->servername = talloc_strdup(mem_ctx, servername);
3849 W_ERROR_HAVE_NO_MEMORY(r->servername);
3851 r->servername = NULL;
3854 count = print_queue_length(msg_ctx, snum, &status);
3856 /* check if we already have a counter for this printer */
3857 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3858 if (session_counter->snum == snum)
3862 /* it's the first time, add it to the list */
3863 if (session_counter == NULL) {
3864 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3865 W_ERROR_HAVE_NO_MEMORY(session_counter);
3866 session_counter->snum = snum;
3867 session_counter->counter = 0;
3868 DLIST_ADD(counter_list, session_counter);
3872 session_counter->counter++;
3878 get_startup_time(&setuptime);
3879 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3882 * the global_counter should be stored in a TDB as it's common to all the clients
3883 * and should be zeroed on samba startup
3885 r->global_counter = session_counter->counter;
3887 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3888 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3889 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3890 r->free_build = SPOOLSS_RELEASE_BUILD;
3892 r->max_spooling = 0;
3893 r->session_counter = session_counter->counter;
3894 r->num_error_out_of_paper = 0x0;
3895 r->num_error_not_ready = 0x0; /* number of print failure */
3897 r->number_of_processors = 0x1;
3898 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3899 r->high_part_total_bytes = 0x0;
3901 /* ChangeID in milliseconds*/
3902 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3903 info2->sharename, &r->change_id);
3905 r->last_error = WERR_OK;
3906 r->status = nt_printq_status(status.status);
3907 r->enumerate_network_printers = 0x0;
3908 r->c_setprinter = 0x0;
3909 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3910 r->processor_level = 0x6; /* 6 ???*/
3919 /********************************************************************
3920 * construct_printer_info1
3921 * fill a spoolss_PrinterInfo1 struct
3922 ********************************************************************/
3924 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3925 const struct spoolss_PrinterInfo2 *info2,
3927 const char *servername,
3928 struct spoolss_PrinterInfo1 *r,
3935 if (info2->comment == NULL || info2->comment[0] == '\0') {
3936 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3938 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3940 W_ERROR_HAVE_NO_MEMORY(r->comment);
3942 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3943 if (!W_ERROR_IS_OK(result)) {
3947 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3951 W_ERROR_HAVE_NO_MEMORY(r->description);
3956 /********************************************************************
3957 * construct_printer_info2
3958 * fill a spoolss_PrinterInfo2 struct
3959 ********************************************************************/
3961 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3962 struct messaging_context *msg_ctx,
3963 const struct spoolss_PrinterInfo2 *info2,
3964 const char *servername,
3965 struct spoolss_PrinterInfo2 *r,
3969 print_status_struct status;
3972 count = print_queue_length(msg_ctx, snum, &status);
3975 r->servername = talloc_strdup(mem_ctx, servername);
3976 W_ERROR_HAVE_NO_MEMORY(r->servername);
3978 r->servername = NULL;
3981 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3982 if (!W_ERROR_IS_OK(result)) {
3986 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3987 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3988 r->portname = talloc_strdup(mem_ctx, info2->portname);
3989 W_ERROR_HAVE_NO_MEMORY(r->portname);
3990 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3991 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3993 if (info2->comment[0] == '\0') {
3994 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3996 r->comment = talloc_strdup(mem_ctx, info2->comment);
3998 W_ERROR_HAVE_NO_MEMORY(r->comment);
4000 r->location = talloc_strdup(mem_ctx, info2->location);
4001 W_ERROR_HAVE_NO_MEMORY(r->location);
4002 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4003 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4004 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4005 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4006 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4007 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4008 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4009 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4011 r->attributes = info2->attributes;
4013 r->priority = info2->priority;
4014 r->defaultpriority = info2->defaultpriority;
4015 r->starttime = info2->starttime;
4016 r->untiltime = info2->untiltime;
4017 r->status = nt_printq_status(status.status);
4019 r->averageppm = info2->averageppm;
4021 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4023 DEBUG(8,("Returning NULL Devicemode!\n"));
4026 compose_devicemode_devicename(r->devmode, r->printername);
4030 if (info2->secdesc != NULL) {
4031 /* don't use talloc_steal() here unless you do a deep steal of all
4032 the SEC_DESC members */
4034 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4040 /********************************************************************
4041 * construct_printer_info3
4042 * fill a spoolss_PrinterInfo3 struct
4043 ********************************************************************/
4045 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4046 const struct spoolss_PrinterInfo2 *info2,
4047 const char *servername,
4048 struct spoolss_PrinterInfo3 *r,
4051 /* These are the components of the SD we are returning. */
4053 if (info2->secdesc != NULL) {
4054 /* don't use talloc_steal() here unless you do a deep steal of all
4055 the SEC_DESC members */
4057 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4058 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4064 /********************************************************************
4065 * construct_printer_info4
4066 * fill a spoolss_PrinterInfo4 struct
4067 ********************************************************************/
4069 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4070 const struct spoolss_PrinterInfo2 *info2,
4071 const char *servername,
4072 struct spoolss_PrinterInfo4 *r,
4077 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4078 if (!W_ERROR_IS_OK(result)) {
4083 r->servername = talloc_strdup(mem_ctx, servername);
4084 W_ERROR_HAVE_NO_MEMORY(r->servername);
4086 r->servername = NULL;
4089 r->attributes = info2->attributes;
4094 /********************************************************************
4095 * construct_printer_info5
4096 * fill a spoolss_PrinterInfo5 struct
4097 ********************************************************************/
4099 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4100 const struct spoolss_PrinterInfo2 *info2,
4101 const char *servername,
4102 struct spoolss_PrinterInfo5 *r,
4107 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4108 if (!W_ERROR_IS_OK(result)) {
4112 r->portname = talloc_strdup(mem_ctx, info2->portname);
4113 W_ERROR_HAVE_NO_MEMORY(r->portname);
4115 r->attributes = info2->attributes;
4117 /* these two are not used by NT+ according to MSDN */
4118 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4119 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4124 /********************************************************************
4125 * construct_printer_info_6
4126 * fill a spoolss_PrinterInfo6 struct
4127 ********************************************************************/
4129 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4130 struct messaging_context *msg_ctx,
4131 const struct spoolss_PrinterInfo2 *info2,
4132 const char *servername,
4133 struct spoolss_PrinterInfo6 *r,
4137 print_status_struct status;
4139 count = print_queue_length(msg_ctx, snum, &status);
4141 r->status = nt_printq_status(status.status);
4146 /********************************************************************
4147 * construct_printer_info7
4148 * fill a spoolss_PrinterInfo7 struct
4149 ********************************************************************/
4151 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4152 struct messaging_context *msg_ctx,
4153 const char *servername,
4154 struct spoolss_PrinterInfo7 *r,
4157 struct auth_serversupplied_info *session_info;
4161 status = make_session_info_system(mem_ctx, &session_info);
4162 if (!NT_STATUS_IS_OK(status)) {
4163 DEBUG(0, ("construct_printer_info7: "
4164 "Could not create system session_info\n"));
4168 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4170 lp_servicename(snum), &guid, NULL)) {
4171 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4172 r->action = DSPRINT_PUBLISH;
4174 r->guid = talloc_strdup(mem_ctx, "");
4175 r->action = DSPRINT_UNPUBLISH;
4177 W_ERROR_HAVE_NO_MEMORY(r->guid);
4179 TALLOC_FREE(session_info);
4183 /********************************************************************
4184 * construct_printer_info8
4185 * fill a spoolss_PrinterInfo8 struct
4186 ********************************************************************/
4188 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4189 const struct spoolss_PrinterInfo2 *info2,
4190 const char *servername,
4191 struct spoolss_DeviceModeInfo *r,
4195 const char *printername;
4197 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4198 if (!W_ERROR_IS_OK(result)) {
4202 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4204 DEBUG(8,("Returning NULL Devicemode!\n"));
4207 compose_devicemode_devicename(r->devmode, printername);
4213 /********************************************************************
4214 ********************************************************************/
4216 static bool snum_is_shared_printer(int snum)
4218 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4221 /********************************************************************
4222 Spoolss_enumprinters.
4223 ********************************************************************/
4225 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4226 const struct auth_serversupplied_info *session_info,
4227 struct messaging_context *msg_ctx,
4228 const char *servername,
4231 union spoolss_PrinterInfo **info_p,
4235 int n_services = lp_numservices();
4236 union spoolss_PrinterInfo *info = NULL;
4238 WERROR result = WERR_OK;
4243 for (snum = 0; snum < n_services; snum++) {
4245 const char *printer;
4246 struct spoolss_PrinterInfo2 *info2;
4248 if (!snum_is_shared_printer(snum)) {
4252 printer = lp_const_servicename(snum);
4254 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4257 result = winreg_create_printer(mem_ctx,
4261 if (!W_ERROR_IS_OK(result)) {
4265 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4266 union spoolss_PrinterInfo,
4269 result = WERR_NOMEM;
4273 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4275 if (!W_ERROR_IS_OK(result)) {
4281 result = construct_printer_info0(info, session_info,
4284 &info[count].info0, snum);
4287 result = construct_printer_info1(info, info2, flags,
4289 &info[count].info1, snum);
4292 result = construct_printer_info2(info, msg_ctx, info2,
4294 &info[count].info2, snum);
4297 result = construct_printer_info4(info, info2,
4299 &info[count].info4, snum);
4302 result = construct_printer_info5(info, info2,
4304 &info[count].info5, snum);
4308 result = WERR_UNKNOWN_LEVEL;
4312 if (!W_ERROR_IS_OK(result)) {
4323 if (!W_ERROR_IS_OK(result)) {
4333 /********************************************************************
4334 * handle enumeration of printers at level 0
4335 ********************************************************************/
4337 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4338 const struct auth_serversupplied_info *session_info,
4339 struct messaging_context *msg_ctx,
4341 const char *servername,
4342 union spoolss_PrinterInfo **info,
4345 DEBUG(4,("enum_all_printers_info_0\n"));
4347 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4348 servername, 0, flags, info, count);
4352 /********************************************************************
4353 ********************************************************************/
4355 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4356 const struct auth_serversupplied_info *session_info,
4357 struct messaging_context *msg_ctx,
4358 const char *servername,
4360 union spoolss_PrinterInfo **info,
4363 DEBUG(4,("enum_all_printers_info_1\n"));
4365 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4366 servername, 1, flags, info, count);
4369 /********************************************************************
4370 enum_all_printers_info_1_local.
4371 *********************************************************************/
4373 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4374 const struct auth_serversupplied_info *session_info,
4375 struct messaging_context *msg_ctx,
4376 const char *servername,
4377 union spoolss_PrinterInfo **info,
4380 DEBUG(4,("enum_all_printers_info_1_local\n"));
4382 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4383 servername, PRINTER_ENUM_ICON8, info, count);
4386 /********************************************************************
4387 enum_all_printers_info_1_name.
4388 *********************************************************************/
4390 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4391 const struct auth_serversupplied_info *session_info,
4392 struct messaging_context *msg_ctx,
4393 const char *servername,
4394 union spoolss_PrinterInfo **info,
4397 const char *s = servername;
4399 DEBUG(4,("enum_all_printers_info_1_name\n"));
4401 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4405 if (!is_myname_or_ipaddr(s)) {
4406 return WERR_INVALID_NAME;
4409 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4410 servername, PRINTER_ENUM_ICON8, info, count);
4413 /********************************************************************
4414 enum_all_printers_info_1_network.
4415 *********************************************************************/
4417 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4418 const struct auth_serversupplied_info *session_info,
4419 struct messaging_context *msg_ctx,
4420 const char *servername,
4421 union spoolss_PrinterInfo **info,
4424 const char *s = servername;
4426 DEBUG(4,("enum_all_printers_info_1_network\n"));
4428 /* If we respond to a enum_printers level 1 on our name with flags
4429 set to PRINTER_ENUM_REMOTE with a list of printers then these
4430 printers incorrectly appear in the APW browse list.
4431 Specifically the printers for the server appear at the workgroup
4432 level where all the other servers in the domain are
4433 listed. Windows responds to this call with a
4434 WERR_CAN_NOT_COMPLETE so we should do the same. */
4436 if (servername[0] == '\\' && servername[1] == '\\') {
4440 if (is_myname_or_ipaddr(s)) {
4441 return WERR_CAN_NOT_COMPLETE;
4444 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4445 servername, PRINTER_ENUM_NAME, info, count);
4448 /********************************************************************
4449 * api_spoolss_enumprinters
4451 * called from api_spoolss_enumprinters (see this to understand)
4452 ********************************************************************/
4454 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4455 const struct auth_serversupplied_info *session_info,
4456 struct messaging_context *msg_ctx,
4457 const char *servername,
4458 union spoolss_PrinterInfo **info,
4461 DEBUG(4,("enum_all_printers_info_2\n"));
4463 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4464 servername, 2, 0, info, count);
4467 /********************************************************************
4468 * handle enumeration of printers at level 1
4469 ********************************************************************/
4471 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4472 const struct auth_serversupplied_info *session_info,
4473 struct messaging_context *msg_ctx,
4475 const char *servername,
4476 union spoolss_PrinterInfo **info,
4479 /* Not all the flags are equals */
4481 if (flags & PRINTER_ENUM_LOCAL) {
4482 return enum_all_printers_info_1_local(mem_ctx, session_info,
4483 msg_ctx, servername, info, count);
4486 if (flags & PRINTER_ENUM_NAME) {
4487 return enum_all_printers_info_1_name(mem_ctx, session_info,
4488 msg_ctx, servername, info,
4492 if (flags & PRINTER_ENUM_NETWORK) {
4493 return enum_all_printers_info_1_network(mem_ctx, session_info,
4494 msg_ctx, servername, info,
4498 return WERR_OK; /* NT4sp5 does that */
4501 /********************************************************************
4502 * handle enumeration of printers at level 2
4503 ********************************************************************/
4505 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4506 const struct auth_serversupplied_info *session_info,
4507 struct messaging_context *msg_ctx,
4509 const char *servername,
4510 union spoolss_PrinterInfo **info,
4513 if (flags & PRINTER_ENUM_LOCAL) {
4515 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4520 if (flags & PRINTER_ENUM_NAME) {
4521 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4522 return WERR_INVALID_NAME;
4525 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4530 if (flags & PRINTER_ENUM_REMOTE) {
4531 return WERR_UNKNOWN_LEVEL;
4537 /********************************************************************
4538 * handle enumeration of printers at level 4
4539 ********************************************************************/
4541 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4542 const struct auth_serversupplied_info *session_info,
4543 struct messaging_context *msg_ctx,
4545 const char *servername,
4546 union spoolss_PrinterInfo **info,
4549 DEBUG(4,("enum_all_printers_info_4\n"));
4551 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4552 servername, 4, flags, info, count);
4556 /********************************************************************
4557 * handle enumeration of printers at level 5
4558 ********************************************************************/
4560 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4561 const struct auth_serversupplied_info *session_info,
4562 struct messaging_context *msg_ctx,
4564 const char *servername,
4565 union spoolss_PrinterInfo **info,
4568 DEBUG(4,("enum_all_printers_info_5\n"));
4570 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4571 servername, 5, flags, info, count);
4574 /****************************************************************
4575 _spoolss_EnumPrinters
4576 ****************************************************************/
4578 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4579 struct spoolss_EnumPrinters *r)
4581 const struct auth_serversupplied_info *session_info = get_session_info_system();
4584 /* that's an [in out] buffer */
4586 if (!r->in.buffer && (r->in.offered != 0)) {
4587 return WERR_INVALID_PARAM;
4590 DEBUG(4,("_spoolss_EnumPrinters\n"));
4594 *r->out.info = NULL;
4598 * flags==PRINTER_ENUM_NAME
4599 * if name=="" then enumerates all printers
4600 * if name!="" then enumerate the printer
4601 * flags==PRINTER_ENUM_REMOTE
4602 * name is NULL, enumerate printers
4603 * Level 2: name!="" enumerates printers, name can't be NULL
4604 * Level 3: doesn't exist
4605 * Level 4: does a local registry lookup
4606 * Level 5: same as Level 2
4609 if (r->in.server && r->in.server[0] == '\0') {
4610 r->in.server = NULL;
4613 switch (r->in.level) {
4615 result = enumprinters_level0(p->mem_ctx, session_info,
4616 p->msg_ctx, r->in.flags,
4618 r->out.info, r->out.count);
4621 result = enumprinters_level1(p->mem_ctx, session_info,
4622 p->msg_ctx, r->in.flags,
4624 r->out.info, r->out.count);
4627 result = enumprinters_level2(p->mem_ctx, session_info,
4628 p->msg_ctx, r->in.flags,
4630 r->out.info, r->out.count);
4633 result = enumprinters_level4(p->mem_ctx, session_info,
4634 p->msg_ctx, r->in.flags,
4636 r->out.info, r->out.count);
4639 result = enumprinters_level5(p->mem_ctx, session_info,
4640 p->msg_ctx, r->in.flags,
4642 r->out.info, r->out.count);
4645 return WERR_UNKNOWN_LEVEL;
4648 if (!W_ERROR_IS_OK(result)) {
4652 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4653 spoolss_EnumPrinters,
4654 *r->out.info, r->in.level,
4656 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4657 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4659 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4662 /****************************************************************
4664 ****************************************************************/
4666 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4667 struct spoolss_GetPrinter *r)
4669 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4670 struct spoolss_PrinterInfo2 *info2 = NULL;
4671 WERROR result = WERR_OK;
4674 /* that's an [in out] buffer */
4676 if (!r->in.buffer && (r->in.offered != 0)) {
4677 return WERR_INVALID_PARAM;
4682 if (Printer == NULL) {
4686 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4690 result = winreg_get_printer(p->mem_ctx,
4691 get_session_info_system(),
4693 lp_const_servicename(snum),
4695 if (!W_ERROR_IS_OK(result)) {
4699 switch (r->in.level) {
4701 result = construct_printer_info0(p->mem_ctx,
4702 get_session_info_system(),
4705 Printer->servername,
4706 &r->out.info->info0,
4710 result = construct_printer_info1(p->mem_ctx, info2,
4712 Printer->servername,
4713 &r->out.info->info1, snum);
4716 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4717 Printer->servername,
4718 &r->out.info->info2, snum);
4721 result = construct_printer_info3(p->mem_ctx, info2,
4722 Printer->servername,
4723 &r->out.info->info3, snum);
4726 result = construct_printer_info4(p->mem_ctx, info2,
4727 Printer->servername,
4728 &r->out.info->info4, snum);
4731 result = construct_printer_info5(p->mem_ctx, info2,
4732 Printer->servername,
4733 &r->out.info->info5, snum);
4736 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4737 Printer->servername,
4738 &r->out.info->info6, snum);
4741 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4742 Printer->servername,
4743 &r->out.info->info7, snum);
4746 result = construct_printer_info8(p->mem_ctx, info2,
4747 Printer->servername,
4748 &r->out.info->info8, snum);
4751 result = WERR_UNKNOWN_LEVEL;
4756 if (!W_ERROR_IS_OK(result)) {
4757 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4758 r->in.level, win_errstr(result)));
4759 TALLOC_FREE(r->out.info);
4763 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4764 r->out.info, r->in.level);
4765 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4767 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4770 /********************************************************************
4771 ********************************************************************/
4773 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4775 if (in && strlen(in)) { \
4776 out = talloc_strdup(mem_ctx, in); \
4778 out = talloc_strdup(mem_ctx, ""); \
4780 W_ERROR_HAVE_NO_MEMORY(out); \
4783 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4785 if (in && strlen(in)) { \
4786 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4788 out = talloc_strdup(mem_ctx, ""); \
4790 W_ERROR_HAVE_NO_MEMORY(out); \
4793 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4794 const char **string_array,
4795 const char ***presult,
4796 const char *cservername,
4800 int i, num_strings = 0;
4801 const char **array = NULL;
4803 if (string_array == NULL) {
4804 return WERR_INVALID_PARAMETER;
4807 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4808 const char *str = NULL;
4810 if (cservername == NULL || arch == NULL) {
4811 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4813 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4816 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4823 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4824 &array, &num_strings);
4834 /********************************************************************
4835 * fill a spoolss_DriverInfo1 struct
4836 ********************************************************************/
4838 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4839 struct spoolss_DriverInfo1 *r,
4840 const struct spoolss_DriverInfo8 *driver,
4841 const char *servername)
4843 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4844 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4849 /********************************************************************
4850 * fill a spoolss_DriverInfo2 struct
4851 ********************************************************************/
4853 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4854 struct spoolss_DriverInfo2 *r,
4855 const struct spoolss_DriverInfo8 *driver,
4856 const char *servername)
4859 const char *cservername = canon_servername(servername);
4861 r->version = driver->version;
4863 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4864 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4865 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4866 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4868 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4869 driver->architecture,
4871 driver->driver_path,
4874 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4875 driver->architecture,
4880 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4881 driver->architecture,
4883 driver->config_file,
4889 /********************************************************************
4890 * fill a spoolss_DriverInfo3 struct
4891 ********************************************************************/
4893 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4894 struct spoolss_DriverInfo3 *r,
4895 const struct spoolss_DriverInfo8 *driver,
4896 const char *servername)
4898 const char *cservername = canon_servername(servername);
4900 r->version = driver->version;
4902 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4903 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4904 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4905 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4907 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4908 driver->architecture,
4910 driver->driver_path,
4913 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4914 driver->architecture,
4919 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4920 driver->architecture,
4922 driver->config_file,
4925 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4926 driver->architecture,
4931 FILL_DRIVER_STRING(mem_ctx,
4932 driver->monitor_name,
4935 FILL_DRIVER_STRING(mem_ctx,
4936 driver->default_datatype,
4937 r->default_datatype);
4939 return string_array_from_driver_info(mem_ctx,
4940 driver->dependent_files,
4941 &r->dependent_files,
4943 driver->architecture,
4947 /********************************************************************
4948 * fill a spoolss_DriverInfo4 struct
4949 ********************************************************************/
4951 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4952 struct spoolss_DriverInfo4 *r,
4953 const struct spoolss_DriverInfo8 *driver,
4954 const char *servername)
4956 const char *cservername = canon_servername(servername);
4959 r->version = driver->version;
4961 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4962 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4963 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4964 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4966 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4967 driver->architecture,
4969 driver->driver_path,
4972 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4973 driver->architecture,
4978 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979 driver->architecture,
4981 driver->config_file,
4984 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985 driver->architecture,
4990 result = string_array_from_driver_info(mem_ctx,
4991 driver->dependent_files,
4992 &r->dependent_files,
4994 driver->architecture,
4996 if (!W_ERROR_IS_OK(result)) {
5000 FILL_DRIVER_STRING(mem_ctx,
5001 driver->monitor_name,
5004 FILL_DRIVER_STRING(mem_ctx,
5005 driver->default_datatype,
5006 r->default_datatype);
5009 result = string_array_from_driver_info(mem_ctx,
5010 driver->previous_names,
5017 /********************************************************************
5018 * fill a spoolss_DriverInfo5 struct
5019 ********************************************************************/
5021 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5022 struct spoolss_DriverInfo5 *r,
5023 const struct spoolss_DriverInfo8 *driver,
5024 const char *servername)
5026 const char *cservername = canon_servername(servername);
5028 r->version = driver->version;
5030 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5031 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5032 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5033 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5035 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5036 driver->architecture,
5038 driver->driver_path,
5041 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5042 driver->architecture,
5047 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5048 driver->architecture,
5050 driver->config_file,
5053 r->driver_attributes = 0;
5054 r->config_version = 0;
5055 r->driver_version = 0;
5059 /********************************************************************
5060 * fill a spoolss_DriverInfo6 struct
5061 ********************************************************************/
5063 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5064 struct spoolss_DriverInfo6 *r,
5065 const struct spoolss_DriverInfo8 *driver,
5066 const char *servername)
5068 const char *cservername = canon_servername(servername);
5071 r->version = driver->version;
5073 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5074 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5075 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5076 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5078 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5079 driver->architecture,
5081 driver->driver_path,
5084 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5085 driver->architecture,
5090 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5091 driver->architecture,
5093 driver->config_file,
5096 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5097 driver->architecture,
5102 FILL_DRIVER_STRING(mem_ctx,
5103 driver->monitor_name,
5106 FILL_DRIVER_STRING(mem_ctx,
5107 driver->default_datatype,
5108 r->default_datatype);
5110 result = string_array_from_driver_info(mem_ctx,
5111 driver->dependent_files,
5112 &r->dependent_files,
5114 driver->architecture,
5116 if (!W_ERROR_IS_OK(result)) {
5120 result = string_array_from_driver_info(mem_ctx,
5121 driver->previous_names,
5124 if (!W_ERROR_IS_OK(result)) {
5128 r->driver_date = driver->driver_date;
5129 r->driver_version = driver->driver_version;
5131 FILL_DRIVER_STRING(mem_ctx,
5132 driver->manufacturer_name,
5133 r->manufacturer_name);
5134 FILL_DRIVER_STRING(mem_ctx,
5135 driver->manufacturer_url,
5136 r->manufacturer_url);
5137 FILL_DRIVER_STRING(mem_ctx,
5138 driver->hardware_id,
5140 FILL_DRIVER_STRING(mem_ctx,
5147 /********************************************************************
5148 * fill a spoolss_DriverInfo8 struct
5149 ********************************************************************/
5151 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5152 struct spoolss_DriverInfo8 *r,
5153 const struct spoolss_DriverInfo8 *driver,
5154 const char *servername)
5156 const char *cservername = canon_servername(servername);
5159 r->version = driver->version;
5161 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5162 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5163 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5164 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5166 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5167 driver->architecture,
5169 driver->driver_path,
5172 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5173 driver->architecture,
5178 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179 driver->architecture,
5181 driver->config_file,
5184 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185 driver->architecture,
5190 FILL_DRIVER_STRING(mem_ctx,
5191 driver->monitor_name,
5194 FILL_DRIVER_STRING(mem_ctx,
5195 driver->default_datatype,
5196 r->default_datatype);
5198 result = string_array_from_driver_info(mem_ctx,
5199 driver->dependent_files,
5200 &r->dependent_files,
5202 driver->architecture,
5204 if (!W_ERROR_IS_OK(result)) {
5208 result = string_array_from_driver_info(mem_ctx,
5209 driver->previous_names,
5212 if (!W_ERROR_IS_OK(result)) {
5216 r->driver_date = driver->driver_date;
5217 r->driver_version = driver->driver_version;
5219 FILL_DRIVER_STRING(mem_ctx,
5220 driver->manufacturer_name,
5221 r->manufacturer_name);
5222 FILL_DRIVER_STRING(mem_ctx,
5223 driver->manufacturer_url,
5224 r->manufacturer_url);
5225 FILL_DRIVER_STRING(mem_ctx,
5226 driver->hardware_id,
5228 FILL_DRIVER_STRING(mem_ctx,
5232 FILL_DRIVER_STRING(mem_ctx,
5233 driver->print_processor,
5234 r->print_processor);
5235 FILL_DRIVER_STRING(mem_ctx,
5236 driver->vendor_setup,
5239 result = string_array_from_driver_info(mem_ctx,
5240 driver->color_profiles,
5243 if (!W_ERROR_IS_OK(result)) {
5247 FILL_DRIVER_STRING(mem_ctx,
5251 r->printer_driver_attributes = driver->printer_driver_attributes;
5253 result = string_array_from_driver_info(mem_ctx,
5254 driver->core_driver_dependencies,
5255 &r->core_driver_dependencies,
5257 if (!W_ERROR_IS_OK(result)) {
5261 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5262 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5267 #if 0 /* disabled until marshalling issues are resolved - gd */
5268 /********************************************************************
5269 ********************************************************************/
5271 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5272 struct spoolss_DriverFileInfo *r,
5273 const char *cservername,
5274 const char *file_name,
5275 enum spoolss_DriverFileType file_type,
5276 uint32_t file_version)
5278 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5279 cservername, file_name);
5280 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5281 r->file_type = file_type;
5282 r->file_version = file_version;
5287 /********************************************************************
5288 ********************************************************************/
5290 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5291 const struct spoolss_DriverInfo8 *driver,
5292 const char *cservername,
5293 struct spoolss_DriverFileInfo **info_p,
5296 struct spoolss_DriverFileInfo *info = NULL;
5304 if (strlen(driver->driver_path)) {
5305 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5306 struct spoolss_DriverFileInfo,
5308 W_ERROR_HAVE_NO_MEMORY(info);
5309 result = fill_spoolss_DriverFileInfo(info,
5312 driver->driver_path,
5313 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5315 W_ERROR_NOT_OK_RETURN(result);
5319 if (strlen(driver->config_file)) {
5320 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5321 struct spoolss_DriverFileInfo,
5323 W_ERROR_HAVE_NO_MEMORY(info);
5324 result = fill_spoolss_DriverFileInfo(info,
5327 driver->config_file,
5328 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5330 W_ERROR_NOT_OK_RETURN(result);
5334 if (strlen(driver->data_file)) {
5335 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5336 struct spoolss_DriverFileInfo,
5338 W_ERROR_HAVE_NO_MEMORY(info);
5339 result = fill_spoolss_DriverFileInfo(info,
5343 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5345 W_ERROR_NOT_OK_RETURN(result);
5349 if (strlen(driver->help_file)) {
5350 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5351 struct spoolss_DriverFileInfo,
5353 W_ERROR_HAVE_NO_MEMORY(info);
5354 result = fill_spoolss_DriverFileInfo(info,
5358 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5360 W_ERROR_NOT_OK_RETURN(result);
5364 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5365 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5366 struct spoolss_DriverFileInfo,
5368 W_ERROR_HAVE_NO_MEMORY(info);
5369 result = fill_spoolss_DriverFileInfo(info,
5372 driver->dependent_files[i],
5373 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5375 W_ERROR_NOT_OK_RETURN(result);
5385 /********************************************************************
5386 * fill a spoolss_DriverInfo101 struct
5387 ********************************************************************/
5389 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5390 struct spoolss_DriverInfo101 *r,
5391 const struct spoolss_DriverInfo8 *driver,
5392 const char *servername)
5394 const char *cservername = canon_servername(servername);
5397 r->version = driver->version;
5399 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5400 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5401 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5402 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5404 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5408 if (!W_ERROR_IS_OK(result)) {
5412 FILL_DRIVER_STRING(mem_ctx,
5413 driver->monitor_name,
5416 FILL_DRIVER_STRING(mem_ctx,
5417 driver->default_datatype,
5418 r->default_datatype);
5420 result = string_array_from_driver_info(mem_ctx,
5421 driver->previous_names,
5424 if (!W_ERROR_IS_OK(result)) {
5428 r->driver_date = driver->driver_date;
5429 r->driver_version = driver->driver_version;
5431 FILL_DRIVER_STRING(mem_ctx,
5432 driver->manufacturer_name,
5433 r->manufacturer_name);
5434 FILL_DRIVER_STRING(mem_ctx,
5435 driver->manufacturer_url,
5436 r->manufacturer_url);
5437 FILL_DRIVER_STRING(mem_ctx,
5438 driver->hardware_id,
5440 FILL_DRIVER_STRING(mem_ctx,
5447 /********************************************************************
5448 ********************************************************************/
5450 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5451 const struct auth_serversupplied_info *session_info,
5452 struct messaging_context *msg_ctx,
5454 union spoolss_DriverInfo *r,
5456 const char *servername,
5457 const char *architecture,
5460 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5461 struct spoolss_DriverInfo8 *driver;
5465 return WERR_UNKNOWN_LEVEL;
5468 result = winreg_get_printer(mem_ctx,
5471 lp_const_servicename(snum),
5474 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5475 win_errstr(result)));
5477 if (!W_ERROR_IS_OK(result)) {
5478 return WERR_INVALID_PRINTER_NAME;
5481 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5483 pinfo2->drivername, version, &driver);
5485 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5486 win_errstr(result)));
5488 if (!W_ERROR_IS_OK(result)) {
5490 * Is this a W2k client ?
5494 talloc_free(pinfo2);
5495 return WERR_UNKNOWN_PRINTER_DRIVER;
5498 /* Yes - try again with a WinNT driver. */
5500 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5504 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5505 win_errstr(result)));
5506 if (!W_ERROR_IS_OK(result)) {
5507 talloc_free(pinfo2);
5508 return WERR_UNKNOWN_PRINTER_DRIVER;
5514 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5517 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5520 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5523 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5526 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5529 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5532 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5534 #if 0 /* disabled until marshalling issues are resolved - gd */
5536 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5540 result = WERR_UNKNOWN_LEVEL;
5544 talloc_free(pinfo2);
5545 talloc_free(driver);
5550 /****************************************************************
5551 _spoolss_GetPrinterDriver2
5552 ****************************************************************/
5554 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5555 struct spoolss_GetPrinterDriver2 *r)
5557 struct printer_handle *printer;
5562 /* that's an [in out] buffer */
5564 if (!r->in.buffer && (r->in.offered != 0)) {
5565 return WERR_INVALID_PARAM;
5568 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5570 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5571 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5572 return WERR_INVALID_PRINTER_NAME;
5576 *r->out.server_major_version = 0;
5577 *r->out.server_minor_version = 0;
5579 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5583 result = construct_printer_driver_info_level(p->mem_ctx,
5584 get_session_info_system(),
5586 r->in.level, r->out.info,
5587 snum, printer->servername,
5589 r->in.client_major_version);
5590 if (!W_ERROR_IS_OK(result)) {
5591 TALLOC_FREE(r->out.info);
5595 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5596 r->out.info, r->in.level);
5597 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5599 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5603 /****************************************************************
5604 _spoolss_StartPagePrinter
5605 ****************************************************************/
5607 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5608 struct spoolss_StartPagePrinter *r)
5610 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5613 DEBUG(3,("_spoolss_StartPagePrinter: "
5614 "Error in startpageprinter printer handle\n"));
5618 Printer->page_started = true;
5622 /****************************************************************
5623 _spoolss_EndPagePrinter
5624 ****************************************************************/
5626 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5627 struct spoolss_EndPagePrinter *r)
5631 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5634 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5635 OUR_HANDLE(r->in.handle)));
5639 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5642 Printer->page_started = false;
5643 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5648 /****************************************************************
5649 _spoolss_StartDocPrinter
5650 ****************************************************************/
5652 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5653 struct spoolss_StartDocPrinter *r)
5655 struct spoolss_DocumentInfo1 *info_1;
5657 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5661 DEBUG(2,("_spoolss_StartDocPrinter: "
5662 "Invalid handle (%s:%u:%u)\n",
5663 OUR_HANDLE(r->in.handle)));
5667 if (Printer->jobid) {
5668 DEBUG(2, ("_spoolss_StartDocPrinter: "
5669 "StartDocPrinter called twice! "
5670 "(existing jobid = %d)\n", Printer->jobid));
5671 return WERR_INVALID_HANDLE;
5674 if (r->in.level != 1) {
5675 return WERR_UNKNOWN_LEVEL;
5678 info_1 = r->in.info.info1;
5681 * a nice thing with NT is it doesn't listen to what you tell it.
5682 * when asked to send _only_ RAW datas, it tries to send datas
5685 * So I add checks like in NT Server ...
5688 if (info_1->datatype) {
5689 if (strcmp(info_1->datatype, "RAW") != 0) {
5691 return WERR_INVALID_DATATYPE;
5695 /* get the share number of the printer */
5696 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5700 werr = print_job_start(p->session_info,
5704 info_1->document_name,
5705 info_1->output_file,
5709 /* An error occured in print_job_start() so return an appropriate
5712 if (!W_ERROR_IS_OK(werr)) {
5716 Printer->document_started = true;
5717 *r->out.job_id = Printer->jobid;
5722 /****************************************************************
5723 _spoolss_EndDocPrinter
5724 ****************************************************************/
5726 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5727 struct spoolss_EndDocPrinter *r)
5729 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5734 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5735 OUR_HANDLE(r->in.handle)));
5739 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5743 Printer->document_started = false;
5744 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5745 if (!NT_STATUS_IS_OK(status)) {
5746 DEBUG(2, ("_spoolss_EndDocPrinter: "
5747 "print_job_end failed [%s]\n",
5748 nt_errstr(status)));
5752 return ntstatus_to_werror(status);
5755 /****************************************************************
5756 _spoolss_WritePrinter
5757 ****************************************************************/
5759 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5760 struct spoolss_WritePrinter *r)
5762 ssize_t buffer_written;
5764 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5767 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5768 OUR_HANDLE(r->in.handle)));
5769 *r->out.num_written = r->in._data_size;
5773 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5776 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5777 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5778 snum, Printer->jobid,
5779 (const char *)r->in.data.data,
5780 (size_t)r->in._data_size);
5781 if (buffer_written == (ssize_t)-1) {
5782 *r->out.num_written = 0;
5783 if (errno == ENOSPC)
5784 return WERR_NO_SPOOL_SPACE;
5786 return WERR_ACCESS_DENIED;
5789 *r->out.num_written = r->in._data_size;
5794 /********************************************************************
5795 * api_spoolss_getprinter
5796 * called from the spoolss dispatcher
5798 ********************************************************************/
5800 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5801 struct pipes_struct *p)
5803 const struct auth_serversupplied_info *session_info = p->session_info;
5805 WERROR errcode = WERR_BADFUNC;
5806 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5809 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5810 OUR_HANDLE(handle)));
5814 if (!get_printer_snum(p, handle, &snum, NULL))
5818 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5819 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5821 case SPOOLSS_PRINTER_CONTROL_RESUME:
5822 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5823 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5825 case SPOOLSS_PRINTER_CONTROL_PURGE:
5826 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5829 return WERR_UNKNOWN_LEVEL;
5836 /****************************************************************
5837 _spoolss_AbortPrinter
5838 * From MSDN: "Deletes printer's spool file if printer is configured
5840 ****************************************************************/
5842 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5843 struct spoolss_AbortPrinter *r)
5845 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5847 WERROR errcode = WERR_OK;
5850 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5851 OUR_HANDLE(r->in.handle)));
5855 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5858 if (!Printer->document_started) {
5859 return WERR_SPL_NO_STARTDOC;
5862 errcode = print_job_delete(p->session_info,
5870 /********************************************************************
5871 * called by spoolss_api_setprinter
5872 * when updating a printer description
5873 ********************************************************************/
5875 static WERROR update_printer_sec(struct policy_handle *handle,
5876 struct pipes_struct *p,
5877 struct sec_desc_buf *secdesc_ctr)
5879 struct spoolss_security_descriptor *new_secdesc = NULL;
5880 struct spoolss_security_descriptor *old_secdesc = NULL;
5881 const char *printer;
5885 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5887 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5888 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5889 OUR_HANDLE(handle)));
5891 result = WERR_BADFID;
5895 if (secdesc_ctr == NULL) {
5896 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5897 result = WERR_INVALID_PARAM;
5900 printer = lp_const_servicename(snum);
5902 /* Check the user has permissions to change the security
5903 descriptor. By experimentation with two NT machines, the user
5904 requires Full Access to the printer to change security
5907 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5908 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5909 result = WERR_ACCESS_DENIED;
5913 /* NT seems to like setting the security descriptor even though
5914 nothing may have actually changed. */
5915 result = winreg_get_printer_secdesc(p->mem_ctx,
5916 get_session_info_system(),
5920 if (!W_ERROR_IS_OK(result)) {
5921 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5922 result = WERR_BADFID;
5926 if (DEBUGLEVEL >= 10) {
5927 struct security_acl *the_acl;
5930 the_acl = old_secdesc->dacl;
5931 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5932 printer, the_acl->num_aces));
5934 for (i = 0; i < the_acl->num_aces; i++) {
5935 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5936 &the_acl->aces[i].trustee),
5937 the_acl->aces[i].access_mask));
5940 the_acl = secdesc_ctr->sd->dacl;
5943 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5944 printer, the_acl->num_aces));
5946 for (i = 0; i < the_acl->num_aces; i++) {
5947 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5948 &the_acl->aces[i].trustee),
5949 the_acl->aces[i].access_mask));
5952 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5956 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5957 if (new_secdesc == NULL) {
5958 result = WERR_NOMEM;
5962 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5967 result = winreg_set_printer_secdesc(p->mem_ctx,
5968 get_session_info_system(),
5977 /********************************************************************
5978 Canonicalize printer info from a client
5979 ********************************************************************/
5981 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5982 struct spoolss_SetPrinterInfo2 *info2,
5985 fstring printername;
5988 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5989 "portname=%s drivername=%s comment=%s location=%s\n",
5990 info2->servername, info2->printername, info2->sharename,
5991 info2->portname, info2->drivername, info2->comment,
5994 /* we force some elements to "correct" values */
5995 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5996 if (info2->servername == NULL) {
5999 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6000 if (info2->sharename == NULL) {
6004 /* check to see if we allow printername != sharename */
6005 if (lp_force_printername(snum)) {
6006 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6007 global_myname(), info2->sharename);
6009 /* make sure printername is in \\server\printername format */
6010 fstrcpy(printername, info2->printername);
6012 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6013 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6017 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6018 global_myname(), p);
6020 if (info2->printername == NULL) {
6024 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6025 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6030 /****************************************************************************
6031 ****************************************************************************/
6033 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6035 char *cmd = lp_addport_cmd();
6036 char *command = NULL;
6038 bool is_print_op = false;
6041 return WERR_ACCESS_DENIED;
6044 command = talloc_asprintf(ctx,
6045 "%s \"%s\" \"%s\"", cmd, portname, uri );
6051 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6053 DEBUG(10,("Running [%s]\n", command));
6055 /********* BEGIN SePrintOperatorPrivilege **********/
6060 ret = smbrun(command, NULL);
6065 /********* END SePrintOperatorPrivilege **********/
6067 DEBUGADD(10,("returned [%d]\n", ret));
6069 TALLOC_FREE(command);
6072 return WERR_ACCESS_DENIED;
6078 /****************************************************************************
6079 ****************************************************************************/
6081 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6082 struct spoolss_SetPrinterInfo2 *info2,
6083 const char *remote_machine,
6084 struct messaging_context *msg_ctx)
6086 char *cmd = lp_addprinter_cmd();
6088 char *command = NULL;
6092 bool is_print_op = false;
6094 if (!remote_machine) {
6098 command = talloc_asprintf(ctx,
6099 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6100 cmd, info2->printername, info2->sharename,
6101 info2->portname, info2->drivername,
6102 info2->location, info2->comment, remote_machine);
6108 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6110 DEBUG(10,("Running [%s]\n", command));
6112 /********* BEGIN SePrintOperatorPrivilege **********/
6117 if ( (ret = smbrun(command, &fd)) == 0 ) {
6118 /* Tell everyone we updated smb.conf. */
6119 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6125 /********* END SePrintOperatorPrivilege **********/
6127 DEBUGADD(10,("returned [%d]\n", ret));
6129 TALLOC_FREE(command);
6137 /* reload our services immediately */
6139 reload_services(msg_ctx, -1, false);
6143 /* Get lines and convert them back to dos-codepage */
6144 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6145 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6148 /* Set the portname to what the script says the portname should be. */
6149 /* but don't require anything to be return from the script exit a good error code */
6152 /* Set the portname to what the script says the portname should be. */
6153 info2->portname = talloc_strdup(ctx, qlines[0]);
6154 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6157 TALLOC_FREE(qlines);
6161 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6162 const struct auth_serversupplied_info *session_info,
6163 struct messaging_context *msg_ctx,
6165 struct spoolss_SetPrinterInfo2 *printer,
6166 struct spoolss_PrinterInfo2 *old_printer)
6168 bool force_update = (old_printer == NULL);
6169 const char *dnsdomname;
6170 const char *longname;
6171 const char *uncname;
6172 const char *spooling;
6174 WERROR result = WERR_OK;
6176 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6177 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6178 winreg_set_printer_dataex(mem_ctx,
6182 SPOOL_DSSPOOLER_KEY,
6183 SPOOL_REG_DRIVERNAME,
6188 if (!force_update) {
6189 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6190 printer->drivername));
6192 notify_printer_driver(server_event_context(), msg_ctx,
6193 snum, printer->drivername ?
6194 printer->drivername : "");
6198 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6199 push_reg_sz(mem_ctx, &buffer, printer->comment);
6200 winreg_set_printer_dataex(mem_ctx,
6204 SPOOL_DSSPOOLER_KEY,
6205 SPOOL_REG_DESCRIPTION,
6210 if (!force_update) {
6211 notify_printer_comment(server_event_context(), msg_ctx,
6212 snum, printer->comment ?
6213 printer->comment : "");
6217 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6218 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6219 winreg_set_printer_dataex(mem_ctx,
6223 SPOOL_DSSPOOLER_KEY,
6224 SPOOL_REG_PRINTSHARENAME,
6229 if (!force_update) {
6230 notify_printer_sharename(server_event_context(),
6232 snum, printer->sharename ?
6233 printer->sharename : "");
6237 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6240 p = strrchr(printer->printername, '\\' );
6244 p = printer->printername;
6247 push_reg_sz(mem_ctx, &buffer, p);
6248 winreg_set_printer_dataex(mem_ctx,
6252 SPOOL_DSSPOOLER_KEY,
6253 SPOOL_REG_PRINTERNAME,
6258 if (!force_update) {
6259 notify_printer_printername(server_event_context(),
6260 msg_ctx, snum, p ? p : "");
6264 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6265 push_reg_sz(mem_ctx, &buffer, printer->portname);
6266 winreg_set_printer_dataex(mem_ctx,
6270 SPOOL_DSSPOOLER_KEY,
6276 if (!force_update) {
6277 notify_printer_port(server_event_context(),
6278 msg_ctx, snum, printer->portname ?
6279 printer->portname : "");
6283 if (force_update || !strequal(printer->location, old_printer->location)) {
6284 push_reg_sz(mem_ctx, &buffer, printer->location);
6285 winreg_set_printer_dataex(mem_ctx,
6289 SPOOL_DSSPOOLER_KEY,
6295 if (!force_update) {
6296 notify_printer_location(server_event_context(),
6299 printer->location : "");
6303 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6304 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6305 winreg_set_printer_dataex(mem_ctx,
6309 SPOOL_DSSPOOLER_KEY,
6310 SPOOL_REG_PRINTSEPARATORFILE,
6315 if (!force_update) {
6316 notify_printer_sepfile(server_event_context(),
6319 printer->sepfile : "");
6323 if (force_update || printer->starttime != old_printer->starttime) {
6324 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6325 SIVAL(buffer.data, 0, printer->starttime);
6326 winreg_set_printer_dataex(mem_ctx,
6330 SPOOL_DSSPOOLER_KEY,
6331 SPOOL_REG_PRINTSTARTTIME,
6337 if (force_update || printer->untiltime != old_printer->untiltime) {
6338 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6339 SIVAL(buffer.data, 0, printer->untiltime);
6340 winreg_set_printer_dataex(mem_ctx,
6344 SPOOL_DSSPOOLER_KEY,
6345 SPOOL_REG_PRINTENDTIME,
6351 if (force_update || printer->priority != old_printer->priority) {
6352 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6353 SIVAL(buffer.data, 0, printer->priority);
6354 winreg_set_printer_dataex(mem_ctx,
6358 SPOOL_DSSPOOLER_KEY,
6365 if (force_update || printer->attributes != old_printer->attributes) {
6366 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6367 SIVAL(buffer.data, 0, (printer->attributes &
6368 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6369 winreg_set_printer_dataex(mem_ctx,
6373 SPOOL_DSSPOOLER_KEY,
6374 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6379 switch (printer->attributes & 0x3) {
6381 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6384 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6387 spooling = SPOOL_REGVAL_PRINTDIRECT;
6390 spooling = "unknown";
6392 push_reg_sz(mem_ctx, &buffer, spooling);
6393 winreg_set_printer_dataex(mem_ctx,
6397 SPOOL_DSSPOOLER_KEY,
6398 SPOOL_REG_PRINTSPOOLING,
6404 push_reg_sz(mem_ctx, &buffer, global_myname());
6405 winreg_set_printer_dataex(mem_ctx,
6409 SPOOL_DSSPOOLER_KEY,
6410 SPOOL_REG_SHORTSERVERNAME,
6415 dnsdomname = get_mydnsfullname();
6416 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6417 longname = talloc_strdup(mem_ctx, dnsdomname);
6419 longname = talloc_strdup(mem_ctx, global_myname());
6421 if (longname == NULL) {
6422 result = WERR_NOMEM;
6426 push_reg_sz(mem_ctx, &buffer, longname);
6427 winreg_set_printer_dataex(mem_ctx,
6431 SPOOL_DSSPOOLER_KEY,
6432 SPOOL_REG_SERVERNAME,
6437 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6438 global_myname(), printer->sharename);
6439 push_reg_sz(mem_ctx, &buffer, uncname);
6440 winreg_set_printer_dataex(mem_ctx,
6444 SPOOL_DSSPOOLER_KEY,
6454 /********************************************************************
6455 * Called by spoolss_api_setprinter
6456 * when updating a printer description.
6457 ********************************************************************/
6459 static WERROR update_printer(struct pipes_struct *p,
6460 struct policy_handle *handle,
6461 struct spoolss_SetPrinterInfoCtr *info_ctr,
6462 struct spoolss_DeviceMode *devmode)
6464 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6465 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6466 struct spoolss_PrinterInfo2 *old_printer;
6467 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6469 WERROR result = WERR_OK;
6470 TALLOC_CTX *tmp_ctx;
6472 DEBUG(8,("update_printer\n"));
6474 tmp_ctx = talloc_new(p->mem_ctx);
6475 if (tmp_ctx == NULL) {
6480 result = WERR_BADFID;
6484 if (!get_printer_snum(p, handle, &snum, NULL)) {
6485 result = WERR_BADFID;
6489 result = winreg_get_printer(tmp_ctx,
6490 get_session_info_system(),
6492 lp_const_servicename(snum),
6494 if (!W_ERROR_IS_OK(result)) {
6495 result = WERR_BADFID;
6499 /* Do sanity check on the requested changes for Samba */
6500 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6501 result = WERR_INVALID_PARAM;
6505 /* FIXME!!! If the driver has changed we really should verify that
6506 it is installed before doing much else --jerry */
6508 /* Check calling user has permission to update printer description */
6509 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6510 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6511 result = WERR_ACCESS_DENIED;
6515 /* Call addprinter hook */
6516 /* Check changes to see if this is really needed */
6518 if (*lp_addprinter_cmd() &&
6519 (!strequal(printer->drivername, old_printer->drivername) ||
6520 !strequal(printer->comment, old_printer->comment) ||
6521 !strequal(printer->portname, old_printer->portname) ||
6522 !strequal(printer->location, old_printer->location)) )
6524 /* add_printer_hook() will call reload_services() */
6525 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6526 printer, p->client_id->addr,
6528 result = WERR_ACCESS_DENIED;
6533 update_dsspooler(tmp_ctx,
6534 get_session_info_system(),
6540 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6542 if (devmode == NULL) {
6543 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6545 result = winreg_update_printer(tmp_ctx,
6546 get_session_info_system(),
6555 talloc_free(tmp_ctx);
6560 /****************************************************************************
6561 ****************************************************************************/
6562 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6563 struct policy_handle *handle,
6564 struct spoolss_SetPrinterInfo7 *info7)
6567 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6570 struct printer_handle *Printer;
6572 if ( lp_security() != SEC_ADS ) {
6573 return WERR_UNKNOWN_LEVEL;
6576 Printer = find_printer_index_by_hnd(p, handle);
6578 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6583 if (!get_printer_snum(p, handle, &snum, NULL))
6586 result = winreg_get_printer(p->mem_ctx,
6587 get_session_info_system(),
6589 lp_servicename(snum),
6591 if (!W_ERROR_IS_OK(result)) {
6595 nt_printer_publish(pinfo2,
6596 get_session_info_system(),
6601 TALLOC_FREE(pinfo2);
6604 return WERR_UNKNOWN_LEVEL;
6608 /********************************************************************
6609 ********************************************************************/
6611 static WERROR update_printer_devmode(struct pipes_struct *p,
6612 struct policy_handle *handle,
6613 struct spoolss_DeviceMode *devmode)
6616 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6617 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6619 DEBUG(8,("update_printer_devmode\n"));
6625 if (!get_printer_snum(p, handle, &snum, NULL)) {
6629 /* Check calling user has permission to update printer description */
6630 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6631 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6632 return WERR_ACCESS_DENIED;
6635 return winreg_update_printer(p->mem_ctx,
6636 get_session_info_system(),
6638 lp_const_servicename(snum),
6646 /****************************************************************
6648 ****************************************************************/
6650 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6651 struct spoolss_SetPrinter *r)
6655 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6658 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6659 OUR_HANDLE(r->in.handle)));
6663 /* check the level */
6664 switch (r->in.info_ctr->level) {
6666 return control_printer(r->in.handle, r->in.command, p);
6668 result = update_printer(p, r->in.handle,
6670 r->in.devmode_ctr->devmode);
6671 if (!W_ERROR_IS_OK(result))
6673 if (r->in.secdesc_ctr->sd)
6674 result = update_printer_sec(r->in.handle, p,
6678 return update_printer_sec(r->in.handle, p,
6681 return publish_or_unpublish_printer(p, r->in.handle,
6682 r->in.info_ctr->info.info7);
6684 return update_printer_devmode(p, r->in.handle,
6685 r->in.devmode_ctr->devmode);
6687 return WERR_UNKNOWN_LEVEL;
6691 /****************************************************************
6692 _spoolss_FindClosePrinterNotify
6693 ****************************************************************/
6695 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6696 struct spoolss_FindClosePrinterNotify *r)
6698 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6701 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6702 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6706 if (Printer->notify.cli_chan != NULL &&
6707 Printer->notify.cli_chan->active_connections > 0) {
6710 if (Printer->printer_type == SPLHND_PRINTER) {
6711 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6716 srv_spoolss_replycloseprinter(snum, Printer);
6719 Printer->notify.flags=0;
6720 Printer->notify.options=0;
6721 Printer->notify.localmachine[0]='\0';
6722 Printer->notify.printerlocal=0;
6723 TALLOC_FREE(Printer->notify.option);
6728 /****************************************************************
6730 ****************************************************************/
6732 WERROR _spoolss_AddJob(struct pipes_struct *p,
6733 struct spoolss_AddJob *r)
6735 if (!r->in.buffer && (r->in.offered != 0)) {
6736 return WERR_INVALID_PARAM;
6739 /* this is what a NT server returns for AddJob. AddJob must fail on
6740 * non-local printers */
6742 if (r->in.level != 1) {
6743 return WERR_UNKNOWN_LEVEL;
6746 return WERR_INVALID_PARAM;
6749 /****************************************************************************
6751 ****************************************************************************/
6753 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6754 struct spoolss_JobInfo1 *r,
6755 const print_queue_struct *queue,
6756 int position, int snum,
6757 struct spoolss_PrinterInfo2 *pinfo2)
6761 t = gmtime(&queue->time);
6763 r->job_id = queue->job;
6765 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6766 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6767 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6768 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6769 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6770 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6771 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6772 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6773 r->data_type = talloc_strdup(mem_ctx, "RAW");
6774 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6775 r->text_status = talloc_strdup(mem_ctx, "");
6776 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6778 r->status = nt_printj_status(queue->status);
6779 r->priority = queue->priority;
6780 r->position = position;
6781 r->total_pages = queue->page_count;
6782 r->pages_printed = 0; /* ??? */
6784 init_systemtime(&r->submitted, t);
6789 /****************************************************************************
6791 ****************************************************************************/
6793 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6794 struct spoolss_JobInfo2 *r,
6795 const print_queue_struct *queue,
6796 int position, int snum,
6797 struct spoolss_PrinterInfo2 *pinfo2,
6798 struct spoolss_DeviceMode *devmode)
6802 t = gmtime(&queue->time);
6804 r->job_id = queue->job;
6806 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6807 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6808 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6809 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6810 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6811 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6812 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6813 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6814 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6815 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6816 r->data_type = talloc_strdup(mem_ctx, "RAW");
6817 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6818 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6819 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6820 r->parameters = talloc_strdup(mem_ctx, "");
6821 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6822 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6823 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6825 r->devmode = devmode;
6827 r->text_status = talloc_strdup(mem_ctx, "");
6828 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6832 r->status = nt_printj_status(queue->status);
6833 r->priority = queue->priority;
6834 r->position = position;
6837 r->total_pages = queue->page_count;
6838 r->size = queue->size;
6839 init_systemtime(&r->submitted, t);
6841 r->pages_printed = 0; /* ??? */
6846 /****************************************************************************
6848 ****************************************************************************/
6850 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6851 struct spoolss_JobInfo3 *r,
6852 const print_queue_struct *queue,
6853 const print_queue_struct *next_queue,
6854 int position, int snum,
6855 struct spoolss_PrinterInfo2 *pinfo2)
6857 r->job_id = queue->job;
6860 r->next_job_id = next_queue->job;
6867 /****************************************************************************
6868 Enumjobs at level 1.
6869 ****************************************************************************/
6871 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6872 const print_queue_struct *queue,
6873 uint32_t num_queues, int snum,
6874 struct spoolss_PrinterInfo2 *pinfo2,
6875 union spoolss_JobInfo **info_p,
6878 union spoolss_JobInfo *info;
6880 WERROR result = WERR_OK;
6882 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6883 W_ERROR_HAVE_NO_MEMORY(info);
6885 *count = num_queues;
6887 for (i=0; i<*count; i++) {
6888 result = fill_job_info1(info,
6894 if (!W_ERROR_IS_OK(result)) {
6900 if (!W_ERROR_IS_OK(result)) {
6911 /****************************************************************************
6912 Enumjobs at level 2.
6913 ****************************************************************************/
6915 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6916 const print_queue_struct *queue,
6917 uint32_t num_queues, int snum,
6918 struct spoolss_PrinterInfo2 *pinfo2,
6919 union spoolss_JobInfo **info_p,
6922 union spoolss_JobInfo *info;
6924 WERROR result = WERR_OK;
6926 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6927 W_ERROR_HAVE_NO_MEMORY(info);
6929 *count = num_queues;
6931 for (i=0; i<*count; i++) {
6932 struct spoolss_DeviceMode *devmode;
6934 result = spoolss_create_default_devmode(info,
6935 pinfo2->printername,
6937 if (!W_ERROR_IS_OK(result)) {
6938 DEBUG(3, ("Can't proceed w/o a devmode!"));
6942 result = fill_job_info2(info,
6949 if (!W_ERROR_IS_OK(result)) {
6955 if (!W_ERROR_IS_OK(result)) {
6966 /****************************************************************************
6967 Enumjobs at level 3.
6968 ****************************************************************************/
6970 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6971 const print_queue_struct *queue,
6972 uint32_t num_queues, int snum,
6973 struct spoolss_PrinterInfo2 *pinfo2,
6974 union spoolss_JobInfo **info_p,
6977 union spoolss_JobInfo *info;
6979 WERROR result = WERR_OK;
6981 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6982 W_ERROR_HAVE_NO_MEMORY(info);
6984 *count = num_queues;
6986 for (i=0; i<*count; i++) {
6987 const print_queue_struct *next_queue = NULL;
6990 next_queue = &queue[i+1];
6993 result = fill_job_info3(info,
7000 if (!W_ERROR_IS_OK(result)) {
7006 if (!W_ERROR_IS_OK(result)) {
7017 /****************************************************************
7019 ****************************************************************/
7021 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7022 struct spoolss_EnumJobs *r)
7025 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7027 print_status_struct prt_status;
7028 print_queue_struct *queue = NULL;
7031 /* that's an [in out] buffer */
7033 if (!r->in.buffer && (r->in.offered != 0)) {
7034 return WERR_INVALID_PARAM;
7037 DEBUG(4,("_spoolss_EnumJobs\n"));
7041 *r->out.info = NULL;
7043 /* lookup the printer snum and tdb entry */
7045 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7049 result = winreg_get_printer(p->mem_ctx,
7050 get_session_info_system(),
7052 lp_const_servicename(snum),
7054 if (!W_ERROR_IS_OK(result)) {
7058 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7059 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7060 count, prt_status.status, prt_status.message));
7064 TALLOC_FREE(pinfo2);
7068 switch (r->in.level) {
7070 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7071 pinfo2, r->out.info, r->out.count);
7074 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7075 pinfo2, r->out.info, r->out.count);
7078 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7079 pinfo2, r->out.info, r->out.count);
7082 result = WERR_UNKNOWN_LEVEL;
7087 TALLOC_FREE(pinfo2);
7089 if (!W_ERROR_IS_OK(result)) {
7093 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7095 *r->out.info, r->in.level,
7097 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7098 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7100 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7103 /****************************************************************
7104 _spoolss_ScheduleJob
7105 ****************************************************************/
7107 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7108 struct spoolss_ScheduleJob *r)
7113 /****************************************************************
7114 ****************************************************************/
7116 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7117 struct messaging_context *msg_ctx,
7118 const char *printer_name,
7120 struct spoolss_SetJobInfo1 *r)
7124 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7128 if (strequal(old_doc_name, r->document_name)) {
7132 if (!print_job_set_name(server_event_context(), msg_ctx,
7133 printer_name, job_id, r->document_name)) {
7140 /****************************************************************
7142 ****************************************************************/
7144 WERROR _spoolss_SetJob(struct pipes_struct *p,
7145 struct spoolss_SetJob *r)
7147 const struct auth_serversupplied_info *session_info = p->session_info;
7149 WERROR errcode = WERR_BADFUNC;
7151 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7155 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7156 return WERR_INVALID_PRINTER_NAME;
7159 switch (r->in.command) {
7160 case SPOOLSS_JOB_CONTROL_CANCEL:
7161 case SPOOLSS_JOB_CONTROL_DELETE:
7162 errcode = print_job_delete(session_info, p->msg_ctx,
7163 snum, r->in.job_id);
7164 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7168 case SPOOLSS_JOB_CONTROL_PAUSE:
7169 if (print_job_pause(session_info, p->msg_ctx,
7170 snum, r->in.job_id, &errcode)) {
7174 case SPOOLSS_JOB_CONTROL_RESTART:
7175 case SPOOLSS_JOB_CONTROL_RESUME:
7176 if (print_job_resume(session_info, p->msg_ctx,
7177 snum, r->in.job_id, &errcode)) {
7185 return WERR_UNKNOWN_LEVEL;
7188 if (!W_ERROR_IS_OK(errcode)) {
7192 if (r->in.ctr == NULL) {
7196 switch (r->in.ctr->level) {
7198 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7199 lp_const_servicename(snum),
7201 r->in.ctr->info.info1);
7207 return WERR_UNKNOWN_LEVEL;
7213 /****************************************************************************
7214 Enumerates all printer drivers by level and architecture.
7215 ****************************************************************************/
7217 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7218 const struct auth_serversupplied_info *session_info,
7219 struct messaging_context *msg_ctx,
7220 const char *servername,
7221 const char *architecture,
7223 union spoolss_DriverInfo **info_p,
7228 struct spoolss_DriverInfo8 *driver;
7229 union spoolss_DriverInfo *info = NULL;
7231 WERROR result = WERR_OK;
7232 uint32_t num_drivers;
7233 const char **drivers;
7238 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7239 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7240 architecture, version,
7241 &num_drivers, &drivers);
7242 if (!W_ERROR_IS_OK(result)) {
7245 DEBUG(4, ("we have:[%d] drivers in environment"
7246 " [%s] and version [%d]\n",
7247 num_drivers, architecture, version));
7249 if (num_drivers != 0) {
7250 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7251 union spoolss_DriverInfo,
7252 count + num_drivers);
7254 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7255 "failed to enlarge driver info buffer!\n"));
7256 result = WERR_NOMEM;
7261 for (i = 0; i < num_drivers; i++) {
7262 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7264 result = winreg_get_driver(mem_ctx, session_info,
7266 architecture, drivers[i],
7268 if (!W_ERROR_IS_OK(result)) {
7274 result = fill_printer_driver_info1(info, &info[count+i].info1,
7275 driver, servername);
7278 result = fill_printer_driver_info2(info, &info[count+i].info2,
7279 driver, servername);
7282 result = fill_printer_driver_info3(info, &info[count+i].info3,
7283 driver, servername);
7286 result = fill_printer_driver_info4(info, &info[count+i].info4,
7287 driver, servername);
7290 result = fill_printer_driver_info5(info, &info[count+i].info5,
7291 driver, servername);
7294 result = fill_printer_driver_info6(info, &info[count+i].info6,
7295 driver, servername);
7298 result = fill_printer_driver_info8(info, &info[count+i].info8,
7299 driver, servername);
7302 result = WERR_UNKNOWN_LEVEL;
7306 TALLOC_FREE(driver);
7308 if (!W_ERROR_IS_OK(result)) {
7313 count += num_drivers;
7314 TALLOC_FREE(drivers);
7318 TALLOC_FREE(drivers);
7320 if (!W_ERROR_IS_OK(result)) {
7331 /****************************************************************************
7332 Enumerates all printer drivers by level.
7333 ****************************************************************************/
7335 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7336 const struct auth_serversupplied_info *session_info,
7337 struct messaging_context *msg_ctx,
7338 const char *servername,
7339 const char *architecture,
7341 union spoolss_DriverInfo **info_p,
7345 WERROR result = WERR_OK;
7347 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7349 for (a=0; archi_table[a].long_archi != NULL; a++) {
7351 union spoolss_DriverInfo *info = NULL;
7354 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7358 archi_table[a].long_archi,
7362 if (!W_ERROR_IS_OK(result)) {
7366 for (i=0; i < count; i++) {
7367 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7368 info[i], info_p, count_p);
7375 return enumprinterdrivers_level_by_architecture(mem_ctx,
7385 /****************************************************************
7386 _spoolss_EnumPrinterDrivers
7387 ****************************************************************/
7389 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7390 struct spoolss_EnumPrinterDrivers *r)
7392 const char *cservername;
7395 /* that's an [in out] buffer */
7397 if (!r->in.buffer && (r->in.offered != 0)) {
7398 return WERR_INVALID_PARAM;
7401 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7405 *r->out.info = NULL;
7407 cservername = canon_servername(r->in.server);
7409 if (!is_myname_or_ipaddr(cservername)) {
7410 return WERR_UNKNOWN_PRINTER_DRIVER;
7413 result = enumprinterdrivers_level(p->mem_ctx,
7414 get_session_info_system(),
7421 if (!W_ERROR_IS_OK(result)) {
7425 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7426 spoolss_EnumPrinterDrivers,
7427 *r->out.info, r->in.level,
7429 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7430 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7432 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7435 /****************************************************************
7437 ****************************************************************/
7439 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7440 struct spoolss_EnumForms *r)
7446 *r->out.info = NULL;
7448 /* that's an [in out] buffer */
7450 if (!r->in.buffer && (r->in.offered != 0) ) {
7451 return WERR_INVALID_PARAM;
7454 DEBUG(4,("_spoolss_EnumForms\n"));
7455 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7456 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7458 switch (r->in.level) {
7460 result = winreg_printer_enumforms1(p->mem_ctx,
7461 get_session_info_system(),
7467 result = WERR_UNKNOWN_LEVEL;
7471 if (!W_ERROR_IS_OK(result)) {
7475 if (*r->out.count == 0) {
7476 return WERR_NO_MORE_ITEMS;
7479 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7481 *r->out.info, r->in.level,
7483 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7484 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7486 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7489 /****************************************************************
7491 ****************************************************************/
7493 WERROR _spoolss_GetForm(struct pipes_struct *p,
7494 struct spoolss_GetForm *r)
7498 /* that's an [in out] buffer */
7500 if (!r->in.buffer && (r->in.offered != 0)) {
7501 return WERR_INVALID_PARAM;
7504 DEBUG(4,("_spoolss_GetForm\n"));
7505 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7506 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7508 switch (r->in.level) {
7510 result = winreg_printer_getform1(p->mem_ctx,
7511 get_session_info_system(),
7514 &r->out.info->info1);
7517 result = WERR_UNKNOWN_LEVEL;
7521 if (!W_ERROR_IS_OK(result)) {
7522 TALLOC_FREE(r->out.info);
7526 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7527 r->out.info, r->in.level);
7528 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7530 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7533 /****************************************************************************
7534 ****************************************************************************/
7536 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7537 struct spoolss_PortInfo1 *r,
7540 r->port_name = talloc_strdup(mem_ctx, name);
7541 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7546 /****************************************************************************
7547 TODO: This probably needs distinguish between TCP/IP and Local ports
7549 ****************************************************************************/
7551 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7552 struct spoolss_PortInfo2 *r,
7555 r->port_name = talloc_strdup(mem_ctx, name);
7556 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7558 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7559 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7561 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7562 W_ERROR_HAVE_NO_MEMORY(r->description);
7564 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7571 /****************************************************************************
7572 wrapper around the enumer ports command
7573 ****************************************************************************/
7575 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7577 char *cmd = lp_enumports_cmd();
7578 char **qlines = NULL;
7579 char *command = NULL;
7587 /* if no hook then just fill in the default port */
7590 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7593 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7594 TALLOC_FREE(qlines);
7601 /* we have a valid enumport command */
7603 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7608 DEBUG(10,("Running [%s]\n", command));
7609 ret = smbrun(command, &fd);
7610 DEBUG(10,("Returned [%d]\n", ret));
7611 TALLOC_FREE(command);
7616 return WERR_ACCESS_DENIED;
7620 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7621 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7631 /****************************************************************************
7633 ****************************************************************************/
7635 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7636 union spoolss_PortInfo **info_p,
7639 union spoolss_PortInfo *info = NULL;
7641 WERROR result = WERR_OK;
7642 char **qlines = NULL;
7645 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7646 if (!W_ERROR_IS_OK(result)) {
7651 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7653 DEBUG(10,("Returning WERR_NOMEM\n"));
7654 result = WERR_NOMEM;
7658 for (i=0; i<numlines; i++) {
7659 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7660 result = fill_port_1(info, &info[i].info1, qlines[i]);
7661 if (!W_ERROR_IS_OK(result)) {
7666 TALLOC_FREE(qlines);
7669 if (!W_ERROR_IS_OK(result)) {
7671 TALLOC_FREE(qlines);
7683 /****************************************************************************
7685 ****************************************************************************/
7687 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7688 union spoolss_PortInfo **info_p,
7691 union spoolss_PortInfo *info = NULL;
7693 WERROR result = WERR_OK;
7694 char **qlines = NULL;
7697 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7698 if (!W_ERROR_IS_OK(result)) {
7703 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7705 DEBUG(10,("Returning WERR_NOMEM\n"));
7706 result = WERR_NOMEM;
7710 for (i=0; i<numlines; i++) {
7711 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7712 result = fill_port_2(info, &info[i].info2, qlines[i]);
7713 if (!W_ERROR_IS_OK(result)) {
7718 TALLOC_FREE(qlines);
7721 if (!W_ERROR_IS_OK(result)) {
7723 TALLOC_FREE(qlines);
7735 /****************************************************************
7737 ****************************************************************/
7739 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7740 struct spoolss_EnumPorts *r)
7744 /* that's an [in out] buffer */
7746 if (!r->in.buffer && (r->in.offered != 0)) {
7747 return WERR_INVALID_PARAM;
7750 DEBUG(4,("_spoolss_EnumPorts\n"));
7754 *r->out.info = NULL;
7756 switch (r->in.level) {
7758 result = enumports_level_1(p->mem_ctx, r->out.info,
7762 result = enumports_level_2(p->mem_ctx, r->out.info,
7766 return WERR_UNKNOWN_LEVEL;
7769 if (!W_ERROR_IS_OK(result)) {
7773 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7775 *r->out.info, r->in.level,
7777 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7778 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7780 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7783 /****************************************************************************
7784 ****************************************************************************/
7786 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7788 struct spoolss_SetPrinterInfoCtr *info_ctr,
7789 struct spoolss_DeviceMode *devmode,
7790 struct security_descriptor *secdesc,
7791 struct spoolss_UserLevelCtr *user_ctr,
7792 struct policy_handle *handle)
7794 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7795 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7797 WERROR err = WERR_OK;
7799 /* samba does not have a concept of local, non-shared printers yet, so
7800 * make sure we always setup sharename - gd */
7801 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7802 (info2->printername != NULL && info2->printername[0] != '\0')) {
7803 DEBUG(5, ("spoolss_addprinterex_level_2: "
7804 "no sharename has been set, setting printername %s as sharename\n",
7805 info2->printername));
7806 info2->sharename = info2->printername;
7809 /* check to see if the printer already exists */
7810 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7811 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7813 return WERR_PRINTER_ALREADY_EXISTS;
7816 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7817 if ((snum = print_queue_snum(info2->printername)) != -1) {
7818 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7819 info2->printername));
7820 return WERR_PRINTER_ALREADY_EXISTS;
7824 /* validate printer info struct */
7825 if (!info2->printername || strlen(info2->printername) == 0) {
7826 return WERR_INVALID_PRINTER_NAME;
7828 if (!info2->portname || strlen(info2->portname) == 0) {
7829 return WERR_UNKNOWN_PORT;
7831 if (!info2->drivername || strlen(info2->drivername) == 0) {
7832 return WERR_UNKNOWN_PRINTER_DRIVER;
7834 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7835 return WERR_UNKNOWN_PRINTPROCESSOR;
7838 /* FIXME!!! smbd should check to see if the driver is installed before
7839 trying to add a printer like this --jerry */
7841 if (*lp_addprinter_cmd() ) {
7842 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7843 info2, p->client_id->addr,
7845 return WERR_ACCESS_DENIED;
7848 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7849 "smb.conf parameter \"addprinter command\" is defined. This"
7850 "parameter must exist for this call to succeed\n",
7851 info2->sharename ));
7854 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7855 return WERR_ACCESS_DENIED;
7858 /* you must be a printer admin to add a new printer */
7859 if (!print_access_check(p->session_info,
7862 PRINTER_ACCESS_ADMINISTER)) {
7863 return WERR_ACCESS_DENIED;
7867 * Do sanity check on the requested changes for Samba.
7870 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7871 return WERR_INVALID_PARAM;
7874 if (devmode == NULL) {
7875 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7878 update_dsspooler(p->mem_ctx,
7879 get_session_info_system(),
7885 err = winreg_update_printer(p->mem_ctx,
7886 get_session_info_system(),
7893 if (!W_ERROR_IS_OK(err)) {
7897 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7898 if (!W_ERROR_IS_OK(err)) {
7899 /* Handle open failed - remove addition. */
7900 ZERO_STRUCTP(handle);
7907 /****************************************************************
7908 _spoolss_AddPrinterEx
7909 ****************************************************************/
7911 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7912 struct spoolss_AddPrinterEx *r)
7914 switch (r->in.info_ctr->level) {
7916 /* we don't handle yet */
7917 /* but I know what to do ... */
7918 return WERR_UNKNOWN_LEVEL;
7920 return spoolss_addprinterex_level_2(p, r->in.server,
7922 r->in.devmode_ctr->devmode,
7923 r->in.secdesc_ctr->sd,
7924 r->in.userlevel_ctr,
7927 return WERR_UNKNOWN_LEVEL;
7931 /****************************************************************
7933 ****************************************************************/
7935 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7936 struct spoolss_AddPrinter *r)
7938 struct spoolss_AddPrinterEx a;
7939 struct spoolss_UserLevelCtr userlevel_ctr;
7941 ZERO_STRUCT(userlevel_ctr);
7943 userlevel_ctr.level = 1;
7945 a.in.server = r->in.server;
7946 a.in.info_ctr = r->in.info_ctr;
7947 a.in.devmode_ctr = r->in.devmode_ctr;
7948 a.in.secdesc_ctr = r->in.secdesc_ctr;
7949 a.in.userlevel_ctr = &userlevel_ctr;
7950 a.out.handle = r->out.handle;
7952 return _spoolss_AddPrinterEx(p, &a);
7955 /****************************************************************
7956 _spoolss_AddPrinterDriverEx
7957 ****************************************************************/
7959 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7960 struct spoolss_AddPrinterDriverEx *r)
7962 WERROR err = WERR_OK;
7963 const char *driver_name = NULL;
7968 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7969 fn = "_spoolss_AddPrinterDriver";
7971 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7972 fn = "_spoolss_AddPrinterDriverEx";
7975 return WERR_INVALID_PARAM;
7979 * we only support the semantics of AddPrinterDriver()
7980 * i.e. only copy files that are newer than existing ones
7983 if (r->in.flags == 0) {
7984 return WERR_INVALID_PARAM;
7987 if (r->in.flags != APD_COPY_NEW_FILES) {
7988 return WERR_ACCESS_DENIED;
7992 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7993 /* Clever hack from Martin Zielinski <mz@seh.de>
7994 * to allow downgrade from level 8 (Vista).
7996 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7997 r->in.info_ctr->level));
7998 return WERR_UNKNOWN_LEVEL;
8001 DEBUG(5,("Cleaning driver's information\n"));
8002 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8003 if (!W_ERROR_IS_OK(err))
8006 DEBUG(5,("Moving driver to final destination\n"));
8007 err = move_driver_to_download_area(p, r->in.info_ctr);
8008 if (!W_ERROR_IS_OK(err)) {
8012 err = winreg_add_driver(p->mem_ctx,
8013 get_session_info_system(),
8018 if (!W_ERROR_IS_OK(err)) {
8023 * I think this is where he DrvUpgradePrinter() hook would be
8024 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8025 * server. Right now, we just need to send ourselves a message
8026 * to update each printer bound to this driver. --jerry
8029 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8030 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8038 /****************************************************************
8039 _spoolss_AddPrinterDriver
8040 ****************************************************************/
8042 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8043 struct spoolss_AddPrinterDriver *r)
8045 struct spoolss_AddPrinterDriverEx a;
8047 switch (r->in.info_ctr->level) {
8054 return WERR_UNKNOWN_LEVEL;
8057 a.in.servername = r->in.servername;
8058 a.in.info_ctr = r->in.info_ctr;
8059 a.in.flags = APD_COPY_NEW_FILES;
8061 return _spoolss_AddPrinterDriverEx(p, &a);
8064 /****************************************************************************
8065 ****************************************************************************/
8067 struct _spoolss_paths {
8073 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8075 static const struct _spoolss_paths spoolss_paths[]= {
8076 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8077 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8080 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8081 const char *servername,
8082 const char *environment,
8086 const char *pservername = NULL;
8087 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8088 const char *short_archi;
8092 /* environment may be empty */
8093 if (environment && strlen(environment)) {
8094 long_archi = environment;
8097 /* servername may be empty */
8098 if (servername && strlen(servername)) {
8099 pservername = canon_servername(servername);
8101 if (!is_myname_or_ipaddr(pservername)) {
8102 return WERR_INVALID_PARAM;
8106 if (!(short_archi = get_short_archi(long_archi))) {
8107 return WERR_INVALID_ENVIRONMENT;
8110 switch (component) {
8111 case SPOOLSS_PRTPROCS_PATH:
8112 case SPOOLSS_DRIVER_PATH:
8114 *path = talloc_asprintf(mem_ctx,
8117 spoolss_paths[component].share,
8120 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8121 SPOOLSS_DEFAULT_SERVER_PATH,
8122 spoolss_paths[component].dir,
8127 return WERR_INVALID_PARAM;
8137 /****************************************************************************
8138 ****************************************************************************/
8140 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8141 const char *servername,
8142 const char *environment,
8143 struct spoolss_DriverDirectoryInfo1 *r)
8148 werr = compose_spoolss_server_path(mem_ctx,
8151 SPOOLSS_DRIVER_PATH,
8153 if (!W_ERROR_IS_OK(werr)) {
8157 DEBUG(4,("printer driver directory: [%s]\n", path));
8159 r->directory_name = path;
8164 /****************************************************************
8165 _spoolss_GetPrinterDriverDirectory
8166 ****************************************************************/
8168 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8169 struct spoolss_GetPrinterDriverDirectory *r)
8173 /* that's an [in out] buffer */
8175 if (!r->in.buffer && (r->in.offered != 0)) {
8176 return WERR_INVALID_PARAM;
8179 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8184 /* r->in.level is ignored */
8186 werror = getprinterdriverdir_level_1(p->mem_ctx,
8189 &r->out.info->info1);
8190 if (!W_ERROR_IS_OK(werror)) {
8191 TALLOC_FREE(r->out.info);
8195 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8196 r->out.info, r->in.level);
8197 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8199 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8202 /****************************************************************
8203 _spoolss_EnumPrinterData
8204 ****************************************************************/
8206 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8207 struct spoolss_EnumPrinterData *r)
8210 struct spoolss_EnumPrinterDataEx r2;
8212 struct spoolss_PrinterEnumValues *info, *val = NULL;
8215 r2.in.handle = r->in.handle;
8216 r2.in.key_name = "PrinterDriverData";
8218 r2.out.count = &count;
8219 r2.out.info = &info;
8220 r2.out.needed = &needed;
8222 result = _spoolss_EnumPrinterDataEx(p, &r2);
8223 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8224 r2.in.offered = needed;
8225 result = _spoolss_EnumPrinterDataEx(p, &r2);
8227 if (!W_ERROR_IS_OK(result)) {
8232 * The NT machine wants to know the biggest size of value and data
8234 * cf: MSDN EnumPrinterData remark section
8237 if (!r->in.value_offered && !r->in.data_offered) {
8238 uint32_t biggest_valuesize = 0;
8239 uint32_t biggest_datasize = 0;
8242 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8244 for (i=0; i<count; i++) {
8246 name_length = strlen(info[i].value_name);
8247 if (strlen(info[i].value_name) > biggest_valuesize) {
8248 biggest_valuesize = name_length;
8251 if (info[i].data_length > biggest_datasize) {
8252 biggest_datasize = info[i].data_length;
8255 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8259 /* the value is an UNICODE string but real_value_size is the length
8260 in bytes including the trailing 0 */
8262 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8263 *r->out.data_needed = biggest_datasize;
8265 DEBUG(6,("final values: [%d], [%d]\n",
8266 *r->out.value_needed, *r->out.data_needed));
8271 if (r->in.enum_index < count) {
8272 val = &info[r->in.enum_index];
8276 /* out_value should default to "" or else NT4 has
8277 problems unmarshalling the response */
8279 if (r->in.value_offered) {
8280 *r->out.value_needed = 1;
8281 r->out.value_name = talloc_strdup(r, "");
8282 if (!r->out.value_name) {
8286 r->out.value_name = NULL;
8287 *r->out.value_needed = 0;
8290 /* the data is counted in bytes */
8292 *r->out.data_needed = r->in.data_offered;
8294 result = WERR_NO_MORE_ITEMS;
8298 * - counted in bytes in the request
8299 * - counted in UNICODE chars in the max reply
8300 * - counted in bytes in the real size
8302 * take a pause *before* coding not *during* coding
8306 if (r->in.value_offered) {
8307 r->out.value_name = talloc_strdup(r, val->value_name);
8308 if (!r->out.value_name) {
8311 *r->out.value_needed = val->value_name_len;
8313 r->out.value_name = NULL;
8314 *r->out.value_needed = 0;
8319 *r->out.type = val->type;
8321 /* data - counted in bytes */
8324 * See the section "Dynamically Typed Query Parameters"
8328 if (r->out.data && val->data && val->data->data &&
8329 val->data_length && r->in.data_offered) {
8330 memcpy(r->out.data, val->data->data,
8331 MIN(val->data_length,r->in.data_offered));
8334 *r->out.data_needed = val->data_length;
8342 /****************************************************************
8343 _spoolss_SetPrinterData
8344 ****************************************************************/
8346 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8347 struct spoolss_SetPrinterData *r)
8349 struct spoolss_SetPrinterDataEx r2;
8351 r2.in.handle = r->in.handle;
8352 r2.in.key_name = "PrinterDriverData";
8353 r2.in.value_name = r->in.value_name;
8354 r2.in.type = r->in.type;
8355 r2.in.data = r->in.data;
8356 r2.in.offered = r->in.offered;
8358 return _spoolss_SetPrinterDataEx(p, &r2);
8361 /****************************************************************
8362 _spoolss_ResetPrinter
8363 ****************************************************************/
8365 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8366 struct spoolss_ResetPrinter *r)
8368 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8371 DEBUG(5,("_spoolss_ResetPrinter\n"));
8374 * All we do is to check to see if the handle and queue is valid.
8375 * This call really doesn't mean anything to us because we only
8376 * support RAW printing. --jerry
8380 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8381 OUR_HANDLE(r->in.handle)));
8385 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8389 /* blindly return success */
8393 /****************************************************************
8394 _spoolss_DeletePrinterData
8395 ****************************************************************/
8397 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8398 struct spoolss_DeletePrinterData *r)
8400 struct spoolss_DeletePrinterDataEx r2;
8402 r2.in.handle = r->in.handle;
8403 r2.in.key_name = "PrinterDriverData";
8404 r2.in.value_name = r->in.value_name;
8406 return _spoolss_DeletePrinterDataEx(p, &r2);
8409 /****************************************************************
8411 ****************************************************************/
8413 WERROR _spoolss_AddForm(struct pipes_struct *p,
8414 struct spoolss_AddForm *r)
8416 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8418 WERROR status = WERR_OK;
8420 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8422 DEBUG(5,("_spoolss_AddForm\n"));
8425 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8426 OUR_HANDLE(r->in.handle)));
8430 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8431 and not a printer admin, then fail */
8433 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8434 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8435 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8436 p->session_info->info3->base.domain.string,
8438 p->session_info->security_token,
8439 lp_printer_admin(snum))) {
8440 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8441 return WERR_ACCESS_DENIED;
8444 switch (form->flags) {
8445 case SPOOLSS_FORM_USER:
8446 case SPOOLSS_FORM_BUILTIN:
8447 case SPOOLSS_FORM_PRINTER:
8450 return WERR_INVALID_PARAM;
8453 status = winreg_printer_addform1(p->mem_ctx,
8454 get_session_info_system(),
8457 if (!W_ERROR_IS_OK(status)) {
8462 * ChangeID must always be set if this is a printer
8464 if (Printer->printer_type == SPLHND_PRINTER) {
8465 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8469 status = winreg_printer_update_changeid(p->mem_ctx,
8470 get_session_info_system(),
8472 lp_const_servicename(snum));
8473 if (!W_ERROR_IS_OK(status)) {
8481 /****************************************************************
8483 ****************************************************************/
8485 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8486 struct spoolss_DeleteForm *r)
8488 const char *form_name = r->in.form_name;
8489 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8491 WERROR status = WERR_OK;
8493 DEBUG(5,("_spoolss_DeleteForm\n"));
8496 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8497 OUR_HANDLE(r->in.handle)));
8501 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8502 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8503 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8504 p->session_info->info3->base.domain.string,
8506 p->session_info->security_token,
8507 lp_printer_admin(snum))) {
8508 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8509 return WERR_ACCESS_DENIED;
8512 status = winreg_printer_deleteform1(p->mem_ctx,
8513 get_session_info_system(),
8516 if (!W_ERROR_IS_OK(status)) {
8521 * ChangeID must always be set if this is a printer
8523 if (Printer->printer_type == SPLHND_PRINTER) {
8524 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8528 status = winreg_printer_update_changeid(p->mem_ctx,
8529 get_session_info_system(),
8531 lp_const_servicename(snum));
8532 if (!W_ERROR_IS_OK(status)) {
8540 /****************************************************************
8542 ****************************************************************/
8544 WERROR _spoolss_SetForm(struct pipes_struct *p,
8545 struct spoolss_SetForm *r)
8547 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8548 const char *form_name = r->in.form_name;
8550 WERROR status = WERR_OK;
8552 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8554 DEBUG(5,("_spoolss_SetForm\n"));
8557 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8558 OUR_HANDLE(r->in.handle)));
8562 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8563 and not a printer admin, then fail */
8565 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8566 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8567 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8568 p->session_info->info3->base.domain.string,
8570 p->session_info->security_token,
8571 lp_printer_admin(snum))) {
8572 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8573 return WERR_ACCESS_DENIED;
8576 status = winreg_printer_setform1(p->mem_ctx,
8577 get_session_info_system(),
8581 if (!W_ERROR_IS_OK(status)) {
8586 * ChangeID must always be set if this is a printer
8588 if (Printer->printer_type == SPLHND_PRINTER) {
8589 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8593 status = winreg_printer_update_changeid(p->mem_ctx,
8594 get_session_info_system(),
8596 lp_const_servicename(snum));
8597 if (!W_ERROR_IS_OK(status)) {
8605 /****************************************************************************
8606 fill_print_processor1
8607 ****************************************************************************/
8609 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8610 struct spoolss_PrintProcessorInfo1 *r,
8611 const char *print_processor_name)
8613 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8614 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8619 /****************************************************************************
8620 enumprintprocessors level 1.
8621 ****************************************************************************/
8623 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8624 union spoolss_PrintProcessorInfo **info_p,
8627 union spoolss_PrintProcessorInfo *info;
8630 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8631 W_ERROR_HAVE_NO_MEMORY(info);
8635 result = fill_print_processor1(info, &info[0].info1, "winprint");
8636 if (!W_ERROR_IS_OK(result)) {
8641 if (!W_ERROR_IS_OK(result)) {
8652 /****************************************************************
8653 _spoolss_EnumPrintProcessors
8654 ****************************************************************/
8656 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8657 struct spoolss_EnumPrintProcessors *r)
8661 /* that's an [in out] buffer */
8663 if (!r->in.buffer && (r->in.offered != 0)) {
8664 return WERR_INVALID_PARAM;
8667 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8670 * Enumerate the print processors ...
8672 * Just reply with "winprint", to keep NT happy
8673 * and I can use my nice printer checker.
8678 *r->out.info = NULL;
8680 if (!get_short_archi(r->in.environment)) {
8681 return WERR_INVALID_ENVIRONMENT;
8684 switch (r->in.level) {
8686 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8690 return WERR_UNKNOWN_LEVEL;
8693 if (!W_ERROR_IS_OK(result)) {
8697 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8698 spoolss_EnumPrintProcessors,
8699 *r->out.info, r->in.level,
8701 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8702 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8704 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8707 /****************************************************************************
8708 fill_printprocdatatype1
8709 ****************************************************************************/
8711 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8712 struct spoolss_PrintProcDataTypesInfo1 *r,
8713 const char *name_array)
8715 r->name_array = talloc_strdup(mem_ctx, name_array);
8716 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8721 /****************************************************************************
8722 enumprintprocdatatypes level 1.
8723 ****************************************************************************/
8725 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8726 union spoolss_PrintProcDataTypesInfo **info_p,
8730 union spoolss_PrintProcDataTypesInfo *info;
8732 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8733 W_ERROR_HAVE_NO_MEMORY(info);
8737 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8738 if (!W_ERROR_IS_OK(result)) {
8743 if (!W_ERROR_IS_OK(result)) {
8754 /****************************************************************
8755 _spoolss_EnumPrintProcDataTypes
8756 ****************************************************************/
8758 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8759 struct spoolss_EnumPrintProcDataTypes *r)
8763 /* that's an [in out] buffer */
8765 if (!r->in.buffer && (r->in.offered != 0)) {
8766 return WERR_INVALID_PARAM;
8769 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8773 *r->out.info = NULL;
8775 if (r->in.print_processor_name == NULL ||
8776 !strequal(r->in.print_processor_name, "winprint")) {
8777 return WERR_UNKNOWN_PRINTPROCESSOR;
8780 switch (r->in.level) {
8782 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8786 return WERR_UNKNOWN_LEVEL;
8789 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8790 spoolss_EnumPrintProcDataTypes,
8791 *r->out.info, r->in.level,
8793 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8794 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8796 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8799 /****************************************************************************
8801 ****************************************************************************/
8803 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8804 struct spoolss_MonitorInfo1 *r,
8805 const char *monitor_name)
8807 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8808 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8813 /****************************************************************************
8815 ****************************************************************************/
8817 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8818 struct spoolss_MonitorInfo2 *r,
8819 const char *monitor_name,
8820 const char *environment,
8821 const char *dll_name)
8823 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8824 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8825 r->environment = talloc_strdup(mem_ctx, environment);
8826 W_ERROR_HAVE_NO_MEMORY(r->environment);
8827 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8828 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8833 /****************************************************************************
8834 enumprintmonitors level 1.
8835 ****************************************************************************/
8837 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8838 union spoolss_MonitorInfo **info_p,
8841 union spoolss_MonitorInfo *info;
8842 WERROR result = WERR_OK;
8844 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8845 W_ERROR_HAVE_NO_MEMORY(info);
8849 result = fill_monitor_1(info, &info[0].info1,
8851 if (!W_ERROR_IS_OK(result)) {
8855 result = fill_monitor_1(info, &info[1].info1,
8857 if (!W_ERROR_IS_OK(result)) {
8862 if (!W_ERROR_IS_OK(result)) {
8873 /****************************************************************************
8874 enumprintmonitors level 2.
8875 ****************************************************************************/
8877 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8878 union spoolss_MonitorInfo **info_p,
8881 union spoolss_MonitorInfo *info;
8882 WERROR result = WERR_OK;
8884 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8885 W_ERROR_HAVE_NO_MEMORY(info);
8889 result = fill_monitor_2(info, &info[0].info2,
8891 "Windows NT X86", /* FIXME */
8893 if (!W_ERROR_IS_OK(result)) {
8897 result = fill_monitor_2(info, &info[1].info2,
8899 "Windows NT X86", /* FIXME */
8901 if (!W_ERROR_IS_OK(result)) {
8906 if (!W_ERROR_IS_OK(result)) {
8917 /****************************************************************
8918 _spoolss_EnumMonitors
8919 ****************************************************************/
8921 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8922 struct spoolss_EnumMonitors *r)
8926 /* that's an [in out] buffer */
8928 if (!r->in.buffer && (r->in.offered != 0)) {
8929 return WERR_INVALID_PARAM;
8932 DEBUG(5,("_spoolss_EnumMonitors\n"));
8935 * Enumerate the print monitors ...
8937 * Just reply with "Local Port", to keep NT happy
8938 * and I can use my nice printer checker.
8943 *r->out.info = NULL;
8945 switch (r->in.level) {
8947 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8951 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8955 return WERR_UNKNOWN_LEVEL;
8958 if (!W_ERROR_IS_OK(result)) {
8962 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8963 spoolss_EnumMonitors,
8964 *r->out.info, r->in.level,
8966 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8967 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8969 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8972 /****************************************************************************
8973 ****************************************************************************/
8975 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8976 const print_queue_struct *queue,
8977 int count, int snum,
8978 struct spoolss_PrinterInfo2 *pinfo2,
8980 struct spoolss_JobInfo1 *r)
8985 for (i=0; i<count; i++) {
8986 if (queue[i].job == (int)jobid) {
8992 if (found == false) {
8993 /* NT treats not found as bad param... yet another bad choice */
8994 return WERR_INVALID_PARAM;
8997 return fill_job_info1(mem_ctx,
9005 /****************************************************************************
9006 ****************************************************************************/
9008 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9009 const print_queue_struct *queue,
9010 int count, int snum,
9011 struct spoolss_PrinterInfo2 *pinfo2,
9013 struct spoolss_JobInfo2 *r)
9017 struct spoolss_DeviceMode *devmode;
9020 for (i=0; i<count; i++) {
9021 if (queue[i].job == (int)jobid) {
9027 if (found == false) {
9028 /* NT treats not found as bad param... yet another bad
9030 return WERR_INVALID_PARAM;
9034 * if the print job does not have a DEVMODE associated with it,
9035 * just use the one for the printer. A NULL devicemode is not
9036 * a failure condition
9039 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9041 result = spoolss_create_default_devmode(mem_ctx,
9042 pinfo2->printername,
9044 if (!W_ERROR_IS_OK(result)) {
9045 DEBUG(3, ("Can't proceed w/o a devmode!"));
9050 return fill_job_info2(mem_ctx,
9059 /****************************************************************
9061 ****************************************************************/
9063 WERROR _spoolss_GetJob(struct pipes_struct *p,
9064 struct spoolss_GetJob *r)
9066 WERROR result = WERR_OK;
9067 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9070 print_queue_struct *queue = NULL;
9071 print_status_struct prt_status;
9073 /* that's an [in out] buffer */
9075 if (!r->in.buffer && (r->in.offered != 0)) {
9076 return WERR_INVALID_PARAM;
9079 DEBUG(5,("_spoolss_GetJob\n"));
9083 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9087 result = winreg_get_printer(p->mem_ctx,
9088 get_session_info_system(),
9090 lp_const_servicename(snum),
9092 if (!W_ERROR_IS_OK(result)) {
9096 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9098 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9099 count, prt_status.status, prt_status.message));
9101 switch (r->in.level) {
9103 result = getjob_level_1(p->mem_ctx,
9104 queue, count, snum, pinfo2,
9105 r->in.job_id, &r->out.info->info1);
9108 result = getjob_level_2(p->mem_ctx,
9109 queue, count, snum, pinfo2,
9110 r->in.job_id, &r->out.info->info2);
9113 result = WERR_UNKNOWN_LEVEL;
9118 TALLOC_FREE(pinfo2);
9120 if (!W_ERROR_IS_OK(result)) {
9121 TALLOC_FREE(r->out.info);
9125 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9127 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9129 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9132 /****************************************************************
9133 _spoolss_GetPrinterDataEx
9134 ****************************************************************/
9136 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9137 struct spoolss_GetPrinterDataEx *r)
9140 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9141 const char *printer;
9143 WERROR result = WERR_OK;
9145 enum winreg_Type val_type;
9150 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9152 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9153 r->in.key_name, r->in.value_name));
9155 /* in case of problem, return some default values */
9158 *r->out.type = REG_NONE;
9161 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9162 OUR_HANDLE(r->in.handle)));
9163 result = WERR_BADFID;
9167 /* Is the handle to a printer or to the server? */
9169 if (Printer->printer_type == SPLHND_SERVER) {
9171 union spoolss_PrinterData data;
9173 result = getprinterdata_printer_server(p->mem_ctx,
9177 if (!W_ERROR_IS_OK(result)) {
9181 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9182 *r->out.type, &data);
9183 if (!W_ERROR_IS_OK(result)) {
9187 *r->out.needed = blob.length;
9189 if (r->in.offered >= *r->out.needed) {
9190 memcpy(r->out.data, blob.data, blob.length);
9193 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9196 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9199 printer = lp_const_servicename(snum);
9201 /* check to see if the keyname is valid */
9202 if (!strlen(r->in.key_name)) {
9203 return WERR_INVALID_PARAM;
9206 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9207 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9208 strequal(r->in.value_name, "ChangeId")) {
9209 *r->out.type = REG_DWORD;
9211 if (r->in.offered >= *r->out.needed) {
9212 uint32_t changeid = 0;
9214 result = winreg_printer_get_changeid(p->mem_ctx,
9215 get_session_info_system(),
9219 if (!W_ERROR_IS_OK(result)) {
9223 SIVAL(r->out.data, 0, changeid);
9229 result = winreg_get_printer_dataex(p->mem_ctx,
9230 get_session_info_system(),
9238 if (!W_ERROR_IS_OK(result)) {
9242 *r->out.needed = val_size;
9243 *r->out.type = val_type;
9245 if (r->in.offered >= *r->out.needed) {
9246 memcpy(r->out.data, val_data, val_size);
9250 /* retain type when returning WERR_MORE_DATA */
9251 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9253 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9256 /****************************************************************
9257 _spoolss_SetPrinterDataEx
9258 ****************************************************************/
9260 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9261 struct spoolss_SetPrinterDataEx *r)
9263 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9265 WERROR result = WERR_OK;
9266 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9269 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9271 /* From MSDN documentation of SetPrinterDataEx: pass request to
9272 SetPrinterData if key is "PrinterDriverData" */
9275 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9276 OUR_HANDLE(r->in.handle)));
9280 if (Printer->printer_type == SPLHND_SERVER) {
9281 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9282 "Not implemented for server handles yet\n"));
9283 return WERR_INVALID_PARAM;
9286 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9291 * Access check : NT returns "access denied" if you make a
9292 * SetPrinterData call without the necessary privildge.
9293 * we were originally returning OK if nothing changed
9294 * which made Win2k issue **a lot** of SetPrinterData
9295 * when connecting to a printer --jerry
9298 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9299 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9300 "change denied by handle access permissions\n"));
9301 return WERR_ACCESS_DENIED;
9304 result = winreg_get_printer(Printer,
9305 get_session_info_system(),
9307 lp_servicename(snum),
9309 if (!W_ERROR_IS_OK(result)) {
9313 /* check for OID in valuename */
9315 oid_string = strchr(r->in.value_name, ',');
9321 /* save the registry data */
9323 result = winreg_set_printer_dataex(p->mem_ctx,
9324 get_session_info_system(),
9333 if (W_ERROR_IS_OK(result)) {
9334 /* save the OID if one was specified */
9336 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9337 r->in.key_name, SPOOL_OID_KEY);
9339 result = WERR_NOMEM;
9344 * I'm not checking the status here on purpose. Don't know
9345 * if this is right, but I'm returning the status from the
9346 * previous set_printer_dataex() call. I have no idea if
9347 * this is right. --jerry
9349 winreg_set_printer_dataex(p->mem_ctx,
9350 get_session_info_system(),
9356 (uint8_t *) oid_string,
9357 strlen(oid_string) + 1);
9360 result = winreg_printer_update_changeid(p->mem_ctx,
9361 get_session_info_system(),
9363 lp_const_servicename(snum));
9368 talloc_free(pinfo2);
9372 /****************************************************************
9373 _spoolss_DeletePrinterDataEx
9374 ****************************************************************/
9376 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9377 struct spoolss_DeletePrinterDataEx *r)
9379 const char *printer;
9381 WERROR status = WERR_OK;
9382 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9384 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9387 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9388 "Invalid handle (%s:%u:%u).\n",
9389 OUR_HANDLE(r->in.handle)));
9393 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9394 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9395 "printer properties change denied by handle\n"));
9396 return WERR_ACCESS_DENIED;
9399 if (!r->in.value_name || !r->in.key_name) {
9403 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9406 printer = lp_const_servicename(snum);
9408 status = winreg_delete_printer_dataex(p->mem_ctx,
9409 get_session_info_system(),
9414 if (W_ERROR_IS_OK(status)) {
9415 status = winreg_printer_update_changeid(p->mem_ctx,
9416 get_session_info_system(),
9424 /****************************************************************
9425 _spoolss_EnumPrinterKey
9426 ****************************************************************/
9428 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9429 struct spoolss_EnumPrinterKey *r)
9432 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9434 WERROR result = WERR_BADFILE;
9435 const char **array = NULL;
9438 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9441 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9442 OUR_HANDLE(r->in.handle)));
9446 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9450 result = winreg_enum_printer_key(p->mem_ctx,
9451 get_session_info_system(),
9453 lp_const_servicename(snum),
9457 if (!W_ERROR_IS_OK(result)) {
9461 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9462 result = WERR_NOMEM;
9466 *r->out._ndr_size = r->in.offered / 2;
9467 *r->out.needed = blob.length;
9469 if (r->in.offered < *r->out.needed) {
9470 result = WERR_MORE_DATA;
9473 r->out.key_buffer->string_array = array;
9477 if (!W_ERROR_IS_OK(result)) {
9479 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9487 /****************************************************************
9488 _spoolss_DeletePrinterKey
9489 ****************************************************************/
9491 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9492 struct spoolss_DeletePrinterKey *r)
9494 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9497 const char *printer;
9499 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9502 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9503 OUR_HANDLE(r->in.handle)));
9507 /* if keyname == NULL, return error */
9508 if ( !r->in.key_name )
9509 return WERR_INVALID_PARAM;
9511 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9515 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9516 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9517 "printer properties change denied by handle\n"));
9518 return WERR_ACCESS_DENIED;
9521 printer = lp_const_servicename(snum);
9523 /* delete the key and all subkeys */
9524 status = winreg_delete_printer_key(p->mem_ctx,
9525 get_session_info_system(),
9529 if (W_ERROR_IS_OK(status)) {
9530 status = winreg_printer_update_changeid(p->mem_ctx,
9531 get_session_info_system(),
9539 /****************************************************************
9540 _spoolss_EnumPrinterDataEx
9541 ****************************************************************/
9543 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9544 struct spoolss_EnumPrinterDataEx *r)
9547 struct spoolss_PrinterEnumValues *info = NULL;
9548 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9552 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9556 *r->out.info = NULL;
9559 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9560 OUR_HANDLE(r->in.handle)));
9565 * first check for a keyname of NULL or "". Win2k seems to send
9566 * this a lot and we should send back WERR_INVALID_PARAM
9567 * no need to spend time looking up the printer in this case.
9571 if (!strlen(r->in.key_name)) {
9572 result = WERR_INVALID_PARAM;
9576 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9580 /* now look for a match on the key name */
9581 result = winreg_enum_printer_dataex(p->mem_ctx,
9582 get_session_info_system(),
9584 lp_const_servicename(snum),
9588 if (!W_ERROR_IS_OK(result)) {
9592 #if 0 /* FIXME - gd */
9593 /* housekeeping information in the reply */
9595 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9596 * the hand marshalled container size is a multiple
9597 * of 4 bytes for RPC alignment.
9601 needed += 4-(needed % 4);
9604 *r->out.count = count;
9605 *r->out.info = info;
9608 if (!W_ERROR_IS_OK(result)) {
9612 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9613 spoolss_EnumPrinterDataEx,
9616 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9617 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9619 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9622 /****************************************************************************
9623 ****************************************************************************/
9625 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9626 const char *servername,
9627 const char *environment,
9628 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9633 werr = compose_spoolss_server_path(mem_ctx,
9636 SPOOLSS_PRTPROCS_PATH,
9638 if (!W_ERROR_IS_OK(werr)) {
9642 DEBUG(4,("print processor directory: [%s]\n", path));
9644 r->directory_name = path;
9649 /****************************************************************
9650 _spoolss_GetPrintProcessorDirectory
9651 ****************************************************************/
9653 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9654 struct spoolss_GetPrintProcessorDirectory *r)
9657 char *prnproc_share = NULL;
9658 bool prnproc_share_exists = false;
9661 /* that's an [in out] buffer */
9663 if (!r->in.buffer && (r->in.offered != 0)) {
9664 return WERR_INVALID_PARAM;
9667 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9672 /* r->in.level is ignored */
9674 /* We always should reply with a local print processor directory so that
9675 * users are not forced to have a [prnproc$] share on the Samba spoolss
9676 * server, if users decide to do so, lets announce it though - Guenther */
9678 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9679 if (!prnproc_share) {
9683 prnproc_share_exists = true;
9686 result = getprintprocessordirectory_level_1(p->mem_ctx,
9687 prnproc_share_exists ? r->in.server : NULL,
9689 &r->out.info->info1);
9690 if (!W_ERROR_IS_OK(result)) {
9691 TALLOC_FREE(r->out.info);
9695 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9696 r->out.info, r->in.level);
9697 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9699 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9702 /*******************************************************************
9703 ********************************************************************/
9705 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9706 const char *dllname)
9708 enum ndr_err_code ndr_err;
9709 struct spoolss_MonitorUi ui;
9711 ui.dll_name = dllname;
9713 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9714 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9715 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9716 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9718 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9721 /*******************************************************************
9722 Streams the monitor UI DLL name in UNICODE
9723 *******************************************************************/
9725 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9726 struct security_token *token, DATA_BLOB *in,
9727 DATA_BLOB *out, uint32_t *needed)
9729 const char *dllname = "tcpmonui.dll";
9731 *needed = (strlen(dllname)+1) * 2;
9733 if (out->length < *needed) {
9734 return WERR_INSUFFICIENT_BUFFER;
9737 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9744 /*******************************************************************
9745 ********************************************************************/
9747 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9748 struct spoolss_PortData1 *port1,
9749 const DATA_BLOB *buf)
9751 enum ndr_err_code ndr_err;
9752 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9753 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9754 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9755 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9757 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9760 /*******************************************************************
9761 ********************************************************************/
9763 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9764 struct spoolss_PortData2 *port2,
9765 const DATA_BLOB *buf)
9767 enum ndr_err_code ndr_err;
9768 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9769 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9770 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9771 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9773 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9776 /*******************************************************************
9777 Create a new TCP/IP port
9778 *******************************************************************/
9780 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9781 struct security_token *token, DATA_BLOB *in,
9782 DATA_BLOB *out, uint32_t *needed)
9784 struct spoolss_PortData1 port1;
9785 struct spoolss_PortData2 port2;
9786 char *device_uri = NULL;
9789 const char *portname;
9790 const char *hostaddress;
9792 uint32_t port_number;
9795 /* peek for spoolss_PortData version */
9797 if (!in || (in->length < (128 + 4))) {
9798 return WERR_GENERAL_FAILURE;
9801 version = IVAL(in->data, 128);
9807 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9811 portname = port1.portname;
9812 hostaddress = port1.hostaddress;
9813 queue = port1.queue;
9814 protocol = port1.protocol;
9815 port_number = port1.port_number;
9821 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9825 portname = port2.portname;
9826 hostaddress = port2.hostaddress;
9827 queue = port2.queue;
9828 protocol = port2.protocol;
9829 port_number = port2.port_number;
9833 DEBUG(1,("xcvtcp_addport: "
9834 "unknown version of port_data: %d\n", version));
9835 return WERR_UNKNOWN_PORT;
9838 /* create the device URI and call the add_port_hook() */
9841 case PROTOCOL_RAWTCP_TYPE:
9842 device_uri = talloc_asprintf(mem_ctx,
9843 "socket://%s:%d/", hostaddress,
9847 case PROTOCOL_LPR_TYPE:
9848 device_uri = talloc_asprintf(mem_ctx,
9849 "lpr://%s/%s", hostaddress, queue );
9853 return WERR_UNKNOWN_PORT;
9860 return add_port_hook(mem_ctx, token, portname, device_uri);
9863 /*******************************************************************
9864 *******************************************************************/
9866 struct xcv_api_table xcvtcp_cmds[] = {
9867 { "MonitorUI", xcvtcp_monitorui },
9868 { "AddPort", xcvtcp_addport},
9872 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9873 struct security_token *token, const char *command,
9880 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9882 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9883 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9884 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9887 return WERR_BADFUNC;
9890 /*******************************************************************
9891 *******************************************************************/
9892 #if 0 /* don't support management using the "Local Port" monitor */
9894 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9895 struct security_token *token, DATA_BLOB *in,
9896 DATA_BLOB *out, uint32_t *needed)
9898 const char *dllname = "localui.dll";
9900 *needed = (strlen(dllname)+1) * 2;
9902 if (out->length < *needed) {
9903 return WERR_INSUFFICIENT_BUFFER;
9906 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9913 /*******************************************************************
9914 *******************************************************************/
9916 struct xcv_api_table xcvlocal_cmds[] = {
9917 { "MonitorUI", xcvlocal_monitorui },
9921 struct xcv_api_table xcvlocal_cmds[] = {
9928 /*******************************************************************
9929 *******************************************************************/
9931 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9932 struct security_token *token, const char *command,
9933 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9938 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9940 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9941 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9942 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9944 return WERR_BADFUNC;
9947 /****************************************************************
9949 ****************************************************************/
9951 WERROR _spoolss_XcvData(struct pipes_struct *p,
9952 struct spoolss_XcvData *r)
9954 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9955 DATA_BLOB out_data = data_blob_null;
9959 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9960 OUR_HANDLE(r->in.handle)));
9964 /* Has to be a handle to the TCP/IP port monitor */
9966 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9967 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9971 /* requires administrative access to the server */
9973 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9974 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9975 return WERR_ACCESS_DENIED;
9978 /* Allocate the outgoing buffer */
9980 if (r->in.out_data_size) {
9981 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9982 if (out_data.data == NULL) {
9987 switch ( Printer->printer_type ) {
9988 case SPLHND_PORTMON_TCP:
9989 werror = process_xcvtcp_command(p->mem_ctx,
9990 p->session_info->security_token,
9991 r->in.function_name,
9992 &r->in.in_data, &out_data,
9995 case SPLHND_PORTMON_LOCAL:
9996 werror = process_xcvlocal_command(p->mem_ctx,
9997 p->session_info->security_token,
9998 r->in.function_name,
9999 &r->in.in_data, &out_data,
10003 werror = WERR_INVALID_PRINT_MONITOR;
10006 if (!W_ERROR_IS_OK(werror)) {
10010 *r->out.status_code = 0;
10012 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10013 memcpy(r->out.out_data, out_data.data,
10014 MIN(r->in.out_data_size, out_data.length));
10020 /****************************************************************
10021 _spoolss_AddPrintProcessor
10022 ****************************************************************/
10024 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10025 struct spoolss_AddPrintProcessor *r)
10027 /* for now, just indicate success and ignore the add. We'll
10028 automatically set the winprint processor for printer
10029 entries later. Used to debug the LexMark Optra S 1855 PCL
10035 /****************************************************************
10037 ****************************************************************/
10039 WERROR _spoolss_AddPort(struct pipes_struct *p,
10040 struct spoolss_AddPort *r)
10042 /* do what w2k3 does */
10044 return WERR_NOT_SUPPORTED;
10047 /****************************************************************
10048 _spoolss_GetPrinterDriver
10049 ****************************************************************/
10051 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10052 struct spoolss_GetPrinterDriver *r)
10054 p->rng_fault_state = true;
10055 return WERR_NOT_SUPPORTED;
10058 /****************************************************************
10059 _spoolss_ReadPrinter
10060 ****************************************************************/
10062 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10063 struct spoolss_ReadPrinter *r)
10065 p->rng_fault_state = true;
10066 return WERR_NOT_SUPPORTED;
10069 /****************************************************************
10070 _spoolss_WaitForPrinterChange
10071 ****************************************************************/
10073 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10074 struct spoolss_WaitForPrinterChange *r)
10076 p->rng_fault_state = true;
10077 return WERR_NOT_SUPPORTED;
10080 /****************************************************************
10081 _spoolss_ConfigurePort
10082 ****************************************************************/
10084 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10085 struct spoolss_ConfigurePort *r)
10087 p->rng_fault_state = true;
10088 return WERR_NOT_SUPPORTED;
10091 /****************************************************************
10092 _spoolss_DeletePort
10093 ****************************************************************/
10095 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10096 struct spoolss_DeletePort *r)
10098 p->rng_fault_state = true;
10099 return WERR_NOT_SUPPORTED;
10102 /****************************************************************
10103 _spoolss_CreatePrinterIC
10104 ****************************************************************/
10106 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10107 struct spoolss_CreatePrinterIC *r)
10109 p->rng_fault_state = true;
10110 return WERR_NOT_SUPPORTED;
10113 /****************************************************************
10114 _spoolss_PlayGDIScriptOnPrinterIC
10115 ****************************************************************/
10117 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10118 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10120 p->rng_fault_state = true;
10121 return WERR_NOT_SUPPORTED;
10124 /****************************************************************
10125 _spoolss_DeletePrinterIC
10126 ****************************************************************/
10128 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10129 struct spoolss_DeletePrinterIC *r)
10131 p->rng_fault_state = true;
10132 return WERR_NOT_SUPPORTED;
10135 /****************************************************************
10136 _spoolss_AddPrinterConnection
10137 ****************************************************************/
10139 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10140 struct spoolss_AddPrinterConnection *r)
10142 p->rng_fault_state = true;
10143 return WERR_NOT_SUPPORTED;
10146 /****************************************************************
10147 _spoolss_DeletePrinterConnection
10148 ****************************************************************/
10150 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10151 struct spoolss_DeletePrinterConnection *r)
10153 p->rng_fault_state = true;
10154 return WERR_NOT_SUPPORTED;
10157 /****************************************************************
10158 _spoolss_PrinterMessageBox
10159 ****************************************************************/
10161 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10162 struct spoolss_PrinterMessageBox *r)
10164 p->rng_fault_state = true;
10165 return WERR_NOT_SUPPORTED;
10168 /****************************************************************
10169 _spoolss_AddMonitor
10170 ****************************************************************/
10172 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10173 struct spoolss_AddMonitor *r)
10175 p->rng_fault_state = true;
10176 return WERR_NOT_SUPPORTED;
10179 /****************************************************************
10180 _spoolss_DeleteMonitor
10181 ****************************************************************/
10183 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10184 struct spoolss_DeleteMonitor *r)
10186 p->rng_fault_state = true;
10187 return WERR_NOT_SUPPORTED;
10190 /****************************************************************
10191 _spoolss_DeletePrintProcessor
10192 ****************************************************************/
10194 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10195 struct spoolss_DeletePrintProcessor *r)
10197 p->rng_fault_state = true;
10198 return WERR_NOT_SUPPORTED;
10201 /****************************************************************
10202 _spoolss_AddPrintProvidor
10203 ****************************************************************/
10205 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10206 struct spoolss_AddPrintProvidor *r)
10208 p->rng_fault_state = true;
10209 return WERR_NOT_SUPPORTED;
10212 /****************************************************************
10213 _spoolss_DeletePrintProvidor
10214 ****************************************************************/
10216 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10217 struct spoolss_DeletePrintProvidor *r)
10219 p->rng_fault_state = true;
10220 return WERR_NOT_SUPPORTED;
10223 /****************************************************************
10224 _spoolss_FindFirstPrinterChangeNotification
10225 ****************************************************************/
10227 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10228 struct spoolss_FindFirstPrinterChangeNotification *r)
10230 p->rng_fault_state = true;
10231 return WERR_NOT_SUPPORTED;
10234 /****************************************************************
10235 _spoolss_FindNextPrinterChangeNotification
10236 ****************************************************************/
10238 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10239 struct spoolss_FindNextPrinterChangeNotification *r)
10241 p->rng_fault_state = true;
10242 return WERR_NOT_SUPPORTED;
10245 /****************************************************************
10246 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10247 ****************************************************************/
10249 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10250 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10252 p->rng_fault_state = true;
10253 return WERR_NOT_SUPPORTED;
10256 /****************************************************************
10257 _spoolss_ReplyOpenPrinter
10258 ****************************************************************/
10260 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10261 struct spoolss_ReplyOpenPrinter *r)
10263 p->rng_fault_state = true;
10264 return WERR_NOT_SUPPORTED;
10267 /****************************************************************
10268 _spoolss_RouterReplyPrinter
10269 ****************************************************************/
10271 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10272 struct spoolss_RouterReplyPrinter *r)
10274 p->rng_fault_state = true;
10275 return WERR_NOT_SUPPORTED;
10278 /****************************************************************
10279 _spoolss_ReplyClosePrinter
10280 ****************************************************************/
10282 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10283 struct spoolss_ReplyClosePrinter *r)
10285 p->rng_fault_state = true;
10286 return WERR_NOT_SUPPORTED;
10289 /****************************************************************
10291 ****************************************************************/
10293 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10294 struct spoolss_AddPortEx *r)
10296 p->rng_fault_state = true;
10297 return WERR_NOT_SUPPORTED;
10300 /****************************************************************
10301 _spoolss_RouterFindFirstPrinterChangeNotification
10302 ****************************************************************/
10304 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10305 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10307 p->rng_fault_state = true;
10308 return WERR_NOT_SUPPORTED;
10311 /****************************************************************
10312 _spoolss_SpoolerInit
10313 ****************************************************************/
10315 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10316 struct spoolss_SpoolerInit *r)
10318 p->rng_fault_state = true;
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_ResetPrinterEx
10324 ****************************************************************/
10326 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10327 struct spoolss_ResetPrinterEx *r)
10329 p->rng_fault_state = true;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_RouterReplyPrinterEx
10335 ****************************************************************/
10337 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10338 struct spoolss_RouterReplyPrinterEx *r)
10340 p->rng_fault_state = true;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10346 ****************************************************************/
10348 WERROR _spoolss_44(struct pipes_struct *p,
10349 struct spoolss_44 *r)
10351 p->rng_fault_state = true;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10357 ****************************************************************/
10359 WERROR _spoolss_SetPort(struct pipes_struct *p,
10360 struct spoolss_SetPort *r)
10362 p->rng_fault_state = true;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10368 ****************************************************************/
10370 WERROR _spoolss_4a(struct pipes_struct *p,
10371 struct spoolss_4a *r)
10373 p->rng_fault_state = true;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10379 ****************************************************************/
10381 WERROR _spoolss_4b(struct pipes_struct *p,
10382 struct spoolss_4b *r)
10384 p->rng_fault_state = true;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10390 ****************************************************************/
10392 WERROR _spoolss_4c(struct pipes_struct *p,
10393 struct spoolss_4c *r)
10395 p->rng_fault_state = true;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10401 ****************************************************************/
10403 WERROR _spoolss_53(struct pipes_struct *p,
10404 struct spoolss_53 *r)
10406 p->rng_fault_state = true;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10411 _spoolss_AddPerMachineConnection
10412 ****************************************************************/
10414 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10415 struct spoolss_AddPerMachineConnection *r)
10417 p->rng_fault_state = true;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_DeletePerMachineConnection
10423 ****************************************************************/
10425 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10426 struct spoolss_DeletePerMachineConnection *r)
10428 p->rng_fault_state = true;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_EnumPerMachineConnections
10434 ****************************************************************/
10436 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10437 struct spoolss_EnumPerMachineConnections *r)
10439 p->rng_fault_state = true;
10440 return WERR_NOT_SUPPORTED;
10443 /****************************************************************
10445 ****************************************************************/
10447 WERROR _spoolss_5a(struct pipes_struct *p,
10448 struct spoolss_5a *r)
10450 p->rng_fault_state = true;
10451 return WERR_NOT_SUPPORTED;
10454 /****************************************************************
10456 ****************************************************************/
10458 WERROR _spoolss_5b(struct pipes_struct *p,
10459 struct spoolss_5b *r)
10461 p->rng_fault_state = true;
10462 return WERR_NOT_SUPPORTED;
10465 /****************************************************************
10467 ****************************************************************/
10469 WERROR _spoolss_5c(struct pipes_struct *p,
10470 struct spoolss_5c *r)
10472 p->rng_fault_state = true;
10473 return WERR_NOT_SUPPORTED;
10476 /****************************************************************
10478 ****************************************************************/
10480 WERROR _spoolss_5d(struct pipes_struct *p,
10481 struct spoolss_5d *r)
10483 p->rng_fault_state = true;
10484 return WERR_NOT_SUPPORTED;
10487 /****************************************************************
10489 ****************************************************************/
10491 WERROR _spoolss_5e(struct pipes_struct *p,
10492 struct spoolss_5e *r)
10494 p->rng_fault_state = true;
10495 return WERR_NOT_SUPPORTED;
10498 /****************************************************************
10500 ****************************************************************/
10502 WERROR _spoolss_5f(struct pipes_struct *p,
10503 struct spoolss_5f *r)
10505 p->rng_fault_state = true;
10506 return WERR_NOT_SUPPORTED;
10509 /****************************************************************
10511 ****************************************************************/
10513 WERROR _spoolss_60(struct pipes_struct *p,
10514 struct spoolss_60 *r)
10516 p->rng_fault_state = true;
10517 return WERR_NOT_SUPPORTED;
10520 /****************************************************************
10522 ****************************************************************/
10524 WERROR _spoolss_61(struct pipes_struct *p,
10525 struct spoolss_61 *r)
10527 p->rng_fault_state = true;
10528 return WERR_NOT_SUPPORTED;
10531 /****************************************************************
10533 ****************************************************************/
10535 WERROR _spoolss_62(struct pipes_struct *p,
10536 struct spoolss_62 *r)
10538 p->rng_fault_state = true;
10539 return WERR_NOT_SUPPORTED;
10542 /****************************************************************
10544 ****************************************************************/
10546 WERROR _spoolss_63(struct pipes_struct *p,
10547 struct spoolss_63 *r)
10549 p->rng_fault_state = true;
10550 return WERR_NOT_SUPPORTED;
10553 /****************************************************************
10555 ****************************************************************/
10557 WERROR _spoolss_64(struct pipes_struct *p,
10558 struct spoolss_64 *r)
10560 p->rng_fault_state = true;
10561 return WERR_NOT_SUPPORTED;
10564 /****************************************************************
10566 ****************************************************************/
10568 WERROR _spoolss_65(struct pipes_struct *p,
10569 struct spoolss_65 *r)
10571 p->rng_fault_state = true;
10572 return WERR_NOT_SUPPORTED;
10575 /****************************************************************
10576 _spoolss_GetCorePrinterDrivers
10577 ****************************************************************/
10579 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10580 struct spoolss_GetCorePrinterDrivers *r)
10582 p->rng_fault_state = true;
10583 return WERR_NOT_SUPPORTED;
10586 /****************************************************************
10588 ****************************************************************/
10590 WERROR _spoolss_67(struct pipes_struct *p,
10591 struct spoolss_67 *r)
10593 p->rng_fault_state = true;
10594 return WERR_NOT_SUPPORTED;
10597 /****************************************************************
10598 _spoolss_GetPrinterDriverPackagePath
10599 ****************************************************************/
10601 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10602 struct spoolss_GetPrinterDriverPackagePath *r)
10604 p->rng_fault_state = true;
10605 return WERR_NOT_SUPPORTED;
10608 /****************************************************************
10610 ****************************************************************/
10612 WERROR _spoolss_69(struct pipes_struct *p,
10613 struct spoolss_69 *r)
10615 p->rng_fault_state = true;
10616 return WERR_NOT_SUPPORTED;
10619 /****************************************************************
10621 ****************************************************************/
10623 WERROR _spoolss_6a(struct pipes_struct *p,
10624 struct spoolss_6a *r)
10626 p->rng_fault_state = true;
10627 return WERR_NOT_SUPPORTED;
10630 /****************************************************************
10632 ****************************************************************/
10634 WERROR _spoolss_6b(struct pipes_struct *p,
10635 struct spoolss_6b *r)
10637 p->rng_fault_state = true;
10638 return WERR_NOT_SUPPORTED;
10641 /****************************************************************
10643 ****************************************************************/
10645 WERROR _spoolss_6c(struct pipes_struct *p,
10646 struct spoolss_6c *r)
10648 p->rng_fault_state = true;
10649 return WERR_NOT_SUPPORTED;
10652 /****************************************************************
10654 ****************************************************************/
10656 WERROR _spoolss_6d(struct pipes_struct *p,
10657 struct spoolss_6d *r)
10659 p->rng_fault_state = true;
10660 return WERR_NOT_SUPPORTED;