2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
44 #include "../librpc/gen_ndr/netlogon.h"
46 #include "printing/notify.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "rpc_client/cli_winreg_spoolss.h"
58 /* macros stolen from s4 spoolss server */
59 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
60 ((info)?ndr_size_##fn(info, level, 0):0)
62 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
63 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
65 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
66 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
68 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71 #define DBGC_CLASS DBGC_RPC_SRV
73 #ifndef MAX_OPEN_PRINTER_EXS
74 #define MAX_OPEN_PRINTER_EXS 50
77 struct notify_back_channel;
79 /* structure to store the printer handles */
80 /* and a reference to what it's pointing to */
81 /* and the notify info asked about */
82 /* that's the central struct */
83 struct printer_handle {
84 struct printer_handle *prev, *next;
85 bool document_started;
87 uint32 jobid; /* jobid in printing backend */
89 const char *servername;
92 uint32 access_granted;
98 struct spoolss_NotifyOption *option;
99 struct policy_handle cli_hnd;
100 struct notify_back_channel *cli_chan;
102 /* are we in a FindNextPrinterChangeNotify() call? */
104 struct messaging_context *msg_ctx;
111 /* devmode sent in the OpenPrinter() call */
112 struct spoolss_DeviceMode *devmode;
114 /* TODO cache the printer info2 structure */
115 struct spoolss_PrinterInfo2 *info2;
119 static struct printer_handle *printers_list;
121 struct printer_session_counter {
122 struct printer_session_counter *next;
123 struct printer_session_counter *prev;
129 static struct printer_session_counter *counter_list;
131 struct notify_back_channel {
132 struct notify_back_channel *prev, *next;
134 /* associated client */
135 struct sockaddr_storage client_address;
137 /* print notify back-channel pipe handle*/
138 struct rpc_pipe_client *cli_pipe;
139 struct dcerpc_binding_handle *binding_handle;
140 uint32_t active_connections;
143 static struct notify_back_channel *back_channels;
145 /* Map generic permissions to printer object specific permissions */
147 const struct standard_mapping printer_std_mapping = {
154 /* Map generic permissions to print server object specific permissions */
156 const struct standard_mapping printserver_std_mapping = {
163 /* API table for Xcv Monitor functions */
165 struct xcv_api_table {
167 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 static void prune_printername_cache(void);
172 /********************************************************************
173 * Canonicalize servername.
174 ********************************************************************/
176 static const char *canon_servername(const char *servername)
178 const char *pservername = servername;
179 while (*pservername == '\\') {
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
192 return JOB_STATUS_PAUSED;
194 return JOB_STATUS_SPOOLING;
196 return JOB_STATUS_PRINTING;
198 return JOB_STATUS_ERROR;
200 return JOB_STATUS_DELETING;
202 return JOB_STATUS_OFFLINE;
204 return JOB_STATUS_PAPEROUT;
206 return JOB_STATUS_PRINTED;
208 return JOB_STATUS_DELETED;
210 return JOB_STATUS_BLOCKED_DEVQ;
211 case LPQ_USER_INTERVENTION:
212 return JOB_STATUS_USER_INTERVENTION;
217 static int nt_printq_status(int v)
221 return PRINTER_STATUS_PAUSED;
230 /***************************************************************************
231 Disconnect from the client
232 ****************************************************************************/
234 static void srv_spoolss_replycloseprinter(int snum,
235 struct printer_handle *prn_hnd)
241 * Tell the specific printing tdb we no longer want messages for this printer
242 * by deregistering our PID.
245 if (!print_notify_deregister_pid(snum)) {
246 DEBUG(0, ("Failed to register our pid for printer %s\n",
247 lp_const_servicename(snum)));
250 /* weird if the test succeeds !!! */
251 if (prn_hnd->notify.cli_chan == NULL ||
252 prn_hnd->notify.cli_chan->active_connections == 0) {
253 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
254 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
255 TALLOC_FREE(prn_hnd->notify.cli_chan);
259 status = dcerpc_spoolss_ReplyClosePrinter(
260 prn_hnd->notify.cli_chan->binding_handle,
262 &prn_hnd->notify.cli_hnd,
264 if (!NT_STATUS_IS_OK(status)) {
265 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
267 result = ntstatus_to_werror(status);
268 } else if (!W_ERROR_IS_OK(result)) {
269 DEBUG(0, ("reply_close_printer failed [%s].\n",
270 win_errstr(result)));
273 /* if it's the last connection, deconnect the IPC$ share */
274 if (prn_hnd->notify.cli_chan->active_connections == 1) {
276 prn_hnd->notify.cli_chan->binding_handle = NULL;
277 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
278 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
279 TALLOC_FREE(prn_hnd->notify.cli_chan);
281 if (prn_hnd->notify.msg_ctx != NULL) {
282 messaging_deregister(prn_hnd->notify.msg_ctx,
283 MSG_PRINTER_NOTIFY2, NULL);
286 * Tell the serverid.tdb we're no longer
287 * interested in printer notify messages.
290 serverid_register_msg_flags(
291 messaging_server_id(prn_hnd->notify.msg_ctx),
292 false, FLAG_MSG_PRINT_NOTIFY);
296 if (prn_hnd->notify.cli_chan) {
297 prn_hnd->notify.cli_chan->active_connections--;
298 prn_hnd->notify.cli_chan = NULL;
302 /****************************************************************************
303 Functions to free a printer entry datastruct.
304 ****************************************************************************/
306 static int printer_entry_destructor(struct printer_handle *Printer)
308 if (Printer->notify.cli_chan != NULL &&
309 Printer->notify.cli_chan->active_connections > 0) {
312 switch(Printer->printer_type) {
314 srv_spoolss_replycloseprinter(snum, Printer);
318 snum = print_queue_snum(Printer->sharename);
320 srv_spoolss_replycloseprinter(snum, Printer);
328 Printer->notify.flags=0;
329 Printer->notify.options=0;
330 Printer->notify.localmachine[0]='\0';
331 Printer->notify.printerlocal=0;
332 TALLOC_FREE(Printer->notify.option);
333 TALLOC_FREE(Printer->devmode);
335 /* Remove from the internal list. */
336 DLIST_REMOVE(printers_list, Printer);
340 /****************************************************************************
341 find printer index by handle
342 ****************************************************************************/
344 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
345 struct policy_handle *hnd)
347 struct printer_handle *find_printer = NULL;
349 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
350 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
357 /****************************************************************************
358 Close printer index by handle.
359 ****************************************************************************/
361 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
363 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
366 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
371 close_policy_hnd(p, hnd);
376 /****************************************************************************
377 Delete a printer given a handle.
378 ****************************************************************************/
380 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
381 const char *sharename,
382 struct messaging_context *msg_ctx)
384 char *cmd = lp_deleteprinter_cmd();
385 char *command = NULL;
387 bool is_print_op = false;
389 /* can't fail if we don't try */
394 command = talloc_asprintf(ctx,
401 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
403 DEBUG(10,("Running [%s]\n", command));
405 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
410 if ( (ret = smbrun(command, NULL)) == 0 ) {
411 /* Tell everyone we updated smb.conf. */
412 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
418 /********** END SePrintOperatorPrivlege BLOCK **********/
420 DEBUGADD(10,("returned [%d]\n", ret));
422 TALLOC_FREE(command);
425 return WERR_BADFID; /* What to return here? */
427 /* go ahead and re-read the services immediately */
429 reload_services(msg_ctx, -1, false);
432 if ( lp_servicenumber( sharename ) >= 0 )
433 return WERR_ACCESS_DENIED;
438 /****************************************************************************
439 Delete a printer given a handle.
440 ****************************************************************************/
442 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
444 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
448 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
454 * It turns out that Windows allows delete printer on a handle
455 * opened by an admin user, then used on a pipe handle created
456 * by an anonymous user..... but they're working on security.... riiight !
460 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
461 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
462 return WERR_ACCESS_DENIED;
465 /* this does not need a become root since the access check has been
466 done on the handle already */
468 result = winreg_delete_printer_key_internal(p->mem_ctx,
469 get_session_info_system(),
473 if (!W_ERROR_IS_OK(result)) {
474 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
478 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
479 Printer->sharename, p->msg_ctx);
480 if (!W_ERROR_IS_OK(result)) {
483 prune_printername_cache();
487 /****************************************************************************
488 Return the snum of a printer corresponding to an handle.
489 ****************************************************************************/
491 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
492 int *number, struct share_params **params)
494 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
497 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
502 switch (Printer->printer_type) {
504 DEBUG(4,("short name:%s\n", Printer->sharename));
505 *number = print_queue_snum(Printer->sharename);
506 return (*number != -1);
514 /****************************************************************************
515 Set printer handle type.
516 Check if it's \\server or \\server\printer
517 ****************************************************************************/
519 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
521 DEBUG(3,("Setting printer type=%s\n", handlename));
523 /* it's a print server */
524 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
525 DEBUGADD(4,("Printer is a print server\n"));
526 Printer->printer_type = SPLHND_SERVER;
528 /* it's a printer (set_printer_hnd_name() will handle port monitors */
530 DEBUGADD(4,("Printer is a printer\n"));
531 Printer->printer_type = SPLHND_PRINTER;
537 static void prune_printername_cache_fn(const char *key, const char *value,
538 time_t timeout, void *private_data)
543 static void prune_printername_cache(void)
545 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
548 /****************************************************************************
549 Set printer handle name.. Accept names like \\server, \\server\printer,
550 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
551 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
552 XcvDataPort() interface.
553 ****************************************************************************/
555 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
556 const struct auth_serversupplied_info *session_info,
557 struct messaging_context *msg_ctx,
558 struct printer_handle *Printer,
559 const char *handlename)
562 int n_services=lp_numservices();
564 const char *printername;
565 const char *servername = NULL;
568 struct spoolss_PrinterInfo2 *info2 = NULL;
573 * Hopefully nobody names his printers like this. Maybe \ or ,
574 * are illegal in printer names even?
576 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
580 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
581 (unsigned long)strlen(handlename)));
583 aprinter = CONST_DISCARD(char *, handlename);
584 if ( *handlename == '\\' ) {
585 servername = canon_servername(handlename);
586 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
590 if (!is_myname_or_ipaddr(servername)) {
591 return WERR_INVALID_PRINTER_NAME;
593 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
594 if (Printer->servername == NULL) {
599 if (Printer->printer_type == SPLHND_SERVER) {
603 if (Printer->printer_type != SPLHND_PRINTER) {
604 return WERR_INVALID_HANDLE;
607 DEBUGADD(5, ("searching for [%s]\n", aprinter));
609 p = strchr(aprinter, ',');
616 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
618 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
624 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
627 /* check for the Port Monitor Interface */
628 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
629 Printer->printer_type = SPLHND_PORTMON_TCP;
630 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
633 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
634 Printer->printer_type = SPLHND_PORTMON_LOCAL;
635 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
640 * With hundreds of printers, the "for" loop iterating all
641 * shares can be quite expensive, as it is done on every
642 * OpenPrinter. The loop maps "aprinter" to "sname", the
643 * result of which we cache in gencache.
646 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
648 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
650 found = (strcmp(tmp, printer_not_found) != 0);
652 DEBUG(4, ("Printer %s not found\n", aprinter));
654 return WERR_INVALID_PRINTER_NAME;
660 /* Search all sharenames first as this is easier than pulling
661 the printer_info_2 off of disk. Don't use find_service() since
662 that calls out to map_username() */
664 /* do another loop to look for printernames */
665 for (snum = 0; !found && snum < n_services; snum++) {
666 const char *printer = lp_const_servicename(snum);
668 /* no point going on if this is not a printer */
669 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
673 /* ignore [printers] share */
674 if (strequal(printer, "printers")) {
678 fstrcpy(sname, printer);
679 if (strequal(aprinter, printer)) {
684 /* no point looking up the printer object if
685 we aren't allowing printername != sharename */
686 if (lp_force_printername(snum)) {
690 result = winreg_get_printer_internal(mem_ctx,
695 if ( !W_ERROR_IS_OK(result) ) {
696 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
697 sname, win_errstr(result)));
701 printername = strrchr(info2->printername, '\\');
702 if (printername == NULL) {
703 printername = info2->printername;
708 if (strequal(printername, aprinter)) {
713 DEBUGADD(10, ("printername: %s\n", printername));
719 if (cache_key != NULL) {
720 gencache_set(cache_key, printer_not_found,
722 TALLOC_FREE(cache_key);
724 DEBUGADD(4,("Printer not found\n"));
725 return WERR_INVALID_PRINTER_NAME;
728 if (cache_key != NULL) {
729 gencache_set(cache_key, sname, time(NULL)+300);
730 TALLOC_FREE(cache_key);
733 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
735 fstrcpy(Printer->sharename, sname);
740 /****************************************************************************
741 Find first available printer slot. creates a printer handle for you.
742 ****************************************************************************/
744 static WERROR open_printer_hnd(struct pipes_struct *p,
745 struct policy_handle *hnd,
747 uint32_t access_granted)
749 struct printer_handle *new_printer;
752 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
754 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
755 if (new_printer == NULL) {
758 talloc_set_destructor(new_printer, printer_entry_destructor);
760 /* This also steals the printer_handle on the policy_handle */
761 if (!create_policy_hnd(p, hnd, new_printer)) {
762 TALLOC_FREE(new_printer);
763 return WERR_INVALID_HANDLE;
766 /* Add to the internal list. */
767 DLIST_ADD(printers_list, new_printer);
769 new_printer->notify.option=NULL;
771 if (!set_printer_hnd_printertype(new_printer, name)) {
772 close_printer_handle(p, hnd);
773 return WERR_INVALID_HANDLE;
776 result = set_printer_hnd_name(p->mem_ctx,
777 get_session_info_system(),
780 if (!W_ERROR_IS_OK(result)) {
781 close_printer_handle(p, hnd);
785 new_printer->access_granted = access_granted;
787 DEBUG(5, ("%d printer handles active\n",
788 (int)num_pipe_handles(p)));
793 /***************************************************************************
794 check to see if the client motify handle is monitoring the notification
795 given by (notify_type, notify_field).
796 **************************************************************************/
798 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
799 uint16_t notify_field)
804 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
805 uint16_t notify_field)
807 struct spoolss_NotifyOption *option = p->notify.option;
811 * Flags should always be zero when the change notify
812 * is registered by the client's spooler. A user Win32 app
813 * might use the flags though instead of the NOTIFY_OPTION_INFO
822 return is_monitoring_event_flags(
823 p->notify.flags, notify_type, notify_field);
825 for (i = 0; i < option->count; i++) {
827 /* Check match for notify_type */
829 if (option->types[i].type != notify_type)
832 /* Check match for field */
834 for (j = 0; j < option->types[i].count; j++) {
835 if (option->types[i].fields[j].field == notify_field) {
841 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
842 p->servername, p->sharename, notify_type, notify_field));
847 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
848 _data->data.integer[0] = _integer; \
849 _data->data.integer[1] = 0;
852 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
853 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
854 if (!_data->data.string.string) {\
855 _data->data.string.size = 0; \
857 _data->data.string.size = strlen_m_term(_p) * 2;
859 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
860 _data->data.devmode.devmode = _devmode;
862 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
863 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
864 if (!_data->data.sd.sd) { \
865 _data->data.sd.sd_size = 0; \
867 _data->data.sd.sd_size = \
868 ndr_size_security_descriptor(_data->data.sd.sd, 0);
870 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
875 struct spoolss_Time st;
879 if (!init_systemtime(&st, t)) {
883 p = talloc_array(mem_ctx, char, len);
889 * Systemtime must be linearized as a set of UINT16's.
890 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
893 SSVAL(p, 0, st.year);
894 SSVAL(p, 2, st.month);
895 SSVAL(p, 4, st.day_of_week);
897 SSVAL(p, 8, st.hour);
898 SSVAL(p, 10, st.minute);
899 SSVAL(p, 12, st.second);
900 SSVAL(p, 14, st.millisecond);
906 /* Convert a notification message to a struct spoolss_Notify */
908 static void notify_one_value(struct spoolss_notify_msg *msg,
909 struct spoolss_Notify *data,
912 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
915 static void notify_string(struct spoolss_notify_msg *msg,
916 struct spoolss_Notify *data,
919 /* The length of the message includes the trailing \0 */
921 data->data.string.size = msg->len * 2;
922 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
923 if (!data->data.string.string) {
924 data->data.string.size = 0;
929 static void notify_system_time(struct spoolss_notify_msg *msg,
930 struct spoolss_Notify *data,
933 data->data.string.string = NULL;
934 data->data.string.size = 0;
936 if (msg->len != sizeof(time_t)) {
937 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
942 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
943 &data->data.string.string,
944 &data->data.string.size);
947 struct notify2_message_table {
949 void (*fn)(struct spoolss_notify_msg *msg,
950 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
953 static struct notify2_message_table printer_notify_table[] = {
954 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
955 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
956 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
957 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
958 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
959 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
960 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
961 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
962 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
963 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
964 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
965 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
966 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
967 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
968 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
969 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
970 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
971 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
972 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
975 static struct notify2_message_table job_notify_table[] = {
976 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
977 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
978 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
979 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
980 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
981 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
982 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
983 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
984 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
985 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
986 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
987 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
988 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
989 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
990 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
991 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
992 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
993 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
994 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
995 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
996 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
997 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
998 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
999 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1003 /***********************************************************************
1004 Allocate talloc context for container object
1005 **********************************************************************/
1007 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1012 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1017 /***********************************************************************
1018 release all allocated memory and zero out structure
1019 **********************************************************************/
1021 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1027 talloc_destroy(ctr->ctx);
1034 /***********************************************************************
1035 **********************************************************************/
1037 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1045 /***********************************************************************
1046 **********************************************************************/
1048 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1050 if ( !ctr || !ctr->msg_groups )
1053 if ( idx >= ctr->num_groups )
1056 return &ctr->msg_groups[idx];
1060 /***********************************************************************
1061 How many groups of change messages do we have ?
1062 **********************************************************************/
1064 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1069 return ctr->num_groups;
1072 /***********************************************************************
1073 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1074 **********************************************************************/
1076 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1078 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1079 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1080 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1086 /* loop over all groups looking for a matching printer name */
1088 for ( i=0; i<ctr->num_groups; i++ ) {
1089 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1093 /* add a new group? */
1095 if ( i == ctr->num_groups ) {
1098 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1099 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1102 ctr->msg_groups = groups;
1104 /* clear the new entry and set the printer name */
1106 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1107 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1110 /* add the change messages; 'i' is the correct index now regardless */
1112 msg_grp = &ctr->msg_groups[i];
1114 msg_grp->num_msgs++;
1116 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1117 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1120 msg_grp->msgs = msg_list;
1122 new_slot = msg_grp->num_msgs-1;
1123 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1125 /* need to allocate own copy of data */
1127 if ( msg->len != 0 )
1128 msg_grp->msgs[new_slot].notify.data = (char *)
1129 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1131 return ctr->num_groups;
1134 static void construct_info_data(struct spoolss_Notify *info_data,
1135 enum spoolss_NotifyType type,
1136 uint16_t field, int id);
1138 /***********************************************************************
1139 Send a change notication message on all handles which have a call
1141 **********************************************************************/
1143 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1144 struct printer_handle *prn_hnd,
1145 SPOOLSS_NOTIFY_MSG *messages,
1147 struct spoolss_Notify **_notifies,
1150 struct spoolss_Notify *notifies;
1151 SPOOLSS_NOTIFY_MSG *msg;
1156 notifies = talloc_zero_array(mem_ctx,
1157 struct spoolss_Notify, num_msgs);
1162 for (i = 0; i < num_msgs; i++) {
1166 /* Are we monitoring this event? */
1168 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1172 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1173 "for printer [%s]\n",
1174 msg->type, msg->field, prn_hnd->sharename));
1177 * if the is a printer notification handle and not a job
1178 * notification type, then set the id to 0.
1179 * Otherwise just use what was specified in the message.
1181 * When registering change notification on a print server
1182 * handle we always need to send back the id (snum) matching
1183 * the printer for which the change took place.
1184 * For change notify registered on a printer handle,
1185 * this does not matter and the id should be 0.
1190 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1191 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1197 /* Convert unix jobid to smb jobid */
1199 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1200 id = sysjob_to_jobid(msg->id);
1203 DEBUG(3, ("no such unix jobid %d\n",
1209 construct_info_data(¬ifies[count],
1210 msg->type, msg->field, id);
1213 case PRINTER_NOTIFY_TYPE:
1214 if (printer_notify_table[msg->field].fn) {
1215 printer_notify_table[msg->field].fn(msg,
1216 ¬ifies[count], mem_ctx);
1220 case JOB_NOTIFY_TYPE:
1221 if (job_notify_table[msg->field].fn) {
1222 job_notify_table[msg->field].fn(msg,
1223 ¬ifies[count], mem_ctx);
1228 DEBUG(5, ("Unknown notification type %d\n",
1236 *_notifies = notifies;
1242 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1243 struct printer_handle *prn_hnd,
1244 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1246 struct spoolss_Notify *notifies;
1248 union spoolss_ReplyPrinterInfo info;
1249 struct spoolss_NotifyInfo info0;
1250 uint32_t reply_result;
1255 /* Is there notification on this handle? */
1256 if (prn_hnd->notify.cli_chan == NULL ||
1257 prn_hnd->notify.cli_chan->active_connections == 0) {
1261 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1262 prn_hnd->servername, prn_hnd->sharename));
1264 /* For this printer? Print servers always receive notifications. */
1265 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1266 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1270 DEBUG(10,("Our printer\n"));
1272 /* build the array of change notifications */
1273 ret = build_notify2_messages(mem_ctx, prn_hnd,
1275 msg_group->num_msgs,
1281 info0.version = 0x2;
1282 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1283 info0.count = count;
1284 info0.notifies = notifies;
1286 info.info0 = &info0;
1288 status = dcerpc_spoolss_RouterReplyPrinterEx(
1289 prn_hnd->notify.cli_chan->binding_handle,
1291 &prn_hnd->notify.cli_hnd,
1292 prn_hnd->notify.change, /* color */
1293 prn_hnd->notify.flags,
1295 0, /* reply_type, must be 0 */
1297 if (!NT_STATUS_IS_OK(status)) {
1298 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1300 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301 nt_errstr(status)));
1302 werr = ntstatus_to_werror(status);
1303 } else if (!W_ERROR_IS_OK(werr)) {
1304 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1306 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1309 switch (reply_result) {
1312 case PRINTER_NOTIFY_INFO_DISCARDED:
1313 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1314 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1323 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1325 struct printer_handle *p;
1326 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1327 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1331 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1335 if (!msg_group->msgs) {
1336 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1340 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1342 /* loop over all printers */
1344 for (p = printers_list; p; p = p->next) {
1345 ret = send_notify2_printer(mem_ctx, p, msg_group);
1352 DEBUG(8,("send_notify2_changes: Exit...\n"));
1356 /***********************************************************************
1357 **********************************************************************/
1359 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1362 uint32_t tv_sec, tv_usec;
1365 /* Unpack message */
1367 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1370 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1372 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1375 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1376 &msg->notify.value[0], &msg->notify.value[1]);
1378 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1379 &msg->len, &msg->notify.data);
1381 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1382 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1384 tv->tv_sec = tv_sec;
1385 tv->tv_usec = tv_usec;
1388 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1389 msg->notify.value[1]));
1391 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1396 /********************************************************************
1397 Receive a notify2 message list
1398 ********************************************************************/
1400 static void receive_notify2_message_list(struct messaging_context *msg,
1403 struct server_id server_id,
1406 size_t msg_count, i;
1407 char *buf = (char *)data->data;
1410 SPOOLSS_NOTIFY_MSG notify;
1411 SPOOLSS_NOTIFY_MSG_CTR messages;
1414 if (data->length < 4) {
1415 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1419 msg_count = IVAL(buf, 0);
1422 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1424 if (msg_count == 0) {
1425 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1429 /* initialize the container */
1431 ZERO_STRUCT( messages );
1432 notify_msg_ctr_init( &messages );
1435 * build message groups for each printer identified
1436 * in a change_notify msg. Remember that a PCN message
1437 * includes the handle returned for the srv_spoolss_replyopenprinter()
1438 * call. Therefore messages are grouped according to printer handle.
1441 for ( i=0; i<msg_count; i++ ) {
1442 struct timeval msg_tv;
1444 if (msg_ptr + 4 - buf > data->length) {
1445 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1449 msg_len = IVAL(msg_ptr,0);
1452 if (msg_ptr + msg_len - buf > data->length) {
1453 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1457 /* unpack messages */
1459 ZERO_STRUCT( notify );
1460 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1463 /* add to correct list in container */
1465 notify_msg_ctr_addmsg( &messages, ¬ify );
1467 /* free memory that might have been allocated by notify2_unpack_msg() */
1469 if ( notify.len != 0 )
1470 SAFE_FREE( notify.notify.data );
1473 /* process each group of messages */
1475 num_groups = notify_msg_ctr_numgroups( &messages );
1476 for ( i=0; i<num_groups; i++ )
1477 send_notify2_changes( &messages, i );
1482 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1483 (uint32_t)msg_count ));
1485 notify_msg_ctr_destroy( &messages );
1490 /********************************************************************
1491 Send a message to ourself about new driver being installed
1492 so we can upgrade the information for each printer bound to this
1494 ********************************************************************/
1496 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1497 struct messaging_context *msg_ctx)
1499 int len = strlen(drivername);
1504 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1507 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1508 MSG_PRINTER_DRVUPGRADE,
1509 (uint8_t *)drivername, len+1);
1514 void srv_spoolss_cleanup(void)
1516 struct printer_session_counter *session_counter;
1518 for (session_counter = counter_list;
1519 session_counter != NULL;
1520 session_counter = counter_list) {
1521 DLIST_REMOVE(counter_list, session_counter);
1522 TALLOC_FREE(session_counter);
1526 /**********************************************************************
1527 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1528 over all printers, upgrading ones as necessary
1529 **********************************************************************/
1531 void do_drv_upgrade_printer(struct messaging_context *msg,
1534 struct server_id server_id,
1537 TALLOC_CTX *tmp_ctx;
1538 struct auth_serversupplied_info *session_info = NULL;
1539 struct spoolss_PrinterInfo2 *pinfo2;
1542 const char *drivername;
1544 int n_services = lp_numservices();
1545 struct dcerpc_binding_handle *b = NULL;
1547 tmp_ctx = talloc_new(NULL);
1548 if (!tmp_ctx) return;
1550 status = make_session_info_system(tmp_ctx, &session_info);
1551 if (!NT_STATUS_IS_OK(status)) {
1552 DEBUG(0, ("do_drv_upgrade_printer: "
1553 "Could not create system session_info\n"));
1557 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1559 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1563 DEBUG(10, ("do_drv_upgrade_printer: "
1564 "Got message for new driver [%s]\n", drivername));
1566 /* Iterate the printer list */
1568 for (snum = 0; snum < n_services; snum++) {
1569 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1573 /* ignore [printers] share */
1574 if (strequal(lp_const_servicename(snum), "printers")) {
1579 result = winreg_printer_binding_handle(tmp_ctx,
1583 if (!W_ERROR_IS_OK(result)) {
1588 result = winreg_get_printer(tmp_ctx, b,
1589 lp_const_servicename(snum),
1592 if (!W_ERROR_IS_OK(result)) {
1596 if (!pinfo2->drivername) {
1600 if (strcmp(drivername, pinfo2->drivername) != 0) {
1604 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1606 /* all we care about currently is the change_id */
1607 result = winreg_printer_update_changeid(tmp_ctx, b,
1608 pinfo2->printername);
1610 if (!W_ERROR_IS_OK(result)) {
1611 DEBUG(3, ("do_drv_upgrade_printer: "
1612 "Failed to update changeid [%s]\n",
1613 win_errstr(result)));
1619 talloc_free(tmp_ctx);
1622 /********************************************************************
1623 Update the cache for all printq's with a registered client
1625 ********************************************************************/
1627 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1629 struct printer_handle *printer = printers_list;
1632 /* loop through all printers and update the cache where
1633 a client is connected */
1635 if ((printer->printer_type == SPLHND_PRINTER) &&
1636 ((printer->notify.cli_chan != NULL) &&
1637 (printer->notify.cli_chan->active_connections > 0))) {
1638 snum = print_queue_snum(printer->sharename);
1639 print_queue_status(msg_ctx, snum, NULL, NULL);
1642 printer = printer->next;
1648 /****************************************************************
1649 _spoolss_OpenPrinter
1650 ****************************************************************/
1652 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1653 struct spoolss_OpenPrinter *r)
1655 struct spoolss_OpenPrinterEx e;
1658 ZERO_STRUCT(e.in.userlevel);
1660 e.in.printername = r->in.printername;
1661 e.in.datatype = r->in.datatype;
1662 e.in.devmode_ctr = r->in.devmode_ctr;
1663 e.in.access_mask = r->in.access_mask;
1666 e.out.handle = r->out.handle;
1668 werr = _spoolss_OpenPrinterEx(p, &e);
1670 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1671 /* OpenPrinterEx returns this for a bad
1672 * printer name. We must return WERR_INVALID_PRINTER_NAME
1675 werr = WERR_INVALID_PRINTER_NAME;
1681 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1682 struct spoolss_DeviceMode *orig,
1683 struct spoolss_DeviceMode **dest)
1685 struct spoolss_DeviceMode *dm;
1687 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1692 /* copy all values, then duplicate strings and structs */
1695 dm->devicename = talloc_strdup(dm, orig->devicename);
1696 if (!dm->devicename) {
1699 dm->formname = talloc_strdup(dm, orig->formname);
1700 if (!dm->formname) {
1703 if (orig->driverextra_data.data) {
1704 dm->driverextra_data.data =
1705 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1706 orig->driverextra_data.length);
1707 if (!dm->driverextra_data.data) {
1716 /****************************************************************
1717 _spoolss_OpenPrinterEx
1718 ****************************************************************/
1720 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1721 struct spoolss_OpenPrinterEx *r)
1724 struct printer_handle *Printer=NULL;
1727 if (!r->in.printername) {
1728 return WERR_INVALID_PARAM;
1731 if (r->in.level > 3) {
1732 return WERR_INVALID_PARAM;
1734 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1735 (r->in.level == 2 && !r->in.userlevel.level2) ||
1736 (r->in.level == 3 && !r->in.userlevel.level3)) {
1737 return WERR_INVALID_PARAM;
1740 /* some sanity check because you can open a printer or a print server */
1741 /* aka: \\server\printer or \\server */
1743 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1745 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1746 if (!W_ERROR_IS_OK(result)) {
1747 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1748 "for printer %s\n", r->in.printername));
1749 ZERO_STRUCTP(r->out.handle);
1753 Printer = find_printer_index_by_hnd(p, r->out.handle);
1755 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1756 "handle we created for printer %s\n", r->in.printername));
1757 close_printer_handle(p, r->out.handle);
1758 ZERO_STRUCTP(r->out.handle);
1759 return WERR_INVALID_PARAM;
1763 * First case: the user is opening the print server:
1765 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1766 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1768 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1769 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1770 * or if the user is listed in the smb.conf printer admin parameter.
1772 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1773 * client view printer folder, but does not show the MSAPW.
1775 * Note: this test needs code to check access rights here too. Jeremy
1776 * could you look at this?
1778 * Second case: the user is opening a printer:
1779 * NT doesn't let us connect to a printer if the connecting user
1780 * doesn't have print permission.
1782 * Third case: user is opening a Port Monitor
1783 * access checks same as opening a handle to the print server.
1786 switch (Printer->printer_type )
1789 case SPLHND_PORTMON_TCP:
1790 case SPLHND_PORTMON_LOCAL:
1791 /* Printserver handles use global struct... */
1795 /* Map standard access rights to object specific access rights */
1797 se_map_standard(&r->in.access_mask,
1798 &printserver_std_mapping);
1800 /* Deny any object specific bits that don't apply to print
1801 servers (i.e printer and job specific bits) */
1803 r->in.access_mask &= SEC_MASK_SPECIFIC;
1805 if (r->in.access_mask &
1806 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1807 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1808 close_printer_handle(p, r->out.handle);
1809 ZERO_STRUCTP(r->out.handle);
1810 return WERR_ACCESS_DENIED;
1813 /* Allow admin access */
1815 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1817 if (!lp_ms_add_printer_wizard()) {
1818 close_printer_handle(p, r->out.handle);
1819 ZERO_STRUCTP(r->out.handle);
1820 return WERR_ACCESS_DENIED;
1823 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1824 and not a printer admin, then fail */
1826 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1827 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1828 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1829 !token_contains_name_in_list(
1830 uidtoname(p->session_info->utok.uid),
1831 p->session_info->info3->base.domain.string,
1833 p->session_info->security_token,
1834 lp_printer_admin(snum))) {
1835 close_printer_handle(p, r->out.handle);
1836 ZERO_STRUCTP(r->out.handle);
1837 DEBUG(3,("access DENIED as user is not root, "
1838 "has no printoperator privilege, "
1839 "not a member of the printoperator builtin group and "
1840 "is not in printer admin list"));
1841 return WERR_ACCESS_DENIED;
1844 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1848 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1851 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1852 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1854 /* We fall through to return WERR_OK */
1857 case SPLHND_PRINTER:
1858 /* NT doesn't let us connect to a printer if the connecting user
1859 doesn't have print permission. */
1861 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1862 close_printer_handle(p, r->out.handle);
1863 ZERO_STRUCTP(r->out.handle);
1867 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1868 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1871 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1873 /* map an empty access mask to the minimum access mask */
1874 if (r->in.access_mask == 0x0)
1875 r->in.access_mask = PRINTER_ACCESS_USE;
1878 * If we are not serving the printer driver for this printer,
1879 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1880 * will keep NT clients happy --jerry
1883 if (lp_use_client_driver(snum)
1884 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1886 r->in.access_mask = PRINTER_ACCESS_USE;
1889 /* check smb.conf parameters and the the sec_desc */
1891 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1892 p->client_id->name, p->client_id->addr)) {
1893 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894 ZERO_STRUCTP(r->out.handle);
1895 return WERR_ACCESS_DENIED;
1898 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1899 p->session_info->security_token, snum) ||
1900 !print_access_check(p->session_info,
1903 r->in.access_mask)) {
1904 DEBUG(3, ("access DENIED for printer open\n"));
1905 close_printer_handle(p, r->out.handle);
1906 ZERO_STRUCTP(r->out.handle);
1907 return WERR_ACCESS_DENIED;
1910 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 close_printer_handle(p, r->out.handle);
1913 ZERO_STRUCTP(r->out.handle);
1914 return WERR_ACCESS_DENIED;
1917 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1920 r->in.access_mask = PRINTER_ACCESS_USE;
1922 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1925 winreg_create_printer_internal(p->mem_ctx,
1926 get_session_info_system(),
1928 lp_const_servicename(snum));
1933 /* sanity check to prevent programmer error */
1934 ZERO_STRUCTP(r->out.handle);
1938 Printer->access_granted = r->in.access_mask;
1941 * If the client sent a devmode in the OpenPrinter() call, then
1942 * save it here in case we get a job submission on this handle
1945 if ((Printer->printer_type != SPLHND_SERVER) &&
1946 r->in.devmode_ctr.devmode) {
1947 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1951 #if 0 /* JERRY -- I'm doubtful this is really effective */
1952 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1953 optimization in Windows 2000 clients --jerry */
1955 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1956 && (RA_WIN2K == get_remote_arch()) )
1958 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1959 sys_usleep( 500000 );
1966 /****************************************************************
1967 _spoolss_ClosePrinter
1968 ****************************************************************/
1970 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1971 struct spoolss_ClosePrinter *r)
1973 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1975 if (Printer && Printer->document_started) {
1976 struct spoolss_EndDocPrinter e;
1978 e.in.handle = r->in.handle;
1980 _spoolss_EndDocPrinter(p, &e);
1983 if (!close_printer_handle(p, r->in.handle))
1986 /* clear the returned printer handle. Observed behavior
1987 from Win2k server. Don't think this really matters.
1988 Previous code just copied the value of the closed
1991 ZERO_STRUCTP(r->out.handle);
1996 /****************************************************************
1997 _spoolss_DeletePrinter
1998 ****************************************************************/
2000 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2001 struct spoolss_DeletePrinter *r)
2003 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2007 if (Printer && Printer->document_started) {
2008 struct spoolss_EndDocPrinter e;
2010 e.in.handle = r->in.handle;
2012 _spoolss_EndDocPrinter(p, &e);
2015 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2016 winreg_delete_printer_key_internal(p->mem_ctx,
2017 get_session_info_system(),
2019 lp_const_servicename(snum),
2023 result = delete_printer_handle(p, r->in.handle);
2028 /*******************************************************************
2029 * static function to lookup the version id corresponding to an
2030 * long architecture string
2031 ******************************************************************/
2033 static const struct print_architecture_table_node archi_table[]= {
2035 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2036 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2037 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2038 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2039 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2040 {"Windows IA64", SPL_ARCH_IA64, 3 },
2041 {"Windows x64", SPL_ARCH_X64, 3 },
2045 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2046 SPOOLSS_DRIVER_VERSION_NT35,
2047 SPOOLSS_DRIVER_VERSION_NT4,
2048 SPOOLSS_DRIVER_VERSION_200X,
2051 static int get_version_id(const char *arch)
2055 for (i=0; archi_table[i].long_archi != NULL; i++)
2057 if (strcmp(arch, archi_table[i].long_archi) == 0)
2058 return (archi_table[i].version);
2064 /****************************************************************
2065 _spoolss_DeletePrinterDriver
2066 ****************************************************************/
2068 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2069 struct spoolss_DeletePrinterDriver *r)
2072 struct spoolss_DriverInfo8 *info = NULL;
2075 struct dcerpc_binding_handle *b;
2076 TALLOC_CTX *tmp_ctx = NULL;
2080 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2081 and not a printer admin, then fail */
2083 if ( (p->session_info->utok.uid != sec_initial_uid())
2084 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2085 && !token_contains_name_in_list(
2086 uidtoname(p->session_info->utok.uid),
2087 p->session_info->info3->base.domain.string,
2089 p->session_info->security_token,
2090 lp_printer_admin(-1)) )
2092 return WERR_ACCESS_DENIED;
2095 /* check that we have a valid driver name first */
2097 if ((version = get_version_id(r->in.architecture)) == -1)
2098 return WERR_INVALID_ENVIRONMENT;
2100 tmp_ctx = talloc_new(p->mem_ctx);
2105 status = winreg_printer_binding_handle(tmp_ctx,
2106 get_session_info_system(),
2109 if (!W_ERROR_IS_OK(status)) {
2113 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2114 status = winreg_get_driver(tmp_ctx, b,
2115 r->in.architecture, r->in.driver,
2116 drv_cversion[i], &info);
2117 if (!W_ERROR_IS_OK(status)) {
2118 DEBUG(5, ("skipping del of driver with version %d\n",
2124 if (printer_driver_in_use(tmp_ctx, get_session_info_system(),
2125 p->msg_ctx, info)) {
2126 status = WERR_PRINTER_DRIVER_IN_USE;
2130 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2131 if (!W_ERROR_IS_OK(status)) {
2132 DEBUG(0, ("failed del of driver with version %d\n",
2137 if (found == false) {
2138 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2139 status = WERR_UNKNOWN_PRINTER_DRIVER;
2145 talloc_free(tmp_ctx);
2149 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2150 struct pipes_struct *p,
2151 struct spoolss_DeletePrinterDriverEx *r,
2152 struct dcerpc_binding_handle *b,
2153 struct spoolss_DriverInfo8 *info)
2158 if (printer_driver_in_use(mem_ctx, get_session_info_system(),
2159 p->msg_ctx, info)) {
2160 status = WERR_PRINTER_DRIVER_IN_USE;
2165 * we have a couple of cases to consider.
2166 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2167 * then the delete should fail if **any** files overlap with
2169 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2170 * non-overlapping files
2171 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2172 * is set, then do not delete any files
2173 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2176 delete_files = r->in.delete_flags
2177 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2180 bool in_use = printer_driver_files_in_use(mem_ctx,
2181 get_session_info_system(),
2184 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2185 status = WERR_PRINTER_DRIVER_IN_USE;
2189 * printer_driver_files_in_use() has trimmed overlapping files
2190 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2194 status = winreg_del_driver(mem_ctx, b, info, info->version);
2195 if (!W_ERROR_IS_OK(status)) {
2200 * now delete any associated files if delete_files is
2201 * true. Even if this part failes, we return succes
2202 * because the driver doesn not exist any more
2205 delete_driver_files(get_session_info_system(), info);
2212 /****************************************************************
2213 _spoolss_DeletePrinterDriverEx
2214 ****************************************************************/
2216 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2217 struct spoolss_DeletePrinterDriverEx *r)
2219 struct spoolss_DriverInfo8 *info = NULL;
2221 struct dcerpc_binding_handle *b;
2222 TALLOC_CTX *tmp_ctx = NULL;
2226 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2227 and not a printer admin, then fail */
2229 if ( (p->session_info->utok.uid != sec_initial_uid())
2230 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2231 && !token_contains_name_in_list(
2232 uidtoname(p->session_info->utok.uid),
2233 p->session_info->info3->base.domain.string,
2235 p->session_info->security_token, lp_printer_admin(-1)) )
2237 return WERR_ACCESS_DENIED;
2240 /* check that we have a valid driver name first */
2241 if (get_version_id(r->in.architecture) == -1) {
2242 /* this is what NT returns */
2243 return WERR_INVALID_ENVIRONMENT;
2246 tmp_ctx = talloc_new(p->mem_ctx);
2251 status = winreg_printer_binding_handle(tmp_ctx,
2252 get_session_info_system(),
2255 if (!W_ERROR_IS_OK(status)) {
2259 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2260 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2261 && (drv_cversion[i] != r->in.version)) {
2265 /* check if a driver with this version exists before delete */
2266 status = winreg_get_driver(tmp_ctx, b,
2267 r->in.architecture, r->in.driver,
2268 drv_cversion[i], &info);
2269 if (!W_ERROR_IS_OK(status)) {
2270 DEBUG(5, ("skipping del of driver with version %d\n",
2276 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2277 if (!W_ERROR_IS_OK(status)) {
2278 DEBUG(0, ("failed to delete driver with version %d\n",
2283 if (found == false) {
2284 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2285 status = WERR_UNKNOWN_PRINTER_DRIVER;
2291 talloc_free(tmp_ctx);
2296 /********************************************************************
2297 GetPrinterData on a printer server Handle.
2298 ********************************************************************/
2300 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2302 enum winreg_Type *type,
2303 union spoolss_PrinterData *data)
2305 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2307 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2313 if (!StrCaseCmp(value, "BeepEnabled")) {
2319 if (!StrCaseCmp(value, "EventLog")) {
2321 /* formally was 0x1b */
2326 if (!StrCaseCmp(value, "NetPopup")) {
2332 if (!StrCaseCmp(value, "MajorVersion")) {
2335 /* Windows NT 4.0 seems to not allow uploading of drivers
2336 to a server that reports 0x3 as the MajorVersion.
2337 need to investigate more how Win2k gets around this .
2340 if (RA_WINNT == get_remote_arch()) {
2349 if (!StrCaseCmp(value, "MinorVersion")) {
2356 * uint32_t size = 0x114
2357 * uint32_t major = 5
2358 * uint32_t minor = [0|1]
2359 * uint32_t build = [2195|2600]
2360 * extra unicode string = e.g. "Service Pack 3"
2362 if (!StrCaseCmp(value, "OSVersion")) {
2364 enum ndr_err_code ndr_err;
2365 struct spoolss_OSVersion os;
2367 os.major = 5; /* Windows 2000 == 5.0 */
2369 os.build = 2195; /* build */
2370 os.extra_string = ""; /* leave extra string empty */
2372 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2373 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2374 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2375 return WERR_GENERAL_FAILURE;
2379 data->binary = blob;
2385 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2388 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2389 W_ERROR_HAVE_NO_MEMORY(data->string);
2394 if (!StrCaseCmp(value, "Architecture")) {
2396 data->string = talloc_strdup(mem_ctx,
2397 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2398 W_ERROR_HAVE_NO_MEMORY(data->string);
2403 if (!StrCaseCmp(value, "DsPresent")) {
2406 /* only show the publish check box if we are a
2407 member of a AD domain */
2409 if (lp_security() == SEC_ADS) {
2417 if (!StrCaseCmp(value, "DNSMachineName")) {
2418 const char *hostname = get_mydnsfullname();
2421 return WERR_BADFILE;
2425 data->string = talloc_strdup(mem_ctx, hostname);
2426 W_ERROR_HAVE_NO_MEMORY(data->string);
2433 return WERR_INVALID_PARAM;
2436 /****************************************************************
2437 _spoolss_GetPrinterData
2438 ****************************************************************/
2440 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2441 struct spoolss_GetPrinterData *r)
2443 struct spoolss_GetPrinterDataEx r2;
2445 r2.in.handle = r->in.handle;
2446 r2.in.key_name = "PrinterDriverData";
2447 r2.in.value_name = r->in.value_name;
2448 r2.in.offered = r->in.offered;
2449 r2.out.type = r->out.type;
2450 r2.out.data = r->out.data;
2451 r2.out.needed = r->out.needed;
2453 return _spoolss_GetPrinterDataEx(p, &r2);
2456 /*********************************************************
2457 Connect to the client machine.
2458 **********************************************************/
2460 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2461 struct sockaddr_storage *client_ss, const char *remote_machine)
2464 struct cli_state *the_cli;
2465 struct sockaddr_storage rm_addr;
2466 char addr[INET6_ADDRSTRLEN];
2468 if ( is_zero_addr(client_ss) ) {
2469 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2471 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2472 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2475 print_sockaddr(addr, sizeof(addr), &rm_addr);
2477 rm_addr = *client_ss;
2478 print_sockaddr(addr, sizeof(addr), &rm_addr);
2479 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2483 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2484 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2489 /* setup the connection */
2490 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2491 &rm_addr, 0, "IPC$", "IPC",
2495 0, lp_client_signing());
2497 if ( !NT_STATUS_IS_OK( ret ) ) {
2498 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2503 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2504 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2505 cli_shutdown(the_cli);
2510 * Ok - we have an anonymous connection to the IPC$ share.
2511 * Now start the NT Domain stuff :-).
2514 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2515 if (!NT_STATUS_IS_OK(ret)) {
2516 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2517 remote_machine, nt_errstr(ret)));
2518 cli_shutdown(the_cli);
2525 /***************************************************************************
2526 Connect to the client.
2527 ****************************************************************************/
2529 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2530 uint32_t localprinter,
2531 enum winreg_Type type,
2532 struct policy_handle *handle,
2533 struct notify_back_channel **_chan,
2534 struct sockaddr_storage *client_ss,
2535 struct messaging_context *msg_ctx)
2539 struct notify_back_channel *chan;
2541 for (chan = back_channels; chan; chan = chan->next) {
2542 if (memcmp(&chan->client_address, client_ss,
2543 sizeof(struct sockaddr_storage)) == 0) {
2549 * If it's the first connection, contact the client
2550 * and connect to the IPC$ share anonymously
2553 fstring unix_printer;
2555 /* the +2 is to strip the leading 2 backslashs */
2556 fstrcpy(unix_printer, printer + 2);
2558 chan = talloc_zero(back_channels, struct notify_back_channel);
2562 chan->client_address = *client_ss;
2564 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2568 chan->binding_handle = chan->cli_pipe->binding_handle;
2570 DLIST_ADD(back_channels, chan);
2572 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2573 receive_notify2_message_list);
2574 /* Tell the connections db we're now interested in printer
2575 * notify messages. */
2576 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2577 true, FLAG_MSG_PRINT_NOTIFY);
2581 * Tell the specific printing tdb we want messages for this printer
2582 * by registering our PID.
2585 if (!print_notify_register_pid(snum)) {
2586 DEBUG(0, ("Failed to register our pid for printer %s\n",
2590 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2599 if (!NT_STATUS_IS_OK(status)) {
2600 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2601 result = ntstatus_to_werror(status);
2602 } else if (!W_ERROR_IS_OK(result)) {
2603 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2606 chan->active_connections++;
2609 return (W_ERROR_IS_OK(result));
2612 /****************************************************************
2613 ****************************************************************/
2615 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2616 const struct spoolss_NotifyOption *r)
2618 struct spoolss_NotifyOption *option;
2625 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2632 if (!option->count) {
2636 option->types = talloc_zero_array(option,
2637 struct spoolss_NotifyOptionType, option->count);
2638 if (!option->types) {
2639 talloc_free(option);
2643 for (i=0; i < option->count; i++) {
2644 option->types[i] = r->types[i];
2646 if (option->types[i].count) {
2647 option->types[i].fields = talloc_zero_array(option,
2648 union spoolss_Field, option->types[i].count);
2649 if (!option->types[i].fields) {
2650 talloc_free(option);
2653 for (k=0; k<option->types[i].count; k++) {
2654 option->types[i].fields[k] =
2655 r->types[i].fields[k];
2663 /****************************************************************
2664 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2666 * before replying OK: status=0 a rpc call is made to the workstation
2667 * asking ReplyOpenPrinter
2669 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2670 * called from api_spoolss_rffpcnex
2671 ****************************************************************/
2673 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2674 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2677 struct spoolss_NotifyOption *option = r->in.notify_options;
2678 struct sockaddr_storage client_ss;
2680 /* store the notify value in the printer struct */
2682 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2685 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2686 "Invalid handle (%s:%u:%u).\n",
2687 OUR_HANDLE(r->in.handle)));
2691 Printer->notify.flags = r->in.flags;
2692 Printer->notify.options = r->in.options;
2693 Printer->notify.printerlocal = r->in.printer_local;
2694 Printer->notify.msg_ctx = p->msg_ctx;
2696 TALLOC_FREE(Printer->notify.option);
2697 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2699 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2701 /* Connect to the client machine and send a ReplyOpenPrinter */
2703 if ( Printer->printer_type == SPLHND_SERVER)
2705 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2706 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2709 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2710 "client_address is %s\n", p->client_id->addr));
2712 if (!lp_print_notify_backchannel(snum)) {
2713 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2714 "backchannel disabled\n"));
2715 return WERR_SERVER_UNAVAILABLE;
2718 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2720 return WERR_SERVER_UNAVAILABLE;
2723 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2724 Printer->notify.printerlocal, REG_SZ,
2725 &Printer->notify.cli_hnd,
2726 &Printer->notify.cli_chan,
2727 &client_ss, p->msg_ctx)) {
2728 return WERR_SERVER_UNAVAILABLE;
2734 /*******************************************************************
2735 * fill a notify_info_data with the servername
2736 ********************************************************************/
2738 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2740 struct spoolss_Notify *data,
2741 print_queue_struct *queue,
2742 struct spoolss_PrinterInfo2 *pinfo2,
2743 TALLOC_CTX *mem_ctx)
2745 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2748 /*******************************************************************
2749 * fill a notify_info_data with the printername (not including the servername).
2750 ********************************************************************/
2752 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2754 struct spoolss_Notify *data,
2755 print_queue_struct *queue,
2756 struct spoolss_PrinterInfo2 *pinfo2,
2757 TALLOC_CTX *mem_ctx)
2759 /* the notify name should not contain the \\server\ part */
2760 const char *p = strrchr(pinfo2->printername, '\\');
2763 p = pinfo2->printername;
2768 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2771 /*******************************************************************
2772 * fill a notify_info_data with the servicename
2773 ********************************************************************/
2775 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2777 struct spoolss_Notify *data,
2778 print_queue_struct *queue,
2779 struct spoolss_PrinterInfo2 *pinfo2,
2780 TALLOC_CTX *mem_ctx)
2782 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2785 /*******************************************************************
2786 * fill a notify_info_data with the port name
2787 ********************************************************************/
2789 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2791 struct spoolss_Notify *data,
2792 print_queue_struct *queue,
2793 struct spoolss_PrinterInfo2 *pinfo2,
2794 TALLOC_CTX *mem_ctx)
2796 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2799 /*******************************************************************
2800 * fill a notify_info_data with the printername
2801 * but it doesn't exist, have to see what to do
2802 ********************************************************************/
2804 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2806 struct spoolss_Notify *data,
2807 print_queue_struct *queue,
2808 struct spoolss_PrinterInfo2 *pinfo2,
2809 TALLOC_CTX *mem_ctx)
2811 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2814 /*******************************************************************
2815 * fill a notify_info_data with the comment
2816 ********************************************************************/
2818 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2820 struct spoolss_Notify *data,
2821 print_queue_struct *queue,
2822 struct spoolss_PrinterInfo2 *pinfo2,
2823 TALLOC_CTX *mem_ctx)
2827 if (*pinfo2->comment == '\0') {
2828 p = lp_comment(snum);
2830 p = pinfo2->comment;
2833 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2836 /*******************************************************************
2837 * fill a notify_info_data with the comment
2838 * location = "Room 1, floor 2, building 3"
2839 ********************************************************************/
2841 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2843 struct spoolss_Notify *data,
2844 print_queue_struct *queue,
2845 struct spoolss_PrinterInfo2 *pinfo2,
2846 TALLOC_CTX *mem_ctx)
2848 const char *loc = pinfo2->location;
2851 status = printer_list_get_printer(mem_ctx,
2856 if (NT_STATUS_IS_OK(status)) {
2858 loc = pinfo2->location;
2862 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2865 /*******************************************************************
2866 * fill a notify_info_data with the device mode
2867 * jfm:xxxx don't to it for know but that's a real problem !!!
2868 ********************************************************************/
2870 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2872 struct spoolss_Notify *data,
2873 print_queue_struct *queue,
2874 struct spoolss_PrinterInfo2 *pinfo2,
2875 TALLOC_CTX *mem_ctx)
2877 /* for a dummy implementation we have to zero the fields */
2878 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2881 /*******************************************************************
2882 * fill a notify_info_data with the separator file name
2883 ********************************************************************/
2885 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2887 struct spoolss_Notify *data,
2888 print_queue_struct *queue,
2889 struct spoolss_PrinterInfo2 *pinfo2,
2890 TALLOC_CTX *mem_ctx)
2892 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2895 /*******************************************************************
2896 * fill a notify_info_data with the print processor
2897 * jfm:xxxx return always winprint to indicate we don't do anything to it
2898 ********************************************************************/
2900 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2902 struct spoolss_Notify *data,
2903 print_queue_struct *queue,
2904 struct spoolss_PrinterInfo2 *pinfo2,
2905 TALLOC_CTX *mem_ctx)
2907 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2910 /*******************************************************************
2911 * fill a notify_info_data with the print processor options
2912 * jfm:xxxx send an empty string
2913 ********************************************************************/
2915 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2917 struct spoolss_Notify *data,
2918 print_queue_struct *queue,
2919 struct spoolss_PrinterInfo2 *pinfo2,
2920 TALLOC_CTX *mem_ctx)
2922 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2925 /*******************************************************************
2926 * fill a notify_info_data with the data type
2927 * jfm:xxxx always send RAW as data type
2928 ********************************************************************/
2930 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2932 struct spoolss_Notify *data,
2933 print_queue_struct *queue,
2934 struct spoolss_PrinterInfo2 *pinfo2,
2935 TALLOC_CTX *mem_ctx)
2937 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2940 /*******************************************************************
2941 * fill a notify_info_data with the security descriptor
2942 * jfm:xxxx send an null pointer to say no security desc
2943 * have to implement security before !
2944 ********************************************************************/
2946 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 struct spoolss_PrinterInfo2 *pinfo2,
2951 TALLOC_CTX *mem_ctx)
2953 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2956 /*******************************************************************
2957 * fill a notify_info_data with the attributes
2958 * jfm:xxxx a samba printer is always shared
2959 ********************************************************************/
2961 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2963 struct spoolss_Notify *data,
2964 print_queue_struct *queue,
2965 struct spoolss_PrinterInfo2 *pinfo2,
2966 TALLOC_CTX *mem_ctx)
2968 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2971 /*******************************************************************
2972 * fill a notify_info_data with the priority
2973 ********************************************************************/
2975 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2977 struct spoolss_Notify *data,
2978 print_queue_struct *queue,
2979 struct spoolss_PrinterInfo2 *pinfo2,
2980 TALLOC_CTX *mem_ctx)
2982 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2985 /*******************************************************************
2986 * fill a notify_info_data with the default priority
2987 ********************************************************************/
2989 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2991 struct spoolss_Notify *data,
2992 print_queue_struct *queue,
2993 struct spoolss_PrinterInfo2 *pinfo2,
2994 TALLOC_CTX *mem_ctx)
2996 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2999 /*******************************************************************
3000 * fill a notify_info_data with the start time
3001 ********************************************************************/
3003 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3005 struct spoolss_Notify *data,
3006 print_queue_struct *queue,
3007 struct spoolss_PrinterInfo2 *pinfo2,
3008 TALLOC_CTX *mem_ctx)
3010 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3013 /*******************************************************************
3014 * fill a notify_info_data with the until time
3015 ********************************************************************/
3017 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3019 struct spoolss_Notify *data,
3020 print_queue_struct *queue,
3021 struct spoolss_PrinterInfo2 *pinfo2,
3022 TALLOC_CTX *mem_ctx)
3024 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3027 /*******************************************************************
3028 * fill a notify_info_data with the status
3029 ********************************************************************/
3031 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 struct spoolss_PrinterInfo2 *pinfo2,
3036 TALLOC_CTX *mem_ctx)
3038 print_status_struct status;
3040 print_queue_length(msg_ctx, snum, &status);
3041 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3044 /*******************************************************************
3045 * fill a notify_info_data with the number of jobs queued
3046 ********************************************************************/
3048 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3050 struct spoolss_Notify *data,
3051 print_queue_struct *queue,
3052 struct spoolss_PrinterInfo2 *pinfo2,
3053 TALLOC_CTX *mem_ctx)
3055 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3056 data, print_queue_length(msg_ctx, snum, NULL));
3059 /*******************************************************************
3060 * fill a notify_info_data with the average ppm
3061 ********************************************************************/
3063 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3065 struct spoolss_Notify *data,
3066 print_queue_struct *queue,
3067 struct spoolss_PrinterInfo2 *pinfo2,
3068 TALLOC_CTX *mem_ctx)
3070 /* always respond 8 pages per minutes */
3071 /* a little hard ! */
3072 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3075 /*******************************************************************
3076 * fill a notify_info_data with username
3077 ********************************************************************/
3079 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3081 struct spoolss_Notify *data,
3082 print_queue_struct *queue,
3083 struct spoolss_PrinterInfo2 *pinfo2,
3084 TALLOC_CTX *mem_ctx)
3086 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3089 /*******************************************************************
3090 * fill a notify_info_data with job status
3091 ********************************************************************/
3093 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3095 struct spoolss_Notify *data,
3096 print_queue_struct *queue,
3097 struct spoolss_PrinterInfo2 *pinfo2,
3098 TALLOC_CTX *mem_ctx)
3100 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3103 /*******************************************************************
3104 * fill a notify_info_data with job name
3105 ********************************************************************/
3107 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3109 struct spoolss_Notify *data,
3110 print_queue_struct *queue,
3111 struct spoolss_PrinterInfo2 *pinfo2,
3112 TALLOC_CTX *mem_ctx)
3114 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3117 /*******************************************************************
3118 * fill a notify_info_data with job status
3119 ********************************************************************/
3121 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3123 struct spoolss_Notify *data,
3124 print_queue_struct *queue,
3125 struct spoolss_PrinterInfo2 *pinfo2,
3126 TALLOC_CTX *mem_ctx)
3129 * Now we're returning job status codes we just return a "" here. JRA.
3134 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3137 switch (queue->status) {
3142 p = ""; /* NT provides the paused string */
3151 #endif /* NO LONGER NEEDED. */
3153 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3156 /*******************************************************************
3157 * fill a notify_info_data with job time
3158 ********************************************************************/
3160 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3162 struct spoolss_Notify *data,
3163 print_queue_struct *queue,
3164 struct spoolss_PrinterInfo2 *pinfo2,
3165 TALLOC_CTX *mem_ctx)
3167 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3170 /*******************************************************************
3171 * fill a notify_info_data with job size
3172 ********************************************************************/
3174 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3176 struct spoolss_Notify *data,
3177 print_queue_struct *queue,
3178 struct spoolss_PrinterInfo2 *pinfo2,
3179 TALLOC_CTX *mem_ctx)
3181 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3184 /*******************************************************************
3185 * fill a notify_info_data with page info
3186 ********************************************************************/
3187 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3189 struct spoolss_Notify *data,
3190 print_queue_struct *queue,
3191 struct spoolss_PrinterInfo2 *pinfo2,
3192 TALLOC_CTX *mem_ctx)
3194 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3197 /*******************************************************************
3198 * fill a notify_info_data with pages printed info.
3199 ********************************************************************/
3200 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3202 struct spoolss_Notify *data,
3203 print_queue_struct *queue,
3204 struct spoolss_PrinterInfo2 *pinfo2,
3205 TALLOC_CTX *mem_ctx)
3207 /* Add code when back-end tracks this */
3208 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3211 /*******************************************************************
3212 Fill a notify_info_data with job position.
3213 ********************************************************************/
3215 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3217 struct spoolss_Notify *data,
3218 print_queue_struct *queue,
3219 struct spoolss_PrinterInfo2 *pinfo2,
3220 TALLOC_CTX *mem_ctx)
3222 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3225 /*******************************************************************
3226 Fill a notify_info_data with submitted time.
3227 ********************************************************************/
3229 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3231 struct spoolss_Notify *data,
3232 print_queue_struct *queue,
3233 struct spoolss_PrinterInfo2 *pinfo2,
3234 TALLOC_CTX *mem_ctx)
3236 data->data.string.string = NULL;
3237 data->data.string.size = 0;
3239 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3240 &data->data.string.string,
3241 &data->data.string.size);
3245 struct s_notify_info_data_table
3247 enum spoolss_NotifyType type;
3250 enum spoolss_NotifyTable variable_type;
3251 void (*fn) (struct messaging_context *msg_ctx,
3252 int snum, struct spoolss_Notify *data,
3253 print_queue_struct *queue,
3254 struct spoolss_PrinterInfo2 *pinfo2,
3255 TALLOC_CTX *mem_ctx);
3258 /* A table describing the various print notification constants and
3259 whether the notification data is a pointer to a variable sized
3260 buffer, a one value uint32_t or a two value uint32_t. */
3262 static const struct s_notify_info_data_table notify_info_data_table[] =
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3315 /*******************************************************************
3316 Return the variable_type of info_data structure.
3317 ********************************************************************/
3319 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3324 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3325 if ( (notify_info_data_table[i].type == type) &&
3326 (notify_info_data_table[i].field == field) ) {
3327 return notify_info_data_table[i].variable_type;
3331 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3333 return (enum spoolss_NotifyTable) 0;
3336 /****************************************************************************
3337 ****************************************************************************/
3339 static bool search_notify(enum spoolss_NotifyType type,
3345 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3346 if (notify_info_data_table[i].type == type &&
3347 notify_info_data_table[i].field == field &&
3348 notify_info_data_table[i].fn != NULL) {
3357 /****************************************************************************
3358 ****************************************************************************/
3360 static void construct_info_data(struct spoolss_Notify *info_data,
3361 enum spoolss_NotifyType type,
3362 uint16_t field, int id)
3364 info_data->type = type;
3365 info_data->field.field = field;
3366 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3367 info_data->job_id = id;
3370 /*******************************************************************
3372 * fill a notify_info struct with info asked
3374 ********************************************************************/
3376 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3377 struct printer_handle *print_hnd,
3378 struct spoolss_NotifyInfo *info,
3379 struct spoolss_PrinterInfo2 *pinfo2,
3381 const struct spoolss_NotifyOptionType *option_type,
3383 TALLOC_CTX *mem_ctx)
3386 enum spoolss_NotifyType type;
3389 struct spoolss_Notify *current_data;
3391 type = option_type->type;
3393 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3394 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3395 option_type->count, lp_servicename(snum)));
3397 for(field_num=0; field_num < option_type->count; field_num++) {
3398 field = option_type->fields[field_num].field;
3400 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3402 if (!search_notify(type, field, &j) )
3405 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3406 struct spoolss_Notify,
3408 if (info->notifies == NULL) {
3409 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3413 current_data = &info->notifies[info->count];
3415 construct_info_data(current_data, type, field, id);
3417 DEBUG(10, ("construct_notify_printer_info: "
3418 "calling [%s] snum=%d printername=[%s])\n",
3419 notify_info_data_table[j].name, snum,
3420 pinfo2->printername));
3422 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3423 NULL, pinfo2, mem_ctx);
3431 /*******************************************************************
3433 * fill a notify_info struct with info asked
3435 ********************************************************************/
3437 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3438 print_queue_struct *queue,
3439 struct spoolss_NotifyInfo *info,
3440 struct spoolss_PrinterInfo2 *pinfo2,
3442 const struct spoolss_NotifyOptionType *option_type,
3444 TALLOC_CTX *mem_ctx)
3447 enum spoolss_NotifyType type;
3449 struct spoolss_Notify *current_data;
3451 DEBUG(4,("construct_notify_jobs_info\n"));
3453 type = option_type->type;
3455 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3456 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3457 option_type->count));
3459 for(field_num=0; field_num<option_type->count; field_num++) {
3460 field = option_type->fields[field_num].field;
3462 if (!search_notify(type, field, &j) )
3465 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3466 struct spoolss_Notify,
3468 if (info->notifies == NULL) {
3469 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3473 current_data=&(info->notifies[info->count]);
3475 construct_info_data(current_data, type, field, id);
3476 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3477 queue, pinfo2, mem_ctx);
3485 * JFM: The enumeration is not that simple, it's even non obvious.
3487 * let's take an example: I want to monitor the PRINTER SERVER for
3488 * the printer's name and the number of jobs currently queued.
3489 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3490 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3492 * I have 3 printers on the back of my server.
3494 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3497 * 1 printer 1 name 1
3498 * 2 printer 1 cjob 1
3499 * 3 printer 2 name 2
3500 * 4 printer 2 cjob 2
3501 * 5 printer 3 name 3
3502 * 6 printer 3 name 3
3504 * that's the print server case, the printer case is even worse.
3507 /*******************************************************************
3509 * enumerate all printers on the printserver
3510 * fill a notify_info struct with info asked
3512 ********************************************************************/
3514 static WERROR printserver_notify_info(struct pipes_struct *p,
3515 struct policy_handle *hnd,
3516 struct spoolss_NotifyInfo *info,
3517 TALLOC_CTX *mem_ctx)
3520 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3521 int n_services=lp_numservices();
3523 struct spoolss_NotifyOption *option;
3524 struct spoolss_NotifyOptionType option_type;
3525 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3528 DEBUG(4,("printserver_notify_info\n"));
3533 option = Printer->notify.option;
3536 info->notifies = NULL;
3539 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3540 sending a ffpcn() request first */
3545 for (i=0; i<option->count; i++) {
3546 option_type = option->types[i];
3548 if (option_type.type != PRINTER_NOTIFY_TYPE)
3551 for (snum = 0; snum < n_services; snum++) {
3552 if (!lp_browseable(snum) ||
3553 !lp_snum_ok(snum) ||
3554 !lp_print_ok(snum)) {
3555 continue; /* skip */
3558 /* Maybe we should use the SYSTEM session_info here... */
3559 result = winreg_get_printer_internal(mem_ctx,
3560 get_session_info_system(),
3562 lp_servicename(snum),
3564 if (!W_ERROR_IS_OK(result)) {
3565 DEBUG(4, ("printserver_notify_info: "
3566 "Failed to get printer [%s]\n",
3567 lp_servicename(snum)));
3572 construct_notify_printer_info(p->msg_ctx,
3578 TALLOC_FREE(pinfo2);
3584 * Debugging information, don't delete.
3587 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3588 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3589 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3591 for (i=0; i<info->count; i++) {
3592 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3593 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3594 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3601 /*******************************************************************
3603 * fill a notify_info struct with info asked
3605 ********************************************************************/
3607 static WERROR printer_notify_info(struct pipes_struct *p,
3608 struct policy_handle *hnd,
3609 struct spoolss_NotifyInfo *info,
3610 TALLOC_CTX *mem_ctx)
3613 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3616 struct spoolss_NotifyOption *option;
3617 struct spoolss_NotifyOptionType option_type;
3619 print_queue_struct *queue=NULL;
3620 print_status_struct status;
3621 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3624 DEBUG(4,("printer_notify_info\n"));
3629 option = Printer->notify.option;
3633 info->notifies = NULL;
3636 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3637 sending a ffpcn() request first */
3642 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3646 /* Maybe we should use the SYSTEM session_info here... */
3647 result = winreg_get_printer_internal(mem_ctx,
3648 get_session_info_system(),
3650 lp_servicename(snum), &pinfo2);
3651 if (!W_ERROR_IS_OK(result)) {
3656 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3657 * correct servername.
3659 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3660 if (pinfo2->servername == NULL) {
3664 for (i=0; i<option->count; i++) {
3665 option_type = option->types[i];
3667 switch (option_type.type) {
3668 case PRINTER_NOTIFY_TYPE:
3669 if (construct_notify_printer_info(p->msg_ctx,
3678 case JOB_NOTIFY_TYPE:
3680 count = print_queue_status(p->msg_ctx, snum, &queue,
3683 for (j=0; j<count; j++) {
3684 construct_notify_jobs_info(p->msg_ctx,
3698 * Debugging information, don't delete.
3701 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3702 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3703 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3705 for (i=0; i<info->count; i++) {
3706 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3707 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3708 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3712 talloc_free(pinfo2);
3716 /****************************************************************
3717 _spoolss_RouterRefreshPrinterChangeNotify
3718 ****************************************************************/
3720 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3721 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3723 struct spoolss_NotifyInfo *info;
3725 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3726 WERROR result = WERR_BADFID;
3728 /* we always have a spoolss_NotifyInfo struct */
3729 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3731 result = WERR_NOMEM;
3735 *r->out.info = info;
3738 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3739 "Invalid handle (%s:%u:%u).\n",
3740 OUR_HANDLE(r->in.handle)));
3744 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3747 * We are now using the change value, and
3748 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3749 * I don't have a global notification system, I'm sending back all the
3750 * information even when _NOTHING_ has changed.
3753 /* We need to keep track of the change value to send back in
3754 RRPCN replies otherwise our updates are ignored. */
3756 Printer->notify.fnpcn = true;
3758 if (Printer->notify.cli_chan != NULL &&
3759 Printer->notify.cli_chan->active_connections > 0) {
3760 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3761 "Saving change value in request [%x]\n",
3763 Printer->notify.change = r->in.change_low;
3766 /* just ignore the spoolss_NotifyOption */
3768 switch (Printer->printer_type) {
3770 result = printserver_notify_info(p, r->in.handle,
3774 case SPLHND_PRINTER:
3775 result = printer_notify_info(p, r->in.handle,
3780 Printer->notify.fnpcn = false;
3786 /********************************************************************
3787 ********************************************************************/
3789 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3790 const char *servername,
3791 const char *printername,
3792 const char **printername_p)
3794 /* FIXME: add lp_force_printername() */
3796 if (servername == NULL) {
3797 *printername_p = talloc_strdup(mem_ctx, printername);
3798 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3802 if (servername[0] == '\\' && servername[1] == '\\') {
3806 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3807 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3812 /********************************************************************
3813 ********************************************************************/
3815 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3816 const char *printername)
3822 dm->devicename = talloc_strndup(dm, printername,
3823 MIN(strlen(printername), 31));
3826 /********************************************************************
3827 * construct_printer_info_0
3828 * fill a printer_info_0 struct
3829 ********************************************************************/
3831 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3832 const struct auth_serversupplied_info *session_info,
3833 struct messaging_context *msg_ctx,
3834 struct spoolss_PrinterInfo2 *info2,
3835 const char *servername,
3836 struct spoolss_PrinterInfo0 *r,
3840 struct printer_session_counter *session_counter;
3841 struct timeval setuptime;
3842 print_status_struct status;
3845 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3846 if (!W_ERROR_IS_OK(result)) {
3851 r->servername = talloc_strdup(mem_ctx, servername);
3852 W_ERROR_HAVE_NO_MEMORY(r->servername);
3854 r->servername = NULL;
3857 count = print_queue_length(msg_ctx, snum, &status);
3859 /* check if we already have a counter for this printer */
3860 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3861 if (session_counter->snum == snum)
3865 /* it's the first time, add it to the list */
3866 if (session_counter == NULL) {
3867 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3868 W_ERROR_HAVE_NO_MEMORY(session_counter);
3869 session_counter->snum = snum;
3870 session_counter->counter = 0;
3871 DLIST_ADD(counter_list, session_counter);
3875 session_counter->counter++;
3881 get_startup_time(&setuptime);
3882 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3885 * the global_counter should be stored in a TDB as it's common to all the clients
3886 * and should be zeroed on samba startup
3888 r->global_counter = session_counter->counter;
3890 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3891 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3892 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3893 r->free_build = SPOOLSS_RELEASE_BUILD;
3895 r->max_spooling = 0;
3896 r->session_counter = session_counter->counter;
3897 r->num_error_out_of_paper = 0x0;
3898 r->num_error_not_ready = 0x0; /* number of print failure */
3900 r->number_of_processors = 0x1;
3901 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3902 r->high_part_total_bytes = 0x0;
3904 /* ChangeID in milliseconds*/
3905 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3906 info2->sharename, &r->change_id);
3908 r->last_error = WERR_OK;
3909 r->status = nt_printq_status(status.status);
3910 r->enumerate_network_printers = 0x0;
3911 r->c_setprinter = 0x0;
3912 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3913 r->processor_level = 0x6; /* 6 ???*/
3922 /********************************************************************
3923 * construct_printer_info1
3924 * fill a spoolss_PrinterInfo1 struct
3925 ********************************************************************/
3927 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3928 const struct spoolss_PrinterInfo2 *info2,
3930 const char *servername,
3931 struct spoolss_PrinterInfo1 *r,
3938 if (info2->comment == NULL || info2->comment[0] == '\0') {
3939 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3941 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3943 W_ERROR_HAVE_NO_MEMORY(r->comment);
3945 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3946 if (!W_ERROR_IS_OK(result)) {
3950 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3954 W_ERROR_HAVE_NO_MEMORY(r->description);
3959 /********************************************************************
3960 * construct_printer_info2
3961 * fill a spoolss_PrinterInfo2 struct
3962 ********************************************************************/
3964 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3965 struct messaging_context *msg_ctx,
3966 const struct spoolss_PrinterInfo2 *info2,
3967 const char *servername,
3968 struct spoolss_PrinterInfo2 *r,
3972 print_status_struct status;
3975 count = print_queue_length(msg_ctx, snum, &status);
3978 r->servername = talloc_strdup(mem_ctx, servername);
3979 W_ERROR_HAVE_NO_MEMORY(r->servername);
3981 r->servername = NULL;
3984 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3985 if (!W_ERROR_IS_OK(result)) {
3989 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3990 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3991 r->portname = talloc_strdup(mem_ctx, info2->portname);
3992 W_ERROR_HAVE_NO_MEMORY(r->portname);
3993 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3994 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3996 if (info2->comment[0] == '\0') {
3997 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3999 r->comment = talloc_strdup(mem_ctx, info2->comment);
4001 W_ERROR_HAVE_NO_MEMORY(r->comment);
4003 r->location = talloc_strdup(mem_ctx, info2->location);
4004 if (info2->location[0] == '\0') {
4005 const char *loc = NULL;
4008 nt_status = printer_list_get_printer(mem_ctx,
4013 if (NT_STATUS_IS_OK(nt_status)) {
4015 r->location = talloc_strdup(mem_ctx, loc);
4019 W_ERROR_HAVE_NO_MEMORY(r->location);
4021 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4022 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4023 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4024 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4025 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4026 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4027 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4028 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4030 r->attributes = info2->attributes;
4032 r->priority = info2->priority;
4033 r->defaultpriority = info2->defaultpriority;
4034 r->starttime = info2->starttime;
4035 r->untiltime = info2->untiltime;
4036 r->status = nt_printq_status(status.status);
4038 r->averageppm = info2->averageppm;
4040 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4042 DEBUG(8,("Returning NULL Devicemode!\n"));
4045 compose_devicemode_devicename(r->devmode, r->printername);
4049 if (info2->secdesc != NULL) {
4050 /* don't use talloc_steal() here unless you do a deep steal of all
4051 the SEC_DESC members */
4053 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4059 /********************************************************************
4060 * construct_printer_info3
4061 * fill a spoolss_PrinterInfo3 struct
4062 ********************************************************************/
4064 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4065 const struct spoolss_PrinterInfo2 *info2,
4066 const char *servername,
4067 struct spoolss_PrinterInfo3 *r,
4070 /* These are the components of the SD we are returning. */
4072 if (info2->secdesc != NULL) {
4073 /* don't use talloc_steal() here unless you do a deep steal of all
4074 the SEC_DESC members */
4076 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4077 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4083 /********************************************************************
4084 * construct_printer_info4
4085 * fill a spoolss_PrinterInfo4 struct
4086 ********************************************************************/
4088 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4089 const struct spoolss_PrinterInfo2 *info2,
4090 const char *servername,
4091 struct spoolss_PrinterInfo4 *r,
4096 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4097 if (!W_ERROR_IS_OK(result)) {
4102 r->servername = talloc_strdup(mem_ctx, servername);
4103 W_ERROR_HAVE_NO_MEMORY(r->servername);
4105 r->servername = NULL;
4108 r->attributes = info2->attributes;
4113 /********************************************************************
4114 * construct_printer_info5
4115 * fill a spoolss_PrinterInfo5 struct
4116 ********************************************************************/
4118 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4119 const struct spoolss_PrinterInfo2 *info2,
4120 const char *servername,
4121 struct spoolss_PrinterInfo5 *r,
4126 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4127 if (!W_ERROR_IS_OK(result)) {
4131 r->portname = talloc_strdup(mem_ctx, info2->portname);
4132 W_ERROR_HAVE_NO_MEMORY(r->portname);
4134 r->attributes = info2->attributes;
4136 /* these two are not used by NT+ according to MSDN */
4137 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4138 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4143 /********************************************************************
4144 * construct_printer_info_6
4145 * fill a spoolss_PrinterInfo6 struct
4146 ********************************************************************/
4148 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4149 struct messaging_context *msg_ctx,
4150 const struct spoolss_PrinterInfo2 *info2,
4151 const char *servername,
4152 struct spoolss_PrinterInfo6 *r,
4156 print_status_struct status;
4158 count = print_queue_length(msg_ctx, snum, &status);
4160 r->status = nt_printq_status(status.status);
4165 /********************************************************************
4166 * construct_printer_info7
4167 * fill a spoolss_PrinterInfo7 struct
4168 ********************************************************************/
4170 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4171 struct messaging_context *msg_ctx,
4172 const char *servername,
4173 struct spoolss_PrinterInfo7 *r,
4176 struct auth_serversupplied_info *session_info;
4180 status = make_session_info_system(mem_ctx, &session_info);
4181 if (!NT_STATUS_IS_OK(status)) {
4182 DEBUG(0, ("construct_printer_info7: "
4183 "Could not create system session_info\n"));
4187 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4189 lp_servicename(snum), &guid, NULL)) {
4190 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4191 r->action = DSPRINT_PUBLISH;
4193 r->guid = talloc_strdup(mem_ctx, "");
4194 r->action = DSPRINT_UNPUBLISH;
4196 W_ERROR_HAVE_NO_MEMORY(r->guid);
4198 TALLOC_FREE(session_info);
4202 /********************************************************************
4203 * construct_printer_info8
4204 * fill a spoolss_PrinterInfo8 struct
4205 ********************************************************************/
4207 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4208 const struct spoolss_PrinterInfo2 *info2,
4209 const char *servername,
4210 struct spoolss_DeviceModeInfo *r,
4214 const char *printername;
4216 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4217 if (!W_ERROR_IS_OK(result)) {
4221 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4223 DEBUG(8,("Returning NULL Devicemode!\n"));
4226 compose_devicemode_devicename(r->devmode, printername);
4232 /********************************************************************
4233 ********************************************************************/
4235 static bool snum_is_shared_printer(int snum)
4237 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4240 /********************************************************************
4241 Spoolss_enumprinters.
4242 ********************************************************************/
4244 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4245 const struct auth_serversupplied_info *session_info,
4246 struct messaging_context *msg_ctx,
4247 const char *servername,
4250 union spoolss_PrinterInfo **info_p,
4254 int n_services = lp_numservices();
4255 union spoolss_PrinterInfo *info = NULL;
4257 WERROR result = WERR_OK;
4258 struct dcerpc_binding_handle *b = NULL;
4263 for (snum = 0; snum < n_services; snum++) {
4265 const char *printer;
4266 struct spoolss_PrinterInfo2 *info2;
4268 if (!snum_is_shared_printer(snum)) {
4272 printer = lp_const_servicename(snum);
4274 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4278 result = winreg_printer_binding_handle(mem_ctx,
4282 if (!W_ERROR_IS_OK(result)) {
4287 result = winreg_create_printer(mem_ctx, b,
4289 if (!W_ERROR_IS_OK(result)) {
4293 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4294 union spoolss_PrinterInfo,
4297 result = WERR_NOMEM;
4301 result = winreg_get_printer(mem_ctx, b,
4303 if (!W_ERROR_IS_OK(result)) {
4309 result = construct_printer_info0(info, session_info,
4312 &info[count].info0, snum);
4315 result = construct_printer_info1(info, info2, flags,
4317 &info[count].info1, snum);
4320 result = construct_printer_info2(info, msg_ctx, info2,
4322 &info[count].info2, snum);
4325 result = construct_printer_info4(info, info2,
4327 &info[count].info4, snum);
4330 result = construct_printer_info5(info, info2,
4332 &info[count].info5, snum);
4336 result = WERR_UNKNOWN_LEVEL;
4340 if (!W_ERROR_IS_OK(result)) {
4351 if (!W_ERROR_IS_OK(result)) {
4361 /********************************************************************
4362 * handle enumeration of printers at level 0
4363 ********************************************************************/
4365 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4366 const struct auth_serversupplied_info *session_info,
4367 struct messaging_context *msg_ctx,
4369 const char *servername,
4370 union spoolss_PrinterInfo **info,
4373 DEBUG(4,("enum_all_printers_info_0\n"));
4375 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4376 servername, 0, flags, info, count);
4380 /********************************************************************
4381 ********************************************************************/
4383 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4384 const struct auth_serversupplied_info *session_info,
4385 struct messaging_context *msg_ctx,
4386 const char *servername,
4388 union spoolss_PrinterInfo **info,
4391 DEBUG(4,("enum_all_printers_info_1\n"));
4393 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4394 servername, 1, flags, info, count);
4397 /********************************************************************
4398 enum_all_printers_info_1_local.
4399 *********************************************************************/
4401 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4402 const struct auth_serversupplied_info *session_info,
4403 struct messaging_context *msg_ctx,
4404 const char *servername,
4405 union spoolss_PrinterInfo **info,
4408 DEBUG(4,("enum_all_printers_info_1_local\n"));
4410 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4411 servername, PRINTER_ENUM_ICON8, info, count);
4414 /********************************************************************
4415 enum_all_printers_info_1_name.
4416 *********************************************************************/
4418 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4419 const struct auth_serversupplied_info *session_info,
4420 struct messaging_context *msg_ctx,
4421 const char *servername,
4422 union spoolss_PrinterInfo **info,
4425 const char *s = servername;
4427 DEBUG(4,("enum_all_printers_info_1_name\n"));
4429 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4433 if (!is_myname_or_ipaddr(s)) {
4434 return WERR_INVALID_NAME;
4437 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4438 servername, PRINTER_ENUM_ICON8, info, count);
4441 /********************************************************************
4442 enum_all_printers_info_1_network.
4443 *********************************************************************/
4445 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4446 const struct auth_serversupplied_info *session_info,
4447 struct messaging_context *msg_ctx,
4448 const char *servername,
4449 union spoolss_PrinterInfo **info,
4452 const char *s = servername;
4454 DEBUG(4,("enum_all_printers_info_1_network\n"));
4456 /* If we respond to a enum_printers level 1 on our name with flags
4457 set to PRINTER_ENUM_REMOTE with a list of printers then these
4458 printers incorrectly appear in the APW browse list.
4459 Specifically the printers for the server appear at the workgroup
4460 level where all the other servers in the domain are
4461 listed. Windows responds to this call with a
4462 WERR_CAN_NOT_COMPLETE so we should do the same. */
4464 if (servername[0] == '\\' && servername[1] == '\\') {
4468 if (is_myname_or_ipaddr(s)) {
4469 return WERR_CAN_NOT_COMPLETE;
4472 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4473 servername, PRINTER_ENUM_NAME, info, count);
4476 /********************************************************************
4477 * api_spoolss_enumprinters
4479 * called from api_spoolss_enumprinters (see this to understand)
4480 ********************************************************************/
4482 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4483 const struct auth_serversupplied_info *session_info,
4484 struct messaging_context *msg_ctx,
4485 const char *servername,
4486 union spoolss_PrinterInfo **info,
4489 DEBUG(4,("enum_all_printers_info_2\n"));
4491 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4492 servername, 2, 0, info, count);
4495 /********************************************************************
4496 * handle enumeration of printers at level 1
4497 ********************************************************************/
4499 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4500 const struct auth_serversupplied_info *session_info,
4501 struct messaging_context *msg_ctx,
4503 const char *servername,
4504 union spoolss_PrinterInfo **info,
4507 /* Not all the flags are equals */
4509 if (flags & PRINTER_ENUM_LOCAL) {
4510 return enum_all_printers_info_1_local(mem_ctx, session_info,
4511 msg_ctx, servername, info, count);
4514 if (flags & PRINTER_ENUM_NAME) {
4515 return enum_all_printers_info_1_name(mem_ctx, session_info,
4516 msg_ctx, servername, info,
4520 if (flags & PRINTER_ENUM_NETWORK) {
4521 return enum_all_printers_info_1_network(mem_ctx, session_info,
4522 msg_ctx, servername, info,
4526 return WERR_OK; /* NT4sp5 does that */
4529 /********************************************************************
4530 * handle enumeration of printers at level 2
4531 ********************************************************************/
4533 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4534 const struct auth_serversupplied_info *session_info,
4535 struct messaging_context *msg_ctx,
4537 const char *servername,
4538 union spoolss_PrinterInfo **info,
4541 if (flags & PRINTER_ENUM_LOCAL) {
4543 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4548 if (flags & PRINTER_ENUM_NAME) {
4549 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4550 return WERR_INVALID_NAME;
4553 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4558 if (flags & PRINTER_ENUM_REMOTE) {
4559 return WERR_UNKNOWN_LEVEL;
4565 /********************************************************************
4566 * handle enumeration of printers at level 4
4567 ********************************************************************/
4569 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4570 const struct auth_serversupplied_info *session_info,
4571 struct messaging_context *msg_ctx,
4573 const char *servername,
4574 union spoolss_PrinterInfo **info,
4577 DEBUG(4,("enum_all_printers_info_4\n"));
4579 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4580 servername, 4, flags, info, count);
4584 /********************************************************************
4585 * handle enumeration of printers at level 5
4586 ********************************************************************/
4588 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4589 const struct auth_serversupplied_info *session_info,
4590 struct messaging_context *msg_ctx,
4592 const char *servername,
4593 union spoolss_PrinterInfo **info,
4596 DEBUG(4,("enum_all_printers_info_5\n"));
4598 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4599 servername, 5, flags, info, count);
4602 /****************************************************************
4603 _spoolss_EnumPrinters
4604 ****************************************************************/
4606 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4607 struct spoolss_EnumPrinters *r)
4609 const struct auth_serversupplied_info *session_info = get_session_info_system();
4612 /* that's an [in out] buffer */
4614 if (!r->in.buffer && (r->in.offered != 0)) {
4615 return WERR_INVALID_PARAM;
4618 DEBUG(4,("_spoolss_EnumPrinters\n"));
4622 *r->out.info = NULL;
4626 * flags==PRINTER_ENUM_NAME
4627 * if name=="" then enumerates all printers
4628 * if name!="" then enumerate the printer
4629 * flags==PRINTER_ENUM_REMOTE
4630 * name is NULL, enumerate printers
4631 * Level 2: name!="" enumerates printers, name can't be NULL
4632 * Level 3: doesn't exist
4633 * Level 4: does a local registry lookup
4634 * Level 5: same as Level 2
4637 if (r->in.server && r->in.server[0] == '\0') {
4638 r->in.server = NULL;
4641 switch (r->in.level) {
4643 result = enumprinters_level0(p->mem_ctx, session_info,
4644 p->msg_ctx, r->in.flags,
4646 r->out.info, r->out.count);
4649 result = enumprinters_level1(p->mem_ctx, session_info,
4650 p->msg_ctx, r->in.flags,
4652 r->out.info, r->out.count);
4655 result = enumprinters_level2(p->mem_ctx, session_info,
4656 p->msg_ctx, r->in.flags,
4658 r->out.info, r->out.count);
4661 result = enumprinters_level4(p->mem_ctx, session_info,
4662 p->msg_ctx, r->in.flags,
4664 r->out.info, r->out.count);
4667 result = enumprinters_level5(p->mem_ctx, session_info,
4668 p->msg_ctx, r->in.flags,
4670 r->out.info, r->out.count);
4673 return WERR_UNKNOWN_LEVEL;
4676 if (!W_ERROR_IS_OK(result)) {
4680 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4681 spoolss_EnumPrinters,
4682 *r->out.info, r->in.level,
4684 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4685 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4687 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4690 /****************************************************************
4692 ****************************************************************/
4694 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4695 struct spoolss_GetPrinter *r)
4697 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4698 struct spoolss_PrinterInfo2 *info2 = NULL;
4699 WERROR result = WERR_OK;
4702 /* that's an [in out] buffer */
4704 if (!r->in.buffer && (r->in.offered != 0)) {
4705 return WERR_INVALID_PARAM;
4710 if (Printer == NULL) {
4714 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4718 result = winreg_get_printer_internal(p->mem_ctx,
4719 get_session_info_system(),
4721 lp_const_servicename(snum),
4723 if (!W_ERROR_IS_OK(result)) {
4727 switch (r->in.level) {
4729 result = construct_printer_info0(p->mem_ctx,
4730 get_session_info_system(),
4733 Printer->servername,
4734 &r->out.info->info0,
4738 result = construct_printer_info1(p->mem_ctx, info2,
4740 Printer->servername,
4741 &r->out.info->info1, snum);
4744 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4745 Printer->servername,
4746 &r->out.info->info2, snum);
4749 result = construct_printer_info3(p->mem_ctx, info2,
4750 Printer->servername,
4751 &r->out.info->info3, snum);
4754 result = construct_printer_info4(p->mem_ctx, info2,
4755 Printer->servername,
4756 &r->out.info->info4, snum);
4759 result = construct_printer_info5(p->mem_ctx, info2,
4760 Printer->servername,
4761 &r->out.info->info5, snum);
4764 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4765 Printer->servername,
4766 &r->out.info->info6, snum);
4769 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4770 Printer->servername,
4771 &r->out.info->info7, snum);
4774 result = construct_printer_info8(p->mem_ctx, info2,
4775 Printer->servername,
4776 &r->out.info->info8, snum);
4779 result = WERR_UNKNOWN_LEVEL;
4784 if (!W_ERROR_IS_OK(result)) {
4785 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4786 r->in.level, win_errstr(result)));
4787 TALLOC_FREE(r->out.info);
4791 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4792 r->out.info, r->in.level);
4793 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4795 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4798 /********************************************************************
4799 ********************************************************************/
4801 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4803 if (in && strlen(in)) { \
4804 out = talloc_strdup(mem_ctx, in); \
4806 out = talloc_strdup(mem_ctx, ""); \
4808 W_ERROR_HAVE_NO_MEMORY(out); \
4811 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4813 if (in && strlen(in)) { \
4814 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4816 out = talloc_strdup(mem_ctx, ""); \
4818 W_ERROR_HAVE_NO_MEMORY(out); \
4821 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4822 const char **string_array,
4823 const char ***presult,
4824 const char *cservername,
4828 int i, num_strings = 0;
4829 const char **array = NULL;
4831 if (string_array == NULL) {
4832 return WERR_INVALID_PARAMETER;
4835 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4836 const char *str = NULL;
4838 if (cservername == NULL || arch == NULL) {
4839 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4841 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4844 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4851 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4852 &array, &num_strings);
4862 /********************************************************************
4863 * fill a spoolss_DriverInfo1 struct
4864 ********************************************************************/
4866 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4867 struct spoolss_DriverInfo1 *r,
4868 const struct spoolss_DriverInfo8 *driver,
4869 const char *servername)
4871 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4872 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4877 /********************************************************************
4878 * fill a spoolss_DriverInfo2 struct
4879 ********************************************************************/
4881 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4882 struct spoolss_DriverInfo2 *r,
4883 const struct spoolss_DriverInfo8 *driver,
4884 const char *servername)
4887 const char *cservername = canon_servername(servername);
4889 r->version = driver->version;
4891 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4892 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4893 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4894 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4896 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4897 driver->architecture,
4899 driver->driver_path,
4902 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4903 driver->architecture,
4908 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4909 driver->architecture,
4911 driver->config_file,
4917 /********************************************************************
4918 * fill a spoolss_DriverInfo3 struct
4919 ********************************************************************/
4921 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4922 struct spoolss_DriverInfo3 *r,
4923 const struct spoolss_DriverInfo8 *driver,
4924 const char *servername)
4926 const char *cservername = canon_servername(servername);
4928 r->version = driver->version;
4930 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4931 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4932 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4933 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4935 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4936 driver->architecture,
4938 driver->driver_path,
4941 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4942 driver->architecture,
4947 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4948 driver->architecture,
4950 driver->config_file,
4953 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954 driver->architecture,
4959 FILL_DRIVER_STRING(mem_ctx,
4960 driver->monitor_name,
4963 FILL_DRIVER_STRING(mem_ctx,
4964 driver->default_datatype,
4965 r->default_datatype);
4967 return string_array_from_driver_info(mem_ctx,
4968 driver->dependent_files,
4969 &r->dependent_files,
4971 driver->architecture,
4975 /********************************************************************
4976 * fill a spoolss_DriverInfo4 struct
4977 ********************************************************************/
4979 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4980 struct spoolss_DriverInfo4 *r,
4981 const struct spoolss_DriverInfo8 *driver,
4982 const char *servername)
4984 const char *cservername = canon_servername(servername);
4987 r->version = driver->version;
4989 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4990 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4991 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4992 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4994 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995 driver->architecture,
4997 driver->driver_path,
5000 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001 driver->architecture,
5006 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5007 driver->architecture,
5009 driver->config_file,
5012 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013 driver->architecture,
5018 result = string_array_from_driver_info(mem_ctx,
5019 driver->dependent_files,
5020 &r->dependent_files,
5022 driver->architecture,
5024 if (!W_ERROR_IS_OK(result)) {
5028 FILL_DRIVER_STRING(mem_ctx,
5029 driver->monitor_name,
5032 FILL_DRIVER_STRING(mem_ctx,
5033 driver->default_datatype,
5034 r->default_datatype);
5037 result = string_array_from_driver_info(mem_ctx,
5038 driver->previous_names,
5045 /********************************************************************
5046 * fill a spoolss_DriverInfo5 struct
5047 ********************************************************************/
5049 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5050 struct spoolss_DriverInfo5 *r,
5051 const struct spoolss_DriverInfo8 *driver,
5052 const char *servername)
5054 const char *cservername = canon_servername(servername);
5056 r->version = driver->version;
5058 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5059 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5060 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5061 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5063 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5064 driver->architecture,
5066 driver->driver_path,
5069 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5070 driver->architecture,
5075 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5076 driver->architecture,
5078 driver->config_file,
5081 r->driver_attributes = 0;
5082 r->config_version = 0;
5083 r->driver_version = 0;
5087 /********************************************************************
5088 * fill a spoolss_DriverInfo6 struct
5089 ********************************************************************/
5091 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5092 struct spoolss_DriverInfo6 *r,
5093 const struct spoolss_DriverInfo8 *driver,
5094 const char *servername)
5096 const char *cservername = canon_servername(servername);
5099 r->version = driver->version;
5101 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5102 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5103 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5104 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5106 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107 driver->architecture,
5109 driver->driver_path,
5112 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113 driver->architecture,
5118 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119 driver->architecture,
5121 driver->config_file,
5124 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125 driver->architecture,
5130 FILL_DRIVER_STRING(mem_ctx,
5131 driver->monitor_name,
5134 FILL_DRIVER_STRING(mem_ctx,
5135 driver->default_datatype,
5136 r->default_datatype);
5138 result = string_array_from_driver_info(mem_ctx,
5139 driver->dependent_files,
5140 &r->dependent_files,
5142 driver->architecture,
5144 if (!W_ERROR_IS_OK(result)) {
5148 result = string_array_from_driver_info(mem_ctx,
5149 driver->previous_names,
5152 if (!W_ERROR_IS_OK(result)) {
5156 r->driver_date = driver->driver_date;
5157 r->driver_version = driver->driver_version;
5159 FILL_DRIVER_STRING(mem_ctx,
5160 driver->manufacturer_name,
5161 r->manufacturer_name);
5162 FILL_DRIVER_STRING(mem_ctx,
5163 driver->manufacturer_url,
5164 r->manufacturer_url);
5165 FILL_DRIVER_STRING(mem_ctx,
5166 driver->hardware_id,
5168 FILL_DRIVER_STRING(mem_ctx,
5175 /********************************************************************
5176 * fill a spoolss_DriverInfo8 struct
5177 ********************************************************************/
5179 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5180 struct spoolss_DriverInfo8 *r,
5181 const struct spoolss_DriverInfo8 *driver,
5182 const char *servername)
5184 const char *cservername = canon_servername(servername);
5187 r->version = driver->version;
5189 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5190 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5191 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5192 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5194 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5195 driver->architecture,
5197 driver->driver_path,
5200 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5201 driver->architecture,
5206 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5207 driver->architecture,
5209 driver->config_file,
5212 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213 driver->architecture,
5218 FILL_DRIVER_STRING(mem_ctx,
5219 driver->monitor_name,
5222 FILL_DRIVER_STRING(mem_ctx,
5223 driver->default_datatype,
5224 r->default_datatype);
5226 result = string_array_from_driver_info(mem_ctx,
5227 driver->dependent_files,
5228 &r->dependent_files,
5230 driver->architecture,
5232 if (!W_ERROR_IS_OK(result)) {
5236 result = string_array_from_driver_info(mem_ctx,
5237 driver->previous_names,
5240 if (!W_ERROR_IS_OK(result)) {
5244 r->driver_date = driver->driver_date;
5245 r->driver_version = driver->driver_version;
5247 FILL_DRIVER_STRING(mem_ctx,
5248 driver->manufacturer_name,
5249 r->manufacturer_name);
5250 FILL_DRIVER_STRING(mem_ctx,
5251 driver->manufacturer_url,
5252 r->manufacturer_url);
5253 FILL_DRIVER_STRING(mem_ctx,
5254 driver->hardware_id,
5256 FILL_DRIVER_STRING(mem_ctx,
5260 FILL_DRIVER_STRING(mem_ctx,
5261 driver->print_processor,
5262 r->print_processor);
5263 FILL_DRIVER_STRING(mem_ctx,
5264 driver->vendor_setup,
5267 result = string_array_from_driver_info(mem_ctx,
5268 driver->color_profiles,
5271 if (!W_ERROR_IS_OK(result)) {
5275 FILL_DRIVER_STRING(mem_ctx,
5279 r->printer_driver_attributes = driver->printer_driver_attributes;
5281 result = string_array_from_driver_info(mem_ctx,
5282 driver->core_driver_dependencies,
5283 &r->core_driver_dependencies,
5285 if (!W_ERROR_IS_OK(result)) {
5289 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5290 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5295 #if 0 /* disabled until marshalling issues are resolved - gd */
5296 /********************************************************************
5297 ********************************************************************/
5299 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5300 struct spoolss_DriverFileInfo *r,
5301 const char *cservername,
5302 const char *file_name,
5303 enum spoolss_DriverFileType file_type,
5304 uint32_t file_version)
5306 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5307 cservername, file_name);
5308 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5309 r->file_type = file_type;
5310 r->file_version = file_version;
5315 /********************************************************************
5316 ********************************************************************/
5318 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5319 const struct spoolss_DriverInfo8 *driver,
5320 const char *cservername,
5321 struct spoolss_DriverFileInfo **info_p,
5324 struct spoolss_DriverFileInfo *info = NULL;
5332 if (strlen(driver->driver_path)) {
5333 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5334 struct spoolss_DriverFileInfo,
5336 W_ERROR_HAVE_NO_MEMORY(info);
5337 result = fill_spoolss_DriverFileInfo(info,
5340 driver->driver_path,
5341 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5343 W_ERROR_NOT_OK_RETURN(result);
5347 if (strlen(driver->config_file)) {
5348 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5349 struct spoolss_DriverFileInfo,
5351 W_ERROR_HAVE_NO_MEMORY(info);
5352 result = fill_spoolss_DriverFileInfo(info,
5355 driver->config_file,
5356 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5358 W_ERROR_NOT_OK_RETURN(result);
5362 if (strlen(driver->data_file)) {
5363 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5364 struct spoolss_DriverFileInfo,
5366 W_ERROR_HAVE_NO_MEMORY(info);
5367 result = fill_spoolss_DriverFileInfo(info,
5371 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5373 W_ERROR_NOT_OK_RETURN(result);
5377 if (strlen(driver->help_file)) {
5378 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5379 struct spoolss_DriverFileInfo,
5381 W_ERROR_HAVE_NO_MEMORY(info);
5382 result = fill_spoolss_DriverFileInfo(info,
5386 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5388 W_ERROR_NOT_OK_RETURN(result);
5392 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5393 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5394 struct spoolss_DriverFileInfo,
5396 W_ERROR_HAVE_NO_MEMORY(info);
5397 result = fill_spoolss_DriverFileInfo(info,
5400 driver->dependent_files[i],
5401 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5403 W_ERROR_NOT_OK_RETURN(result);
5413 /********************************************************************
5414 * fill a spoolss_DriverInfo101 struct
5415 ********************************************************************/
5417 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5418 struct spoolss_DriverInfo101 *r,
5419 const struct spoolss_DriverInfo8 *driver,
5420 const char *servername)
5422 const char *cservername = canon_servername(servername);
5425 r->version = driver->version;
5427 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5428 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5429 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5430 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5432 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5436 if (!W_ERROR_IS_OK(result)) {
5440 FILL_DRIVER_STRING(mem_ctx,
5441 driver->monitor_name,
5444 FILL_DRIVER_STRING(mem_ctx,
5445 driver->default_datatype,
5446 r->default_datatype);
5448 result = string_array_from_driver_info(mem_ctx,
5449 driver->previous_names,
5452 if (!W_ERROR_IS_OK(result)) {
5456 r->driver_date = driver->driver_date;
5457 r->driver_version = driver->driver_version;
5459 FILL_DRIVER_STRING(mem_ctx,
5460 driver->manufacturer_name,
5461 r->manufacturer_name);
5462 FILL_DRIVER_STRING(mem_ctx,
5463 driver->manufacturer_url,
5464 r->manufacturer_url);
5465 FILL_DRIVER_STRING(mem_ctx,
5466 driver->hardware_id,
5468 FILL_DRIVER_STRING(mem_ctx,
5475 /********************************************************************
5476 ********************************************************************/
5478 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5479 const struct auth_serversupplied_info *session_info,
5480 struct messaging_context *msg_ctx,
5482 union spoolss_DriverInfo *r,
5484 const char *servername,
5485 const char *architecture,
5488 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5489 struct spoolss_DriverInfo8 *driver;
5491 struct dcerpc_binding_handle *b;
5494 return WERR_UNKNOWN_LEVEL;
5497 result = winreg_printer_binding_handle(mem_ctx,
5501 if (!W_ERROR_IS_OK(result)) {
5505 result = winreg_get_printer(mem_ctx, b,
5506 lp_const_servicename(snum),
5509 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5510 win_errstr(result)));
5512 if (!W_ERROR_IS_OK(result)) {
5513 return WERR_INVALID_PRINTER_NAME;
5516 result = winreg_get_driver(mem_ctx, b,
5518 pinfo2->drivername, version, &driver);
5520 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5521 win_errstr(result)));
5523 if (!W_ERROR_IS_OK(result)) {
5525 * Is this a W2k client ?
5529 talloc_free(pinfo2);
5530 return WERR_UNKNOWN_PRINTER_DRIVER;
5533 /* Yes - try again with a WinNT driver. */
5535 result = winreg_get_driver(mem_ctx, b,
5539 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5540 win_errstr(result)));
5541 if (!W_ERROR_IS_OK(result)) {
5542 talloc_free(pinfo2);
5543 return WERR_UNKNOWN_PRINTER_DRIVER;
5549 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5552 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5555 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5558 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5561 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5564 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5567 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5569 #if 0 /* disabled until marshalling issues are resolved - gd */
5571 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5575 result = WERR_UNKNOWN_LEVEL;
5579 talloc_free(pinfo2);
5580 talloc_free(driver);
5585 /****************************************************************
5586 _spoolss_GetPrinterDriver2
5587 ****************************************************************/
5589 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5590 struct spoolss_GetPrinterDriver2 *r)
5592 struct printer_handle *printer;
5597 /* that's an [in out] buffer */
5599 if (!r->in.buffer && (r->in.offered != 0)) {
5600 return WERR_INVALID_PARAM;
5603 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5605 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5606 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5607 return WERR_INVALID_PRINTER_NAME;
5611 *r->out.server_major_version = 0;
5612 *r->out.server_minor_version = 0;
5614 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5618 result = construct_printer_driver_info_level(p->mem_ctx,
5619 get_session_info_system(),
5621 r->in.level, r->out.info,
5622 snum, printer->servername,
5624 r->in.client_major_version);
5625 if (!W_ERROR_IS_OK(result)) {
5626 TALLOC_FREE(r->out.info);
5630 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5631 r->out.info, r->in.level);
5632 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5634 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5638 /****************************************************************
5639 _spoolss_StartPagePrinter
5640 ****************************************************************/
5642 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5643 struct spoolss_StartPagePrinter *r)
5645 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5648 DEBUG(3,("_spoolss_StartPagePrinter: "
5649 "Error in startpageprinter printer handle\n"));
5653 Printer->page_started = true;
5657 /****************************************************************
5658 _spoolss_EndPagePrinter
5659 ****************************************************************/
5661 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5662 struct spoolss_EndPagePrinter *r)
5666 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5669 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5670 OUR_HANDLE(r->in.handle)));
5674 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5677 Printer->page_started = false;
5678 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5683 /****************************************************************
5684 _spoolss_StartDocPrinter
5685 ****************************************************************/
5687 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5688 struct spoolss_StartDocPrinter *r)
5690 struct spoolss_DocumentInfo1 *info_1;
5692 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5696 DEBUG(2,("_spoolss_StartDocPrinter: "
5697 "Invalid handle (%s:%u:%u)\n",
5698 OUR_HANDLE(r->in.handle)));
5702 if (Printer->jobid) {
5703 DEBUG(2, ("_spoolss_StartDocPrinter: "
5704 "StartDocPrinter called twice! "
5705 "(existing jobid = %d)\n", Printer->jobid));
5706 return WERR_INVALID_HANDLE;
5709 if (r->in.level != 1) {
5710 return WERR_UNKNOWN_LEVEL;
5713 info_1 = r->in.info.info1;
5716 * a nice thing with NT is it doesn't listen to what you tell it.
5717 * when asked to send _only_ RAW datas, it tries to send datas
5720 * So I add checks like in NT Server ...
5723 if (info_1->datatype) {
5724 if (strcmp(info_1->datatype, "RAW") != 0) {
5726 return WERR_INVALID_DATATYPE;
5730 /* get the share number of the printer */
5731 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5735 werr = print_job_start(p->session_info,
5739 info_1->document_name,
5740 info_1->output_file,
5744 /* An error occured in print_job_start() so return an appropriate
5747 if (!W_ERROR_IS_OK(werr)) {
5751 Printer->document_started = true;
5752 *r->out.job_id = Printer->jobid;
5757 /****************************************************************
5758 _spoolss_EndDocPrinter
5759 ****************************************************************/
5761 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5762 struct spoolss_EndDocPrinter *r)
5764 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5769 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5770 OUR_HANDLE(r->in.handle)));
5774 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5778 Printer->document_started = false;
5779 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5780 if (!NT_STATUS_IS_OK(status)) {
5781 DEBUG(2, ("_spoolss_EndDocPrinter: "
5782 "print_job_end failed [%s]\n",
5783 nt_errstr(status)));
5787 return ntstatus_to_werror(status);
5790 /****************************************************************
5791 _spoolss_WritePrinter
5792 ****************************************************************/
5794 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5795 struct spoolss_WritePrinter *r)
5797 ssize_t buffer_written;
5799 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5802 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5803 OUR_HANDLE(r->in.handle)));
5804 *r->out.num_written = r->in._data_size;
5808 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5811 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5812 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5813 snum, Printer->jobid,
5814 (const char *)r->in.data.data,
5815 (size_t)r->in._data_size);
5816 if (buffer_written == (ssize_t)-1) {
5817 *r->out.num_written = 0;
5818 if (errno == ENOSPC)
5819 return WERR_NO_SPOOL_SPACE;
5821 return WERR_ACCESS_DENIED;
5824 *r->out.num_written = r->in._data_size;
5829 /********************************************************************
5830 * api_spoolss_getprinter
5831 * called from the spoolss dispatcher
5833 ********************************************************************/
5835 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5836 struct pipes_struct *p)
5838 const struct auth_serversupplied_info *session_info = p->session_info;
5840 WERROR errcode = WERR_BADFUNC;
5841 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5844 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5845 OUR_HANDLE(handle)));
5849 if (!get_printer_snum(p, handle, &snum, NULL))
5853 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5854 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5856 case SPOOLSS_PRINTER_CONTROL_RESUME:
5857 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5858 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5860 case SPOOLSS_PRINTER_CONTROL_PURGE:
5861 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5864 return WERR_UNKNOWN_LEVEL;
5871 /****************************************************************
5872 _spoolss_AbortPrinter
5873 * From MSDN: "Deletes printer's spool file if printer is configured
5875 ****************************************************************/
5877 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5878 struct spoolss_AbortPrinter *r)
5880 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5882 WERROR errcode = WERR_OK;
5885 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5886 OUR_HANDLE(r->in.handle)));
5890 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5893 if (!Printer->document_started) {
5894 return WERR_SPL_NO_STARTDOC;
5897 errcode = print_job_delete(p->session_info,
5905 /********************************************************************
5906 * called by spoolss_api_setprinter
5907 * when updating a printer description
5908 ********************************************************************/
5910 static WERROR update_printer_sec(struct policy_handle *handle,
5911 struct pipes_struct *p,
5912 struct sec_desc_buf *secdesc_ctr)
5914 struct spoolss_security_descriptor *new_secdesc = NULL;
5915 struct spoolss_security_descriptor *old_secdesc = NULL;
5916 const char *printer;
5919 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5920 struct dcerpc_binding_handle *b;
5922 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5923 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5924 OUR_HANDLE(handle)));
5926 result = WERR_BADFID;
5930 if (secdesc_ctr == NULL) {
5931 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5932 result = WERR_INVALID_PARAM;
5935 printer = lp_const_servicename(snum);
5937 /* Check the user has permissions to change the security
5938 descriptor. By experimentation with two NT machines, the user
5939 requires Full Access to the printer to change security
5942 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5943 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5944 result = WERR_ACCESS_DENIED;
5948 result = winreg_printer_binding_handle(p->mem_ctx,
5949 get_session_info_system(),
5952 if (!W_ERROR_IS_OK(result)) {
5956 /* NT seems to like setting the security descriptor even though
5957 nothing may have actually changed. */
5958 result = winreg_get_printer_secdesc(p->mem_ctx, b,
5961 if (!W_ERROR_IS_OK(result)) {
5962 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5963 result = WERR_BADFID;
5967 if (DEBUGLEVEL >= 10) {
5968 struct security_acl *the_acl;
5971 the_acl = old_secdesc->dacl;
5972 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5973 printer, the_acl->num_aces));
5975 for (i = 0; i < the_acl->num_aces; i++) {
5976 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5977 &the_acl->aces[i].trustee),
5978 the_acl->aces[i].access_mask));
5981 the_acl = secdesc_ctr->sd->dacl;
5984 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5985 printer, the_acl->num_aces));
5987 for (i = 0; i < the_acl->num_aces; i++) {
5988 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5989 &the_acl->aces[i].trustee),
5990 the_acl->aces[i].access_mask));
5993 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5997 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5998 if (new_secdesc == NULL) {
5999 result = WERR_NOMEM;
6003 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6008 result = winreg_set_printer_secdesc(p->mem_ctx, b,
6016 /********************************************************************
6017 Canonicalize printer info from a client
6018 ********************************************************************/
6020 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6021 struct spoolss_SetPrinterInfo2 *info2,
6024 fstring printername;
6027 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6028 "portname=%s drivername=%s comment=%s location=%s\n",
6029 info2->servername, info2->printername, info2->sharename,
6030 info2->portname, info2->drivername, info2->comment,
6033 /* we force some elements to "correct" values */
6034 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6035 if (info2->servername == NULL) {
6038 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6039 if (info2->sharename == NULL) {
6043 /* check to see if we allow printername != sharename */
6044 if (lp_force_printername(snum)) {
6045 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6046 global_myname(), info2->sharename);
6048 /* make sure printername is in \\server\printername format */
6049 fstrcpy(printername, info2->printername);
6051 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6052 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6056 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6057 global_myname(), p);
6059 if (info2->printername == NULL) {
6063 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6064 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6069 /****************************************************************************
6070 ****************************************************************************/
6072 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6074 char *cmd = lp_addport_cmd();
6075 char *command = NULL;
6077 bool is_print_op = false;
6080 return WERR_ACCESS_DENIED;
6083 command = talloc_asprintf(ctx,
6084 "%s \"%s\" \"%s\"", cmd, portname, uri );
6090 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6092 DEBUG(10,("Running [%s]\n", command));
6094 /********* BEGIN SePrintOperatorPrivilege **********/
6099 ret = smbrun(command, NULL);
6104 /********* END SePrintOperatorPrivilege **********/
6106 DEBUGADD(10,("returned [%d]\n", ret));
6108 TALLOC_FREE(command);
6111 return WERR_ACCESS_DENIED;
6117 /****************************************************************************
6118 ****************************************************************************/
6120 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6121 struct spoolss_SetPrinterInfo2 *info2,
6122 const char *remote_machine,
6123 struct messaging_context *msg_ctx)
6125 char *cmd = lp_addprinter_cmd();
6127 char *command = NULL;
6131 bool is_print_op = false;
6133 if (!remote_machine) {
6137 command = talloc_asprintf(ctx,
6138 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6139 cmd, info2->printername, info2->sharename,
6140 info2->portname, info2->drivername,
6141 info2->location, info2->comment, remote_machine);
6147 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6149 DEBUG(10,("Running [%s]\n", command));
6151 /********* BEGIN SePrintOperatorPrivilege **********/
6156 if ( (ret = smbrun(command, &fd)) == 0 ) {
6157 /* Tell everyone we updated smb.conf. */
6158 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6164 /********* END SePrintOperatorPrivilege **********/
6166 DEBUGADD(10,("returned [%d]\n", ret));
6168 TALLOC_FREE(command);
6176 /* reload our services immediately */
6178 reload_services(msg_ctx, -1, false);
6182 /* Get lines and convert them back to dos-codepage */
6183 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6184 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6187 /* Set the portname to what the script says the portname should be. */
6188 /* but don't require anything to be return from the script exit a good error code */
6191 /* Set the portname to what the script says the portname should be. */
6192 info2->portname = talloc_strdup(ctx, qlines[0]);
6193 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6196 TALLOC_FREE(qlines);
6200 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6201 const struct auth_serversupplied_info *session_info,
6202 struct messaging_context *msg_ctx,
6204 struct spoolss_SetPrinterInfo2 *printer,
6205 struct spoolss_PrinterInfo2 *old_printer)
6207 bool force_update = (old_printer == NULL);
6208 const char *dnsdomname;
6209 const char *longname;
6210 const char *uncname;
6211 const char *spooling;
6213 WERROR result = WERR_OK;
6214 struct dcerpc_binding_handle *b;
6216 result = winreg_printer_binding_handle(mem_ctx,
6220 if (!W_ERROR_IS_OK(result)) {
6224 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6225 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6226 winreg_set_printer_dataex(mem_ctx, b,
6228 SPOOL_DSSPOOLER_KEY,
6229 SPOOL_REG_DRIVERNAME,
6234 if (!force_update) {
6235 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6236 printer->drivername));
6238 notify_printer_driver(server_event_context(), msg_ctx,
6239 snum, printer->drivername ?
6240 printer->drivername : "");
6244 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6245 push_reg_sz(mem_ctx, &buffer, printer->comment);
6246 winreg_set_printer_dataex(mem_ctx, b,
6248 SPOOL_DSSPOOLER_KEY,
6249 SPOOL_REG_DESCRIPTION,
6254 if (!force_update) {
6255 notify_printer_comment(server_event_context(), msg_ctx,
6256 snum, printer->comment ?
6257 printer->comment : "");
6261 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6262 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6263 winreg_set_printer_dataex(mem_ctx, b,
6265 SPOOL_DSSPOOLER_KEY,
6266 SPOOL_REG_PRINTSHARENAME,
6271 if (!force_update) {
6272 notify_printer_sharename(server_event_context(),
6274 snum, printer->sharename ?
6275 printer->sharename : "");
6279 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6282 p = strrchr(printer->printername, '\\' );
6286 p = printer->printername;
6289 push_reg_sz(mem_ctx, &buffer, p);
6290 winreg_set_printer_dataex(mem_ctx, b,
6292 SPOOL_DSSPOOLER_KEY,
6293 SPOOL_REG_PRINTERNAME,
6298 if (!force_update) {
6299 notify_printer_printername(server_event_context(),
6300 msg_ctx, snum, p ? p : "");
6304 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6305 push_reg_sz(mem_ctx, &buffer, printer->portname);
6306 winreg_set_printer_dataex(mem_ctx, b,
6308 SPOOL_DSSPOOLER_KEY,
6314 if (!force_update) {
6315 notify_printer_port(server_event_context(),
6316 msg_ctx, snum, printer->portname ?
6317 printer->portname : "");
6321 if (force_update || !strequal(printer->location, old_printer->location)) {
6322 push_reg_sz(mem_ctx, &buffer, printer->location);
6323 winreg_set_printer_dataex(mem_ctx, b,
6325 SPOOL_DSSPOOLER_KEY,
6331 if (!force_update) {
6332 notify_printer_location(server_event_context(),
6335 printer->location : "");
6339 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6340 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6341 winreg_set_printer_dataex(mem_ctx, b,
6343 SPOOL_DSSPOOLER_KEY,
6344 SPOOL_REG_PRINTSEPARATORFILE,
6349 if (!force_update) {
6350 notify_printer_sepfile(server_event_context(),
6353 printer->sepfile : "");
6357 if (force_update || printer->starttime != old_printer->starttime) {
6358 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6359 SIVAL(buffer.data, 0, printer->starttime);
6360 winreg_set_printer_dataex(mem_ctx, b,
6362 SPOOL_DSSPOOLER_KEY,
6363 SPOOL_REG_PRINTSTARTTIME,
6369 if (force_update || printer->untiltime != old_printer->untiltime) {
6370 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6371 SIVAL(buffer.data, 0, printer->untiltime);
6372 winreg_set_printer_dataex(mem_ctx, b,
6374 SPOOL_DSSPOOLER_KEY,
6375 SPOOL_REG_PRINTENDTIME,
6381 if (force_update || printer->priority != old_printer->priority) {
6382 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6383 SIVAL(buffer.data, 0, printer->priority);
6384 winreg_set_printer_dataex(mem_ctx, b,
6386 SPOOL_DSSPOOLER_KEY,
6393 if (force_update || printer->attributes != old_printer->attributes) {
6394 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6395 SIVAL(buffer.data, 0, (printer->attributes &
6396 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6397 winreg_set_printer_dataex(mem_ctx, b,
6399 SPOOL_DSSPOOLER_KEY,
6400 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6405 switch (printer->attributes & 0x3) {
6407 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6410 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6413 spooling = SPOOL_REGVAL_PRINTDIRECT;
6416 spooling = "unknown";
6418 push_reg_sz(mem_ctx, &buffer, spooling);
6419 winreg_set_printer_dataex(mem_ctx, b,
6421 SPOOL_DSSPOOLER_KEY,
6422 SPOOL_REG_PRINTSPOOLING,
6428 push_reg_sz(mem_ctx, &buffer, global_myname());
6429 winreg_set_printer_dataex(mem_ctx, b,
6431 SPOOL_DSSPOOLER_KEY,
6432 SPOOL_REG_SHORTSERVERNAME,
6437 dnsdomname = get_mydnsfullname();
6438 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6439 longname = talloc_strdup(mem_ctx, dnsdomname);
6441 longname = talloc_strdup(mem_ctx, global_myname());
6443 if (longname == NULL) {
6444 result = WERR_NOMEM;
6448 push_reg_sz(mem_ctx, &buffer, longname);
6449 winreg_set_printer_dataex(mem_ctx, b,
6451 SPOOL_DSSPOOLER_KEY,
6452 SPOOL_REG_SERVERNAME,
6457 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6458 global_myname(), printer->sharename);
6459 push_reg_sz(mem_ctx, &buffer, uncname);
6460 winreg_set_printer_dataex(mem_ctx, b,
6462 SPOOL_DSSPOOLER_KEY,
6472 /********************************************************************
6473 * Called by spoolss_api_setprinter
6474 * when updating a printer description.
6475 ********************************************************************/
6477 static WERROR update_printer(struct pipes_struct *p,
6478 struct policy_handle *handle,
6479 struct spoolss_SetPrinterInfoCtr *info_ctr,
6480 struct spoolss_DeviceMode *devmode)
6482 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6483 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6484 struct spoolss_PrinterInfo2 *old_printer;
6485 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6487 WERROR result = WERR_OK;
6488 TALLOC_CTX *tmp_ctx;
6489 struct dcerpc_binding_handle *b;
6491 DEBUG(8,("update_printer\n"));
6493 tmp_ctx = talloc_new(p->mem_ctx);
6494 if (tmp_ctx == NULL) {
6499 result = WERR_BADFID;
6503 if (!get_printer_snum(p, handle, &snum, NULL)) {
6504 result = WERR_BADFID;
6508 result = winreg_printer_binding_handle(tmp_ctx,
6509 get_session_info_system(),
6512 if (!W_ERROR_IS_OK(result)) {
6516 result = winreg_get_printer(tmp_ctx, b,
6517 lp_const_servicename(snum),
6519 if (!W_ERROR_IS_OK(result)) {
6520 result = WERR_BADFID;
6524 /* Do sanity check on the requested changes for Samba */
6525 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6526 result = WERR_INVALID_PARAM;
6530 /* FIXME!!! If the driver has changed we really should verify that
6531 it is installed before doing much else --jerry */
6533 /* Check calling user has permission to update printer description */
6534 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6535 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6536 result = WERR_ACCESS_DENIED;
6540 /* Call addprinter hook */
6541 /* Check changes to see if this is really needed */
6543 if (*lp_addprinter_cmd() &&
6544 (!strequal(printer->drivername, old_printer->drivername) ||
6545 !strequal(printer->comment, old_printer->comment) ||
6546 !strequal(printer->portname, old_printer->portname) ||
6547 !strequal(printer->location, old_printer->location)) )
6549 /* add_printer_hook() will call reload_services() */
6550 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6551 printer, p->client_id->addr,
6553 result = WERR_ACCESS_DENIED;
6558 update_dsspooler(tmp_ctx,
6559 get_session_info_system(),
6565 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6567 if (devmode == NULL) {
6568 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6570 result = winreg_update_printer(tmp_ctx, b,
6578 talloc_free(tmp_ctx);
6583 /****************************************************************************
6584 ****************************************************************************/
6585 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6586 struct policy_handle *handle,
6587 struct spoolss_SetPrinterInfo7 *info7)
6590 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6593 struct printer_handle *Printer;
6595 if ( lp_security() != SEC_ADS ) {
6596 return WERR_UNKNOWN_LEVEL;
6599 Printer = find_printer_index_by_hnd(p, handle);
6601 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6606 if (!get_printer_snum(p, handle, &snum, NULL))
6609 result = winreg_get_printer_internal(p->mem_ctx,
6610 get_session_info_system(),
6612 lp_servicename(snum),
6614 if (!W_ERROR_IS_OK(result)) {
6618 nt_printer_publish(pinfo2,
6619 get_session_info_system(),
6624 TALLOC_FREE(pinfo2);
6627 return WERR_UNKNOWN_LEVEL;
6631 /********************************************************************
6632 ********************************************************************/
6634 static WERROR update_printer_devmode(struct pipes_struct *p,
6635 struct policy_handle *handle,
6636 struct spoolss_DeviceMode *devmode)
6639 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6640 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6642 DEBUG(8,("update_printer_devmode\n"));
6648 if (!get_printer_snum(p, handle, &snum, NULL)) {
6652 /* Check calling user has permission to update printer description */
6653 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6654 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6655 return WERR_ACCESS_DENIED;
6658 return winreg_update_printer_internal(p->mem_ctx,
6659 get_session_info_system(),
6661 lp_const_servicename(snum),
6669 /****************************************************************
6671 ****************************************************************/
6673 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6674 struct spoolss_SetPrinter *r)
6678 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6681 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6682 OUR_HANDLE(r->in.handle)));
6686 /* check the level */
6687 switch (r->in.info_ctr->level) {
6689 return control_printer(r->in.handle, r->in.command, p);
6691 result = update_printer(p, r->in.handle,
6693 r->in.devmode_ctr->devmode);
6694 if (!W_ERROR_IS_OK(result))
6696 if (r->in.secdesc_ctr->sd)
6697 result = update_printer_sec(r->in.handle, p,
6701 return update_printer_sec(r->in.handle, p,
6704 return publish_or_unpublish_printer(p, r->in.handle,
6705 r->in.info_ctr->info.info7);
6707 return update_printer_devmode(p, r->in.handle,
6708 r->in.devmode_ctr->devmode);
6710 return WERR_UNKNOWN_LEVEL;
6714 /****************************************************************
6715 _spoolss_FindClosePrinterNotify
6716 ****************************************************************/
6718 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6719 struct spoolss_FindClosePrinterNotify *r)
6721 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6724 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6725 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6729 if (Printer->notify.cli_chan != NULL &&
6730 Printer->notify.cli_chan->active_connections > 0) {
6733 if (Printer->printer_type == SPLHND_PRINTER) {
6734 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6739 srv_spoolss_replycloseprinter(snum, Printer);
6742 Printer->notify.flags=0;
6743 Printer->notify.options=0;
6744 Printer->notify.localmachine[0]='\0';
6745 Printer->notify.printerlocal=0;
6746 TALLOC_FREE(Printer->notify.option);
6751 /****************************************************************
6753 ****************************************************************/
6755 WERROR _spoolss_AddJob(struct pipes_struct *p,
6756 struct spoolss_AddJob *r)
6758 if (!r->in.buffer && (r->in.offered != 0)) {
6759 return WERR_INVALID_PARAM;
6762 /* this is what a NT server returns for AddJob. AddJob must fail on
6763 * non-local printers */
6765 if (r->in.level != 1) {
6766 return WERR_UNKNOWN_LEVEL;
6769 return WERR_INVALID_PARAM;
6772 /****************************************************************************
6774 ****************************************************************************/
6776 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6777 struct spoolss_JobInfo1 *r,
6778 const print_queue_struct *queue,
6779 int position, int snum,
6780 struct spoolss_PrinterInfo2 *pinfo2)
6784 t = gmtime(&queue->time);
6786 r->job_id = queue->sysjob;
6788 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6789 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6790 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6791 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6792 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6793 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6794 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6795 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6796 r->data_type = talloc_strdup(mem_ctx, "RAW");
6797 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6798 r->text_status = talloc_strdup(mem_ctx, "");
6799 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6801 r->status = nt_printj_status(queue->status);
6802 r->priority = queue->priority;
6803 r->position = position;
6804 r->total_pages = queue->page_count;
6805 r->pages_printed = 0; /* ??? */
6807 init_systemtime(&r->submitted, t);
6812 /****************************************************************************
6814 ****************************************************************************/
6816 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6817 struct spoolss_JobInfo2 *r,
6818 const print_queue_struct *queue,
6819 int position, int snum,
6820 struct spoolss_PrinterInfo2 *pinfo2,
6821 struct spoolss_DeviceMode *devmode)
6825 t = gmtime(&queue->time);
6827 r->job_id = queue->sysjob;
6829 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6830 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6831 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6832 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6833 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6834 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6835 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6836 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6837 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6838 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6839 r->data_type = talloc_strdup(mem_ctx, "RAW");
6840 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6841 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6842 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6843 r->parameters = talloc_strdup(mem_ctx, "");
6844 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6845 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6846 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6848 r->devmode = devmode;
6850 r->text_status = talloc_strdup(mem_ctx, "");
6851 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6855 r->status = nt_printj_status(queue->status);
6856 r->priority = queue->priority;
6857 r->position = position;
6860 r->total_pages = queue->page_count;
6861 r->size = queue->size;
6862 init_systemtime(&r->submitted, t);
6864 r->pages_printed = 0; /* ??? */
6869 /****************************************************************************
6871 ****************************************************************************/
6873 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6874 struct spoolss_JobInfo3 *r,
6875 const print_queue_struct *queue,
6876 const print_queue_struct *next_queue,
6877 int position, int snum,
6878 struct spoolss_PrinterInfo2 *pinfo2)
6880 r->job_id = queue->sysjob;
6883 r->next_job_id = next_queue->sysjob;
6890 /****************************************************************************
6891 Enumjobs at level 1.
6892 ****************************************************************************/
6894 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6895 const print_queue_struct *queue,
6896 uint32_t num_queues, int snum,
6897 struct spoolss_PrinterInfo2 *pinfo2,
6898 union spoolss_JobInfo **info_p,
6901 union spoolss_JobInfo *info;
6903 WERROR result = WERR_OK;
6905 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6906 W_ERROR_HAVE_NO_MEMORY(info);
6908 *count = num_queues;
6910 for (i=0; i<*count; i++) {
6911 result = fill_job_info1(info,
6917 if (!W_ERROR_IS_OK(result)) {
6923 if (!W_ERROR_IS_OK(result)) {
6934 /****************************************************************************
6935 Enumjobs at level 2.
6936 ****************************************************************************/
6938 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6939 const print_queue_struct *queue,
6940 uint32_t num_queues, int snum,
6941 struct spoolss_PrinterInfo2 *pinfo2,
6942 union spoolss_JobInfo **info_p,
6945 union spoolss_JobInfo *info;
6947 WERROR result = WERR_OK;
6949 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6950 W_ERROR_HAVE_NO_MEMORY(info);
6952 *count = num_queues;
6954 for (i=0; i<*count; i++) {
6955 struct spoolss_DeviceMode *devmode;
6957 result = spoolss_create_default_devmode(info,
6958 pinfo2->printername,
6960 if (!W_ERROR_IS_OK(result)) {
6961 DEBUG(3, ("Can't proceed w/o a devmode!"));
6965 result = fill_job_info2(info,
6972 if (!W_ERROR_IS_OK(result)) {
6978 if (!W_ERROR_IS_OK(result)) {
6989 /****************************************************************************
6990 Enumjobs at level 3.
6991 ****************************************************************************/
6993 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6994 const print_queue_struct *queue,
6995 uint32_t num_queues, int snum,
6996 struct spoolss_PrinterInfo2 *pinfo2,
6997 union spoolss_JobInfo **info_p,
7000 union spoolss_JobInfo *info;
7002 WERROR result = WERR_OK;
7004 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7005 W_ERROR_HAVE_NO_MEMORY(info);
7007 *count = num_queues;
7009 for (i=0; i<*count; i++) {
7010 const print_queue_struct *next_queue = NULL;
7013 next_queue = &queue[i+1];
7016 result = fill_job_info3(info,
7023 if (!W_ERROR_IS_OK(result)) {
7029 if (!W_ERROR_IS_OK(result)) {
7040 /****************************************************************
7042 ****************************************************************/
7044 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7045 struct spoolss_EnumJobs *r)
7048 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7050 print_status_struct prt_status;
7051 print_queue_struct *queue = NULL;
7054 /* that's an [in out] buffer */
7056 if (!r->in.buffer && (r->in.offered != 0)) {
7057 return WERR_INVALID_PARAM;
7060 DEBUG(4,("_spoolss_EnumJobs\n"));
7064 *r->out.info = NULL;
7066 /* lookup the printer snum and tdb entry */
7068 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7072 result = winreg_get_printer_internal(p->mem_ctx,
7073 get_session_info_system(),
7075 lp_const_servicename(snum),
7077 if (!W_ERROR_IS_OK(result)) {
7081 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7082 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7083 count, prt_status.status, prt_status.message));
7087 TALLOC_FREE(pinfo2);
7091 switch (r->in.level) {
7093 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7094 pinfo2, r->out.info, r->out.count);
7097 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7098 pinfo2, r->out.info, r->out.count);
7101 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7102 pinfo2, r->out.info, r->out.count);
7105 result = WERR_UNKNOWN_LEVEL;
7110 TALLOC_FREE(pinfo2);
7112 if (!W_ERROR_IS_OK(result)) {
7116 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7118 *r->out.info, r->in.level,
7120 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7121 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7123 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7126 /****************************************************************
7127 _spoolss_ScheduleJob
7128 ****************************************************************/
7130 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7131 struct spoolss_ScheduleJob *r)
7136 /****************************************************************
7137 ****************************************************************/
7139 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7140 struct messaging_context *msg_ctx,
7141 const char *printer_name,
7143 struct spoolss_SetJobInfo1 *r)
7147 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7151 if (strequal(old_doc_name, r->document_name)) {
7155 if (!print_job_set_name(server_event_context(), msg_ctx,
7156 printer_name, job_id, r->document_name)) {
7163 /****************************************************************
7165 ****************************************************************/
7167 WERROR _spoolss_SetJob(struct pipes_struct *p,
7168 struct spoolss_SetJob *r)
7170 const struct auth_serversupplied_info *session_info = p->session_info;
7172 WERROR errcode = WERR_BADFUNC;
7174 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7178 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7179 return WERR_INVALID_PRINTER_NAME;
7182 switch (r->in.command) {
7183 case SPOOLSS_JOB_CONTROL_CANCEL:
7184 case SPOOLSS_JOB_CONTROL_DELETE:
7185 errcode = print_job_delete(session_info, p->msg_ctx,
7186 snum, r->in.job_id);
7187 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7191 case SPOOLSS_JOB_CONTROL_PAUSE:
7192 errcode = print_job_pause(session_info, p->msg_ctx,
7193 snum, r->in.job_id);
7195 case SPOOLSS_JOB_CONTROL_RESTART:
7196 case SPOOLSS_JOB_CONTROL_RESUME:
7197 errcode = print_job_resume(session_info, p->msg_ctx,
7198 snum, r->in.job_id);
7204 return WERR_UNKNOWN_LEVEL;
7207 if (!W_ERROR_IS_OK(errcode)) {
7211 if (r->in.ctr == NULL) {
7215 switch (r->in.ctr->level) {
7217 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7218 lp_const_servicename(snum),
7220 r->in.ctr->info.info1);
7226 return WERR_UNKNOWN_LEVEL;
7232 /****************************************************************************
7233 Enumerates all printer drivers by level and architecture.
7234 ****************************************************************************/
7236 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7237 const struct auth_serversupplied_info *session_info,
7238 struct messaging_context *msg_ctx,
7239 const char *servername,
7240 const char *architecture,
7242 union spoolss_DriverInfo **info_p,
7247 struct spoolss_DriverInfo8 *driver;
7248 union spoolss_DriverInfo *info = NULL;
7250 WERROR result = WERR_OK;
7251 uint32_t num_drivers;
7252 const char **drivers;
7253 struct dcerpc_binding_handle *b;
7258 result = winreg_printer_binding_handle(mem_ctx,
7262 if (!W_ERROR_IS_OK(result)) {
7266 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7267 result = winreg_get_driver_list(mem_ctx, b,
7268 architecture, version,
7269 &num_drivers, &drivers);
7270 if (!W_ERROR_IS_OK(result)) {
7273 DEBUG(4, ("we have:[%d] drivers in environment"
7274 " [%s] and version [%d]\n",
7275 num_drivers, architecture, version));
7277 if (num_drivers != 0) {
7278 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7279 union spoolss_DriverInfo,
7280 count + num_drivers);
7282 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7283 "failed to enlarge driver info buffer!\n"));
7284 result = WERR_NOMEM;
7289 for (i = 0; i < num_drivers; i++) {
7290 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7292 result = winreg_get_driver(mem_ctx, b,
7293 architecture, drivers[i],
7295 if (!W_ERROR_IS_OK(result)) {
7301 result = fill_printer_driver_info1(info, &info[count+i].info1,
7302 driver, servername);
7305 result = fill_printer_driver_info2(info, &info[count+i].info2,
7306 driver, servername);
7309 result = fill_printer_driver_info3(info, &info[count+i].info3,
7310 driver, servername);
7313 result = fill_printer_driver_info4(info, &info[count+i].info4,
7314 driver, servername);
7317 result = fill_printer_driver_info5(info, &info[count+i].info5,
7318 driver, servername);
7321 result = fill_printer_driver_info6(info, &info[count+i].info6,
7322 driver, servername);
7325 result = fill_printer_driver_info8(info, &info[count+i].info8,
7326 driver, servername);
7329 result = WERR_UNKNOWN_LEVEL;
7333 TALLOC_FREE(driver);
7335 if (!W_ERROR_IS_OK(result)) {
7340 count += num_drivers;
7341 TALLOC_FREE(drivers);
7345 TALLOC_FREE(drivers);
7347 if (!W_ERROR_IS_OK(result)) {
7358 /****************************************************************************
7359 Enumerates all printer drivers by level.
7360 ****************************************************************************/
7362 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7363 const struct auth_serversupplied_info *session_info,
7364 struct messaging_context *msg_ctx,
7365 const char *servername,
7366 const char *architecture,
7368 union spoolss_DriverInfo **info_p,
7372 WERROR result = WERR_OK;
7374 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7376 for (a=0; archi_table[a].long_archi != NULL; a++) {
7378 union spoolss_DriverInfo *info = NULL;
7381 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7385 archi_table[a].long_archi,
7389 if (!W_ERROR_IS_OK(result)) {
7393 for (i=0; i < count; i++) {
7394 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7395 info[i], info_p, count_p);
7402 return enumprinterdrivers_level_by_architecture(mem_ctx,
7412 /****************************************************************
7413 _spoolss_EnumPrinterDrivers
7414 ****************************************************************/
7416 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7417 struct spoolss_EnumPrinterDrivers *r)
7419 const char *cservername;
7422 /* that's an [in out] buffer */
7424 if (!r->in.buffer && (r->in.offered != 0)) {
7425 return WERR_INVALID_PARAM;
7428 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7432 *r->out.info = NULL;
7434 cservername = canon_servername(r->in.server);
7436 if (!is_myname_or_ipaddr(cservername)) {
7437 return WERR_UNKNOWN_PRINTER_DRIVER;
7440 result = enumprinterdrivers_level(p->mem_ctx,
7441 get_session_info_system(),
7448 if (!W_ERROR_IS_OK(result)) {
7452 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7453 spoolss_EnumPrinterDrivers,
7454 *r->out.info, r->in.level,
7456 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7457 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7459 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7462 /****************************************************************
7464 ****************************************************************/
7466 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7467 struct spoolss_EnumForms *r)
7473 *r->out.info = NULL;
7475 /* that's an [in out] buffer */
7477 if (!r->in.buffer && (r->in.offered != 0) ) {
7478 return WERR_INVALID_PARAM;
7481 DEBUG(4,("_spoolss_EnumForms\n"));
7482 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7483 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7485 switch (r->in.level) {
7487 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7488 get_session_info_system(),
7494 result = WERR_UNKNOWN_LEVEL;
7498 if (!W_ERROR_IS_OK(result)) {
7502 if (*r->out.count == 0) {
7503 return WERR_NO_MORE_ITEMS;
7506 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7508 *r->out.info, r->in.level,
7510 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7511 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7513 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7516 /****************************************************************
7518 ****************************************************************/
7520 WERROR _spoolss_GetForm(struct pipes_struct *p,
7521 struct spoolss_GetForm *r)
7525 /* that's an [in out] buffer */
7527 if (!r->in.buffer && (r->in.offered != 0)) {
7528 return WERR_INVALID_PARAM;
7531 DEBUG(4,("_spoolss_GetForm\n"));
7532 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7533 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7535 switch (r->in.level) {
7537 result = winreg_printer_getform1_internal(p->mem_ctx,
7538 get_session_info_system(),
7541 &r->out.info->info1);
7544 result = WERR_UNKNOWN_LEVEL;
7548 if (!W_ERROR_IS_OK(result)) {
7549 TALLOC_FREE(r->out.info);
7553 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7554 r->out.info, r->in.level);
7555 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7557 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7560 /****************************************************************************
7561 ****************************************************************************/
7563 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7564 struct spoolss_PortInfo1 *r,
7567 r->port_name = talloc_strdup(mem_ctx, name);
7568 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7573 /****************************************************************************
7574 TODO: This probably needs distinguish between TCP/IP and Local ports
7576 ****************************************************************************/
7578 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7579 struct spoolss_PortInfo2 *r,
7582 r->port_name = talloc_strdup(mem_ctx, name);
7583 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7585 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7586 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7588 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7589 W_ERROR_HAVE_NO_MEMORY(r->description);
7591 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7598 /****************************************************************************
7599 wrapper around the enumer ports command
7600 ****************************************************************************/
7602 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7604 char *cmd = lp_enumports_cmd();
7605 char **qlines = NULL;
7606 char *command = NULL;
7614 /* if no hook then just fill in the default port */
7617 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7620 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7621 TALLOC_FREE(qlines);
7628 /* we have a valid enumport command */
7630 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7635 DEBUG(10,("Running [%s]\n", command));
7636 ret = smbrun(command, &fd);
7637 DEBUG(10,("Returned [%d]\n", ret));
7638 TALLOC_FREE(command);
7643 return WERR_ACCESS_DENIED;
7647 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7648 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7658 /****************************************************************************
7660 ****************************************************************************/
7662 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7663 union spoolss_PortInfo **info_p,
7666 union spoolss_PortInfo *info = NULL;
7668 WERROR result = WERR_OK;
7669 char **qlines = NULL;
7672 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7673 if (!W_ERROR_IS_OK(result)) {
7678 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7680 DEBUG(10,("Returning WERR_NOMEM\n"));
7681 result = WERR_NOMEM;
7685 for (i=0; i<numlines; i++) {
7686 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7687 result = fill_port_1(info, &info[i].info1, qlines[i]);
7688 if (!W_ERROR_IS_OK(result)) {
7693 TALLOC_FREE(qlines);
7696 if (!W_ERROR_IS_OK(result)) {
7698 TALLOC_FREE(qlines);
7710 /****************************************************************************
7712 ****************************************************************************/
7714 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7715 union spoolss_PortInfo **info_p,
7718 union spoolss_PortInfo *info = NULL;
7720 WERROR result = WERR_OK;
7721 char **qlines = NULL;
7724 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7725 if (!W_ERROR_IS_OK(result)) {
7730 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7732 DEBUG(10,("Returning WERR_NOMEM\n"));
7733 result = WERR_NOMEM;
7737 for (i=0; i<numlines; i++) {
7738 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7739 result = fill_port_2(info, &info[i].info2, qlines[i]);
7740 if (!W_ERROR_IS_OK(result)) {
7745 TALLOC_FREE(qlines);
7748 if (!W_ERROR_IS_OK(result)) {
7750 TALLOC_FREE(qlines);
7762 /****************************************************************
7764 ****************************************************************/
7766 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7767 struct spoolss_EnumPorts *r)
7771 /* that's an [in out] buffer */
7773 if (!r->in.buffer && (r->in.offered != 0)) {
7774 return WERR_INVALID_PARAM;
7777 DEBUG(4,("_spoolss_EnumPorts\n"));
7781 *r->out.info = NULL;
7783 switch (r->in.level) {
7785 result = enumports_level_1(p->mem_ctx, r->out.info,
7789 result = enumports_level_2(p->mem_ctx, r->out.info,
7793 return WERR_UNKNOWN_LEVEL;
7796 if (!W_ERROR_IS_OK(result)) {
7800 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7802 *r->out.info, r->in.level,
7804 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7805 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7807 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7810 /****************************************************************************
7811 ****************************************************************************/
7813 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7815 struct spoolss_SetPrinterInfoCtr *info_ctr,
7816 struct spoolss_DeviceMode *devmode,
7817 struct security_descriptor *secdesc,
7818 struct spoolss_UserLevelCtr *user_ctr,
7819 struct policy_handle *handle)
7821 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7822 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7824 WERROR err = WERR_OK;
7826 /* samba does not have a concept of local, non-shared printers yet, so
7827 * make sure we always setup sharename - gd */
7828 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7829 (info2->printername != NULL && info2->printername[0] != '\0')) {
7830 DEBUG(5, ("spoolss_addprinterex_level_2: "
7831 "no sharename has been set, setting printername %s as sharename\n",
7832 info2->printername));
7833 info2->sharename = info2->printername;
7836 /* check to see if the printer already exists */
7837 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7838 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7840 return WERR_PRINTER_ALREADY_EXISTS;
7843 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7844 if ((snum = print_queue_snum(info2->printername)) != -1) {
7845 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7846 info2->printername));
7847 return WERR_PRINTER_ALREADY_EXISTS;
7851 /* validate printer info struct */
7852 if (!info2->printername || strlen(info2->printername) == 0) {
7853 return WERR_INVALID_PRINTER_NAME;
7855 if (!info2->portname || strlen(info2->portname) == 0) {
7856 return WERR_UNKNOWN_PORT;
7858 if (!info2->drivername || strlen(info2->drivername) == 0) {
7859 return WERR_UNKNOWN_PRINTER_DRIVER;
7861 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7862 return WERR_UNKNOWN_PRINTPROCESSOR;
7865 /* FIXME!!! smbd should check to see if the driver is installed before
7866 trying to add a printer like this --jerry */
7868 if (*lp_addprinter_cmd() ) {
7869 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7870 info2, p->client_id->addr,
7872 return WERR_ACCESS_DENIED;
7875 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7876 "smb.conf parameter \"addprinter command\" is defined. This "
7877 "parameter must exist for this call to succeed\n",
7878 info2->sharename ));
7881 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7882 return WERR_ACCESS_DENIED;
7885 /* you must be a printer admin to add a new printer */
7886 if (!print_access_check(p->session_info,
7889 PRINTER_ACCESS_ADMINISTER)) {
7890 return WERR_ACCESS_DENIED;
7894 * Do sanity check on the requested changes for Samba.
7897 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7898 return WERR_INVALID_PARAM;
7901 if (devmode == NULL) {
7902 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7905 update_dsspooler(p->mem_ctx,
7906 get_session_info_system(),
7912 err = winreg_update_printer_internal(p->mem_ctx,
7913 get_session_info_system(),
7920 if (!W_ERROR_IS_OK(err)) {
7924 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7925 if (!W_ERROR_IS_OK(err)) {
7926 /* Handle open failed - remove addition. */
7927 ZERO_STRUCTP(handle);
7934 /****************************************************************
7935 _spoolss_AddPrinterEx
7936 ****************************************************************/
7938 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7939 struct spoolss_AddPrinterEx *r)
7941 switch (r->in.info_ctr->level) {
7943 /* we don't handle yet */
7944 /* but I know what to do ... */
7945 return WERR_UNKNOWN_LEVEL;
7947 return spoolss_addprinterex_level_2(p, r->in.server,
7949 r->in.devmode_ctr->devmode,
7950 r->in.secdesc_ctr->sd,
7951 r->in.userlevel_ctr,
7954 return WERR_UNKNOWN_LEVEL;
7958 /****************************************************************
7960 ****************************************************************/
7962 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7963 struct spoolss_AddPrinter *r)
7965 struct spoolss_AddPrinterEx a;
7966 struct spoolss_UserLevelCtr userlevel_ctr;
7968 ZERO_STRUCT(userlevel_ctr);
7970 userlevel_ctr.level = 1;
7972 a.in.server = r->in.server;
7973 a.in.info_ctr = r->in.info_ctr;
7974 a.in.devmode_ctr = r->in.devmode_ctr;
7975 a.in.secdesc_ctr = r->in.secdesc_ctr;
7976 a.in.userlevel_ctr = &userlevel_ctr;
7977 a.out.handle = r->out.handle;
7979 return _spoolss_AddPrinterEx(p, &a);
7982 /****************************************************************
7983 _spoolss_AddPrinterDriverEx
7984 ****************************************************************/
7986 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7987 struct spoolss_AddPrinterDriverEx *r)
7989 WERROR err = WERR_OK;
7990 const char *driver_name = NULL;
7995 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7996 fn = "_spoolss_AddPrinterDriver";
7998 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7999 fn = "_spoolss_AddPrinterDriverEx";
8002 return WERR_INVALID_PARAM;
8006 * we only support the semantics of AddPrinterDriver()
8007 * i.e. only copy files that are newer than existing ones
8010 if (r->in.flags == 0) {
8011 return WERR_INVALID_PARAM;
8014 if (r->in.flags != APD_COPY_NEW_FILES) {
8015 return WERR_ACCESS_DENIED;
8019 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8020 /* Clever hack from Martin Zielinski <mz@seh.de>
8021 * to allow downgrade from level 8 (Vista).
8023 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8024 r->in.info_ctr->level));
8025 return WERR_UNKNOWN_LEVEL;
8028 DEBUG(5,("Cleaning driver's information\n"));
8029 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8030 if (!W_ERROR_IS_OK(err))
8033 DEBUG(5,("Moving driver to final destination\n"));
8034 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8035 if (!W_ERROR_IS_OK(err)) {
8039 err = winreg_add_driver_internal(p->mem_ctx,
8040 get_session_info_system(),
8045 if (!W_ERROR_IS_OK(err)) {
8050 * I think this is where he DrvUpgradePrinter() hook would be
8051 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8052 * server. Right now, we just need to send ourselves a message
8053 * to update each printer bound to this driver. --jerry
8056 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8057 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8065 /****************************************************************
8066 _spoolss_AddPrinterDriver
8067 ****************************************************************/
8069 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8070 struct spoolss_AddPrinterDriver *r)
8072 struct spoolss_AddPrinterDriverEx a;
8074 switch (r->in.info_ctr->level) {
8081 return WERR_UNKNOWN_LEVEL;
8084 a.in.servername = r->in.servername;
8085 a.in.info_ctr = r->in.info_ctr;
8086 a.in.flags = APD_COPY_NEW_FILES;
8088 return _spoolss_AddPrinterDriverEx(p, &a);
8091 /****************************************************************************
8092 ****************************************************************************/
8094 struct _spoolss_paths {
8100 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8102 static const struct _spoolss_paths spoolss_paths[]= {
8103 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8104 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8107 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8108 const char *servername,
8109 const char *environment,
8113 const char *pservername = NULL;
8114 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8115 const char *short_archi;
8119 /* environment may be empty */
8120 if (environment && strlen(environment)) {
8121 long_archi = environment;
8124 /* servername may be empty */
8125 if (servername && strlen(servername)) {
8126 pservername = canon_servername(servername);
8128 if (!is_myname_or_ipaddr(pservername)) {
8129 return WERR_INVALID_PARAM;
8133 if (!(short_archi = get_short_archi(long_archi))) {
8134 return WERR_INVALID_ENVIRONMENT;
8137 switch (component) {
8138 case SPOOLSS_PRTPROCS_PATH:
8139 case SPOOLSS_DRIVER_PATH:
8141 *path = talloc_asprintf(mem_ctx,
8144 spoolss_paths[component].share,
8147 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8148 SPOOLSS_DEFAULT_SERVER_PATH,
8149 spoolss_paths[component].dir,
8154 return WERR_INVALID_PARAM;
8164 /****************************************************************************
8165 ****************************************************************************/
8167 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8168 const char *servername,
8169 const char *environment,
8170 struct spoolss_DriverDirectoryInfo1 *r)
8175 werr = compose_spoolss_server_path(mem_ctx,
8178 SPOOLSS_DRIVER_PATH,
8180 if (!W_ERROR_IS_OK(werr)) {
8184 DEBUG(4,("printer driver directory: [%s]\n", path));
8186 r->directory_name = path;
8191 /****************************************************************
8192 _spoolss_GetPrinterDriverDirectory
8193 ****************************************************************/
8195 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8196 struct spoolss_GetPrinterDriverDirectory *r)
8200 /* that's an [in out] buffer */
8202 if (!r->in.buffer && (r->in.offered != 0)) {
8203 return WERR_INVALID_PARAM;
8206 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8211 /* r->in.level is ignored */
8213 werror = getprinterdriverdir_level_1(p->mem_ctx,
8216 &r->out.info->info1);
8217 if (!W_ERROR_IS_OK(werror)) {
8218 TALLOC_FREE(r->out.info);
8222 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8223 r->out.info, r->in.level);
8224 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8226 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8229 /****************************************************************
8230 _spoolss_EnumPrinterData
8231 ****************************************************************/
8233 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8234 struct spoolss_EnumPrinterData *r)
8237 struct spoolss_EnumPrinterDataEx r2;
8239 struct spoolss_PrinterEnumValues *info, *val = NULL;
8242 r2.in.handle = r->in.handle;
8243 r2.in.key_name = "PrinterDriverData";
8245 r2.out.count = &count;
8246 r2.out.info = &info;
8247 r2.out.needed = &needed;
8249 result = _spoolss_EnumPrinterDataEx(p, &r2);
8250 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8251 r2.in.offered = needed;
8252 result = _spoolss_EnumPrinterDataEx(p, &r2);
8254 if (!W_ERROR_IS_OK(result)) {
8259 * The NT machine wants to know the biggest size of value and data
8261 * cf: MSDN EnumPrinterData remark section
8264 if (!r->in.value_offered && !r->in.data_offered) {
8265 uint32_t biggest_valuesize = 0;
8266 uint32_t biggest_datasize = 0;
8269 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8271 for (i=0; i<count; i++) {
8273 name_length = strlen(info[i].value_name);
8274 if (strlen(info[i].value_name) > biggest_valuesize) {
8275 biggest_valuesize = name_length;
8278 if (info[i].data_length > biggest_datasize) {
8279 biggest_datasize = info[i].data_length;
8282 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8286 /* the value is an UNICODE string but real_value_size is the length
8287 in bytes including the trailing 0 */
8289 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8290 *r->out.data_needed = biggest_datasize;
8292 DEBUG(6,("final values: [%d], [%d]\n",
8293 *r->out.value_needed, *r->out.data_needed));
8298 if (r->in.enum_index < count) {
8299 val = &info[r->in.enum_index];
8303 /* out_value should default to "" or else NT4 has
8304 problems unmarshalling the response */
8306 if (r->in.value_offered) {
8307 *r->out.value_needed = 1;
8308 r->out.value_name = talloc_strdup(r, "");
8309 if (!r->out.value_name) {
8313 r->out.value_name = NULL;
8314 *r->out.value_needed = 0;
8317 /* the data is counted in bytes */
8319 *r->out.data_needed = r->in.data_offered;
8321 result = WERR_NO_MORE_ITEMS;
8325 * - counted in bytes in the request
8326 * - counted in UNICODE chars in the max reply
8327 * - counted in bytes in the real size
8329 * take a pause *before* coding not *during* coding
8333 if (r->in.value_offered) {
8334 r->out.value_name = talloc_strdup(r, val->value_name);
8335 if (!r->out.value_name) {
8338 *r->out.value_needed = val->value_name_len;
8340 r->out.value_name = NULL;
8341 *r->out.value_needed = 0;
8346 *r->out.type = val->type;
8348 /* data - counted in bytes */
8351 * See the section "Dynamically Typed Query Parameters"
8355 if (r->out.data && val->data && val->data->data &&
8356 val->data_length && r->in.data_offered) {
8357 memcpy(r->out.data, val->data->data,
8358 MIN(val->data_length,r->in.data_offered));
8361 *r->out.data_needed = val->data_length;
8369 /****************************************************************
8370 _spoolss_SetPrinterData
8371 ****************************************************************/
8373 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8374 struct spoolss_SetPrinterData *r)
8376 struct spoolss_SetPrinterDataEx r2;
8378 r2.in.handle = r->in.handle;
8379 r2.in.key_name = "PrinterDriverData";
8380 r2.in.value_name = r->in.value_name;
8381 r2.in.type = r->in.type;
8382 r2.in.data = r->in.data;
8383 r2.in.offered = r->in.offered;
8385 return _spoolss_SetPrinterDataEx(p, &r2);
8388 /****************************************************************
8389 _spoolss_ResetPrinter
8390 ****************************************************************/
8392 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8393 struct spoolss_ResetPrinter *r)
8395 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8398 DEBUG(5,("_spoolss_ResetPrinter\n"));
8401 * All we do is to check to see if the handle and queue is valid.
8402 * This call really doesn't mean anything to us because we only
8403 * support RAW printing. --jerry
8407 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8408 OUR_HANDLE(r->in.handle)));
8412 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8416 /* blindly return success */
8420 /****************************************************************
8421 _spoolss_DeletePrinterData
8422 ****************************************************************/
8424 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8425 struct spoolss_DeletePrinterData *r)
8427 struct spoolss_DeletePrinterDataEx r2;
8429 r2.in.handle = r->in.handle;
8430 r2.in.key_name = "PrinterDriverData";
8431 r2.in.value_name = r->in.value_name;
8433 return _spoolss_DeletePrinterDataEx(p, &r2);
8436 /****************************************************************
8438 ****************************************************************/
8440 WERROR _spoolss_AddForm(struct pipes_struct *p,
8441 struct spoolss_AddForm *r)
8443 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8445 WERROR status = WERR_OK;
8446 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8447 struct dcerpc_binding_handle *b;
8449 DEBUG(5,("_spoolss_AddForm\n"));
8452 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8453 OUR_HANDLE(r->in.handle)));
8457 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8458 and not a printer admin, then fail */
8460 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8461 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8462 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8463 p->session_info->info3->base.domain.string,
8465 p->session_info->security_token,
8466 lp_printer_admin(snum))) {
8467 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8468 return WERR_ACCESS_DENIED;
8471 switch (form->flags) {
8472 case SPOOLSS_FORM_USER:
8473 case SPOOLSS_FORM_BUILTIN:
8474 case SPOOLSS_FORM_PRINTER:
8477 return WERR_INVALID_PARAM;
8480 status = winreg_printer_binding_handle(p->mem_ctx,
8481 get_session_info_system(),
8484 if (!W_ERROR_IS_OK(status)) {
8488 status = winreg_printer_addform1(p->mem_ctx, b,
8490 if (!W_ERROR_IS_OK(status)) {
8495 * ChangeID must always be set if this is a printer
8497 if (Printer->printer_type == SPLHND_PRINTER) {
8498 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8502 status = winreg_printer_update_changeid(p->mem_ctx, b,
8503 lp_const_servicename(snum));
8504 if (!W_ERROR_IS_OK(status)) {
8512 /****************************************************************
8514 ****************************************************************/
8516 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8517 struct spoolss_DeleteForm *r)
8519 const char *form_name = r->in.form_name;
8520 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8522 WERROR status = WERR_OK;
8523 struct dcerpc_binding_handle *b;
8525 DEBUG(5,("_spoolss_DeleteForm\n"));
8528 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8529 OUR_HANDLE(r->in.handle)));
8533 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8534 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8535 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8536 p->session_info->info3->base.domain.string,
8538 p->session_info->security_token,
8539 lp_printer_admin(snum))) {
8540 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8541 return WERR_ACCESS_DENIED;
8544 status = winreg_printer_binding_handle(p->mem_ctx,
8545 get_session_info_system(),
8548 if (!W_ERROR_IS_OK(status)) {
8552 status = winreg_printer_deleteform1(p->mem_ctx, b,
8554 if (!W_ERROR_IS_OK(status)) {
8559 * ChangeID must always be set if this is a printer
8561 if (Printer->printer_type == SPLHND_PRINTER) {
8562 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8566 status = winreg_printer_update_changeid(p->mem_ctx, b,
8567 lp_const_servicename(snum));
8568 if (!W_ERROR_IS_OK(status)) {
8576 /****************************************************************
8578 ****************************************************************/
8580 WERROR _spoolss_SetForm(struct pipes_struct *p,
8581 struct spoolss_SetForm *r)
8583 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8584 const char *form_name = r->in.form_name;
8586 WERROR status = WERR_OK;
8587 struct dcerpc_binding_handle *b;
8589 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8591 DEBUG(5,("_spoolss_SetForm\n"));
8594 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8595 OUR_HANDLE(r->in.handle)));
8599 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8600 and not a printer admin, then fail */
8602 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8603 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8604 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8605 p->session_info->info3->base.domain.string,
8607 p->session_info->security_token,
8608 lp_printer_admin(snum))) {
8609 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8610 return WERR_ACCESS_DENIED;
8613 status = winreg_printer_binding_handle(p->mem_ctx,
8614 get_session_info_system(),
8617 if (!W_ERROR_IS_OK(status)) {
8621 status = winreg_printer_setform1(p->mem_ctx, b,
8624 if (!W_ERROR_IS_OK(status)) {
8629 * ChangeID must always be set if this is a printer
8631 if (Printer->printer_type == SPLHND_PRINTER) {
8632 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8636 status = winreg_printer_update_changeid(p->mem_ctx, b,
8637 lp_const_servicename(snum));
8638 if (!W_ERROR_IS_OK(status)) {
8646 /****************************************************************************
8647 fill_print_processor1
8648 ****************************************************************************/
8650 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8651 struct spoolss_PrintProcessorInfo1 *r,
8652 const char *print_processor_name)
8654 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8655 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8660 /****************************************************************************
8661 enumprintprocessors level 1.
8662 ****************************************************************************/
8664 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8665 union spoolss_PrintProcessorInfo **info_p,
8668 union spoolss_PrintProcessorInfo *info;
8671 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8672 W_ERROR_HAVE_NO_MEMORY(info);
8676 result = fill_print_processor1(info, &info[0].info1, "winprint");
8677 if (!W_ERROR_IS_OK(result)) {
8682 if (!W_ERROR_IS_OK(result)) {
8693 /****************************************************************
8694 _spoolss_EnumPrintProcessors
8695 ****************************************************************/
8697 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8698 struct spoolss_EnumPrintProcessors *r)
8702 /* that's an [in out] buffer */
8704 if (!r->in.buffer && (r->in.offered != 0)) {
8705 return WERR_INVALID_PARAM;
8708 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8711 * Enumerate the print processors ...
8713 * Just reply with "winprint", to keep NT happy
8714 * and I can use my nice printer checker.
8719 *r->out.info = NULL;
8721 if (!get_short_archi(r->in.environment)) {
8722 return WERR_INVALID_ENVIRONMENT;
8725 switch (r->in.level) {
8727 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8731 return WERR_UNKNOWN_LEVEL;
8734 if (!W_ERROR_IS_OK(result)) {
8738 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8739 spoolss_EnumPrintProcessors,
8740 *r->out.info, r->in.level,
8742 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8743 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8745 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8748 /****************************************************************************
8749 fill_printprocdatatype1
8750 ****************************************************************************/
8752 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8753 struct spoolss_PrintProcDataTypesInfo1 *r,
8754 const char *name_array)
8756 r->name_array = talloc_strdup(mem_ctx, name_array);
8757 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8762 /****************************************************************************
8763 enumprintprocdatatypes level 1.
8764 ****************************************************************************/
8766 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8767 union spoolss_PrintProcDataTypesInfo **info_p,
8771 union spoolss_PrintProcDataTypesInfo *info;
8773 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8774 W_ERROR_HAVE_NO_MEMORY(info);
8778 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8779 if (!W_ERROR_IS_OK(result)) {
8784 if (!W_ERROR_IS_OK(result)) {
8795 /****************************************************************
8796 _spoolss_EnumPrintProcDataTypes
8797 ****************************************************************/
8799 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8800 struct spoolss_EnumPrintProcDataTypes *r)
8804 /* that's an [in out] buffer */
8806 if (!r->in.buffer && (r->in.offered != 0)) {
8807 return WERR_INVALID_PARAM;
8810 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8814 *r->out.info = NULL;
8816 if (r->in.print_processor_name == NULL ||
8817 !strequal(r->in.print_processor_name, "winprint")) {
8818 return WERR_UNKNOWN_PRINTPROCESSOR;
8821 switch (r->in.level) {
8823 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8827 return WERR_UNKNOWN_LEVEL;
8830 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8831 spoolss_EnumPrintProcDataTypes,
8832 *r->out.info, r->in.level,
8834 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8835 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8837 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8840 /****************************************************************************
8842 ****************************************************************************/
8844 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8845 struct spoolss_MonitorInfo1 *r,
8846 const char *monitor_name)
8848 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8849 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8854 /****************************************************************************
8856 ****************************************************************************/
8858 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8859 struct spoolss_MonitorInfo2 *r,
8860 const char *monitor_name,
8861 const char *environment,
8862 const char *dll_name)
8864 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8865 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8866 r->environment = talloc_strdup(mem_ctx, environment);
8867 W_ERROR_HAVE_NO_MEMORY(r->environment);
8868 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8869 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8874 /****************************************************************************
8875 enumprintmonitors level 1.
8876 ****************************************************************************/
8878 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8879 union spoolss_MonitorInfo **info_p,
8882 union spoolss_MonitorInfo *info;
8883 WERROR result = WERR_OK;
8885 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8886 W_ERROR_HAVE_NO_MEMORY(info);
8890 result = fill_monitor_1(info, &info[0].info1,
8892 if (!W_ERROR_IS_OK(result)) {
8896 result = fill_monitor_1(info, &info[1].info1,
8898 if (!W_ERROR_IS_OK(result)) {
8903 if (!W_ERROR_IS_OK(result)) {
8914 /****************************************************************************
8915 enumprintmonitors level 2.
8916 ****************************************************************************/
8918 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8919 union spoolss_MonitorInfo **info_p,
8922 union spoolss_MonitorInfo *info;
8923 WERROR result = WERR_OK;
8925 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8926 W_ERROR_HAVE_NO_MEMORY(info);
8930 result = fill_monitor_2(info, &info[0].info2,
8932 "Windows NT X86", /* FIXME */
8934 if (!W_ERROR_IS_OK(result)) {
8938 result = fill_monitor_2(info, &info[1].info2,
8940 "Windows NT X86", /* FIXME */
8942 if (!W_ERROR_IS_OK(result)) {
8947 if (!W_ERROR_IS_OK(result)) {
8958 /****************************************************************
8959 _spoolss_EnumMonitors
8960 ****************************************************************/
8962 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8963 struct spoolss_EnumMonitors *r)
8967 /* that's an [in out] buffer */
8969 if (!r->in.buffer && (r->in.offered != 0)) {
8970 return WERR_INVALID_PARAM;
8973 DEBUG(5,("_spoolss_EnumMonitors\n"));
8976 * Enumerate the print monitors ...
8978 * Just reply with "Local Port", to keep NT happy
8979 * and I can use my nice printer checker.
8984 *r->out.info = NULL;
8986 switch (r->in.level) {
8988 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8992 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8996 return WERR_UNKNOWN_LEVEL;
8999 if (!W_ERROR_IS_OK(result)) {
9003 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9004 spoolss_EnumMonitors,
9005 *r->out.info, r->in.level,
9007 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9008 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9010 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9013 /****************************************************************************
9014 ****************************************************************************/
9016 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9017 const print_queue_struct *queue,
9018 int count, int snum,
9019 struct spoolss_PrinterInfo2 *pinfo2,
9021 struct spoolss_JobInfo1 *r)
9026 for (i=0; i<count; i++) {
9027 if (queue[i].sysjob == (int)jobid) {
9033 if (found == false) {
9034 /* NT treats not found as bad param... yet another bad choice */
9035 return WERR_INVALID_PARAM;
9038 return fill_job_info1(mem_ctx,
9046 /****************************************************************************
9047 ****************************************************************************/
9049 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9050 const print_queue_struct *queue,
9051 int count, int snum,
9052 struct spoolss_PrinterInfo2 *pinfo2,
9054 struct spoolss_JobInfo2 *r)
9058 struct spoolss_DeviceMode *devmode;
9061 for (i=0; i<count; i++) {
9062 if (queue[i].sysjob == (int)jobid) {
9068 if (found == false) {
9069 /* NT treats not found as bad param... yet another bad
9071 return WERR_INVALID_PARAM;
9075 * if the print job does not have a DEVMODE associated with it,
9076 * just use the one for the printer. A NULL devicemode is not
9077 * a failure condition
9080 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9082 result = spoolss_create_default_devmode(mem_ctx,
9083 pinfo2->printername,
9085 if (!W_ERROR_IS_OK(result)) {
9086 DEBUG(3, ("Can't proceed w/o a devmode!"));
9091 return fill_job_info2(mem_ctx,
9100 /****************************************************************
9102 ****************************************************************/
9104 WERROR _spoolss_GetJob(struct pipes_struct *p,
9105 struct spoolss_GetJob *r)
9107 WERROR result = WERR_OK;
9108 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9111 print_queue_struct *queue = NULL;
9112 print_status_struct prt_status;
9114 /* that's an [in out] buffer */
9116 if (!r->in.buffer && (r->in.offered != 0)) {
9117 return WERR_INVALID_PARAM;
9120 DEBUG(5,("_spoolss_GetJob\n"));
9124 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9128 result = winreg_get_printer_internal(p->mem_ctx,
9129 get_session_info_system(),
9131 lp_const_servicename(snum),
9133 if (!W_ERROR_IS_OK(result)) {
9137 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9139 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9140 count, prt_status.status, prt_status.message));
9142 switch (r->in.level) {
9144 result = getjob_level_1(p->mem_ctx,
9145 queue, count, snum, pinfo2,
9146 r->in.job_id, &r->out.info->info1);
9149 result = getjob_level_2(p->mem_ctx,
9150 queue, count, snum, pinfo2,
9151 r->in.job_id, &r->out.info->info2);
9154 result = WERR_UNKNOWN_LEVEL;
9159 TALLOC_FREE(pinfo2);
9161 if (!W_ERROR_IS_OK(result)) {
9162 TALLOC_FREE(r->out.info);
9166 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9168 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9170 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9173 /****************************************************************
9174 _spoolss_GetPrinterDataEx
9175 ****************************************************************/
9177 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9178 struct spoolss_GetPrinterDataEx *r)
9181 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9182 const char *printer;
9184 WERROR result = WERR_OK;
9186 enum winreg_Type val_type = REG_NONE;
9187 uint8_t *val_data = NULL;
9188 uint32_t val_size = 0;
9189 struct dcerpc_binding_handle *b;
9191 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9193 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9194 r->in.key_name, r->in.value_name));
9196 /* in case of problem, return some default values */
9199 *r->out.type = REG_NONE;
9202 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9203 OUR_HANDLE(r->in.handle)));
9204 result = WERR_BADFID;
9208 /* Is the handle to a printer or to the server? */
9210 if (Printer->printer_type == SPLHND_SERVER) {
9212 union spoolss_PrinterData data;
9214 result = getprinterdata_printer_server(p->mem_ctx,
9218 if (!W_ERROR_IS_OK(result)) {
9222 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9223 *r->out.type, &data);
9224 if (!W_ERROR_IS_OK(result)) {
9228 *r->out.needed = blob.length;
9230 if (r->in.offered >= *r->out.needed) {
9231 memcpy(r->out.data, blob.data, blob.length);
9234 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9237 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9240 printer = lp_const_servicename(snum);
9242 /* check to see if the keyname is valid */
9243 if (!strlen(r->in.key_name)) {
9244 return WERR_INVALID_PARAM;
9247 result = winreg_printer_binding_handle(p->mem_ctx,
9248 get_session_info_system(),
9251 if (!W_ERROR_IS_OK(result)) {
9255 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9256 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9257 strequal(r->in.value_name, "ChangeId")) {
9258 *r->out.type = REG_DWORD;
9260 if (r->in.offered >= *r->out.needed) {
9261 uint32_t changeid = 0;
9263 result = winreg_printer_get_changeid(p->mem_ctx, b,
9266 if (!W_ERROR_IS_OK(result)) {
9270 SIVAL(r->out.data, 0, changeid);
9276 result = winreg_get_printer_dataex(p->mem_ctx, b,
9283 if (!W_ERROR_IS_OK(result)) {
9287 *r->out.needed = val_size;
9288 *r->out.type = val_type;
9290 if (r->in.offered >= *r->out.needed) {
9291 memcpy(r->out.data, val_data, val_size);
9295 /* retain type when returning WERR_MORE_DATA */
9296 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9298 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9301 /****************************************************************
9302 _spoolss_SetPrinterDataEx
9303 ****************************************************************/
9305 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9306 struct spoolss_SetPrinterDataEx *r)
9308 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9310 WERROR result = WERR_OK;
9311 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9313 struct dcerpc_binding_handle *b;
9315 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9317 /* From MSDN documentation of SetPrinterDataEx: pass request to
9318 SetPrinterData if key is "PrinterDriverData" */
9321 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9322 OUR_HANDLE(r->in.handle)));
9326 if (Printer->printer_type == SPLHND_SERVER) {
9327 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9328 "Not implemented for server handles yet\n"));
9329 return WERR_INVALID_PARAM;
9332 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9337 * Access check : NT returns "access denied" if you make a
9338 * SetPrinterData call without the necessary privildge.
9339 * we were originally returning OK if nothing changed
9340 * which made Win2k issue **a lot** of SetPrinterData
9341 * when connecting to a printer --jerry
9344 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9345 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9346 "change denied by handle access permissions\n"));
9347 return WERR_ACCESS_DENIED;
9350 result = winreg_printer_binding_handle(p->mem_ctx,
9351 get_session_info_system(),
9354 if (!W_ERROR_IS_OK(result)) {
9358 result = winreg_get_printer(Printer, b,
9359 lp_servicename(snum),
9361 if (!W_ERROR_IS_OK(result)) {
9365 /* check for OID in valuename */
9367 oid_string = strchr(r->in.value_name, ',');
9373 /* save the registry data */
9375 result = winreg_set_printer_dataex(p->mem_ctx, b,
9383 if (W_ERROR_IS_OK(result)) {
9384 /* save the OID if one was specified */
9386 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9387 r->in.key_name, SPOOL_OID_KEY);
9389 result = WERR_NOMEM;
9394 * I'm not checking the status here on purpose. Don't know
9395 * if this is right, but I'm returning the status from the
9396 * previous set_printer_dataex() call. I have no idea if
9397 * this is right. --jerry
9399 winreg_set_printer_dataex(p->mem_ctx, b,
9404 (uint8_t *) oid_string,
9405 strlen(oid_string) + 1);
9408 result = winreg_printer_update_changeid(p->mem_ctx, b,
9409 lp_const_servicename(snum));
9414 talloc_free(pinfo2);
9418 /****************************************************************
9419 _spoolss_DeletePrinterDataEx
9420 ****************************************************************/
9422 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9423 struct spoolss_DeletePrinterDataEx *r)
9425 const char *printer;
9427 WERROR status = WERR_OK;
9428 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9430 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9433 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9434 "Invalid handle (%s:%u:%u).\n",
9435 OUR_HANDLE(r->in.handle)));
9439 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9440 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9441 "printer properties change denied by handle\n"));
9442 return WERR_ACCESS_DENIED;
9445 if (!r->in.value_name || !r->in.key_name) {
9449 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9452 printer = lp_const_servicename(snum);
9454 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9455 get_session_info_system(),
9460 if (W_ERROR_IS_OK(status)) {
9461 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9462 get_session_info_system(),
9470 /****************************************************************
9471 _spoolss_EnumPrinterKey
9472 ****************************************************************/
9474 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9475 struct spoolss_EnumPrinterKey *r)
9478 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9480 WERROR result = WERR_BADFILE;
9481 const char **array = NULL;
9484 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9487 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9488 OUR_HANDLE(r->in.handle)));
9492 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9496 result = winreg_enum_printer_key_internal(p->mem_ctx,
9497 get_session_info_system(),
9499 lp_const_servicename(snum),
9503 if (!W_ERROR_IS_OK(result)) {
9507 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9508 result = WERR_NOMEM;
9512 *r->out._ndr_size = r->in.offered / 2;
9513 *r->out.needed = blob.length;
9515 if (r->in.offered < *r->out.needed) {
9516 result = WERR_MORE_DATA;
9519 r->out.key_buffer->string_array = array;
9523 if (!W_ERROR_IS_OK(result)) {
9525 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9533 /****************************************************************
9534 _spoolss_DeletePrinterKey
9535 ****************************************************************/
9537 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9538 struct spoolss_DeletePrinterKey *r)
9540 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9543 const char *printer;
9544 struct dcerpc_binding_handle *b;
9546 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9549 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9550 OUR_HANDLE(r->in.handle)));
9554 /* if keyname == NULL, return error */
9555 if ( !r->in.key_name )
9556 return WERR_INVALID_PARAM;
9558 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9562 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9563 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9564 "printer properties change denied by handle\n"));
9565 return WERR_ACCESS_DENIED;
9568 printer = lp_const_servicename(snum);
9570 status = winreg_printer_binding_handle(p->mem_ctx,
9571 get_session_info_system(),
9574 if (!W_ERROR_IS_OK(status)) {
9578 /* delete the key and all subkeys */
9579 status = winreg_delete_printer_key(p->mem_ctx, b,
9582 if (W_ERROR_IS_OK(status)) {
9583 status = winreg_printer_update_changeid(p->mem_ctx, b,
9590 /****************************************************************
9591 _spoolss_EnumPrinterDataEx
9592 ****************************************************************/
9594 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9595 struct spoolss_EnumPrinterDataEx *r)
9598 struct spoolss_PrinterEnumValues *info = NULL;
9599 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9603 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9607 *r->out.info = NULL;
9610 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9611 OUR_HANDLE(r->in.handle)));
9616 * first check for a keyname of NULL or "". Win2k seems to send
9617 * this a lot and we should send back WERR_INVALID_PARAM
9618 * no need to spend time looking up the printer in this case.
9622 if (!strlen(r->in.key_name)) {
9623 result = WERR_INVALID_PARAM;
9627 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9631 /* now look for a match on the key name */
9632 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9633 get_session_info_system(),
9635 lp_const_servicename(snum),
9639 if (!W_ERROR_IS_OK(result)) {
9643 #if 0 /* FIXME - gd */
9644 /* housekeeping information in the reply */
9646 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9647 * the hand marshalled container size is a multiple
9648 * of 4 bytes for RPC alignment.
9652 needed += 4-(needed % 4);
9655 *r->out.count = count;
9656 *r->out.info = info;
9659 if (!W_ERROR_IS_OK(result)) {
9663 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9664 spoolss_EnumPrinterDataEx,
9667 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9668 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9670 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9673 /****************************************************************************
9674 ****************************************************************************/
9676 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9677 const char *servername,
9678 const char *environment,
9679 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9684 werr = compose_spoolss_server_path(mem_ctx,
9687 SPOOLSS_PRTPROCS_PATH,
9689 if (!W_ERROR_IS_OK(werr)) {
9693 DEBUG(4,("print processor directory: [%s]\n", path));
9695 r->directory_name = path;
9700 /****************************************************************
9701 _spoolss_GetPrintProcessorDirectory
9702 ****************************************************************/
9704 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9705 struct spoolss_GetPrintProcessorDirectory *r)
9708 char *prnproc_share = NULL;
9709 bool prnproc_share_exists = false;
9712 /* that's an [in out] buffer */
9714 if (!r->in.buffer && (r->in.offered != 0)) {
9715 return WERR_INVALID_PARAM;
9718 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9723 /* r->in.level is ignored */
9725 /* We always should reply with a local print processor directory so that
9726 * users are not forced to have a [prnproc$] share on the Samba spoolss
9727 * server, if users decide to do so, lets announce it though - Guenther */
9729 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9730 if (!prnproc_share) {
9734 prnproc_share_exists = true;
9737 result = getprintprocessordirectory_level_1(p->mem_ctx,
9738 prnproc_share_exists ? r->in.server : NULL,
9740 &r->out.info->info1);
9741 if (!W_ERROR_IS_OK(result)) {
9742 TALLOC_FREE(r->out.info);
9746 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9747 r->out.info, r->in.level);
9748 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9750 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9753 /*******************************************************************
9754 ********************************************************************/
9756 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9757 const char *dllname)
9759 enum ndr_err_code ndr_err;
9760 struct spoolss_MonitorUi ui;
9762 ui.dll_name = dllname;
9764 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9765 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9766 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9767 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9769 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9772 /*******************************************************************
9773 Streams the monitor UI DLL name in UNICODE
9774 *******************************************************************/
9776 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9777 struct security_token *token, DATA_BLOB *in,
9778 DATA_BLOB *out, uint32_t *needed)
9780 const char *dllname = "tcpmonui.dll";
9782 *needed = (strlen(dllname)+1) * 2;
9784 if (out->length < *needed) {
9785 return WERR_INSUFFICIENT_BUFFER;
9788 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9795 /*******************************************************************
9796 ********************************************************************/
9798 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9799 struct spoolss_PortData1 *port1,
9800 const DATA_BLOB *buf)
9802 enum ndr_err_code ndr_err;
9803 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9804 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9805 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9806 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9808 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9811 /*******************************************************************
9812 ********************************************************************/
9814 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9815 struct spoolss_PortData2 *port2,
9816 const DATA_BLOB *buf)
9818 enum ndr_err_code ndr_err;
9819 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9820 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9821 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9822 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9824 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9827 /*******************************************************************
9828 Create a new TCP/IP port
9829 *******************************************************************/
9831 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9832 struct security_token *token, DATA_BLOB *in,
9833 DATA_BLOB *out, uint32_t *needed)
9835 struct spoolss_PortData1 port1;
9836 struct spoolss_PortData2 port2;
9837 char *device_uri = NULL;
9840 const char *portname;
9841 const char *hostaddress;
9843 uint32_t port_number;
9846 /* peek for spoolss_PortData version */
9848 if (!in || (in->length < (128 + 4))) {
9849 return WERR_GENERAL_FAILURE;
9852 version = IVAL(in->data, 128);
9858 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9862 portname = port1.portname;
9863 hostaddress = port1.hostaddress;
9864 queue = port1.queue;
9865 protocol = port1.protocol;
9866 port_number = port1.port_number;
9872 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9876 portname = port2.portname;
9877 hostaddress = port2.hostaddress;
9878 queue = port2.queue;
9879 protocol = port2.protocol;
9880 port_number = port2.port_number;
9884 DEBUG(1,("xcvtcp_addport: "
9885 "unknown version of port_data: %d\n", version));
9886 return WERR_UNKNOWN_PORT;
9889 /* create the device URI and call the add_port_hook() */
9892 case PROTOCOL_RAWTCP_TYPE:
9893 device_uri = talloc_asprintf(mem_ctx,
9894 "socket://%s:%d/", hostaddress,
9898 case PROTOCOL_LPR_TYPE:
9899 device_uri = talloc_asprintf(mem_ctx,
9900 "lpr://%s/%s", hostaddress, queue );
9904 return WERR_UNKNOWN_PORT;
9911 return add_port_hook(mem_ctx, token, portname, device_uri);
9914 /*******************************************************************
9915 *******************************************************************/
9917 struct xcv_api_table xcvtcp_cmds[] = {
9918 { "MonitorUI", xcvtcp_monitorui },
9919 { "AddPort", xcvtcp_addport},
9923 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9924 struct security_token *token, const char *command,
9931 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9933 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9934 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9935 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9938 return WERR_BADFUNC;
9941 /*******************************************************************
9942 *******************************************************************/
9943 #if 0 /* don't support management using the "Local Port" monitor */
9945 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9946 struct security_token *token, DATA_BLOB *in,
9947 DATA_BLOB *out, uint32_t *needed)
9949 const char *dllname = "localui.dll";
9951 *needed = (strlen(dllname)+1) * 2;
9953 if (out->length < *needed) {
9954 return WERR_INSUFFICIENT_BUFFER;
9957 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9964 /*******************************************************************
9965 *******************************************************************/
9967 struct xcv_api_table xcvlocal_cmds[] = {
9968 { "MonitorUI", xcvlocal_monitorui },
9972 struct xcv_api_table xcvlocal_cmds[] = {
9979 /*******************************************************************
9980 *******************************************************************/
9982 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9983 struct security_token *token, const char *command,
9984 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9989 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9991 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9992 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9993 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9995 return WERR_BADFUNC;
9998 /****************************************************************
10000 ****************************************************************/
10002 WERROR _spoolss_XcvData(struct pipes_struct *p,
10003 struct spoolss_XcvData *r)
10005 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10006 DATA_BLOB out_data = data_blob_null;
10010 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10011 OUR_HANDLE(r->in.handle)));
10012 return WERR_BADFID;
10015 /* Has to be a handle to the TCP/IP port monitor */
10017 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10018 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10019 return WERR_BADFID;
10022 /* requires administrative access to the server */
10024 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10025 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10026 return WERR_ACCESS_DENIED;
10029 /* Allocate the outgoing buffer */
10031 if (r->in.out_data_size) {
10032 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10033 if (out_data.data == NULL) {
10038 switch ( Printer->printer_type ) {
10039 case SPLHND_PORTMON_TCP:
10040 werror = process_xcvtcp_command(p->mem_ctx,
10041 p->session_info->security_token,
10042 r->in.function_name,
10043 &r->in.in_data, &out_data,
10046 case SPLHND_PORTMON_LOCAL:
10047 werror = process_xcvlocal_command(p->mem_ctx,
10048 p->session_info->security_token,
10049 r->in.function_name,
10050 &r->in.in_data, &out_data,
10054 werror = WERR_INVALID_PRINT_MONITOR;
10057 if (!W_ERROR_IS_OK(werror)) {
10061 *r->out.status_code = 0;
10063 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10064 memcpy(r->out.out_data, out_data.data,
10065 MIN(r->in.out_data_size, out_data.length));
10071 /****************************************************************
10072 _spoolss_AddPrintProcessor
10073 ****************************************************************/
10075 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10076 struct spoolss_AddPrintProcessor *r)
10078 /* for now, just indicate success and ignore the add. We'll
10079 automatically set the winprint processor for printer
10080 entries later. Used to debug the LexMark Optra S 1855 PCL
10086 /****************************************************************
10088 ****************************************************************/
10090 WERROR _spoolss_AddPort(struct pipes_struct *p,
10091 struct spoolss_AddPort *r)
10093 /* do what w2k3 does */
10095 return WERR_NOT_SUPPORTED;
10098 /****************************************************************
10099 _spoolss_GetPrinterDriver
10100 ****************************************************************/
10102 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10103 struct spoolss_GetPrinterDriver *r)
10105 p->rng_fault_state = true;
10106 return WERR_NOT_SUPPORTED;
10109 /****************************************************************
10110 _spoolss_ReadPrinter
10111 ****************************************************************/
10113 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10114 struct spoolss_ReadPrinter *r)
10116 p->rng_fault_state = true;
10117 return WERR_NOT_SUPPORTED;
10120 /****************************************************************
10121 _spoolss_WaitForPrinterChange
10122 ****************************************************************/
10124 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10125 struct spoolss_WaitForPrinterChange *r)
10127 p->rng_fault_state = true;
10128 return WERR_NOT_SUPPORTED;
10131 /****************************************************************
10132 _spoolss_ConfigurePort
10133 ****************************************************************/
10135 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10136 struct spoolss_ConfigurePort *r)
10138 p->rng_fault_state = true;
10139 return WERR_NOT_SUPPORTED;
10142 /****************************************************************
10143 _spoolss_DeletePort
10144 ****************************************************************/
10146 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10147 struct spoolss_DeletePort *r)
10149 p->rng_fault_state = true;
10150 return WERR_NOT_SUPPORTED;
10153 /****************************************************************
10154 _spoolss_CreatePrinterIC
10155 ****************************************************************/
10157 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10158 struct spoolss_CreatePrinterIC *r)
10160 p->rng_fault_state = true;
10161 return WERR_NOT_SUPPORTED;
10164 /****************************************************************
10165 _spoolss_PlayGDIScriptOnPrinterIC
10166 ****************************************************************/
10168 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10169 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10171 p->rng_fault_state = true;
10172 return WERR_NOT_SUPPORTED;
10175 /****************************************************************
10176 _spoolss_DeletePrinterIC
10177 ****************************************************************/
10179 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10180 struct spoolss_DeletePrinterIC *r)
10182 p->rng_fault_state = true;
10183 return WERR_NOT_SUPPORTED;
10186 /****************************************************************
10187 _spoolss_AddPrinterConnection
10188 ****************************************************************/
10190 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10191 struct spoolss_AddPrinterConnection *r)
10193 p->rng_fault_state = true;
10194 return WERR_NOT_SUPPORTED;
10197 /****************************************************************
10198 _spoolss_DeletePrinterConnection
10199 ****************************************************************/
10201 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10202 struct spoolss_DeletePrinterConnection *r)
10204 p->rng_fault_state = true;
10205 return WERR_NOT_SUPPORTED;
10208 /****************************************************************
10209 _spoolss_PrinterMessageBox
10210 ****************************************************************/
10212 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10213 struct spoolss_PrinterMessageBox *r)
10215 p->rng_fault_state = true;
10216 return WERR_NOT_SUPPORTED;
10219 /****************************************************************
10220 _spoolss_AddMonitor
10221 ****************************************************************/
10223 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10224 struct spoolss_AddMonitor *r)
10226 p->rng_fault_state = true;
10227 return WERR_NOT_SUPPORTED;
10230 /****************************************************************
10231 _spoolss_DeleteMonitor
10232 ****************************************************************/
10234 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10235 struct spoolss_DeleteMonitor *r)
10237 p->rng_fault_state = true;
10238 return WERR_NOT_SUPPORTED;
10241 /****************************************************************
10242 _spoolss_DeletePrintProcessor
10243 ****************************************************************/
10245 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10246 struct spoolss_DeletePrintProcessor *r)
10248 p->rng_fault_state = true;
10249 return WERR_NOT_SUPPORTED;
10252 /****************************************************************
10253 _spoolss_AddPrintProvidor
10254 ****************************************************************/
10256 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10257 struct spoolss_AddPrintProvidor *r)
10259 p->rng_fault_state = true;
10260 return WERR_NOT_SUPPORTED;
10263 /****************************************************************
10264 _spoolss_DeletePrintProvidor
10265 ****************************************************************/
10267 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10268 struct spoolss_DeletePrintProvidor *r)
10270 p->rng_fault_state = true;
10271 return WERR_NOT_SUPPORTED;
10274 /****************************************************************
10275 _spoolss_FindFirstPrinterChangeNotification
10276 ****************************************************************/
10278 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10279 struct spoolss_FindFirstPrinterChangeNotification *r)
10281 p->rng_fault_state = true;
10282 return WERR_NOT_SUPPORTED;
10285 /****************************************************************
10286 _spoolss_FindNextPrinterChangeNotification
10287 ****************************************************************/
10289 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10290 struct spoolss_FindNextPrinterChangeNotification *r)
10292 p->rng_fault_state = true;
10293 return WERR_NOT_SUPPORTED;
10296 /****************************************************************
10297 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10298 ****************************************************************/
10300 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10301 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10303 p->rng_fault_state = true;
10304 return WERR_NOT_SUPPORTED;
10307 /****************************************************************
10308 _spoolss_ReplyOpenPrinter
10309 ****************************************************************/
10311 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10312 struct spoolss_ReplyOpenPrinter *r)
10314 p->rng_fault_state = true;
10315 return WERR_NOT_SUPPORTED;
10318 /****************************************************************
10319 _spoolss_RouterReplyPrinter
10320 ****************************************************************/
10322 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10323 struct spoolss_RouterReplyPrinter *r)
10325 p->rng_fault_state = true;
10326 return WERR_NOT_SUPPORTED;
10329 /****************************************************************
10330 _spoolss_ReplyClosePrinter
10331 ****************************************************************/
10333 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10334 struct spoolss_ReplyClosePrinter *r)
10336 p->rng_fault_state = true;
10337 return WERR_NOT_SUPPORTED;
10340 /****************************************************************
10342 ****************************************************************/
10344 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10345 struct spoolss_AddPortEx *r)
10347 p->rng_fault_state = true;
10348 return WERR_NOT_SUPPORTED;
10351 /****************************************************************
10352 _spoolss_RouterFindFirstPrinterChangeNotification
10353 ****************************************************************/
10355 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10356 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10358 p->rng_fault_state = true;
10359 return WERR_NOT_SUPPORTED;
10362 /****************************************************************
10363 _spoolss_SpoolerInit
10364 ****************************************************************/
10366 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10367 struct spoolss_SpoolerInit *r)
10369 p->rng_fault_state = true;
10370 return WERR_NOT_SUPPORTED;
10373 /****************************************************************
10374 _spoolss_ResetPrinterEx
10375 ****************************************************************/
10377 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10378 struct spoolss_ResetPrinterEx *r)
10380 p->rng_fault_state = true;
10381 return WERR_NOT_SUPPORTED;
10384 /****************************************************************
10385 _spoolss_RouterReplyPrinterEx
10386 ****************************************************************/
10388 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10389 struct spoolss_RouterReplyPrinterEx *r)
10391 p->rng_fault_state = true;
10392 return WERR_NOT_SUPPORTED;
10395 /****************************************************************
10397 ****************************************************************/
10399 WERROR _spoolss_44(struct pipes_struct *p,
10400 struct spoolss_44 *r)
10402 p->rng_fault_state = true;
10403 return WERR_NOT_SUPPORTED;
10406 /****************************************************************
10408 ****************************************************************/
10410 WERROR _spoolss_SetPort(struct pipes_struct *p,
10411 struct spoolss_SetPort *r)
10413 p->rng_fault_state = true;
10414 return WERR_NOT_SUPPORTED;
10417 /****************************************************************
10419 ****************************************************************/
10421 WERROR _spoolss_4a(struct pipes_struct *p,
10422 struct spoolss_4a *r)
10424 p->rng_fault_state = true;
10425 return WERR_NOT_SUPPORTED;
10428 /****************************************************************
10430 ****************************************************************/
10432 WERROR _spoolss_4b(struct pipes_struct *p,
10433 struct spoolss_4b *r)
10435 p->rng_fault_state = true;
10436 return WERR_NOT_SUPPORTED;
10439 /****************************************************************
10441 ****************************************************************/
10443 WERROR _spoolss_4c(struct pipes_struct *p,
10444 struct spoolss_4c *r)
10446 p->rng_fault_state = true;
10447 return WERR_NOT_SUPPORTED;
10450 /****************************************************************
10452 ****************************************************************/
10454 WERROR _spoolss_53(struct pipes_struct *p,
10455 struct spoolss_53 *r)
10457 p->rng_fault_state = true;
10458 return WERR_NOT_SUPPORTED;
10461 /****************************************************************
10462 _spoolss_AddPerMachineConnection
10463 ****************************************************************/
10465 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10466 struct spoolss_AddPerMachineConnection *r)
10468 p->rng_fault_state = true;
10469 return WERR_NOT_SUPPORTED;
10472 /****************************************************************
10473 _spoolss_DeletePerMachineConnection
10474 ****************************************************************/
10476 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10477 struct spoolss_DeletePerMachineConnection *r)
10479 p->rng_fault_state = true;
10480 return WERR_NOT_SUPPORTED;
10483 /****************************************************************
10484 _spoolss_EnumPerMachineConnections
10485 ****************************************************************/
10487 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10488 struct spoolss_EnumPerMachineConnections *r)
10490 p->rng_fault_state = true;
10491 return WERR_NOT_SUPPORTED;
10494 /****************************************************************
10496 ****************************************************************/
10498 WERROR _spoolss_5a(struct pipes_struct *p,
10499 struct spoolss_5a *r)
10501 p->rng_fault_state = true;
10502 return WERR_NOT_SUPPORTED;
10505 /****************************************************************
10507 ****************************************************************/
10509 WERROR _spoolss_5b(struct pipes_struct *p,
10510 struct spoolss_5b *r)
10512 p->rng_fault_state = true;
10513 return WERR_NOT_SUPPORTED;
10516 /****************************************************************
10518 ****************************************************************/
10520 WERROR _spoolss_5c(struct pipes_struct *p,
10521 struct spoolss_5c *r)
10523 p->rng_fault_state = true;
10524 return WERR_NOT_SUPPORTED;
10527 /****************************************************************
10529 ****************************************************************/
10531 WERROR _spoolss_5d(struct pipes_struct *p,
10532 struct spoolss_5d *r)
10534 p->rng_fault_state = true;
10535 return WERR_NOT_SUPPORTED;
10538 /****************************************************************
10540 ****************************************************************/
10542 WERROR _spoolss_5e(struct pipes_struct *p,
10543 struct spoolss_5e *r)
10545 p->rng_fault_state = true;
10546 return WERR_NOT_SUPPORTED;
10549 /****************************************************************
10551 ****************************************************************/
10553 WERROR _spoolss_5f(struct pipes_struct *p,
10554 struct spoolss_5f *r)
10556 p->rng_fault_state = true;
10557 return WERR_NOT_SUPPORTED;
10560 /****************************************************************
10562 ****************************************************************/
10564 WERROR _spoolss_60(struct pipes_struct *p,
10565 struct spoolss_60 *r)
10567 p->rng_fault_state = true;
10568 return WERR_NOT_SUPPORTED;
10571 /****************************************************************
10573 ****************************************************************/
10575 WERROR _spoolss_61(struct pipes_struct *p,
10576 struct spoolss_61 *r)
10578 p->rng_fault_state = true;
10579 return WERR_NOT_SUPPORTED;
10582 /****************************************************************
10584 ****************************************************************/
10586 WERROR _spoolss_62(struct pipes_struct *p,
10587 struct spoolss_62 *r)
10589 p->rng_fault_state = true;
10590 return WERR_NOT_SUPPORTED;
10593 /****************************************************************
10595 ****************************************************************/
10597 WERROR _spoolss_63(struct pipes_struct *p,
10598 struct spoolss_63 *r)
10600 p->rng_fault_state = true;
10601 return WERR_NOT_SUPPORTED;
10604 /****************************************************************
10606 ****************************************************************/
10608 WERROR _spoolss_64(struct pipes_struct *p,
10609 struct spoolss_64 *r)
10611 p->rng_fault_state = true;
10612 return WERR_NOT_SUPPORTED;
10615 /****************************************************************
10617 ****************************************************************/
10619 WERROR _spoolss_65(struct pipes_struct *p,
10620 struct spoolss_65 *r)
10622 p->rng_fault_state = true;
10623 return WERR_NOT_SUPPORTED;
10626 /****************************************************************
10627 _spoolss_GetCorePrinterDrivers
10628 ****************************************************************/
10630 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10631 struct spoolss_GetCorePrinterDrivers *r)
10633 p->rng_fault_state = true;
10634 return WERR_NOT_SUPPORTED;
10637 /****************************************************************
10639 ****************************************************************/
10641 WERROR _spoolss_67(struct pipes_struct *p,
10642 struct spoolss_67 *r)
10644 p->rng_fault_state = true;
10645 return WERR_NOT_SUPPORTED;
10648 /****************************************************************
10649 _spoolss_GetPrinterDriverPackagePath
10650 ****************************************************************/
10652 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10653 struct spoolss_GetPrinterDriverPackagePath *r)
10655 p->rng_fault_state = true;
10656 return WERR_NOT_SUPPORTED;
10659 /****************************************************************
10661 ****************************************************************/
10663 WERROR _spoolss_69(struct pipes_struct *p,
10664 struct spoolss_69 *r)
10666 p->rng_fault_state = true;
10667 return WERR_NOT_SUPPORTED;
10670 /****************************************************************
10672 ****************************************************************/
10674 WERROR _spoolss_6a(struct pipes_struct *p,
10675 struct spoolss_6a *r)
10677 p->rng_fault_state = true;
10678 return WERR_NOT_SUPPORTED;
10681 /****************************************************************
10683 ****************************************************************/
10685 WERROR _spoolss_6b(struct pipes_struct *p,
10686 struct spoolss_6b *r)
10688 p->rng_fault_state = true;
10689 return WERR_NOT_SUPPORTED;
10692 /****************************************************************
10694 ****************************************************************/
10696 WERROR _spoolss_6c(struct pipes_struct *p,
10697 struct spoolss_6c *r)
10699 p->rng_fault_state = true;
10700 return WERR_NOT_SUPPORTED;
10703 /****************************************************************
10705 ****************************************************************/
10707 WERROR _spoolss_6d(struct pipes_struct *p,
10708 struct spoolss_6d *r)
10710 p->rng_fault_state = true;
10711 return WERR_NOT_SUPPORTED;