2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "../libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry/reg_objects.h"
41 #include "include/printing.h"
43 #include "../librpc/gen_ndr/netlogon.h"
45 #include "printing/notify.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
53 /* macros stolen from s4 spoolss server */
54 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
55 ((info)?ndr_size_##fn(info, level, 0):0)
57 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
58 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
60 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
61 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
63 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
66 #define DBGC_CLASS DBGC_RPC_SRV
68 #ifndef MAX_OPEN_PRINTER_EXS
69 #define MAX_OPEN_PRINTER_EXS 50
72 struct notify_back_channel;
74 /* structure to store the printer handles */
75 /* and a reference to what it's pointing to */
76 /* and the notify info asked about */
77 /* that's the central struct */
78 struct printer_handle {
79 struct printer_handle *prev, *next;
80 bool document_started;
82 uint32 jobid; /* jobid in printing backend */
84 const char *servername;
87 uint32 access_granted;
93 struct spoolss_NotifyOption *option;
94 struct policy_handle cli_hnd;
95 struct notify_back_channel *cli_chan;
97 /* are we in a FindNextPrinterChangeNotify() call? */
99 struct messaging_context *msg_ctx;
106 /* devmode sent in the OpenPrinter() call */
107 struct spoolss_DeviceMode *devmode;
109 /* TODO cache the printer info2 structure */
110 struct spoolss_PrinterInfo2 *info2;
114 static struct printer_handle *printers_list;
116 struct printer_session_counter {
117 struct printer_session_counter *next;
118 struct printer_session_counter *prev;
124 static struct printer_session_counter *counter_list;
126 struct notify_back_channel {
127 struct notify_back_channel *prev, *next;
129 /* associated client */
130 struct sockaddr_storage client_address;
132 /* print notify back-channel pipe handle*/
133 struct rpc_pipe_client *cli_pipe;
134 struct dcerpc_binding_handle *binding_handle;
135 uint32_t active_connections;
138 static struct notify_back_channel *back_channels;
140 /* Map generic permissions to printer object specific permissions */
142 const struct standard_mapping printer_std_mapping = {
149 /* Map generic permissions to print server object specific permissions */
151 const struct standard_mapping printserver_std_mapping = {
158 /* API table for Xcv Monitor functions */
160 struct xcv_api_table {
162 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
165 static void prune_printername_cache(void);
167 /********************************************************************
168 * Canonicalize servername.
169 ********************************************************************/
171 static const char *canon_servername(const char *servername)
173 const char *pservername = servername;
174 while (*pservername == '\\') {
180 /* translate between internal status numbers and NT status numbers */
181 static int nt_printj_status(int v)
187 return JOB_STATUS_PAUSED;
189 return JOB_STATUS_SPOOLING;
191 return JOB_STATUS_PRINTING;
193 return JOB_STATUS_ERROR;
195 return JOB_STATUS_DELETING;
197 return JOB_STATUS_OFFLINE;
199 return JOB_STATUS_PAPEROUT;
201 return JOB_STATUS_PRINTED;
203 return JOB_STATUS_DELETED;
205 return JOB_STATUS_BLOCKED_DEVQ;
206 case LPQ_USER_INTERVENTION:
207 return JOB_STATUS_USER_INTERVENTION;
212 static int nt_printq_status(int v)
216 return PRINTER_STATUS_PAUSED;
225 /***************************************************************************
226 Disconnect from the client
227 ****************************************************************************/
229 static void srv_spoolss_replycloseprinter(int snum,
230 struct printer_handle *prn_hnd)
236 * Tell the specific printing tdb we no longer want messages for this printer
237 * by deregistering our PID.
240 if (!print_notify_deregister_pid(snum)) {
241 DEBUG(0, ("Failed to register our pid for printer %s\n",
242 lp_const_servicename(snum)));
245 /* weird if the test succeeds !!! */
246 if (prn_hnd->notify.cli_chan == NULL ||
247 prn_hnd->notify.cli_chan->active_connections == 0) {
248 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
249 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
250 TALLOC_FREE(prn_hnd->notify.cli_chan);
254 status = dcerpc_spoolss_ReplyClosePrinter(
255 prn_hnd->notify.cli_chan->binding_handle,
257 &prn_hnd->notify.cli_hnd,
259 if (!NT_STATUS_IS_OK(status)) {
260 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
262 result = ntstatus_to_werror(status);
263 } else if (!W_ERROR_IS_OK(result)) {
264 DEBUG(0, ("reply_close_printer failed [%s].\n",
265 win_errstr(result)));
268 /* if it's the last connection, deconnect the IPC$ share */
269 if (prn_hnd->notify.cli_chan->active_connections == 1) {
271 prn_hnd->notify.cli_chan->binding_handle = NULL;
272 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
273 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
274 TALLOC_FREE(prn_hnd->notify.cli_chan);
276 if (prn_hnd->notify.msg_ctx != NULL) {
277 messaging_deregister(prn_hnd->notify.msg_ctx,
278 MSG_PRINTER_NOTIFY2, NULL);
281 * Tell the serverid.tdb we're no longer
282 * interested in printer notify messages.
285 serverid_register_msg_flags(
286 messaging_server_id(prn_hnd->notify.msg_ctx),
287 false, FLAG_MSG_PRINT_NOTIFY);
291 if (prn_hnd->notify.cli_chan) {
292 prn_hnd->notify.cli_chan->active_connections--;
296 /****************************************************************************
297 Functions to free a printer entry datastruct.
298 ****************************************************************************/
300 static int printer_entry_destructor(struct printer_handle *Printer)
302 if (Printer->notify.cli_chan != NULL &&
303 Printer->notify.cli_chan->active_connections > 0) {
306 switch(Printer->printer_type) {
308 srv_spoolss_replycloseprinter(snum, Printer);
312 snum = print_queue_snum(Printer->sharename);
314 srv_spoolss_replycloseprinter(snum, Printer);
322 Printer->notify.flags=0;
323 Printer->notify.options=0;
324 Printer->notify.localmachine[0]='\0';
325 Printer->notify.printerlocal=0;
326 TALLOC_FREE(Printer->notify.option);
327 TALLOC_FREE(Printer->devmode);
329 /* Remove from the internal list. */
330 DLIST_REMOVE(printers_list, Printer);
334 /****************************************************************************
335 find printer index by handle
336 ****************************************************************************/
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339 struct policy_handle *hnd)
341 struct printer_handle *find_printer = NULL;
343 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
351 /****************************************************************************
352 Close printer index by handle.
353 ****************************************************************************/
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
357 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
360 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
365 close_policy_hnd(p, hnd);
370 /****************************************************************************
371 Delete a printer given a handle.
372 ****************************************************************************/
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375 const char *sharename,
376 struct messaging_context *msg_ctx)
378 char *cmd = lp_deleteprinter_cmd();
379 char *command = NULL;
381 bool is_print_op = false;
383 /* can't fail if we don't try */
388 command = talloc_asprintf(ctx,
395 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
397 DEBUG(10,("Running [%s]\n", command));
399 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
404 if ( (ret = smbrun(command, NULL)) == 0 ) {
405 /* Tell everyone we updated smb.conf. */
406 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
412 /********** END SePrintOperatorPrivlege BLOCK **********/
414 DEBUGADD(10,("returned [%d]\n", ret));
416 TALLOC_FREE(command);
419 return WERR_BADFID; /* What to return here? */
421 /* go ahead and re-read the services immediately */
423 reload_services(msg_ctx, -1, false);
426 if ( lp_servicenumber( sharename ) >= 0 )
427 return WERR_ACCESS_DENIED;
432 /****************************************************************************
433 Delete a printer given a handle.
434 ****************************************************************************/
436 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
438 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
442 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
448 * It turns out that Windows allows delete printer on a handle
449 * opened by an admin user, then used on a pipe handle created
450 * by an anonymous user..... but they're working on security.... riiight !
454 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
455 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
456 return WERR_ACCESS_DENIED;
459 /* this does not need a become root since the access check has been
460 done on the handle already */
462 result = winreg_delete_printer_key(p->mem_ctx,
463 get_session_info_system(),
467 if (!W_ERROR_IS_OK(result)) {
468 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
472 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
473 Printer->sharename, p->msg_ctx);
474 if (!W_ERROR_IS_OK(result)) {
477 prune_printername_cache();
481 /****************************************************************************
482 Return the snum of a printer corresponding to an handle.
483 ****************************************************************************/
485 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
486 int *number, struct share_params **params)
488 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
491 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
496 switch (Printer->printer_type) {
498 DEBUG(4,("short name:%s\n", Printer->sharename));
499 *number = print_queue_snum(Printer->sharename);
500 return (*number != -1);
508 /****************************************************************************
509 Set printer handle type.
510 Check if it's \\server or \\server\printer
511 ****************************************************************************/
513 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
515 DEBUG(3,("Setting printer type=%s\n", handlename));
517 /* it's a print server */
518 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
519 DEBUGADD(4,("Printer is a print server\n"));
520 Printer->printer_type = SPLHND_SERVER;
522 /* it's a printer (set_printer_hnd_name() will handle port monitors */
524 DEBUGADD(4,("Printer is a printer\n"));
525 Printer->printer_type = SPLHND_PRINTER;
531 static void prune_printername_cache_fn(const char *key, const char *value,
532 time_t timeout, void *private_data)
537 static void prune_printername_cache(void)
539 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
542 /****************************************************************************
543 Set printer handle name.. Accept names like \\server, \\server\printer,
544 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
545 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
546 XcvDataPort() interface.
547 ****************************************************************************/
549 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
550 const struct auth_serversupplied_info *session_info,
551 struct messaging_context *msg_ctx,
552 struct printer_handle *Printer,
553 const char *handlename)
556 int n_services=lp_numservices();
558 const char *printername;
559 const char *servername = NULL;
562 struct spoolss_PrinterInfo2 *info2 = NULL;
567 * Hopefully nobody names his printers like this. Maybe \ or ,
568 * are illegal in printer names even?
570 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
574 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
575 (unsigned long)strlen(handlename)));
577 aprinter = CONST_DISCARD(char *, handlename);
578 if ( *handlename == '\\' ) {
579 servername = canon_servername(handlename);
580 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
584 if (!is_myname_or_ipaddr(servername)) {
585 return WERR_INVALID_PRINTER_NAME;
587 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
588 if (Printer->servername == NULL) {
593 if (Printer->printer_type == SPLHND_SERVER) {
597 if (Printer->printer_type != SPLHND_PRINTER) {
598 return WERR_INVALID_HANDLE;
601 DEBUGADD(5, ("searching for [%s]\n", aprinter));
603 p = strchr(aprinter, ',');
610 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
612 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
618 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
621 /* check for the Port Monitor Interface */
622 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
623 Printer->printer_type = SPLHND_PORTMON_TCP;
624 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
627 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
628 Printer->printer_type = SPLHND_PORTMON_LOCAL;
629 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
634 * With hundreds of printers, the "for" loop iterating all
635 * shares can be quite expensive, as it is done on every
636 * OpenPrinter. The loop maps "aprinter" to "sname", the
637 * result of which we cache in gencache.
640 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
642 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
644 found = (strcmp(tmp, printer_not_found) != 0);
646 DEBUG(4, ("Printer %s not found\n", aprinter));
648 return WERR_INVALID_PRINTER_NAME;
654 /* Search all sharenames first as this is easier than pulling
655 the printer_info_2 off of disk. Don't use find_service() since
656 that calls out to map_username() */
658 /* do another loop to look for printernames */
659 for (snum = 0; !found && snum < n_services; snum++) {
660 const char *printer = lp_const_servicename(snum);
662 /* no point going on if this is not a printer */
663 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
667 /* ignore [printers] share */
668 if (strequal(printer, "printers")) {
672 fstrcpy(sname, printer);
673 if (strequal(aprinter, printer)) {
678 /* no point looking up the printer object if
679 we aren't allowing printername != sharename */
680 if (lp_force_printername(snum)) {
684 result = winreg_get_printer(mem_ctx,
689 if ( !W_ERROR_IS_OK(result) ) {
690 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
691 sname, win_errstr(result)));
695 printername = strrchr(info2->printername, '\\');
696 if (printername == NULL) {
697 printername = info2->printername;
702 if (strequal(printername, aprinter)) {
707 DEBUGADD(10, ("printername: %s\n", printername));
713 if (cache_key != NULL) {
714 gencache_set(cache_key, printer_not_found,
716 TALLOC_FREE(cache_key);
718 DEBUGADD(4,("Printer not found\n"));
719 return WERR_INVALID_PRINTER_NAME;
722 if (cache_key != NULL) {
723 gencache_set(cache_key, sname, time(NULL)+300);
724 TALLOC_FREE(cache_key);
727 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
729 fstrcpy(Printer->sharename, sname);
734 /****************************************************************************
735 Find first available printer slot. creates a printer handle for you.
736 ****************************************************************************/
738 static WERROR open_printer_hnd(struct pipes_struct *p,
739 struct policy_handle *hnd,
741 uint32_t access_granted)
743 struct printer_handle *new_printer;
746 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
748 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
749 if (new_printer == NULL) {
752 talloc_set_destructor(new_printer, printer_entry_destructor);
754 /* This also steals the printer_handle on the policy_handle */
755 if (!create_policy_hnd(p, hnd, new_printer)) {
756 TALLOC_FREE(new_printer);
757 return WERR_INVALID_HANDLE;
760 /* Add to the internal list. */
761 DLIST_ADD(printers_list, new_printer);
763 new_printer->notify.option=NULL;
765 if (!set_printer_hnd_printertype(new_printer, name)) {
766 close_printer_handle(p, hnd);
767 return WERR_INVALID_HANDLE;
770 result = set_printer_hnd_name(p->mem_ctx,
771 get_session_info_system(),
774 if (!W_ERROR_IS_OK(result)) {
775 close_printer_handle(p, hnd);
779 new_printer->access_granted = access_granted;
781 DEBUG(5, ("%d printer handles active\n",
782 (int)num_pipe_handles(p)));
787 /***************************************************************************
788 check to see if the client motify handle is monitoring the notification
789 given by (notify_type, notify_field).
790 **************************************************************************/
792 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
793 uint16_t notify_field)
798 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
799 uint16_t notify_field)
801 struct spoolss_NotifyOption *option = p->notify.option;
805 * Flags should always be zero when the change notify
806 * is registered by the client's spooler. A user Win32 app
807 * might use the flags though instead of the NOTIFY_OPTION_INFO
816 return is_monitoring_event_flags(
817 p->notify.flags, notify_type, notify_field);
819 for (i = 0; i < option->count; i++) {
821 /* Check match for notify_type */
823 if (option->types[i].type != notify_type)
826 /* Check match for field */
828 for (j = 0; j < option->types[i].count; j++) {
829 if (option->types[i].fields[j].field == notify_field) {
835 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
836 p->servername, p->sharename, notify_type, notify_field));
841 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
842 _data->data.integer[0] = _integer; \
843 _data->data.integer[1] = 0;
846 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
847 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
848 if (!_data->data.string.string) {\
849 _data->data.string.size = 0; \
851 _data->data.string.size = strlen_m_term(_p) * 2;
853 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
854 _data->data.devmode.devmode = _devmode;
856 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
857 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
858 if (!_data->data.sd.sd) { \
859 _data->data.sd.sd_size = 0; \
861 _data->data.sd.sd_size = \
862 ndr_size_security_descriptor(_data->data.sd.sd, 0);
864 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
869 struct spoolss_Time st;
873 if (!init_systemtime(&st, t)) {
877 p = talloc_array(mem_ctx, char, len);
883 * Systemtime must be linearized as a set of UINT16's.
884 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
887 SSVAL(p, 0, st.year);
888 SSVAL(p, 2, st.month);
889 SSVAL(p, 4, st.day_of_week);
891 SSVAL(p, 8, st.hour);
892 SSVAL(p, 10, st.minute);
893 SSVAL(p, 12, st.second);
894 SSVAL(p, 14, st.millisecond);
900 /* Convert a notification message to a struct spoolss_Notify */
902 static void notify_one_value(struct spoolss_notify_msg *msg,
903 struct spoolss_Notify *data,
906 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
909 static void notify_string(struct spoolss_notify_msg *msg,
910 struct spoolss_Notify *data,
913 /* The length of the message includes the trailing \0 */
915 data->data.string.size = msg->len * 2;
916 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
917 if (!data->data.string.string) {
918 data->data.string.size = 0;
923 static void notify_system_time(struct spoolss_notify_msg *msg,
924 struct spoolss_Notify *data,
927 data->data.string.string = NULL;
928 data->data.string.size = 0;
930 if (msg->len != sizeof(time_t)) {
931 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
936 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
937 &data->data.string.string,
938 &data->data.string.size);
941 struct notify2_message_table {
943 void (*fn)(struct spoolss_notify_msg *msg,
944 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
947 static struct notify2_message_table printer_notify_table[] = {
948 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
949 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
950 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
951 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
952 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
953 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
954 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
955 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
956 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
957 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
958 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
959 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
960 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
961 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
962 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
963 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
964 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
965 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
966 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
969 static struct notify2_message_table job_notify_table[] = {
970 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
971 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
972 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
973 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
974 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
975 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
976 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
977 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
978 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
979 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
980 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
981 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
982 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
983 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
984 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
985 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
986 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
987 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
988 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
989 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
990 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
991 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
992 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
993 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
997 /***********************************************************************
998 Allocate talloc context for container object
999 **********************************************************************/
1001 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1006 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1011 /***********************************************************************
1012 release all allocated memory and zero out structure
1013 **********************************************************************/
1015 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1021 talloc_destroy(ctr->ctx);
1028 /***********************************************************************
1029 **********************************************************************/
1031 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1039 /***********************************************************************
1040 **********************************************************************/
1042 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1044 if ( !ctr || !ctr->msg_groups )
1047 if ( idx >= ctr->num_groups )
1050 return &ctr->msg_groups[idx];
1054 /***********************************************************************
1055 How many groups of change messages do we have ?
1056 **********************************************************************/
1058 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1063 return ctr->num_groups;
1066 /***********************************************************************
1067 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1068 **********************************************************************/
1070 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1072 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1073 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1074 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1080 /* loop over all groups looking for a matching printer name */
1082 for ( i=0; i<ctr->num_groups; i++ ) {
1083 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1087 /* add a new group? */
1089 if ( i == ctr->num_groups ) {
1092 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1093 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1096 ctr->msg_groups = groups;
1098 /* clear the new entry and set the printer name */
1100 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1101 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1104 /* add the change messages; 'i' is the correct index now regardless */
1106 msg_grp = &ctr->msg_groups[i];
1108 msg_grp->num_msgs++;
1110 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1111 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1114 msg_grp->msgs = msg_list;
1116 new_slot = msg_grp->num_msgs-1;
1117 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1119 /* need to allocate own copy of data */
1121 if ( msg->len != 0 )
1122 msg_grp->msgs[new_slot].notify.data = (char *)
1123 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1125 return ctr->num_groups;
1128 static void construct_info_data(struct spoolss_Notify *info_data,
1129 enum spoolss_NotifyType type,
1130 uint16_t field, int id);
1132 /***********************************************************************
1133 Send a change notication message on all handles which have a call
1135 **********************************************************************/
1137 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1138 struct printer_handle *prn_hnd,
1139 SPOOLSS_NOTIFY_MSG *messages,
1141 struct spoolss_Notify **_notifies,
1144 struct spoolss_Notify *notifies;
1145 SPOOLSS_NOTIFY_MSG *msg;
1150 notifies = talloc_zero_array(mem_ctx,
1151 struct spoolss_Notify, num_msgs);
1156 for (i = 0; i < num_msgs; i++) {
1160 /* Are we monitoring this event? */
1162 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1166 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1167 "for printer [%s]\n",
1168 msg->type, msg->field, prn_hnd->sharename));
1171 * if the is a printer notification handle and not a job
1172 * notification type, then set the id to 0.
1173 * Otherwise just use what was specified in the message.
1175 * When registering change notification on a print server
1176 * handle we always need to send back the id (snum) matching
1177 * the printer for which the change took place.
1178 * For change notify registered on a printer handle,
1179 * this does not matter and the id should be 0.
1184 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1185 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1191 /* Convert unix jobid to smb jobid */
1193 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1194 id = sysjob_to_jobid(msg->id);
1197 DEBUG(3, ("no such unix jobid %d\n",
1203 construct_info_data(¬ifies[count],
1204 msg->type, msg->field, id);
1207 case PRINTER_NOTIFY_TYPE:
1208 if (printer_notify_table[msg->field].fn) {
1209 printer_notify_table[msg->field].fn(msg,
1210 ¬ifies[count], mem_ctx);
1214 case JOB_NOTIFY_TYPE:
1215 if (job_notify_table[msg->field].fn) {
1216 job_notify_table[msg->field].fn(msg,
1217 ¬ifies[count], mem_ctx);
1222 DEBUG(5, ("Unknown notification type %d\n",
1230 *_notifies = notifies;
1236 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1237 struct printer_handle *prn_hnd,
1238 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1240 struct spoolss_Notify *notifies;
1242 union spoolss_ReplyPrinterInfo info;
1243 struct spoolss_NotifyInfo info0;
1244 uint32_t reply_result;
1249 /* Is there notification on this handle? */
1250 if (prn_hnd->notify.cli_chan == NULL ||
1251 prn_hnd->notify.cli_chan->active_connections == 0) {
1255 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1256 prn_hnd->servername, prn_hnd->sharename));
1258 /* For this printer? Print servers always receive notifications. */
1259 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1260 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1264 DEBUG(10,("Our printer\n"));
1266 /* build the array of change notifications */
1267 ret = build_notify2_messages(mem_ctx, prn_hnd,
1269 msg_group->num_msgs,
1275 info0.version = 0x2;
1276 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1277 info0.count = count;
1278 info0.notifies = notifies;
1280 info.info0 = &info0;
1282 status = dcerpc_spoolss_RouterReplyPrinterEx(
1283 prn_hnd->notify.cli_chan->binding_handle,
1285 &prn_hnd->notify.cli_hnd,
1286 prn_hnd->notify.change, /* color */
1287 prn_hnd->notify.flags,
1289 0, /* reply_type, must be 0 */
1291 if (!NT_STATUS_IS_OK(status)) {
1292 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1294 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1295 nt_errstr(status)));
1296 werr = ntstatus_to_werror(status);
1297 } else if (!W_ERROR_IS_OK(werr)) {
1298 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1300 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1303 switch (reply_result) {
1306 case PRINTER_NOTIFY_INFO_DISCARDED:
1307 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1308 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1317 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1319 struct printer_handle *p;
1320 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1321 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1325 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1329 if (!msg_group->msgs) {
1330 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1334 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1336 /* loop over all printers */
1338 for (p = printers_list; p; p = p->next) {
1339 ret = send_notify2_printer(mem_ctx, p, msg_group);
1346 DEBUG(8,("send_notify2_changes: Exit...\n"));
1350 /***********************************************************************
1351 **********************************************************************/
1353 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1356 uint32_t tv_sec, tv_usec;
1359 /* Unpack message */
1361 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1364 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1366 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1369 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1370 &msg->notify.value[0], &msg->notify.value[1]);
1372 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1373 &msg->len, &msg->notify.data);
1375 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1376 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1378 tv->tv_sec = tv_sec;
1379 tv->tv_usec = tv_usec;
1382 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1383 msg->notify.value[1]));
1385 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1390 /********************************************************************
1391 Receive a notify2 message list
1392 ********************************************************************/
1394 static void receive_notify2_message_list(struct messaging_context *msg,
1397 struct server_id server_id,
1400 size_t msg_count, i;
1401 char *buf = (char *)data->data;
1404 SPOOLSS_NOTIFY_MSG notify;
1405 SPOOLSS_NOTIFY_MSG_CTR messages;
1408 if (data->length < 4) {
1409 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1413 msg_count = IVAL(buf, 0);
1416 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1418 if (msg_count == 0) {
1419 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1423 /* initialize the container */
1425 ZERO_STRUCT( messages );
1426 notify_msg_ctr_init( &messages );
1429 * build message groups for each printer identified
1430 * in a change_notify msg. Remember that a PCN message
1431 * includes the handle returned for the srv_spoolss_replyopenprinter()
1432 * call. Therefore messages are grouped according to printer handle.
1435 for ( i=0; i<msg_count; i++ ) {
1436 struct timeval msg_tv;
1438 if (msg_ptr + 4 - buf > data->length) {
1439 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1443 msg_len = IVAL(msg_ptr,0);
1446 if (msg_ptr + msg_len - buf > data->length) {
1447 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1451 /* unpack messages */
1453 ZERO_STRUCT( notify );
1454 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1457 /* add to correct list in container */
1459 notify_msg_ctr_addmsg( &messages, ¬ify );
1461 /* free memory that might have been allocated by notify2_unpack_msg() */
1463 if ( notify.len != 0 )
1464 SAFE_FREE( notify.notify.data );
1467 /* process each group of messages */
1469 num_groups = notify_msg_ctr_numgroups( &messages );
1470 for ( i=0; i<num_groups; i++ )
1471 send_notify2_changes( &messages, i );
1476 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1477 (uint32_t)msg_count ));
1479 notify_msg_ctr_destroy( &messages );
1484 /********************************************************************
1485 Send a message to ourself about new driver being installed
1486 so we can upgrade the information for each printer bound to this
1488 ********************************************************************/
1490 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1491 struct messaging_context *msg_ctx)
1493 int len = strlen(drivername);
1498 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1501 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1502 MSG_PRINTER_DRVUPGRADE,
1503 (uint8_t *)drivername, len+1);
1508 void srv_spoolss_cleanup(void)
1510 struct printer_session_counter *session_counter;
1512 for (session_counter = counter_list;
1513 session_counter != NULL;
1514 session_counter = counter_list) {
1515 DLIST_REMOVE(counter_list, session_counter);
1516 TALLOC_FREE(session_counter);
1520 /**********************************************************************
1521 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1522 over all printers, upgrading ones as necessary
1523 **********************************************************************/
1525 void do_drv_upgrade_printer(struct messaging_context *msg,
1528 struct server_id server_id,
1531 TALLOC_CTX *tmp_ctx;
1532 struct auth_serversupplied_info *session_info = NULL;
1533 struct spoolss_PrinterInfo2 *pinfo2;
1536 const char *drivername;
1538 int n_services = lp_numservices();
1540 tmp_ctx = talloc_new(NULL);
1541 if (!tmp_ctx) return;
1543 status = make_session_info_system(tmp_ctx, &session_info);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 DEBUG(0, ("do_drv_upgrade_printer: "
1546 "Could not create system session_info\n"));
1550 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1552 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1556 DEBUG(10, ("do_drv_upgrade_printer: "
1557 "Got message for new driver [%s]\n", drivername));
1559 /* Iterate the printer list */
1561 for (snum = 0; snum < n_services; snum++) {
1562 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1566 /* ignore [printers] share */
1567 if (strequal(lp_const_servicename(snum), "printers")) {
1571 result = winreg_get_printer(tmp_ctx, session_info, msg,
1572 lp_const_servicename(snum),
1575 if (!W_ERROR_IS_OK(result)) {
1579 if (!pinfo2->drivername) {
1583 if (strcmp(drivername, pinfo2->drivername) != 0) {
1587 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1589 /* all we care about currently is the change_id */
1590 result = winreg_printer_update_changeid(tmp_ctx,
1593 pinfo2->printername);
1595 if (!W_ERROR_IS_OK(result)) {
1596 DEBUG(3, ("do_drv_upgrade_printer: "
1597 "Failed to update changeid [%s]\n",
1598 win_errstr(result)));
1604 talloc_free(tmp_ctx);
1607 /********************************************************************
1608 Update the cache for all printq's with a registered client
1610 ********************************************************************/
1612 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1614 struct printer_handle *printer = printers_list;
1617 /* loop through all printers and update the cache where
1618 a client is connected */
1620 if ((printer->printer_type == SPLHND_PRINTER) &&
1621 ((printer->notify.cli_chan != NULL) &&
1622 (printer->notify.cli_chan->active_connections > 0))) {
1623 snum = print_queue_snum(printer->sharename);
1624 print_queue_status(msg_ctx, snum, NULL, NULL);
1627 printer = printer->next;
1633 /****************************************************************
1634 _spoolss_OpenPrinter
1635 ****************************************************************/
1637 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1638 struct spoolss_OpenPrinter *r)
1640 struct spoolss_OpenPrinterEx e;
1643 ZERO_STRUCT(e.in.userlevel);
1645 e.in.printername = r->in.printername;
1646 e.in.datatype = r->in.datatype;
1647 e.in.devmode_ctr = r->in.devmode_ctr;
1648 e.in.access_mask = r->in.access_mask;
1651 e.out.handle = r->out.handle;
1653 werr = _spoolss_OpenPrinterEx(p, &e);
1655 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1656 /* OpenPrinterEx returns this for a bad
1657 * printer name. We must return WERR_INVALID_PRINTER_NAME
1660 werr = WERR_INVALID_PRINTER_NAME;
1666 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1667 struct spoolss_DeviceMode *orig,
1668 struct spoolss_DeviceMode **dest)
1670 struct spoolss_DeviceMode *dm;
1672 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1677 /* copy all values, then duplicate strings and structs */
1680 dm->devicename = talloc_strdup(dm, orig->devicename);
1681 if (!dm->devicename) {
1684 dm->formname = talloc_strdup(dm, orig->formname);
1685 if (!dm->formname) {
1688 if (orig->driverextra_data.data) {
1689 dm->driverextra_data.data =
1690 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1691 orig->driverextra_data.length);
1692 if (!dm->driverextra_data.data) {
1701 /****************************************************************
1702 _spoolss_OpenPrinterEx
1703 ****************************************************************/
1705 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1706 struct spoolss_OpenPrinterEx *r)
1709 struct printer_handle *Printer=NULL;
1712 if (!r->in.printername) {
1713 return WERR_INVALID_PARAM;
1716 if (r->in.level > 3) {
1717 return WERR_INVALID_PARAM;
1719 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1720 (r->in.level == 2 && !r->in.userlevel.level2) ||
1721 (r->in.level == 3 && !r->in.userlevel.level3)) {
1722 return WERR_INVALID_PARAM;
1725 /* some sanity check because you can open a printer or a print server */
1726 /* aka: \\server\printer or \\server */
1728 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1730 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1731 if (!W_ERROR_IS_OK(result)) {
1732 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1733 "for printer %s\n", r->in.printername));
1734 ZERO_STRUCTP(r->out.handle);
1738 Printer = find_printer_index_by_hnd(p, r->out.handle);
1740 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1741 "handle we created for printer %s\n", r->in.printername));
1742 close_printer_handle(p, r->out.handle);
1743 ZERO_STRUCTP(r->out.handle);
1744 return WERR_INVALID_PARAM;
1748 * First case: the user is opening the print server:
1750 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1751 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1753 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1754 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1755 * or if the user is listed in the smb.conf printer admin parameter.
1757 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1758 * client view printer folder, but does not show the MSAPW.
1760 * Note: this test needs code to check access rights here too. Jeremy
1761 * could you look at this?
1763 * Second case: the user is opening a printer:
1764 * NT doesn't let us connect to a printer if the connecting user
1765 * doesn't have print permission.
1767 * Third case: user is opening a Port Monitor
1768 * access checks same as opening a handle to the print server.
1771 switch (Printer->printer_type )
1774 case SPLHND_PORTMON_TCP:
1775 case SPLHND_PORTMON_LOCAL:
1776 /* Printserver handles use global struct... */
1780 /* Map standard access rights to object specific access rights */
1782 se_map_standard(&r->in.access_mask,
1783 &printserver_std_mapping);
1785 /* Deny any object specific bits that don't apply to print
1786 servers (i.e printer and job specific bits) */
1788 r->in.access_mask &= SEC_MASK_SPECIFIC;
1790 if (r->in.access_mask &
1791 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1792 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1793 close_printer_handle(p, r->out.handle);
1794 ZERO_STRUCTP(r->out.handle);
1795 return WERR_ACCESS_DENIED;
1798 /* Allow admin access */
1800 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1802 if (!lp_ms_add_printer_wizard()) {
1803 close_printer_handle(p, r->out.handle);
1804 ZERO_STRUCTP(r->out.handle);
1805 return WERR_ACCESS_DENIED;
1808 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1809 and not a printer admin, then fail */
1811 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1812 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1813 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1814 !token_contains_name_in_list(
1815 uidtoname(p->session_info->utok.uid),
1816 p->session_info->info3->base.domain.string,
1818 p->session_info->security_token,
1819 lp_printer_admin(snum))) {
1820 close_printer_handle(p, r->out.handle);
1821 ZERO_STRUCTP(r->out.handle);
1822 DEBUG(3,("access DENIED as user is not root, "
1823 "has no printoperator privilege, "
1824 "not a member of the printoperator builtin group and "
1825 "is not in printer admin list"));
1826 return WERR_ACCESS_DENIED;
1829 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1833 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1836 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1839 /* We fall through to return WERR_OK */
1842 case SPLHND_PRINTER:
1843 /* NT doesn't let us connect to a printer if the connecting user
1844 doesn't have print permission. */
1846 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1847 close_printer_handle(p, r->out.handle);
1848 ZERO_STRUCTP(r->out.handle);
1852 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1853 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1856 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1858 /* map an empty access mask to the minimum access mask */
1859 if (r->in.access_mask == 0x0)
1860 r->in.access_mask = PRINTER_ACCESS_USE;
1863 * If we are not serving the printer driver for this printer,
1864 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1865 * will keep NT clients happy --jerry
1868 if (lp_use_client_driver(snum)
1869 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1871 r->in.access_mask = PRINTER_ACCESS_USE;
1874 /* check smb.conf parameters and the the sec_desc */
1876 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1877 p->client_id->name, p->client_id->addr)) {
1878 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1879 ZERO_STRUCTP(r->out.handle);
1880 return WERR_ACCESS_DENIED;
1883 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1884 p->session_info->security_token, snum) ||
1885 !print_access_check(p->session_info,
1888 r->in.access_mask)) {
1889 DEBUG(3, ("access DENIED for printer open\n"));
1890 close_printer_handle(p, r->out.handle);
1891 ZERO_STRUCTP(r->out.handle);
1892 return WERR_ACCESS_DENIED;
1895 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1896 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1897 close_printer_handle(p, r->out.handle);
1898 ZERO_STRUCTP(r->out.handle);
1899 return WERR_ACCESS_DENIED;
1902 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1903 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1905 r->in.access_mask = PRINTER_ACCESS_USE;
1907 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1908 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1910 winreg_create_printer(p->mem_ctx,
1911 get_session_info_system(),
1913 lp_const_servicename(snum));
1918 /* sanity check to prevent programmer error */
1919 ZERO_STRUCTP(r->out.handle);
1923 Printer->access_granted = r->in.access_mask;
1926 * If the client sent a devmode in the OpenPrinter() call, then
1927 * save it here in case we get a job submission on this handle
1930 if ((Printer->printer_type != SPLHND_SERVER) &&
1931 r->in.devmode_ctr.devmode) {
1932 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1936 #if 0 /* JERRY -- I'm doubtful this is really effective */
1937 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1938 optimization in Windows 2000 clients --jerry */
1940 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1941 && (RA_WIN2K == get_remote_arch()) )
1943 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1944 sys_usleep( 500000 );
1951 /****************************************************************
1952 _spoolss_ClosePrinter
1953 ****************************************************************/
1955 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1956 struct spoolss_ClosePrinter *r)
1958 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1960 if (Printer && Printer->document_started) {
1961 struct spoolss_EndDocPrinter e;
1963 e.in.handle = r->in.handle;
1965 _spoolss_EndDocPrinter(p, &e);
1968 if (!close_printer_handle(p, r->in.handle))
1971 /* clear the returned printer handle. Observed behavior
1972 from Win2k server. Don't think this really matters.
1973 Previous code just copied the value of the closed
1976 ZERO_STRUCTP(r->out.handle);
1981 /****************************************************************
1982 _spoolss_DeletePrinter
1983 ****************************************************************/
1985 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1986 struct spoolss_DeletePrinter *r)
1988 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992 if (Printer && Printer->document_started) {
1993 struct spoolss_EndDocPrinter e;
1995 e.in.handle = r->in.handle;
1997 _spoolss_EndDocPrinter(p, &e);
2000 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2001 winreg_delete_printer_key(p->mem_ctx,
2002 get_session_info_system(),
2004 lp_const_servicename(snum),
2008 result = delete_printer_handle(p, r->in.handle);
2013 /*******************************************************************
2014 * static function to lookup the version id corresponding to an
2015 * long architecture string
2016 ******************************************************************/
2018 static const struct print_architecture_table_node archi_table[]= {
2020 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2021 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2022 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2023 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2024 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2025 {"Windows IA64", SPL_ARCH_IA64, 3 },
2026 {"Windows x64", SPL_ARCH_X64, 3 },
2030 static int get_version_id(const char *arch)
2034 for (i=0; archi_table[i].long_archi != NULL; i++)
2036 if (strcmp(arch, archi_table[i].long_archi) == 0)
2037 return (archi_table[i].version);
2043 /****************************************************************
2044 _spoolss_DeletePrinterDriver
2045 ****************************************************************/
2047 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2048 struct spoolss_DeletePrinterDriver *r)
2051 struct spoolss_DriverInfo8 *info = NULL;
2052 struct spoolss_DriverInfo8 *info_win2k = NULL;
2056 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2057 and not a printer admin, then fail */
2059 if ( (p->session_info->utok.uid != sec_initial_uid())
2060 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2061 && !token_contains_name_in_list(
2062 uidtoname(p->session_info->utok.uid),
2063 p->session_info->info3->base.domain.string,
2065 p->session_info->security_token,
2066 lp_printer_admin(-1)) )
2068 return WERR_ACCESS_DENIED;
2071 /* check that we have a valid driver name first */
2073 if ((version = get_version_id(r->in.architecture)) == -1)
2074 return WERR_INVALID_ENVIRONMENT;
2076 status = winreg_get_driver(p->mem_ctx,
2077 get_session_info_system(),
2079 r->in.architecture, r->in.driver,
2081 if (!W_ERROR_IS_OK(status)) {
2082 /* try for Win2k driver if "Windows NT x86" */
2084 if ( version == 2 ) {
2087 status = winreg_get_driver(p->mem_ctx,
2088 get_session_info_system(),
2093 if (!W_ERROR_IS_OK(status)) {
2094 status = WERR_UNKNOWN_PRINTER_DRIVER;
2098 /* otherwise it was a failure */
2100 status = WERR_UNKNOWN_PRINTER_DRIVER;
2106 if (printer_driver_in_use(p->mem_ctx,
2107 get_session_info_system(),
2110 status = WERR_PRINTER_DRIVER_IN_USE;
2115 status = winreg_get_driver(p->mem_ctx,
2116 get_session_info_system(),
2119 r->in.driver, 3, &info_win2k);
2120 if (W_ERROR_IS_OK(status)) {
2121 /* if we get to here, we now have 2 driver info structures to remove */
2122 /* remove the Win2k driver first*/
2124 status = winreg_del_driver(p->mem_ctx,
2125 get_session_info_system(),
2128 talloc_free(info_win2k);
2130 /* this should not have failed---if it did, report to client */
2131 if (!W_ERROR_IS_OK(status)) {
2137 status = winreg_del_driver(p->mem_ctx,
2138 get_session_info_system(),
2148 /****************************************************************
2149 _spoolss_DeletePrinterDriverEx
2150 ****************************************************************/
2152 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2153 struct spoolss_DeletePrinterDriverEx *r)
2155 struct spoolss_DriverInfo8 *info = NULL;
2156 struct spoolss_DriverInfo8 *info_win2k = NULL;
2161 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2162 and not a printer admin, then fail */
2164 if ( (p->session_info->utok.uid != sec_initial_uid())
2165 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2166 && !token_contains_name_in_list(
2167 uidtoname(p->session_info->utok.uid),
2168 p->session_info->info3->base.domain.string,
2170 p->session_info->security_token, lp_printer_admin(-1)) )
2172 return WERR_ACCESS_DENIED;
2175 /* check that we have a valid driver name first */
2176 if ((version = get_version_id(r->in.architecture)) == -1) {
2177 /* this is what NT returns */
2178 return WERR_INVALID_ENVIRONMENT;
2181 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2182 version = r->in.version;
2184 status = winreg_get_driver(p->mem_ctx,
2185 get_session_info_system(),
2191 if (!W_ERROR_IS_OK(status)) {
2192 status = WERR_UNKNOWN_PRINTER_DRIVER;
2195 * if the client asked for a specific version,
2196 * or this is something other than Windows NT x86,
2200 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2203 /* try for Win2k driver if "Windows NT x86" */
2206 status = winreg_get_driver(info,
2207 get_session_info_system(),
2212 if (!W_ERROR_IS_OK(status)) {
2213 status = WERR_UNKNOWN_PRINTER_DRIVER;
2218 if (printer_driver_in_use(info,
2219 get_session_info_system(),
2222 status = WERR_PRINTER_DRIVER_IN_USE;
2227 * we have a couple of cases to consider.
2228 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2229 * then the delete should fail if **any** files overlap with
2231 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2232 * non-overlapping files
2233 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2234 * is set, the do not delete any files
2235 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2238 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2240 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2243 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2244 printer_driver_files_in_use(info,
2245 get_session_info_system(),
2248 /* no idea of the correct error here */
2249 status = WERR_ACCESS_DENIED;
2254 /* also check for W32X86/3 if necessary; maybe we already have? */
2256 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2257 status = winreg_get_driver(info,
2258 get_session_info_system(),
2261 r->in.driver, 3, &info_win2k);
2262 if (W_ERROR_IS_OK(status)) {
2265 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2266 printer_driver_files_in_use(info,
2267 get_session_info_system(),
2270 /* no idea of the correct error here */
2271 talloc_free(info_win2k);
2272 status = WERR_ACCESS_DENIED;
2276 /* if we get to here, we now have 2 driver info structures to remove */
2277 /* remove the Win2k driver first*/
2279 status = winreg_del_driver(info,
2280 get_session_info_system(),
2285 /* this should not have failed---if it did, report to client */
2287 if (!W_ERROR_IS_OK(status)) {
2292 * now delete any associated files if delete_files is
2293 * true. Even if this part failes, we return succes
2294 * because the driver doesn not exist any more
2297 delete_driver_files(get_session_info_system(),
2303 status = winreg_del_driver(info,
2304 get_session_info_system(),
2308 if (!W_ERROR_IS_OK(status)) {
2313 * now delete any associated files if delete_files is
2314 * true. Even if this part failes, we return succes
2315 * because the driver doesn not exist any more
2318 delete_driver_files(get_session_info_system(), info);
2327 /********************************************************************
2328 GetPrinterData on a printer server Handle.
2329 ********************************************************************/
2331 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2333 enum winreg_Type *type,
2334 union spoolss_PrinterData *data)
2336 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2338 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2344 if (!StrCaseCmp(value, "BeepEnabled")) {
2350 if (!StrCaseCmp(value, "EventLog")) {
2352 /* formally was 0x1b */
2357 if (!StrCaseCmp(value, "NetPopup")) {
2363 if (!StrCaseCmp(value, "MajorVersion")) {
2366 /* Windows NT 4.0 seems to not allow uploading of drivers
2367 to a server that reports 0x3 as the MajorVersion.
2368 need to investigate more how Win2k gets around this .
2371 if (RA_WINNT == get_remote_arch()) {
2380 if (!StrCaseCmp(value, "MinorVersion")) {
2387 * uint32_t size = 0x114
2388 * uint32_t major = 5
2389 * uint32_t minor = [0|1]
2390 * uint32_t build = [2195|2600]
2391 * extra unicode string = e.g. "Service Pack 3"
2393 if (!StrCaseCmp(value, "OSVersion")) {
2395 enum ndr_err_code ndr_err;
2396 struct spoolss_OSVersion os;
2398 os.major = 5; /* Windows 2000 == 5.0 */
2400 os.build = 2195; /* build */
2401 os.extra_string = ""; /* leave extra string empty */
2403 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2404 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2405 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2406 return WERR_GENERAL_FAILURE;
2410 data->binary = blob;
2416 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2419 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2420 W_ERROR_HAVE_NO_MEMORY(data->string);
2425 if (!StrCaseCmp(value, "Architecture")) {
2427 data->string = talloc_strdup(mem_ctx,
2428 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2429 W_ERROR_HAVE_NO_MEMORY(data->string);
2434 if (!StrCaseCmp(value, "DsPresent")) {
2437 /* only show the publish check box if we are a
2438 member of a AD domain */
2440 if (lp_security() == SEC_ADS) {
2448 if (!StrCaseCmp(value, "DNSMachineName")) {
2449 const char *hostname = get_mydnsfullname();
2452 return WERR_BADFILE;
2456 data->string = talloc_strdup(mem_ctx, hostname);
2457 W_ERROR_HAVE_NO_MEMORY(data->string);
2464 return WERR_INVALID_PARAM;
2467 /****************************************************************
2468 _spoolss_GetPrinterData
2469 ****************************************************************/
2471 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2472 struct spoolss_GetPrinterData *r)
2474 struct spoolss_GetPrinterDataEx r2;
2476 r2.in.handle = r->in.handle;
2477 r2.in.key_name = "PrinterDriverData";
2478 r2.in.value_name = r->in.value_name;
2479 r2.in.offered = r->in.offered;
2480 r2.out.type = r->out.type;
2481 r2.out.data = r->out.data;
2482 r2.out.needed = r->out.needed;
2484 return _spoolss_GetPrinterDataEx(p, &r2);
2487 /*********************************************************
2488 Connect to the client machine.
2489 **********************************************************/
2491 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2492 struct sockaddr_storage *client_ss, const char *remote_machine)
2495 struct cli_state *the_cli;
2496 struct sockaddr_storage rm_addr;
2497 char addr[INET6_ADDRSTRLEN];
2499 if ( is_zero_addr(client_ss) ) {
2500 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2502 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2503 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2506 print_sockaddr(addr, sizeof(addr), &rm_addr);
2508 rm_addr = *client_ss;
2509 print_sockaddr(addr, sizeof(addr), &rm_addr);
2510 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2514 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2515 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2520 /* setup the connection */
2521 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2522 &rm_addr, 0, "IPC$", "IPC",
2526 0, lp_client_signing());
2528 if ( !NT_STATUS_IS_OK( ret ) ) {
2529 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2534 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2535 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2536 cli_shutdown(the_cli);
2541 * Ok - we have an anonymous connection to the IPC$ share.
2542 * Now start the NT Domain stuff :-).
2545 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2546 if (!NT_STATUS_IS_OK(ret)) {
2547 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2548 remote_machine, nt_errstr(ret)));
2549 cli_shutdown(the_cli);
2556 /***************************************************************************
2557 Connect to the client.
2558 ****************************************************************************/
2560 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2561 uint32_t localprinter,
2562 enum winreg_Type type,
2563 struct policy_handle *handle,
2564 struct notify_back_channel **_chan,
2565 struct sockaddr_storage *client_ss,
2566 struct messaging_context *msg_ctx)
2570 struct notify_back_channel *chan;
2572 for (chan = back_channels; chan; chan = chan->next) {
2573 if (memcmp(&chan->client_address, client_ss,
2574 sizeof(struct sockaddr_storage)) == 0) {
2580 * If it's the first connection, contact the client
2581 * and connect to the IPC$ share anonymously
2584 fstring unix_printer;
2586 /* the +2 is to strip the leading 2 backslashs */
2587 fstrcpy(unix_printer, printer + 2);
2589 chan = talloc_zero(back_channels, struct notify_back_channel);
2593 chan->client_address = *client_ss;
2595 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2599 chan->binding_handle = chan->cli_pipe->binding_handle;
2601 DLIST_ADD(back_channels, chan);
2603 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2604 receive_notify2_message_list);
2605 /* Tell the connections db we're now interested in printer
2606 * notify messages. */
2607 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2608 true, FLAG_MSG_PRINT_NOTIFY);
2612 * Tell the specific printing tdb we want messages for this printer
2613 * by registering our PID.
2616 if (!print_notify_register_pid(snum)) {
2617 DEBUG(0, ("Failed to register our pid for printer %s\n",
2621 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2630 if (!NT_STATUS_IS_OK(status)) {
2631 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2632 result = ntstatus_to_werror(status);
2633 } else if (!W_ERROR_IS_OK(result)) {
2634 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2637 chan->active_connections++;
2640 return (W_ERROR_IS_OK(result));
2643 /****************************************************************
2644 ****************************************************************/
2646 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2647 const struct spoolss_NotifyOption *r)
2649 struct spoolss_NotifyOption *option;
2656 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2663 if (!option->count) {
2667 option->types = talloc_zero_array(option,
2668 struct spoolss_NotifyOptionType, option->count);
2669 if (!option->types) {
2670 talloc_free(option);
2674 for (i=0; i < option->count; i++) {
2675 option->types[i] = r->types[i];
2677 if (option->types[i].count) {
2678 option->types[i].fields = talloc_zero_array(option,
2679 union spoolss_Field, option->types[i].count);
2680 if (!option->types[i].fields) {
2681 talloc_free(option);
2684 for (k=0; k<option->types[i].count; k++) {
2685 option->types[i].fields[k] =
2686 r->types[i].fields[k];
2694 /****************************************************************
2695 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2697 * before replying OK: status=0 a rpc call is made to the workstation
2698 * asking ReplyOpenPrinter
2700 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2701 * called from api_spoolss_rffpcnex
2702 ****************************************************************/
2704 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2705 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2708 struct spoolss_NotifyOption *option = r->in.notify_options;
2709 struct sockaddr_storage client_ss;
2711 /* store the notify value in the printer struct */
2713 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2716 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2717 "Invalid handle (%s:%u:%u).\n",
2718 OUR_HANDLE(r->in.handle)));
2722 Printer->notify.flags = r->in.flags;
2723 Printer->notify.options = r->in.options;
2724 Printer->notify.printerlocal = r->in.printer_local;
2725 Printer->notify.msg_ctx = p->msg_ctx;
2727 TALLOC_FREE(Printer->notify.option);
2728 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2730 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2732 /* Connect to the client machine and send a ReplyOpenPrinter */
2734 if ( Printer->printer_type == SPLHND_SERVER)
2736 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2737 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2740 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2741 "client_address is %s\n", p->client_id->addr));
2743 if (!lp_print_notify_backchannel(snum)) {
2744 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2745 "backchannel disabled\n"));
2746 return WERR_SERVER_UNAVAILABLE;
2749 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2751 return WERR_SERVER_UNAVAILABLE;
2754 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2755 Printer->notify.printerlocal, REG_SZ,
2756 &Printer->notify.cli_hnd,
2757 &Printer->notify.cli_chan,
2758 &client_ss, p->msg_ctx)) {
2759 return WERR_SERVER_UNAVAILABLE;
2765 /*******************************************************************
2766 * fill a notify_info_data with the servername
2767 ********************************************************************/
2769 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2771 struct spoolss_Notify *data,
2772 print_queue_struct *queue,
2773 struct spoolss_PrinterInfo2 *pinfo2,
2774 TALLOC_CTX *mem_ctx)
2776 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2779 /*******************************************************************
2780 * fill a notify_info_data with the printername (not including the servername).
2781 ********************************************************************/
2783 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2785 struct spoolss_Notify *data,
2786 print_queue_struct *queue,
2787 struct spoolss_PrinterInfo2 *pinfo2,
2788 TALLOC_CTX *mem_ctx)
2790 /* the notify name should not contain the \\server\ part */
2791 const char *p = strrchr(pinfo2->printername, '\\');
2794 p = pinfo2->printername;
2799 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2802 /*******************************************************************
2803 * fill a notify_info_data with the servicename
2804 ********************************************************************/
2806 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2808 struct spoolss_Notify *data,
2809 print_queue_struct *queue,
2810 struct spoolss_PrinterInfo2 *pinfo2,
2811 TALLOC_CTX *mem_ctx)
2813 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2816 /*******************************************************************
2817 * fill a notify_info_data with the port name
2818 ********************************************************************/
2820 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 struct spoolss_PrinterInfo2 *pinfo2,
2825 TALLOC_CTX *mem_ctx)
2827 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2830 /*******************************************************************
2831 * fill a notify_info_data with the printername
2832 * but it doesn't exist, have to see what to do
2833 ********************************************************************/
2835 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2837 struct spoolss_Notify *data,
2838 print_queue_struct *queue,
2839 struct spoolss_PrinterInfo2 *pinfo2,
2840 TALLOC_CTX *mem_ctx)
2842 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2845 /*******************************************************************
2846 * fill a notify_info_data with the comment
2847 ********************************************************************/
2849 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2851 struct spoolss_Notify *data,
2852 print_queue_struct *queue,
2853 struct spoolss_PrinterInfo2 *pinfo2,
2854 TALLOC_CTX *mem_ctx)
2858 if (*pinfo2->comment == '\0') {
2859 p = lp_comment(snum);
2861 p = pinfo2->comment;
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2867 /*******************************************************************
2868 * fill a notify_info_data with the comment
2869 * location = "Room 1, floor 2, building 3"
2870 ********************************************************************/
2872 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2874 struct spoolss_Notify *data,
2875 print_queue_struct *queue,
2876 struct spoolss_PrinterInfo2 *pinfo2,
2877 TALLOC_CTX *mem_ctx)
2879 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2882 /*******************************************************************
2883 * fill a notify_info_data with the device mode
2884 * jfm:xxxx don't to it for know but that's a real problem !!!
2885 ********************************************************************/
2887 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2889 struct spoolss_Notify *data,
2890 print_queue_struct *queue,
2891 struct spoolss_PrinterInfo2 *pinfo2,
2892 TALLOC_CTX *mem_ctx)
2894 /* for a dummy implementation we have to zero the fields */
2895 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2898 /*******************************************************************
2899 * fill a notify_info_data with the separator file name
2900 ********************************************************************/
2902 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2904 struct spoolss_Notify *data,
2905 print_queue_struct *queue,
2906 struct spoolss_PrinterInfo2 *pinfo2,
2907 TALLOC_CTX *mem_ctx)
2909 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2912 /*******************************************************************
2913 * fill a notify_info_data with the print processor
2914 * jfm:xxxx return always winprint to indicate we don't do anything to it
2915 ********************************************************************/
2917 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2919 struct spoolss_Notify *data,
2920 print_queue_struct *queue,
2921 struct spoolss_PrinterInfo2 *pinfo2,
2922 TALLOC_CTX *mem_ctx)
2924 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2927 /*******************************************************************
2928 * fill a notify_info_data with the print processor options
2929 * jfm:xxxx send an empty string
2930 ********************************************************************/
2932 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 struct spoolss_PrinterInfo2 *pinfo2,
2937 TALLOC_CTX *mem_ctx)
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2942 /*******************************************************************
2943 * fill a notify_info_data with the data type
2944 * jfm:xxxx always send RAW as data type
2945 ********************************************************************/
2947 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2949 struct spoolss_Notify *data,
2950 print_queue_struct *queue,
2951 struct spoolss_PrinterInfo2 *pinfo2,
2952 TALLOC_CTX *mem_ctx)
2954 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2957 /*******************************************************************
2958 * fill a notify_info_data with the security descriptor
2959 * jfm:xxxx send an null pointer to say no security desc
2960 * have to implement security before !
2961 ********************************************************************/
2963 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2965 struct spoolss_Notify *data,
2966 print_queue_struct *queue,
2967 struct spoolss_PrinterInfo2 *pinfo2,
2968 TALLOC_CTX *mem_ctx)
2970 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2973 /*******************************************************************
2974 * fill a notify_info_data with the attributes
2975 * jfm:xxxx a samba printer is always shared
2976 ********************************************************************/
2978 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2980 struct spoolss_Notify *data,
2981 print_queue_struct *queue,
2982 struct spoolss_PrinterInfo2 *pinfo2,
2983 TALLOC_CTX *mem_ctx)
2985 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2988 /*******************************************************************
2989 * fill a notify_info_data with the priority
2990 ********************************************************************/
2992 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2994 struct spoolss_Notify *data,
2995 print_queue_struct *queue,
2996 struct spoolss_PrinterInfo2 *pinfo2,
2997 TALLOC_CTX *mem_ctx)
2999 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3002 /*******************************************************************
3003 * fill a notify_info_data with the default priority
3004 ********************************************************************/
3006 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3008 struct spoolss_Notify *data,
3009 print_queue_struct *queue,
3010 struct spoolss_PrinterInfo2 *pinfo2,
3011 TALLOC_CTX *mem_ctx)
3013 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3016 /*******************************************************************
3017 * fill a notify_info_data with the start time
3018 ********************************************************************/
3020 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3022 struct spoolss_Notify *data,
3023 print_queue_struct *queue,
3024 struct spoolss_PrinterInfo2 *pinfo2,
3025 TALLOC_CTX *mem_ctx)
3027 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3030 /*******************************************************************
3031 * fill a notify_info_data with the until time
3032 ********************************************************************/
3034 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3036 struct spoolss_Notify *data,
3037 print_queue_struct *queue,
3038 struct spoolss_PrinterInfo2 *pinfo2,
3039 TALLOC_CTX *mem_ctx)
3041 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3044 /*******************************************************************
3045 * fill a notify_info_data with the status
3046 ********************************************************************/
3048 static void spoolss_notify_status(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 print_status_struct status;
3057 print_queue_length(msg_ctx, snum, &status);
3058 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3061 /*******************************************************************
3062 * fill a notify_info_data with the number of jobs queued
3063 ********************************************************************/
3065 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3067 struct spoolss_Notify *data,
3068 print_queue_struct *queue,
3069 struct spoolss_PrinterInfo2 *pinfo2,
3070 TALLOC_CTX *mem_ctx)
3072 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3073 data, print_queue_length(msg_ctx, snum, NULL));
3076 /*******************************************************************
3077 * fill a notify_info_data with the average ppm
3078 ********************************************************************/
3080 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3082 struct spoolss_Notify *data,
3083 print_queue_struct *queue,
3084 struct spoolss_PrinterInfo2 *pinfo2,
3085 TALLOC_CTX *mem_ctx)
3087 /* always respond 8 pages per minutes */
3088 /* a little hard ! */
3089 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3092 /*******************************************************************
3093 * fill a notify_info_data with username
3094 ********************************************************************/
3096 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3098 struct spoolss_Notify *data,
3099 print_queue_struct *queue,
3100 struct spoolss_PrinterInfo2 *pinfo2,
3101 TALLOC_CTX *mem_ctx)
3103 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3106 /*******************************************************************
3107 * fill a notify_info_data with job status
3108 ********************************************************************/
3110 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3112 struct spoolss_Notify *data,
3113 print_queue_struct *queue,
3114 struct spoolss_PrinterInfo2 *pinfo2,
3115 TALLOC_CTX *mem_ctx)
3117 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3120 /*******************************************************************
3121 * fill a notify_info_data with job name
3122 ********************************************************************/
3124 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3126 struct spoolss_Notify *data,
3127 print_queue_struct *queue,
3128 struct spoolss_PrinterInfo2 *pinfo2,
3129 TALLOC_CTX *mem_ctx)
3131 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3134 /*******************************************************************
3135 * fill a notify_info_data with job status
3136 ********************************************************************/
3138 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3140 struct spoolss_Notify *data,
3141 print_queue_struct *queue,
3142 struct spoolss_PrinterInfo2 *pinfo2,
3143 TALLOC_CTX *mem_ctx)
3146 * Now we're returning job status codes we just return a "" here. JRA.
3151 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3154 switch (queue->status) {
3159 p = ""; /* NT provides the paused string */
3168 #endif /* NO LONGER NEEDED. */
3170 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3173 /*******************************************************************
3174 * fill a notify_info_data with job time
3175 ********************************************************************/
3177 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3179 struct spoolss_Notify *data,
3180 print_queue_struct *queue,
3181 struct spoolss_PrinterInfo2 *pinfo2,
3182 TALLOC_CTX *mem_ctx)
3184 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3187 /*******************************************************************
3188 * fill a notify_info_data with job size
3189 ********************************************************************/
3191 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3193 struct spoolss_Notify *data,
3194 print_queue_struct *queue,
3195 struct spoolss_PrinterInfo2 *pinfo2,
3196 TALLOC_CTX *mem_ctx)
3198 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3201 /*******************************************************************
3202 * fill a notify_info_data with page info
3203 ********************************************************************/
3204 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3206 struct spoolss_Notify *data,
3207 print_queue_struct *queue,
3208 struct spoolss_PrinterInfo2 *pinfo2,
3209 TALLOC_CTX *mem_ctx)
3211 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3214 /*******************************************************************
3215 * fill a notify_info_data with pages printed info.
3216 ********************************************************************/
3217 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 struct spoolss_PrinterInfo2 *pinfo2,
3222 TALLOC_CTX *mem_ctx)
3224 /* Add code when back-end tracks this */
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3228 /*******************************************************************
3229 Fill a notify_info_data with job position.
3230 ********************************************************************/
3232 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3234 struct spoolss_Notify *data,
3235 print_queue_struct *queue,
3236 struct spoolss_PrinterInfo2 *pinfo2,
3237 TALLOC_CTX *mem_ctx)
3239 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3242 /*******************************************************************
3243 Fill a notify_info_data with submitted time.
3244 ********************************************************************/
3246 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3248 struct spoolss_Notify *data,
3249 print_queue_struct *queue,
3250 struct spoolss_PrinterInfo2 *pinfo2,
3251 TALLOC_CTX *mem_ctx)
3253 data->data.string.string = NULL;
3254 data->data.string.size = 0;
3256 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3257 &data->data.string.string,
3258 &data->data.string.size);
3262 struct s_notify_info_data_table
3264 enum spoolss_NotifyType type;
3267 enum spoolss_NotifyTable variable_type;
3268 void (*fn) (struct messaging_context *msg_ctx,
3269 int snum, struct spoolss_Notify *data,
3270 print_queue_struct *queue,
3271 struct spoolss_PrinterInfo2 *pinfo2,
3272 TALLOC_CTX *mem_ctx);
3275 /* A table describing the various print notification constants and
3276 whether the notification data is a pointer to a variable sized
3277 buffer, a one value uint32_t or a two value uint32_t. */
3279 static const struct s_notify_info_data_table notify_info_data_table[] =
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3332 /*******************************************************************
3333 Return the variable_type of info_data structure.
3334 ********************************************************************/
3336 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3341 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3342 if ( (notify_info_data_table[i].type == type) &&
3343 (notify_info_data_table[i].field == field) ) {
3344 return notify_info_data_table[i].variable_type;
3348 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3350 return (enum spoolss_NotifyTable) 0;
3353 /****************************************************************************
3354 ****************************************************************************/
3356 static bool search_notify(enum spoolss_NotifyType type,
3362 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3363 if (notify_info_data_table[i].type == type &&
3364 notify_info_data_table[i].field == field &&
3365 notify_info_data_table[i].fn != NULL) {
3374 /****************************************************************************
3375 ****************************************************************************/
3377 static void construct_info_data(struct spoolss_Notify *info_data,
3378 enum spoolss_NotifyType type,
3379 uint16_t field, int id)
3381 info_data->type = type;
3382 info_data->field.field = field;
3383 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3384 info_data->job_id = id;
3387 /*******************************************************************
3389 * fill a notify_info struct with info asked
3391 ********************************************************************/
3393 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3394 struct printer_handle *print_hnd,
3395 struct spoolss_NotifyInfo *info,
3396 struct spoolss_PrinterInfo2 *pinfo2,
3398 const struct spoolss_NotifyOptionType *option_type,
3400 TALLOC_CTX *mem_ctx)
3403 enum spoolss_NotifyType type;
3406 struct spoolss_Notify *current_data;
3407 print_queue_struct *queue=NULL;
3409 type = option_type->type;
3411 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3412 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3413 option_type->count, lp_servicename(snum)));
3415 for(field_num=0; field_num < option_type->count; field_num++) {
3416 field = option_type->fields[field_num].field;
3418 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3420 if (!search_notify(type, field, &j) )
3423 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3424 struct spoolss_Notify,
3426 if (info->notifies == NULL) {
3427 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3431 current_data = &info->notifies[info->count];
3433 construct_info_data(current_data, type, field, id);
3435 DEBUG(10, ("construct_notify_printer_info: "
3436 "calling [%s] snum=%d printername=[%s])\n",
3437 notify_info_data_table[j].name, snum,
3438 pinfo2->printername));
3440 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3441 queue, pinfo2, mem_ctx);
3449 /*******************************************************************
3451 * fill a notify_info struct with info asked
3453 ********************************************************************/
3455 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3456 print_queue_struct *queue,
3457 struct spoolss_NotifyInfo *info,
3458 struct spoolss_PrinterInfo2 *pinfo2,
3460 const struct spoolss_NotifyOptionType *option_type,
3462 TALLOC_CTX *mem_ctx)
3465 enum spoolss_NotifyType type;
3467 struct spoolss_Notify *current_data;
3469 DEBUG(4,("construct_notify_jobs_info\n"));
3471 type = option_type->type;
3473 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3474 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3475 option_type->count));
3477 for(field_num=0; field_num<option_type->count; field_num++) {
3478 field = option_type->fields[field_num].field;
3480 if (!search_notify(type, field, &j) )
3483 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3484 struct spoolss_Notify,
3486 if (info->notifies == NULL) {
3487 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3491 current_data=&(info->notifies[info->count]);
3493 construct_info_data(current_data, type, field, id);
3494 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3495 queue, pinfo2, mem_ctx);
3503 * JFM: The enumeration is not that simple, it's even non obvious.
3505 * let's take an example: I want to monitor the PRINTER SERVER for
3506 * the printer's name and the number of jobs currently queued.
3507 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3508 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3510 * I have 3 printers on the back of my server.
3512 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3515 * 1 printer 1 name 1
3516 * 2 printer 1 cjob 1
3517 * 3 printer 2 name 2
3518 * 4 printer 2 cjob 2
3519 * 5 printer 3 name 3
3520 * 6 printer 3 name 3
3522 * that's the print server case, the printer case is even worse.
3525 /*******************************************************************
3527 * enumerate all printers on the printserver
3528 * fill a notify_info struct with info asked
3530 ********************************************************************/
3532 static WERROR printserver_notify_info(struct pipes_struct *p,
3533 struct policy_handle *hnd,
3534 struct spoolss_NotifyInfo *info,
3535 TALLOC_CTX *mem_ctx)
3538 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3539 int n_services=lp_numservices();
3541 struct spoolss_NotifyOption *option;
3542 struct spoolss_NotifyOptionType option_type;
3543 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3546 DEBUG(4,("printserver_notify_info\n"));
3551 option = Printer->notify.option;
3554 info->notifies = NULL;
3557 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3558 sending a ffpcn() request first */
3563 for (i=0; i<option->count; i++) {
3564 option_type = option->types[i];
3566 if (option_type.type != PRINTER_NOTIFY_TYPE)
3569 for (snum = 0; snum < n_services; snum++) {
3570 if (!lp_browseable(snum) ||
3571 !lp_snum_ok(snum) ||
3572 !lp_print_ok(snum)) {
3573 continue; /* skip */
3576 /* Maybe we should use the SYSTEM session_info here... */
3577 result = winreg_get_printer(mem_ctx,
3578 get_session_info_system(),
3580 lp_servicename(snum),
3582 if (!W_ERROR_IS_OK(result)) {
3583 DEBUG(4, ("printserver_notify_info: "
3584 "Failed to get printer [%s]\n",
3585 lp_servicename(snum)));
3590 construct_notify_printer_info(p->msg_ctx,
3596 TALLOC_FREE(pinfo2);
3602 * Debugging information, don't delete.
3605 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3606 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3607 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3609 for (i=0; i<info->count; i++) {
3610 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3611 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3612 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3619 /*******************************************************************
3621 * fill a notify_info struct with info asked
3623 ********************************************************************/
3625 static WERROR printer_notify_info(struct pipes_struct *p,
3626 struct policy_handle *hnd,
3627 struct spoolss_NotifyInfo *info,
3628 TALLOC_CTX *mem_ctx)
3631 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3634 struct spoolss_NotifyOption *option;
3635 struct spoolss_NotifyOptionType option_type;
3637 print_queue_struct *queue=NULL;
3638 print_status_struct status;
3639 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3642 DEBUG(4,("printer_notify_info\n"));
3647 option = Printer->notify.option;
3651 info->notifies = NULL;
3654 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3655 sending a ffpcn() request first */
3660 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3664 /* Maybe we should use the SYSTEM session_info here... */
3665 result = winreg_get_printer(mem_ctx,
3666 get_session_info_system(),
3668 lp_servicename(snum), &pinfo2);
3669 if (!W_ERROR_IS_OK(result)) {
3673 for (i=0; i<option->count; i++) {
3674 option_type = option->types[i];
3676 switch (option_type.type) {
3677 case PRINTER_NOTIFY_TYPE:
3678 if (construct_notify_printer_info(p->msg_ctx,
3687 case JOB_NOTIFY_TYPE:
3689 count = print_queue_status(p->msg_ctx, snum, &queue,
3692 for (j=0; j<count; j++) {
3693 construct_notify_jobs_info(p->msg_ctx,
3707 * Debugging information, don't delete.
3710 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714 for (i=0; i<info->count; i++) {
3715 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3721 talloc_free(pinfo2);
3725 /****************************************************************
3726 _spoolss_RouterRefreshPrinterChangeNotify
3727 ****************************************************************/
3729 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3730 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3732 struct spoolss_NotifyInfo *info;
3734 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3735 WERROR result = WERR_BADFID;
3737 /* we always have a spoolss_NotifyInfo struct */
3738 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3740 result = WERR_NOMEM;
3744 *r->out.info = info;
3747 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3748 "Invalid handle (%s:%u:%u).\n",
3749 OUR_HANDLE(r->in.handle)));
3753 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3756 * We are now using the change value, and
3757 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3758 * I don't have a global notification system, I'm sending back all the
3759 * information even when _NOTHING_ has changed.
3762 /* We need to keep track of the change value to send back in
3763 RRPCN replies otherwise our updates are ignored. */
3765 Printer->notify.fnpcn = true;
3767 if (Printer->notify.cli_chan != NULL &&
3768 Printer->notify.cli_chan->active_connections > 0) {
3769 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3770 "Saving change value in request [%x]\n",
3772 Printer->notify.change = r->in.change_low;
3775 /* just ignore the spoolss_NotifyOption */
3777 switch (Printer->printer_type) {
3779 result = printserver_notify_info(p, r->in.handle,
3783 case SPLHND_PRINTER:
3784 result = printer_notify_info(p, r->in.handle,
3789 Printer->notify.fnpcn = false;
3795 /********************************************************************
3796 ********************************************************************/
3798 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3799 const char *servername,
3800 const char *printername,
3801 const char **printername_p)
3803 /* FIXME: add lp_force_printername() */
3805 if (servername == NULL) {
3806 *printername_p = talloc_strdup(mem_ctx, printername);
3807 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3811 if (servername[0] == '\\' && servername[1] == '\\') {
3815 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3816 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3821 /********************************************************************
3822 ********************************************************************/
3824 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3825 const char *printername)
3831 dm->devicename = talloc_strndup(dm, printername,
3832 MIN(strlen(printername), 31));
3835 /********************************************************************
3836 * construct_printer_info_0
3837 * fill a printer_info_0 struct
3838 ********************************************************************/
3840 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3841 const struct auth_serversupplied_info *session_info,
3842 struct messaging_context *msg_ctx,
3843 struct spoolss_PrinterInfo2 *info2,
3844 const char *servername,
3845 struct spoolss_PrinterInfo0 *r,
3849 struct printer_session_counter *session_counter;
3850 struct timeval setuptime;
3851 print_status_struct status;
3854 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3855 if (!W_ERROR_IS_OK(result)) {
3860 r->servername = talloc_strdup(mem_ctx, servername);
3861 W_ERROR_HAVE_NO_MEMORY(r->servername);
3863 r->servername = NULL;
3866 count = print_queue_length(msg_ctx, snum, &status);
3868 /* check if we already have a counter for this printer */
3869 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3870 if (session_counter->snum == snum)
3874 /* it's the first time, add it to the list */
3875 if (session_counter == NULL) {
3876 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3877 W_ERROR_HAVE_NO_MEMORY(session_counter);
3878 session_counter->snum = snum;
3879 session_counter->counter = 0;
3880 DLIST_ADD(counter_list, session_counter);
3884 session_counter->counter++;
3890 get_startup_time(&setuptime);
3891 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3894 * the global_counter should be stored in a TDB as it's common to all the clients
3895 * and should be zeroed on samba startup
3897 r->global_counter = session_counter->counter;
3899 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3900 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3901 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3902 r->free_build = SPOOLSS_RELEASE_BUILD;
3904 r->max_spooling = 0;
3905 r->session_counter = session_counter->counter;
3906 r->num_error_out_of_paper = 0x0;
3907 r->num_error_not_ready = 0x0; /* number of print failure */
3909 r->number_of_processors = 0x1;
3910 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3911 r->high_part_total_bytes = 0x0;
3913 /* ChangeID in milliseconds*/
3914 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3915 info2->sharename, &r->change_id);
3917 r->last_error = WERR_OK;
3918 r->status = nt_printq_status(status.status);
3919 r->enumerate_network_printers = 0x0;
3920 r->c_setprinter = 0x0;
3921 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3922 r->processor_level = 0x6; /* 6 ???*/
3931 /********************************************************************
3932 * construct_printer_info1
3933 * fill a spoolss_PrinterInfo1 struct
3934 ********************************************************************/
3936 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3937 const struct spoolss_PrinterInfo2 *info2,
3939 const char *servername,
3940 struct spoolss_PrinterInfo1 *r,
3947 if (info2->comment == NULL || info2->comment[0] == '\0') {
3948 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3950 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3952 W_ERROR_HAVE_NO_MEMORY(r->comment);
3954 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3955 if (!W_ERROR_IS_OK(result)) {
3959 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3963 W_ERROR_HAVE_NO_MEMORY(r->description);
3968 /********************************************************************
3969 * construct_printer_info2
3970 * fill a spoolss_PrinterInfo2 struct
3971 ********************************************************************/
3973 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3974 struct messaging_context *msg_ctx,
3975 const struct spoolss_PrinterInfo2 *info2,
3976 const char *servername,
3977 struct spoolss_PrinterInfo2 *r,
3981 print_status_struct status;
3984 count = print_queue_length(msg_ctx, snum, &status);
3987 r->servername = talloc_strdup(mem_ctx, servername);
3988 W_ERROR_HAVE_NO_MEMORY(r->servername);
3990 r->servername = NULL;
3993 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3994 if (!W_ERROR_IS_OK(result)) {
3998 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3999 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4000 r->portname = talloc_strdup(mem_ctx, info2->portname);
4001 W_ERROR_HAVE_NO_MEMORY(r->portname);
4002 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4003 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4005 if (info2->comment[0] == '\0') {
4006 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4008 r->comment = talloc_strdup(mem_ctx, info2->comment);
4010 W_ERROR_HAVE_NO_MEMORY(r->comment);
4012 r->location = talloc_strdup(mem_ctx, info2->location);
4013 W_ERROR_HAVE_NO_MEMORY(r->location);
4014 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4015 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4016 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4017 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4018 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4019 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4020 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4021 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4023 r->attributes = info2->attributes;
4025 r->priority = info2->priority;
4026 r->defaultpriority = info2->defaultpriority;
4027 r->starttime = info2->starttime;
4028 r->untiltime = info2->untiltime;
4029 r->status = nt_printq_status(status.status);
4031 r->averageppm = info2->averageppm;
4033 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4035 DEBUG(8,("Returning NULL Devicemode!\n"));
4038 compose_devicemode_devicename(r->devmode, r->printername);
4042 if (info2->secdesc != NULL) {
4043 /* don't use talloc_steal() here unless you do a deep steal of all
4044 the SEC_DESC members */
4046 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4052 /********************************************************************
4053 * construct_printer_info3
4054 * fill a spoolss_PrinterInfo3 struct
4055 ********************************************************************/
4057 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4058 const struct spoolss_PrinterInfo2 *info2,
4059 const char *servername,
4060 struct spoolss_PrinterInfo3 *r,
4063 /* These are the components of the SD we are returning. */
4065 if (info2->secdesc != NULL) {
4066 /* don't use talloc_steal() here unless you do a deep steal of all
4067 the SEC_DESC members */
4069 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4070 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4076 /********************************************************************
4077 * construct_printer_info4
4078 * fill a spoolss_PrinterInfo4 struct
4079 ********************************************************************/
4081 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4082 const struct spoolss_PrinterInfo2 *info2,
4083 const char *servername,
4084 struct spoolss_PrinterInfo4 *r,
4089 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4090 if (!W_ERROR_IS_OK(result)) {
4095 r->servername = talloc_strdup(mem_ctx, servername);
4096 W_ERROR_HAVE_NO_MEMORY(r->servername);
4098 r->servername = NULL;
4101 r->attributes = info2->attributes;
4106 /********************************************************************
4107 * construct_printer_info5
4108 * fill a spoolss_PrinterInfo5 struct
4109 ********************************************************************/
4111 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4112 const struct spoolss_PrinterInfo2 *info2,
4113 const char *servername,
4114 struct spoolss_PrinterInfo5 *r,
4119 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4120 if (!W_ERROR_IS_OK(result)) {
4124 r->portname = talloc_strdup(mem_ctx, info2->portname);
4125 W_ERROR_HAVE_NO_MEMORY(r->portname);
4127 r->attributes = info2->attributes;
4129 /* these two are not used by NT+ according to MSDN */
4130 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4131 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4136 /********************************************************************
4137 * construct_printer_info_6
4138 * fill a spoolss_PrinterInfo6 struct
4139 ********************************************************************/
4141 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4142 struct messaging_context *msg_ctx,
4143 const struct spoolss_PrinterInfo2 *info2,
4144 const char *servername,
4145 struct spoolss_PrinterInfo6 *r,
4149 print_status_struct status;
4151 count = print_queue_length(msg_ctx, snum, &status);
4153 r->status = nt_printq_status(status.status);
4158 /********************************************************************
4159 * construct_printer_info7
4160 * fill a spoolss_PrinterInfo7 struct
4161 ********************************************************************/
4163 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4164 struct messaging_context *msg_ctx,
4165 const char *servername,
4166 struct spoolss_PrinterInfo7 *r,
4169 struct auth_serversupplied_info *session_info;
4173 status = make_session_info_system(mem_ctx, &session_info);
4174 if (!NT_STATUS_IS_OK(status)) {
4175 DEBUG(0, ("construct_printer_info7: "
4176 "Could not create system session_info\n"));
4180 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4182 lp_servicename(snum), &guid, NULL)) {
4183 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4184 r->action = DSPRINT_PUBLISH;
4186 r->guid = talloc_strdup(mem_ctx, "");
4187 r->action = DSPRINT_UNPUBLISH;
4189 W_ERROR_HAVE_NO_MEMORY(r->guid);
4191 TALLOC_FREE(session_info);
4195 /********************************************************************
4196 * construct_printer_info8
4197 * fill a spoolss_PrinterInfo8 struct
4198 ********************************************************************/
4200 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4201 const struct spoolss_PrinterInfo2 *info2,
4202 const char *servername,
4203 struct spoolss_DeviceModeInfo *r,
4207 const char *printername;
4209 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4210 if (!W_ERROR_IS_OK(result)) {
4214 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4216 DEBUG(8,("Returning NULL Devicemode!\n"));
4219 compose_devicemode_devicename(r->devmode, printername);
4225 /********************************************************************
4226 ********************************************************************/
4228 static bool snum_is_shared_printer(int snum)
4230 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4233 /********************************************************************
4234 Spoolss_enumprinters.
4235 ********************************************************************/
4237 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4238 const struct auth_serversupplied_info *session_info,
4239 struct messaging_context *msg_ctx,
4240 const char *servername,
4243 union spoolss_PrinterInfo **info_p,
4247 int n_services = lp_numservices();
4248 union spoolss_PrinterInfo *info = NULL;
4250 WERROR result = WERR_OK;
4255 for (snum = 0; snum < n_services; snum++) {
4257 const char *printer;
4258 struct spoolss_PrinterInfo2 *info2;
4260 if (!snum_is_shared_printer(snum)) {
4264 printer = lp_const_servicename(snum);
4266 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4269 result = winreg_create_printer(mem_ctx,
4273 if (!W_ERROR_IS_OK(result)) {
4277 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4278 union spoolss_PrinterInfo,
4281 result = WERR_NOMEM;
4285 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4287 if (!W_ERROR_IS_OK(result)) {
4293 result = construct_printer_info0(info, session_info,
4296 &info[count].info0, snum);
4299 result = construct_printer_info1(info, info2, flags,
4301 &info[count].info1, snum);
4304 result = construct_printer_info2(info, msg_ctx, info2,
4306 &info[count].info2, snum);
4309 result = construct_printer_info4(info, info2,
4311 &info[count].info4, snum);
4314 result = construct_printer_info5(info, info2,
4316 &info[count].info5, snum);
4320 result = WERR_UNKNOWN_LEVEL;
4324 if (!W_ERROR_IS_OK(result)) {
4335 if (!W_ERROR_IS_OK(result)) {
4345 /********************************************************************
4346 * handle enumeration of printers at level 0
4347 ********************************************************************/
4349 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4350 const struct auth_serversupplied_info *session_info,
4351 struct messaging_context *msg_ctx,
4353 const char *servername,
4354 union spoolss_PrinterInfo **info,
4357 DEBUG(4,("enum_all_printers_info_0\n"));
4359 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4360 servername, 0, flags, info, count);
4364 /********************************************************************
4365 ********************************************************************/
4367 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4368 const struct auth_serversupplied_info *session_info,
4369 struct messaging_context *msg_ctx,
4370 const char *servername,
4372 union spoolss_PrinterInfo **info,
4375 DEBUG(4,("enum_all_printers_info_1\n"));
4377 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4378 servername, 1, flags, info, count);
4381 /********************************************************************
4382 enum_all_printers_info_1_local.
4383 *********************************************************************/
4385 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4386 const struct auth_serversupplied_info *session_info,
4387 struct messaging_context *msg_ctx,
4388 const char *servername,
4389 union spoolss_PrinterInfo **info,
4392 DEBUG(4,("enum_all_printers_info_1_local\n"));
4394 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4395 servername, PRINTER_ENUM_ICON8, info, count);
4398 /********************************************************************
4399 enum_all_printers_info_1_name.
4400 *********************************************************************/
4402 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4403 const struct auth_serversupplied_info *session_info,
4404 struct messaging_context *msg_ctx,
4405 const char *servername,
4406 union spoolss_PrinterInfo **info,
4409 const char *s = servername;
4411 DEBUG(4,("enum_all_printers_info_1_name\n"));
4413 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4417 if (!is_myname_or_ipaddr(s)) {
4418 return WERR_INVALID_NAME;
4421 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4422 servername, PRINTER_ENUM_ICON8, info, count);
4425 /********************************************************************
4426 enum_all_printers_info_1_network.
4427 *********************************************************************/
4429 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4430 const struct auth_serversupplied_info *session_info,
4431 struct messaging_context *msg_ctx,
4432 const char *servername,
4433 union spoolss_PrinterInfo **info,
4436 const char *s = servername;
4438 DEBUG(4,("enum_all_printers_info_1_network\n"));
4440 /* If we respond to a enum_printers level 1 on our name with flags
4441 set to PRINTER_ENUM_REMOTE with a list of printers then these
4442 printers incorrectly appear in the APW browse list.
4443 Specifically the printers for the server appear at the workgroup
4444 level where all the other servers in the domain are
4445 listed. Windows responds to this call with a
4446 WERR_CAN_NOT_COMPLETE so we should do the same. */
4448 if (servername[0] == '\\' && servername[1] == '\\') {
4452 if (is_myname_or_ipaddr(s)) {
4453 return WERR_CAN_NOT_COMPLETE;
4456 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4457 servername, PRINTER_ENUM_NAME, info, count);
4460 /********************************************************************
4461 * api_spoolss_enumprinters
4463 * called from api_spoolss_enumprinters (see this to understand)
4464 ********************************************************************/
4466 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4467 const struct auth_serversupplied_info *session_info,
4468 struct messaging_context *msg_ctx,
4469 const char *servername,
4470 union spoolss_PrinterInfo **info,
4473 DEBUG(4,("enum_all_printers_info_2\n"));
4475 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4476 servername, 2, 0, info, count);
4479 /********************************************************************
4480 * handle enumeration of printers at level 1
4481 ********************************************************************/
4483 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4484 const struct auth_serversupplied_info *session_info,
4485 struct messaging_context *msg_ctx,
4487 const char *servername,
4488 union spoolss_PrinterInfo **info,
4491 /* Not all the flags are equals */
4493 if (flags & PRINTER_ENUM_LOCAL) {
4494 return enum_all_printers_info_1_local(mem_ctx, session_info,
4495 msg_ctx, servername, info, count);
4498 if (flags & PRINTER_ENUM_NAME) {
4499 return enum_all_printers_info_1_name(mem_ctx, session_info,
4500 msg_ctx, servername, info,
4504 if (flags & PRINTER_ENUM_NETWORK) {
4505 return enum_all_printers_info_1_network(mem_ctx, session_info,
4506 msg_ctx, servername, info,
4510 return WERR_OK; /* NT4sp5 does that */
4513 /********************************************************************
4514 * handle enumeration of printers at level 2
4515 ********************************************************************/
4517 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4518 const struct auth_serversupplied_info *session_info,
4519 struct messaging_context *msg_ctx,
4521 const char *servername,
4522 union spoolss_PrinterInfo **info,
4525 if (flags & PRINTER_ENUM_LOCAL) {
4527 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4532 if (flags & PRINTER_ENUM_NAME) {
4533 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4534 return WERR_INVALID_NAME;
4537 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4542 if (flags & PRINTER_ENUM_REMOTE) {
4543 return WERR_UNKNOWN_LEVEL;
4549 /********************************************************************
4550 * handle enumeration of printers at level 4
4551 ********************************************************************/
4553 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4554 const struct auth_serversupplied_info *session_info,
4555 struct messaging_context *msg_ctx,
4557 const char *servername,
4558 union spoolss_PrinterInfo **info,
4561 DEBUG(4,("enum_all_printers_info_4\n"));
4563 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4564 servername, 4, flags, info, count);
4568 /********************************************************************
4569 * handle enumeration of printers at level 5
4570 ********************************************************************/
4572 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4573 const struct auth_serversupplied_info *session_info,
4574 struct messaging_context *msg_ctx,
4576 const char *servername,
4577 union spoolss_PrinterInfo **info,
4580 DEBUG(4,("enum_all_printers_info_5\n"));
4582 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4583 servername, 5, flags, info, count);
4586 /****************************************************************
4587 _spoolss_EnumPrinters
4588 ****************************************************************/
4590 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4591 struct spoolss_EnumPrinters *r)
4593 const struct auth_serversupplied_info *session_info = get_session_info_system();
4596 /* that's an [in out] buffer */
4598 if (!r->in.buffer && (r->in.offered != 0)) {
4599 return WERR_INVALID_PARAM;
4602 DEBUG(4,("_spoolss_EnumPrinters\n"));
4606 *r->out.info = NULL;
4610 * flags==PRINTER_ENUM_NAME
4611 * if name=="" then enumerates all printers
4612 * if name!="" then enumerate the printer
4613 * flags==PRINTER_ENUM_REMOTE
4614 * name is NULL, enumerate printers
4615 * Level 2: name!="" enumerates printers, name can't be NULL
4616 * Level 3: doesn't exist
4617 * Level 4: does a local registry lookup
4618 * Level 5: same as Level 2
4621 if (r->in.server && r->in.server[0] == '\0') {
4622 r->in.server = NULL;
4625 switch (r->in.level) {
4627 result = enumprinters_level0(p->mem_ctx, session_info,
4628 p->msg_ctx, r->in.flags,
4630 r->out.info, r->out.count);
4633 result = enumprinters_level1(p->mem_ctx, session_info,
4634 p->msg_ctx, r->in.flags,
4636 r->out.info, r->out.count);
4639 result = enumprinters_level2(p->mem_ctx, session_info,
4640 p->msg_ctx, r->in.flags,
4642 r->out.info, r->out.count);
4645 result = enumprinters_level4(p->mem_ctx, session_info,
4646 p->msg_ctx, r->in.flags,
4648 r->out.info, r->out.count);
4651 result = enumprinters_level5(p->mem_ctx, session_info,
4652 p->msg_ctx, r->in.flags,
4654 r->out.info, r->out.count);
4657 return WERR_UNKNOWN_LEVEL;
4660 if (!W_ERROR_IS_OK(result)) {
4664 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4665 spoolss_EnumPrinters,
4666 *r->out.info, r->in.level,
4668 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4669 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4671 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4674 /****************************************************************
4676 ****************************************************************/
4678 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4679 struct spoolss_GetPrinter *r)
4681 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4682 struct spoolss_PrinterInfo2 *info2 = NULL;
4683 WERROR result = WERR_OK;
4686 /* that's an [in out] buffer */
4688 if (!r->in.buffer && (r->in.offered != 0)) {
4689 return WERR_INVALID_PARAM;
4694 if (Printer == NULL) {
4698 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4702 result = winreg_get_printer(p->mem_ctx,
4703 get_session_info_system(),
4705 lp_const_servicename(snum),
4707 if (!W_ERROR_IS_OK(result)) {
4711 switch (r->in.level) {
4713 result = construct_printer_info0(p->mem_ctx,
4714 get_session_info_system(),
4717 Printer->servername,
4718 &r->out.info->info0,
4722 result = construct_printer_info1(p->mem_ctx, info2,
4724 Printer->servername,
4725 &r->out.info->info1, snum);
4728 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4729 Printer->servername,
4730 &r->out.info->info2, snum);
4733 result = construct_printer_info3(p->mem_ctx, info2,
4734 Printer->servername,
4735 &r->out.info->info3, snum);
4738 result = construct_printer_info4(p->mem_ctx, info2,
4739 Printer->servername,
4740 &r->out.info->info4, snum);
4743 result = construct_printer_info5(p->mem_ctx, info2,
4744 Printer->servername,
4745 &r->out.info->info5, snum);
4748 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4749 Printer->servername,
4750 &r->out.info->info6, snum);
4753 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4754 Printer->servername,
4755 &r->out.info->info7, snum);
4758 result = construct_printer_info8(p->mem_ctx, info2,
4759 Printer->servername,
4760 &r->out.info->info8, snum);
4763 result = WERR_UNKNOWN_LEVEL;
4768 if (!W_ERROR_IS_OK(result)) {
4769 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4770 r->in.level, win_errstr(result)));
4771 TALLOC_FREE(r->out.info);
4775 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4776 r->out.info, r->in.level);
4777 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4779 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4782 /********************************************************************
4783 ********************************************************************/
4785 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4787 if (in && strlen(in)) { \
4788 out = talloc_strdup(mem_ctx, in); \
4790 out = talloc_strdup(mem_ctx, ""); \
4792 W_ERROR_HAVE_NO_MEMORY(out); \
4795 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4797 if (in && strlen(in)) { \
4798 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4800 out = talloc_strdup(mem_ctx, ""); \
4802 W_ERROR_HAVE_NO_MEMORY(out); \
4805 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4806 const char **string_array,
4807 const char ***presult,
4808 const char *cservername,
4812 int i, num_strings = 0;
4813 const char **array = NULL;
4815 if (string_array == NULL) {
4816 return WERR_INVALID_PARAMETER;
4819 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4820 const char *str = NULL;
4822 if (cservername == NULL || arch == NULL) {
4823 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4825 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4828 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4835 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4836 &array, &num_strings);
4846 /********************************************************************
4847 * fill a spoolss_DriverInfo1 struct
4848 ********************************************************************/
4850 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4851 struct spoolss_DriverInfo1 *r,
4852 const struct spoolss_DriverInfo8 *driver,
4853 const char *servername)
4855 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4856 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4861 /********************************************************************
4862 * fill a spoolss_DriverInfo2 struct
4863 ********************************************************************/
4865 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4866 struct spoolss_DriverInfo2 *r,
4867 const struct spoolss_DriverInfo8 *driver,
4868 const char *servername)
4871 const char *cservername = canon_servername(servername);
4873 r->version = driver->version;
4875 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4876 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4877 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4878 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4880 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4881 driver->architecture,
4883 driver->driver_path,
4886 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4887 driver->architecture,
4892 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4893 driver->architecture,
4895 driver->config_file,
4901 /********************************************************************
4902 * fill a spoolss_DriverInfo3 struct
4903 ********************************************************************/
4905 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4906 struct spoolss_DriverInfo3 *r,
4907 const struct spoolss_DriverInfo8 *driver,
4908 const char *servername)
4910 const char *cservername = canon_servername(servername);
4912 r->version = driver->version;
4914 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4915 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4916 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4917 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4919 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4920 driver->architecture,
4922 driver->driver_path,
4925 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4926 driver->architecture,
4931 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4932 driver->architecture,
4934 driver->config_file,
4937 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938 driver->architecture,
4943 FILL_DRIVER_STRING(mem_ctx,
4944 driver->monitor_name,
4947 FILL_DRIVER_STRING(mem_ctx,
4948 driver->default_datatype,
4949 r->default_datatype);
4951 return string_array_from_driver_info(mem_ctx,
4952 driver->dependent_files,
4953 &r->dependent_files,
4955 driver->architecture,
4959 /********************************************************************
4960 * fill a spoolss_DriverInfo4 struct
4961 ********************************************************************/
4963 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4964 struct spoolss_DriverInfo4 *r,
4965 const struct spoolss_DriverInfo8 *driver,
4966 const char *servername)
4968 const char *cservername = canon_servername(servername);
4971 r->version = driver->version;
4973 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4974 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4975 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4976 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4978 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979 driver->architecture,
4981 driver->driver_path,
4984 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985 driver->architecture,
4990 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4991 driver->architecture,
4993 driver->config_file,
4996 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997 driver->architecture,
5002 result = string_array_from_driver_info(mem_ctx,
5003 driver->dependent_files,
5004 &r->dependent_files,
5006 driver->architecture,
5008 if (!W_ERROR_IS_OK(result)) {
5012 FILL_DRIVER_STRING(mem_ctx,
5013 driver->monitor_name,
5016 FILL_DRIVER_STRING(mem_ctx,
5017 driver->default_datatype,
5018 r->default_datatype);
5021 result = string_array_from_driver_info(mem_ctx,
5022 driver->previous_names,
5029 /********************************************************************
5030 * fill a spoolss_DriverInfo5 struct
5031 ********************************************************************/
5033 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5034 struct spoolss_DriverInfo5 *r,
5035 const struct spoolss_DriverInfo8 *driver,
5036 const char *servername)
5038 const char *cservername = canon_servername(servername);
5040 r->version = driver->version;
5042 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5043 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5044 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5045 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5047 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5048 driver->architecture,
5050 driver->driver_path,
5053 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5054 driver->architecture,
5059 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5060 driver->architecture,
5062 driver->config_file,
5065 r->driver_attributes = 0;
5066 r->config_version = 0;
5067 r->driver_version = 0;
5071 /********************************************************************
5072 * fill a spoolss_DriverInfo6 struct
5073 ********************************************************************/
5075 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5076 struct spoolss_DriverInfo6 *r,
5077 const struct spoolss_DriverInfo8 *driver,
5078 const char *servername)
5080 const char *cservername = canon_servername(servername);
5083 r->version = driver->version;
5085 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5086 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5087 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5088 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5090 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5091 driver->architecture,
5093 driver->driver_path,
5096 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5097 driver->architecture,
5102 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5103 driver->architecture,
5105 driver->config_file,
5108 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5109 driver->architecture,
5114 FILL_DRIVER_STRING(mem_ctx,
5115 driver->monitor_name,
5118 FILL_DRIVER_STRING(mem_ctx,
5119 driver->default_datatype,
5120 r->default_datatype);
5122 result = string_array_from_driver_info(mem_ctx,
5123 driver->dependent_files,
5124 &r->dependent_files,
5126 driver->architecture,
5128 if (!W_ERROR_IS_OK(result)) {
5132 result = string_array_from_driver_info(mem_ctx,
5133 driver->previous_names,
5136 if (!W_ERROR_IS_OK(result)) {
5140 r->driver_date = driver->driver_date;
5141 r->driver_version = driver->driver_version;
5143 FILL_DRIVER_STRING(mem_ctx,
5144 driver->manufacturer_name,
5145 r->manufacturer_name);
5146 FILL_DRIVER_STRING(mem_ctx,
5147 driver->manufacturer_url,
5148 r->manufacturer_url);
5149 FILL_DRIVER_STRING(mem_ctx,
5150 driver->hardware_id,
5152 FILL_DRIVER_STRING(mem_ctx,
5159 /********************************************************************
5160 * fill a spoolss_DriverInfo8 struct
5161 ********************************************************************/
5163 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5164 struct spoolss_DriverInfo8 *r,
5165 const struct spoolss_DriverInfo8 *driver,
5166 const char *servername)
5168 const char *cservername = canon_servername(servername);
5171 r->version = driver->version;
5173 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5174 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5175 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5176 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5178 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179 driver->architecture,
5181 driver->driver_path,
5184 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185 driver->architecture,
5190 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5191 driver->architecture,
5193 driver->config_file,
5196 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197 driver->architecture,
5202 FILL_DRIVER_STRING(mem_ctx,
5203 driver->monitor_name,
5206 FILL_DRIVER_STRING(mem_ctx,
5207 driver->default_datatype,
5208 r->default_datatype);
5210 result = string_array_from_driver_info(mem_ctx,
5211 driver->dependent_files,
5212 &r->dependent_files,
5214 driver->architecture,
5216 if (!W_ERROR_IS_OK(result)) {
5220 result = string_array_from_driver_info(mem_ctx,
5221 driver->previous_names,
5224 if (!W_ERROR_IS_OK(result)) {
5228 r->driver_date = driver->driver_date;
5229 r->driver_version = driver->driver_version;
5231 FILL_DRIVER_STRING(mem_ctx,
5232 driver->manufacturer_name,
5233 r->manufacturer_name);
5234 FILL_DRIVER_STRING(mem_ctx,
5235 driver->manufacturer_url,
5236 r->manufacturer_url);
5237 FILL_DRIVER_STRING(mem_ctx,
5238 driver->hardware_id,
5240 FILL_DRIVER_STRING(mem_ctx,
5244 FILL_DRIVER_STRING(mem_ctx,
5245 driver->print_processor,
5246 r->print_processor);
5247 FILL_DRIVER_STRING(mem_ctx,
5248 driver->vendor_setup,
5251 result = string_array_from_driver_info(mem_ctx,
5252 driver->color_profiles,
5255 if (!W_ERROR_IS_OK(result)) {
5259 FILL_DRIVER_STRING(mem_ctx,
5263 r->printer_driver_attributes = driver->printer_driver_attributes;
5265 result = string_array_from_driver_info(mem_ctx,
5266 driver->core_driver_dependencies,
5267 &r->core_driver_dependencies,
5269 if (!W_ERROR_IS_OK(result)) {
5273 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5274 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5279 #if 0 /* disabled until marshalling issues are resolved - gd */
5280 /********************************************************************
5281 ********************************************************************/
5283 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5284 struct spoolss_DriverFileInfo *r,
5285 const char *cservername,
5286 const char *file_name,
5287 enum spoolss_DriverFileType file_type,
5288 uint32_t file_version)
5290 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5291 cservername, file_name);
5292 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5293 r->file_type = file_type;
5294 r->file_version = file_version;
5299 /********************************************************************
5300 ********************************************************************/
5302 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5303 const struct spoolss_DriverInfo8 *driver,
5304 const char *cservername,
5305 struct spoolss_DriverFileInfo **info_p,
5308 struct spoolss_DriverFileInfo *info = NULL;
5316 if (strlen(driver->driver_path)) {
5317 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5318 struct spoolss_DriverFileInfo,
5320 W_ERROR_HAVE_NO_MEMORY(info);
5321 result = fill_spoolss_DriverFileInfo(info,
5324 driver->driver_path,
5325 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5327 W_ERROR_NOT_OK_RETURN(result);
5331 if (strlen(driver->config_file)) {
5332 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5333 struct spoolss_DriverFileInfo,
5335 W_ERROR_HAVE_NO_MEMORY(info);
5336 result = fill_spoolss_DriverFileInfo(info,
5339 driver->config_file,
5340 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5342 W_ERROR_NOT_OK_RETURN(result);
5346 if (strlen(driver->data_file)) {
5347 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5348 struct spoolss_DriverFileInfo,
5350 W_ERROR_HAVE_NO_MEMORY(info);
5351 result = fill_spoolss_DriverFileInfo(info,
5355 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5357 W_ERROR_NOT_OK_RETURN(result);
5361 if (strlen(driver->help_file)) {
5362 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5363 struct spoolss_DriverFileInfo,
5365 W_ERROR_HAVE_NO_MEMORY(info);
5366 result = fill_spoolss_DriverFileInfo(info,
5370 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5372 W_ERROR_NOT_OK_RETURN(result);
5376 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5377 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5378 struct spoolss_DriverFileInfo,
5380 W_ERROR_HAVE_NO_MEMORY(info);
5381 result = fill_spoolss_DriverFileInfo(info,
5384 driver->dependent_files[i],
5385 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5387 W_ERROR_NOT_OK_RETURN(result);
5397 /********************************************************************
5398 * fill a spoolss_DriverInfo101 struct
5399 ********************************************************************/
5401 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5402 struct spoolss_DriverInfo101 *r,
5403 const struct spoolss_DriverInfo8 *driver,
5404 const char *servername)
5406 const char *cservername = canon_servername(servername);
5409 r->version = driver->version;
5411 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5412 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5413 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5414 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5416 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5420 if (!W_ERROR_IS_OK(result)) {
5424 FILL_DRIVER_STRING(mem_ctx,
5425 driver->monitor_name,
5428 FILL_DRIVER_STRING(mem_ctx,
5429 driver->default_datatype,
5430 r->default_datatype);
5432 result = string_array_from_driver_info(mem_ctx,
5433 driver->previous_names,
5436 if (!W_ERROR_IS_OK(result)) {
5440 r->driver_date = driver->driver_date;
5441 r->driver_version = driver->driver_version;
5443 FILL_DRIVER_STRING(mem_ctx,
5444 driver->manufacturer_name,
5445 r->manufacturer_name);
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->manufacturer_url,
5448 r->manufacturer_url);
5449 FILL_DRIVER_STRING(mem_ctx,
5450 driver->hardware_id,
5452 FILL_DRIVER_STRING(mem_ctx,
5459 /********************************************************************
5460 ********************************************************************/
5462 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5463 const struct auth_serversupplied_info *session_info,
5464 struct messaging_context *msg_ctx,
5466 union spoolss_DriverInfo *r,
5468 const char *servername,
5469 const char *architecture,
5472 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5473 struct spoolss_DriverInfo8 *driver;
5477 return WERR_UNKNOWN_LEVEL;
5480 result = winreg_get_printer(mem_ctx,
5483 lp_const_servicename(snum),
5486 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5487 win_errstr(result)));
5489 if (!W_ERROR_IS_OK(result)) {
5490 return WERR_INVALID_PRINTER_NAME;
5493 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5495 pinfo2->drivername, version, &driver);
5497 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5498 win_errstr(result)));
5500 if (!W_ERROR_IS_OK(result)) {
5502 * Is this a W2k client ?
5506 talloc_free(pinfo2);
5507 return WERR_UNKNOWN_PRINTER_DRIVER;
5510 /* Yes - try again with a WinNT driver. */
5512 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5516 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5517 win_errstr(result)));
5518 if (!W_ERROR_IS_OK(result)) {
5519 talloc_free(pinfo2);
5520 return WERR_UNKNOWN_PRINTER_DRIVER;
5526 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5529 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5532 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5535 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5538 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5541 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5544 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5546 #if 0 /* disabled until marshalling issues are resolved - gd */
5548 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5552 result = WERR_UNKNOWN_LEVEL;
5556 talloc_free(pinfo2);
5557 talloc_free(driver);
5562 /****************************************************************
5563 _spoolss_GetPrinterDriver2
5564 ****************************************************************/
5566 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5567 struct spoolss_GetPrinterDriver2 *r)
5569 struct printer_handle *printer;
5574 /* that's an [in out] buffer */
5576 if (!r->in.buffer && (r->in.offered != 0)) {
5577 return WERR_INVALID_PARAM;
5580 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5582 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5583 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5584 return WERR_INVALID_PRINTER_NAME;
5588 *r->out.server_major_version = 0;
5589 *r->out.server_minor_version = 0;
5591 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5595 result = construct_printer_driver_info_level(p->mem_ctx,
5596 get_session_info_system(),
5598 r->in.level, r->out.info,
5599 snum, printer->servername,
5601 r->in.client_major_version);
5602 if (!W_ERROR_IS_OK(result)) {
5603 TALLOC_FREE(r->out.info);
5607 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5608 r->out.info, r->in.level);
5609 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5611 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5615 /****************************************************************
5616 _spoolss_StartPagePrinter
5617 ****************************************************************/
5619 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5620 struct spoolss_StartPagePrinter *r)
5622 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5625 DEBUG(3,("_spoolss_StartPagePrinter: "
5626 "Error in startpageprinter printer handle\n"));
5630 Printer->page_started = true;
5634 /****************************************************************
5635 _spoolss_EndPagePrinter
5636 ****************************************************************/
5638 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5639 struct spoolss_EndPagePrinter *r)
5643 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5646 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5647 OUR_HANDLE(r->in.handle)));
5651 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5654 Printer->page_started = false;
5655 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5660 /****************************************************************
5661 _spoolss_StartDocPrinter
5662 ****************************************************************/
5664 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5665 struct spoolss_StartDocPrinter *r)
5667 struct spoolss_DocumentInfo1 *info_1;
5669 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5673 DEBUG(2,("_spoolss_StartDocPrinter: "
5674 "Invalid handle (%s:%u:%u)\n",
5675 OUR_HANDLE(r->in.handle)));
5679 if (Printer->jobid) {
5680 DEBUG(2, ("_spoolss_StartDocPrinter: "
5681 "StartDocPrinter called twice! "
5682 "(existing jobid = %d)\n", Printer->jobid));
5683 return WERR_INVALID_HANDLE;
5686 if (r->in.level != 1) {
5687 return WERR_UNKNOWN_LEVEL;
5690 info_1 = r->in.info.info1;
5693 * a nice thing with NT is it doesn't listen to what you tell it.
5694 * when asked to send _only_ RAW datas, it tries to send datas
5697 * So I add checks like in NT Server ...
5700 if (info_1->datatype) {
5701 if (strcmp(info_1->datatype, "RAW") != 0) {
5703 return WERR_INVALID_DATATYPE;
5707 /* get the share number of the printer */
5708 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5712 werr = print_job_start(p->session_info,
5716 info_1->document_name,
5717 info_1->output_file,
5721 /* An error occured in print_job_start() so return an appropriate
5724 if (!W_ERROR_IS_OK(werr)) {
5728 Printer->document_started = true;
5729 *r->out.job_id = Printer->jobid;
5734 /****************************************************************
5735 _spoolss_EndDocPrinter
5736 ****************************************************************/
5738 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5739 struct spoolss_EndDocPrinter *r)
5741 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5746 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5747 OUR_HANDLE(r->in.handle)));
5751 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5755 Printer->document_started = false;
5756 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5757 if (!NT_STATUS_IS_OK(status)) {
5758 DEBUG(2, ("_spoolss_EndDocPrinter: "
5759 "print_job_end failed [%s]\n",
5760 nt_errstr(status)));
5764 return ntstatus_to_werror(status);
5767 /****************************************************************
5768 _spoolss_WritePrinter
5769 ****************************************************************/
5771 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5772 struct spoolss_WritePrinter *r)
5774 ssize_t buffer_written;
5776 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5779 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5780 OUR_HANDLE(r->in.handle)));
5781 *r->out.num_written = r->in._data_size;
5785 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5788 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5789 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5790 snum, Printer->jobid,
5791 (const char *)r->in.data.data,
5792 (size_t)r->in._data_size);
5793 if (buffer_written == (ssize_t)-1) {
5794 *r->out.num_written = 0;
5795 if (errno == ENOSPC)
5796 return WERR_NO_SPOOL_SPACE;
5798 return WERR_ACCESS_DENIED;
5801 *r->out.num_written = r->in._data_size;
5806 /********************************************************************
5807 * api_spoolss_getprinter
5808 * called from the spoolss dispatcher
5810 ********************************************************************/
5812 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5813 struct pipes_struct *p)
5815 const struct auth_serversupplied_info *session_info = p->session_info;
5817 WERROR errcode = WERR_BADFUNC;
5818 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5821 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5822 OUR_HANDLE(handle)));
5826 if (!get_printer_snum(p, handle, &snum, NULL))
5830 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5831 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5833 case SPOOLSS_PRINTER_CONTROL_RESUME:
5834 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5835 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5837 case SPOOLSS_PRINTER_CONTROL_PURGE:
5838 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5841 return WERR_UNKNOWN_LEVEL;
5848 /****************************************************************
5849 _spoolss_AbortPrinter
5850 * From MSDN: "Deletes printer's spool file if printer is configured
5852 ****************************************************************/
5854 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5855 struct spoolss_AbortPrinter *r)
5857 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5859 WERROR errcode = WERR_OK;
5862 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5863 OUR_HANDLE(r->in.handle)));
5867 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5870 if (!Printer->document_started) {
5871 return WERR_SPL_NO_STARTDOC;
5874 errcode = print_job_delete(p->session_info,
5882 /********************************************************************
5883 * called by spoolss_api_setprinter
5884 * when updating a printer description
5885 ********************************************************************/
5887 static WERROR update_printer_sec(struct policy_handle *handle,
5888 struct pipes_struct *p,
5889 struct sec_desc_buf *secdesc_ctr)
5891 struct spoolss_security_descriptor *new_secdesc = NULL;
5892 struct spoolss_security_descriptor *old_secdesc = NULL;
5893 const char *printer;
5897 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5899 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5900 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5901 OUR_HANDLE(handle)));
5903 result = WERR_BADFID;
5907 if (secdesc_ctr == NULL) {
5908 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5909 result = WERR_INVALID_PARAM;
5912 printer = lp_const_servicename(snum);
5914 /* Check the user has permissions to change the security
5915 descriptor. By experimentation with two NT machines, the user
5916 requires Full Access to the printer to change security
5919 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5920 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5921 result = WERR_ACCESS_DENIED;
5925 /* NT seems to like setting the security descriptor even though
5926 nothing may have actually changed. */
5927 result = winreg_get_printer_secdesc(p->mem_ctx,
5928 get_session_info_system(),
5932 if (!W_ERROR_IS_OK(result)) {
5933 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5934 result = WERR_BADFID;
5938 if (DEBUGLEVEL >= 10) {
5939 struct security_acl *the_acl;
5942 the_acl = old_secdesc->dacl;
5943 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5944 printer, the_acl->num_aces));
5946 for (i = 0; i < the_acl->num_aces; i++) {
5947 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5948 &the_acl->aces[i].trustee),
5949 the_acl->aces[i].access_mask));
5952 the_acl = secdesc_ctr->sd->dacl;
5955 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5956 printer, the_acl->num_aces));
5958 for (i = 0; i < the_acl->num_aces; i++) {
5959 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5960 &the_acl->aces[i].trustee),
5961 the_acl->aces[i].access_mask));
5964 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5968 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5969 if (new_secdesc == NULL) {
5970 result = WERR_NOMEM;
5974 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5979 result = winreg_set_printer_secdesc(p->mem_ctx,
5980 get_session_info_system(),
5989 /********************************************************************
5990 Canonicalize printer info from a client
5991 ********************************************************************/
5993 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5994 struct spoolss_SetPrinterInfo2 *info2,
5997 fstring printername;
6000 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6001 "portname=%s drivername=%s comment=%s location=%s\n",
6002 info2->servername, info2->printername, info2->sharename,
6003 info2->portname, info2->drivername, info2->comment,
6006 /* we force some elements to "correct" values */
6007 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6008 if (info2->servername == NULL) {
6011 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6012 if (info2->sharename == NULL) {
6016 /* check to see if we allow printername != sharename */
6017 if (lp_force_printername(snum)) {
6018 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6019 global_myname(), info2->sharename);
6021 /* make sure printername is in \\server\printername format */
6022 fstrcpy(printername, info2->printername);
6024 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6025 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6029 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6030 global_myname(), p);
6032 if (info2->printername == NULL) {
6036 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6037 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6042 /****************************************************************************
6043 ****************************************************************************/
6045 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6047 char *cmd = lp_addport_cmd();
6048 char *command = NULL;
6050 bool is_print_op = false;
6053 return WERR_ACCESS_DENIED;
6056 command = talloc_asprintf(ctx,
6057 "%s \"%s\" \"%s\"", cmd, portname, uri );
6063 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6065 DEBUG(10,("Running [%s]\n", command));
6067 /********* BEGIN SePrintOperatorPrivilege **********/
6072 ret = smbrun(command, NULL);
6077 /********* END SePrintOperatorPrivilege **********/
6079 DEBUGADD(10,("returned [%d]\n", ret));
6081 TALLOC_FREE(command);
6084 return WERR_ACCESS_DENIED;
6090 /****************************************************************************
6091 ****************************************************************************/
6093 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6094 struct spoolss_SetPrinterInfo2 *info2,
6095 const char *remote_machine,
6096 struct messaging_context *msg_ctx)
6098 char *cmd = lp_addprinter_cmd();
6100 char *command = NULL;
6104 bool is_print_op = false;
6106 if (!remote_machine) {
6110 command = talloc_asprintf(ctx,
6111 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6112 cmd, info2->printername, info2->sharename,
6113 info2->portname, info2->drivername,
6114 info2->location, info2->comment, remote_machine);
6120 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6122 DEBUG(10,("Running [%s]\n", command));
6124 /********* BEGIN SePrintOperatorPrivilege **********/
6129 if ( (ret = smbrun(command, &fd)) == 0 ) {
6130 /* Tell everyone we updated smb.conf. */
6131 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6137 /********* END SePrintOperatorPrivilege **********/
6139 DEBUGADD(10,("returned [%d]\n", ret));
6141 TALLOC_FREE(command);
6149 /* reload our services immediately */
6151 reload_services(msg_ctx, -1, false);
6155 /* Get lines and convert them back to dos-codepage */
6156 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6157 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6160 /* Set the portname to what the script says the portname should be. */
6161 /* but don't require anything to be return from the script exit a good error code */
6164 /* Set the portname to what the script says the portname should be. */
6165 info2->portname = talloc_strdup(ctx, qlines[0]);
6166 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6169 TALLOC_FREE(qlines);
6173 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6174 const struct auth_serversupplied_info *session_info,
6175 struct messaging_context *msg_ctx,
6177 struct spoolss_SetPrinterInfo2 *printer,
6178 struct spoolss_PrinterInfo2 *old_printer)
6180 bool force_update = (old_printer == NULL);
6181 const char *dnsdomname;
6182 const char *longname;
6183 const char *uncname;
6184 const char *spooling;
6186 WERROR result = WERR_OK;
6188 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6189 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6190 winreg_set_printer_dataex(mem_ctx,
6194 SPOOL_DSSPOOLER_KEY,
6195 SPOOL_REG_DRIVERNAME,
6200 if (!force_update) {
6201 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6202 printer->drivername));
6204 notify_printer_driver(server_event_context(), msg_ctx,
6205 snum, printer->drivername ?
6206 printer->drivername : "");
6210 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6211 push_reg_sz(mem_ctx, &buffer, printer->comment);
6212 winreg_set_printer_dataex(mem_ctx,
6216 SPOOL_DSSPOOLER_KEY,
6217 SPOOL_REG_DESCRIPTION,
6222 if (!force_update) {
6223 notify_printer_comment(server_event_context(), msg_ctx,
6224 snum, printer->comment ?
6225 printer->comment : "");
6229 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6230 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6231 winreg_set_printer_dataex(mem_ctx,
6235 SPOOL_DSSPOOLER_KEY,
6236 SPOOL_REG_PRINTSHARENAME,
6241 if (!force_update) {
6242 notify_printer_sharename(server_event_context(),
6244 snum, printer->sharename ?
6245 printer->sharename : "");
6249 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6252 p = strrchr(printer->printername, '\\' );
6256 p = printer->printername;
6259 push_reg_sz(mem_ctx, &buffer, p);
6260 winreg_set_printer_dataex(mem_ctx,
6264 SPOOL_DSSPOOLER_KEY,
6265 SPOOL_REG_PRINTERNAME,
6270 if (!force_update) {
6271 notify_printer_printername(server_event_context(),
6272 msg_ctx, snum, p ? p : "");
6276 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6277 push_reg_sz(mem_ctx, &buffer, printer->portname);
6278 winreg_set_printer_dataex(mem_ctx,
6282 SPOOL_DSSPOOLER_KEY,
6288 if (!force_update) {
6289 notify_printer_port(server_event_context(),
6290 msg_ctx, snum, printer->portname ?
6291 printer->portname : "");
6295 if (force_update || !strequal(printer->location, old_printer->location)) {
6296 push_reg_sz(mem_ctx, &buffer, printer->location);
6297 winreg_set_printer_dataex(mem_ctx,
6301 SPOOL_DSSPOOLER_KEY,
6307 if (!force_update) {
6308 notify_printer_location(server_event_context(),
6311 printer->location : "");
6315 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6316 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6317 winreg_set_printer_dataex(mem_ctx,
6321 SPOOL_DSSPOOLER_KEY,
6322 SPOOL_REG_PRINTSEPARATORFILE,
6327 if (!force_update) {
6328 notify_printer_sepfile(server_event_context(),
6331 printer->sepfile : "");
6335 if (force_update || printer->starttime != old_printer->starttime) {
6336 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6337 SIVAL(buffer.data, 0, printer->starttime);
6338 winreg_set_printer_dataex(mem_ctx,
6342 SPOOL_DSSPOOLER_KEY,
6343 SPOOL_REG_PRINTSTARTTIME,
6349 if (force_update || printer->untiltime != old_printer->untiltime) {
6350 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6351 SIVAL(buffer.data, 0, printer->untiltime);
6352 winreg_set_printer_dataex(mem_ctx,
6356 SPOOL_DSSPOOLER_KEY,
6357 SPOOL_REG_PRINTENDTIME,
6363 if (force_update || printer->priority != old_printer->priority) {
6364 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6365 SIVAL(buffer.data, 0, printer->priority);
6366 winreg_set_printer_dataex(mem_ctx,
6370 SPOOL_DSSPOOLER_KEY,
6377 if (force_update || printer->attributes != old_printer->attributes) {
6378 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6379 SIVAL(buffer.data, 0, (printer->attributes &
6380 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6381 winreg_set_printer_dataex(mem_ctx,
6385 SPOOL_DSSPOOLER_KEY,
6386 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6391 switch (printer->attributes & 0x3) {
6393 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6396 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6399 spooling = SPOOL_REGVAL_PRINTDIRECT;
6402 spooling = "unknown";
6404 push_reg_sz(mem_ctx, &buffer, spooling);
6405 winreg_set_printer_dataex(mem_ctx,
6409 SPOOL_DSSPOOLER_KEY,
6410 SPOOL_REG_PRINTSPOOLING,
6416 push_reg_sz(mem_ctx, &buffer, global_myname());
6417 winreg_set_printer_dataex(mem_ctx,
6421 SPOOL_DSSPOOLER_KEY,
6422 SPOOL_REG_SHORTSERVERNAME,
6427 dnsdomname = get_mydnsfullname();
6428 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6429 longname = talloc_strdup(mem_ctx, dnsdomname);
6431 longname = talloc_strdup(mem_ctx, global_myname());
6433 if (longname == NULL) {
6434 result = WERR_NOMEM;
6438 push_reg_sz(mem_ctx, &buffer, longname);
6439 winreg_set_printer_dataex(mem_ctx,
6443 SPOOL_DSSPOOLER_KEY,
6444 SPOOL_REG_SERVERNAME,
6449 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6450 global_myname(), printer->sharename);
6451 push_reg_sz(mem_ctx, &buffer, uncname);
6452 winreg_set_printer_dataex(mem_ctx,
6456 SPOOL_DSSPOOLER_KEY,
6466 /********************************************************************
6467 * Called by spoolss_api_setprinter
6468 * when updating a printer description.
6469 ********************************************************************/
6471 static WERROR update_printer(struct pipes_struct *p,
6472 struct policy_handle *handle,
6473 struct spoolss_SetPrinterInfoCtr *info_ctr,
6474 struct spoolss_DeviceMode *devmode)
6476 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6477 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6478 struct spoolss_PrinterInfo2 *old_printer;
6479 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6481 WERROR result = WERR_OK;
6482 TALLOC_CTX *tmp_ctx;
6484 DEBUG(8,("update_printer\n"));
6486 tmp_ctx = talloc_new(p->mem_ctx);
6487 if (tmp_ctx == NULL) {
6492 result = WERR_BADFID;
6496 if (!get_printer_snum(p, handle, &snum, NULL)) {
6497 result = WERR_BADFID;
6501 result = winreg_get_printer(tmp_ctx,
6502 get_session_info_system(),
6504 lp_const_servicename(snum),
6506 if (!W_ERROR_IS_OK(result)) {
6507 result = WERR_BADFID;
6511 /* Do sanity check on the requested changes for Samba */
6512 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6513 result = WERR_INVALID_PARAM;
6517 /* FIXME!!! If the driver has changed we really should verify that
6518 it is installed before doing much else --jerry */
6520 /* Check calling user has permission to update printer description */
6521 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6522 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6523 result = WERR_ACCESS_DENIED;
6527 /* Call addprinter hook */
6528 /* Check changes to see if this is really needed */
6530 if (*lp_addprinter_cmd() &&
6531 (!strequal(printer->drivername, old_printer->drivername) ||
6532 !strequal(printer->comment, old_printer->comment) ||
6533 !strequal(printer->portname, old_printer->portname) ||
6534 !strequal(printer->location, old_printer->location)) )
6536 /* add_printer_hook() will call reload_services() */
6537 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6538 printer, p->client_id->addr,
6540 result = WERR_ACCESS_DENIED;
6545 update_dsspooler(tmp_ctx,
6546 get_session_info_system(),
6552 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6554 if (devmode == NULL) {
6555 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6557 result = winreg_update_printer(tmp_ctx,
6558 get_session_info_system(),
6567 talloc_free(tmp_ctx);
6572 /****************************************************************************
6573 ****************************************************************************/
6574 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6575 struct policy_handle *handle,
6576 struct spoolss_SetPrinterInfo7 *info7)
6579 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6582 struct printer_handle *Printer;
6584 if ( lp_security() != SEC_ADS ) {
6585 return WERR_UNKNOWN_LEVEL;
6588 Printer = find_printer_index_by_hnd(p, handle);
6590 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6595 if (!get_printer_snum(p, handle, &snum, NULL))
6598 result = winreg_get_printer(p->mem_ctx,
6599 get_session_info_system(),
6601 lp_servicename(snum),
6603 if (!W_ERROR_IS_OK(result)) {
6607 nt_printer_publish(pinfo2,
6608 get_session_info_system(),
6613 TALLOC_FREE(pinfo2);
6616 return WERR_UNKNOWN_LEVEL;
6620 /********************************************************************
6621 ********************************************************************/
6623 static WERROR update_printer_devmode(struct pipes_struct *p,
6624 struct policy_handle *handle,
6625 struct spoolss_DeviceMode *devmode)
6628 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6629 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6631 DEBUG(8,("update_printer_devmode\n"));
6637 if (!get_printer_snum(p, handle, &snum, NULL)) {
6641 /* Check calling user has permission to update printer description */
6642 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6643 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6644 return WERR_ACCESS_DENIED;
6647 return winreg_update_printer(p->mem_ctx,
6648 get_session_info_system(),
6650 lp_const_servicename(snum),
6658 /****************************************************************
6660 ****************************************************************/
6662 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6663 struct spoolss_SetPrinter *r)
6667 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6670 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6671 OUR_HANDLE(r->in.handle)));
6675 /* check the level */
6676 switch (r->in.info_ctr->level) {
6678 return control_printer(r->in.handle, r->in.command, p);
6680 result = update_printer(p, r->in.handle,
6682 r->in.devmode_ctr->devmode);
6683 if (!W_ERROR_IS_OK(result))
6685 if (r->in.secdesc_ctr->sd)
6686 result = update_printer_sec(r->in.handle, p,
6690 return update_printer_sec(r->in.handle, p,
6693 return publish_or_unpublish_printer(p, r->in.handle,
6694 r->in.info_ctr->info.info7);
6696 return update_printer_devmode(p, r->in.handle,
6697 r->in.devmode_ctr->devmode);
6699 return WERR_UNKNOWN_LEVEL;
6703 /****************************************************************
6704 _spoolss_FindClosePrinterNotify
6705 ****************************************************************/
6707 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6708 struct spoolss_FindClosePrinterNotify *r)
6710 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6713 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6714 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6718 if (Printer->notify.cli_chan != NULL &&
6719 Printer->notify.cli_chan->active_connections > 0) {
6722 if (Printer->printer_type == SPLHND_PRINTER) {
6723 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6728 srv_spoolss_replycloseprinter(snum, Printer);
6731 Printer->notify.flags=0;
6732 Printer->notify.options=0;
6733 Printer->notify.localmachine[0]='\0';
6734 Printer->notify.printerlocal=0;
6735 TALLOC_FREE(Printer->notify.option);
6740 /****************************************************************
6742 ****************************************************************/
6744 WERROR _spoolss_AddJob(struct pipes_struct *p,
6745 struct spoolss_AddJob *r)
6747 if (!r->in.buffer && (r->in.offered != 0)) {
6748 return WERR_INVALID_PARAM;
6751 /* this is what a NT server returns for AddJob. AddJob must fail on
6752 * non-local printers */
6754 if (r->in.level != 1) {
6755 return WERR_UNKNOWN_LEVEL;
6758 return WERR_INVALID_PARAM;
6761 /****************************************************************************
6763 ****************************************************************************/
6765 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6766 struct spoolss_JobInfo1 *r,
6767 const print_queue_struct *queue,
6768 int position, int snum,
6769 struct spoolss_PrinterInfo2 *pinfo2)
6773 t = gmtime(&queue->time);
6775 r->job_id = queue->job;
6777 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6778 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6779 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6780 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6781 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6782 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6783 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6784 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6785 r->data_type = talloc_strdup(mem_ctx, "RAW");
6786 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6787 r->text_status = talloc_strdup(mem_ctx, "");
6788 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6790 r->status = nt_printj_status(queue->status);
6791 r->priority = queue->priority;
6792 r->position = position;
6793 r->total_pages = queue->page_count;
6794 r->pages_printed = 0; /* ??? */
6796 init_systemtime(&r->submitted, t);
6801 /****************************************************************************
6803 ****************************************************************************/
6805 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6806 struct spoolss_JobInfo2 *r,
6807 const print_queue_struct *queue,
6808 int position, int snum,
6809 struct spoolss_PrinterInfo2 *pinfo2,
6810 struct spoolss_DeviceMode *devmode)
6814 t = gmtime(&queue->time);
6816 r->job_id = queue->job;
6818 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6819 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6820 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6821 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6822 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6823 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6824 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6825 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6826 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6827 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6828 r->data_type = talloc_strdup(mem_ctx, "RAW");
6829 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6830 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6831 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6832 r->parameters = talloc_strdup(mem_ctx, "");
6833 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6834 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6835 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6837 r->devmode = devmode;
6839 r->text_status = talloc_strdup(mem_ctx, "");
6840 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6844 r->status = nt_printj_status(queue->status);
6845 r->priority = queue->priority;
6846 r->position = position;
6849 r->total_pages = queue->page_count;
6850 r->size = queue->size;
6851 init_systemtime(&r->submitted, t);
6853 r->pages_printed = 0; /* ??? */
6858 /****************************************************************************
6860 ****************************************************************************/
6862 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6863 struct spoolss_JobInfo3 *r,
6864 const print_queue_struct *queue,
6865 const print_queue_struct *next_queue,
6866 int position, int snum,
6867 struct spoolss_PrinterInfo2 *pinfo2)
6869 r->job_id = queue->job;
6872 r->next_job_id = next_queue->job;
6879 /****************************************************************************
6880 Enumjobs at level 1.
6881 ****************************************************************************/
6883 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6884 const print_queue_struct *queue,
6885 uint32_t num_queues, int snum,
6886 struct spoolss_PrinterInfo2 *pinfo2,
6887 union spoolss_JobInfo **info_p,
6890 union spoolss_JobInfo *info;
6892 WERROR result = WERR_OK;
6894 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6895 W_ERROR_HAVE_NO_MEMORY(info);
6897 *count = num_queues;
6899 for (i=0; i<*count; i++) {
6900 result = fill_job_info1(info,
6906 if (!W_ERROR_IS_OK(result)) {
6912 if (!W_ERROR_IS_OK(result)) {
6923 /****************************************************************************
6924 Enumjobs at level 2.
6925 ****************************************************************************/
6927 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6928 const print_queue_struct *queue,
6929 uint32_t num_queues, int snum,
6930 struct spoolss_PrinterInfo2 *pinfo2,
6931 union spoolss_JobInfo **info_p,
6934 union spoolss_JobInfo *info;
6936 WERROR result = WERR_OK;
6938 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6939 W_ERROR_HAVE_NO_MEMORY(info);
6941 *count = num_queues;
6943 for (i=0; i<*count; i++) {
6944 struct spoolss_DeviceMode *devmode;
6946 result = spoolss_create_default_devmode(info,
6947 pinfo2->printername,
6949 if (!W_ERROR_IS_OK(result)) {
6950 DEBUG(3, ("Can't proceed w/o a devmode!"));
6954 result = fill_job_info2(info,
6961 if (!W_ERROR_IS_OK(result)) {
6967 if (!W_ERROR_IS_OK(result)) {
6978 /****************************************************************************
6979 Enumjobs at level 3.
6980 ****************************************************************************/
6982 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6983 const print_queue_struct *queue,
6984 uint32_t num_queues, int snum,
6985 struct spoolss_PrinterInfo2 *pinfo2,
6986 union spoolss_JobInfo **info_p,
6989 union spoolss_JobInfo *info;
6991 WERROR result = WERR_OK;
6993 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6994 W_ERROR_HAVE_NO_MEMORY(info);
6996 *count = num_queues;
6998 for (i=0; i<*count; i++) {
6999 const print_queue_struct *next_queue = NULL;
7002 next_queue = &queue[i+1];
7005 result = fill_job_info3(info,
7012 if (!W_ERROR_IS_OK(result)) {
7018 if (!W_ERROR_IS_OK(result)) {
7029 /****************************************************************
7031 ****************************************************************/
7033 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7034 struct spoolss_EnumJobs *r)
7037 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7039 print_status_struct prt_status;
7040 print_queue_struct *queue = NULL;
7043 /* that's an [in out] buffer */
7045 if (!r->in.buffer && (r->in.offered != 0)) {
7046 return WERR_INVALID_PARAM;
7049 DEBUG(4,("_spoolss_EnumJobs\n"));
7053 *r->out.info = NULL;
7055 /* lookup the printer snum and tdb entry */
7057 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7061 result = winreg_get_printer(p->mem_ctx,
7062 get_session_info_system(),
7064 lp_const_servicename(snum),
7066 if (!W_ERROR_IS_OK(result)) {
7070 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7071 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7072 count, prt_status.status, prt_status.message));
7076 TALLOC_FREE(pinfo2);
7080 switch (r->in.level) {
7082 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7083 pinfo2, r->out.info, r->out.count);
7086 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7087 pinfo2, r->out.info, r->out.count);
7090 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7091 pinfo2, r->out.info, r->out.count);
7094 result = WERR_UNKNOWN_LEVEL;
7099 TALLOC_FREE(pinfo2);
7101 if (!W_ERROR_IS_OK(result)) {
7105 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7107 *r->out.info, r->in.level,
7109 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7110 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7112 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7115 /****************************************************************
7116 _spoolss_ScheduleJob
7117 ****************************************************************/
7119 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7120 struct spoolss_ScheduleJob *r)
7125 /****************************************************************
7126 ****************************************************************/
7128 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7129 struct messaging_context *msg_ctx,
7130 const char *printer_name,
7132 struct spoolss_SetJobInfo1 *r)
7136 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7140 if (strequal(old_doc_name, r->document_name)) {
7144 if (!print_job_set_name(server_event_context(), msg_ctx,
7145 printer_name, job_id, r->document_name)) {
7152 /****************************************************************
7154 ****************************************************************/
7156 WERROR _spoolss_SetJob(struct pipes_struct *p,
7157 struct spoolss_SetJob *r)
7159 const struct auth_serversupplied_info *session_info = p->session_info;
7161 WERROR errcode = WERR_BADFUNC;
7163 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7167 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7168 return WERR_INVALID_PRINTER_NAME;
7171 switch (r->in.command) {
7172 case SPOOLSS_JOB_CONTROL_CANCEL:
7173 case SPOOLSS_JOB_CONTROL_DELETE:
7174 errcode = print_job_delete(session_info, p->msg_ctx,
7175 snum, r->in.job_id);
7176 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7180 case SPOOLSS_JOB_CONTROL_PAUSE:
7181 if (print_job_pause(session_info, p->msg_ctx,
7182 snum, r->in.job_id, &errcode)) {
7186 case SPOOLSS_JOB_CONTROL_RESTART:
7187 case SPOOLSS_JOB_CONTROL_RESUME:
7188 if (print_job_resume(session_info, p->msg_ctx,
7189 snum, r->in.job_id, &errcode)) {
7197 return WERR_UNKNOWN_LEVEL;
7200 if (!W_ERROR_IS_OK(errcode)) {
7204 if (r->in.ctr == NULL) {
7208 switch (r->in.ctr->level) {
7210 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7211 lp_const_servicename(snum),
7213 r->in.ctr->info.info1);
7219 return WERR_UNKNOWN_LEVEL;
7225 /****************************************************************************
7226 Enumerates all printer drivers by level and architecture.
7227 ****************************************************************************/
7229 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7230 const struct auth_serversupplied_info *session_info,
7231 struct messaging_context *msg_ctx,
7232 const char *servername,
7233 const char *architecture,
7235 union spoolss_DriverInfo **info_p,
7240 struct spoolss_DriverInfo8 *driver;
7241 union spoolss_DriverInfo *info = NULL;
7243 WERROR result = WERR_OK;
7244 uint32_t num_drivers;
7245 const char **drivers;
7250 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7251 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7252 architecture, version,
7253 &num_drivers, &drivers);
7254 if (!W_ERROR_IS_OK(result)) {
7257 DEBUG(4, ("we have:[%d] drivers in environment"
7258 " [%s] and version [%d]\n",
7259 num_drivers, architecture, version));
7261 if (num_drivers != 0) {
7262 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7263 union spoolss_DriverInfo,
7264 count + num_drivers);
7266 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7267 "failed to enlarge driver info buffer!\n"));
7268 result = WERR_NOMEM;
7273 for (i = 0; i < num_drivers; i++) {
7274 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7276 result = winreg_get_driver(mem_ctx, session_info,
7278 architecture, drivers[i],
7280 if (!W_ERROR_IS_OK(result)) {
7286 result = fill_printer_driver_info1(info, &info[count+i].info1,
7287 driver, servername);
7290 result = fill_printer_driver_info2(info, &info[count+i].info2,
7291 driver, servername);
7294 result = fill_printer_driver_info3(info, &info[count+i].info3,
7295 driver, servername);
7298 result = fill_printer_driver_info4(info, &info[count+i].info4,
7299 driver, servername);
7302 result = fill_printer_driver_info5(info, &info[count+i].info5,
7303 driver, servername);
7306 result = fill_printer_driver_info6(info, &info[count+i].info6,
7307 driver, servername);
7310 result = fill_printer_driver_info8(info, &info[count+i].info8,
7311 driver, servername);
7314 result = WERR_UNKNOWN_LEVEL;
7318 TALLOC_FREE(driver);
7320 if (!W_ERROR_IS_OK(result)) {
7325 count += num_drivers;
7326 TALLOC_FREE(drivers);
7330 TALLOC_FREE(drivers);
7332 if (!W_ERROR_IS_OK(result)) {
7343 /****************************************************************************
7344 Enumerates all printer drivers by level.
7345 ****************************************************************************/
7347 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7348 const struct auth_serversupplied_info *session_info,
7349 struct messaging_context *msg_ctx,
7350 const char *servername,
7351 const char *architecture,
7353 union spoolss_DriverInfo **info_p,
7357 WERROR result = WERR_OK;
7359 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7361 for (a=0; archi_table[a].long_archi != NULL; a++) {
7363 union spoolss_DriverInfo *info = NULL;
7366 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7370 archi_table[a].long_archi,
7374 if (!W_ERROR_IS_OK(result)) {
7378 for (i=0; i < count; i++) {
7379 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7380 info[i], info_p, count_p);
7387 return enumprinterdrivers_level_by_architecture(mem_ctx,
7397 /****************************************************************
7398 _spoolss_EnumPrinterDrivers
7399 ****************************************************************/
7401 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7402 struct spoolss_EnumPrinterDrivers *r)
7404 const char *cservername;
7407 /* that's an [in out] buffer */
7409 if (!r->in.buffer && (r->in.offered != 0)) {
7410 return WERR_INVALID_PARAM;
7413 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7417 *r->out.info = NULL;
7419 cservername = canon_servername(r->in.server);
7421 if (!is_myname_or_ipaddr(cservername)) {
7422 return WERR_UNKNOWN_PRINTER_DRIVER;
7425 result = enumprinterdrivers_level(p->mem_ctx,
7426 get_session_info_system(),
7433 if (!W_ERROR_IS_OK(result)) {
7437 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7438 spoolss_EnumPrinterDrivers,
7439 *r->out.info, r->in.level,
7441 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7442 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7444 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7447 /****************************************************************
7449 ****************************************************************/
7451 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7452 struct spoolss_EnumForms *r)
7458 *r->out.info = NULL;
7460 /* that's an [in out] buffer */
7462 if (!r->in.buffer && (r->in.offered != 0) ) {
7463 return WERR_INVALID_PARAM;
7466 DEBUG(4,("_spoolss_EnumForms\n"));
7467 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7468 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7470 switch (r->in.level) {
7472 result = winreg_printer_enumforms1(p->mem_ctx,
7473 get_session_info_system(),
7479 result = WERR_UNKNOWN_LEVEL;
7483 if (!W_ERROR_IS_OK(result)) {
7487 if (*r->out.count == 0) {
7488 return WERR_NO_MORE_ITEMS;
7491 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7493 *r->out.info, r->in.level,
7495 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7496 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7498 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7501 /****************************************************************
7503 ****************************************************************/
7505 WERROR _spoolss_GetForm(struct pipes_struct *p,
7506 struct spoolss_GetForm *r)
7510 /* that's an [in out] buffer */
7512 if (!r->in.buffer && (r->in.offered != 0)) {
7513 return WERR_INVALID_PARAM;
7516 DEBUG(4,("_spoolss_GetForm\n"));
7517 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7518 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7520 switch (r->in.level) {
7522 result = winreg_printer_getform1(p->mem_ctx,
7523 get_session_info_system(),
7526 &r->out.info->info1);
7529 result = WERR_UNKNOWN_LEVEL;
7533 if (!W_ERROR_IS_OK(result)) {
7534 TALLOC_FREE(r->out.info);
7538 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7539 r->out.info, r->in.level);
7540 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7542 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7545 /****************************************************************************
7546 ****************************************************************************/
7548 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7549 struct spoolss_PortInfo1 *r,
7552 r->port_name = talloc_strdup(mem_ctx, name);
7553 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7558 /****************************************************************************
7559 TODO: This probably needs distinguish between TCP/IP and Local ports
7561 ****************************************************************************/
7563 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7564 struct spoolss_PortInfo2 *r,
7567 r->port_name = talloc_strdup(mem_ctx, name);
7568 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7570 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7571 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7573 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7574 W_ERROR_HAVE_NO_MEMORY(r->description);
7576 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7583 /****************************************************************************
7584 wrapper around the enumer ports command
7585 ****************************************************************************/
7587 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7589 char *cmd = lp_enumports_cmd();
7590 char **qlines = NULL;
7591 char *command = NULL;
7599 /* if no hook then just fill in the default port */
7602 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7605 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7606 TALLOC_FREE(qlines);
7613 /* we have a valid enumport command */
7615 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7620 DEBUG(10,("Running [%s]\n", command));
7621 ret = smbrun(command, &fd);
7622 DEBUG(10,("Returned [%d]\n", ret));
7623 TALLOC_FREE(command);
7628 return WERR_ACCESS_DENIED;
7632 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7633 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7643 /****************************************************************************
7645 ****************************************************************************/
7647 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7648 union spoolss_PortInfo **info_p,
7651 union spoolss_PortInfo *info = NULL;
7653 WERROR result = WERR_OK;
7654 char **qlines = NULL;
7657 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7658 if (!W_ERROR_IS_OK(result)) {
7663 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7665 DEBUG(10,("Returning WERR_NOMEM\n"));
7666 result = WERR_NOMEM;
7670 for (i=0; i<numlines; i++) {
7671 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7672 result = fill_port_1(info, &info[i].info1, qlines[i]);
7673 if (!W_ERROR_IS_OK(result)) {
7678 TALLOC_FREE(qlines);
7681 if (!W_ERROR_IS_OK(result)) {
7683 TALLOC_FREE(qlines);
7695 /****************************************************************************
7697 ****************************************************************************/
7699 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7700 union spoolss_PortInfo **info_p,
7703 union spoolss_PortInfo *info = NULL;
7705 WERROR result = WERR_OK;
7706 char **qlines = NULL;
7709 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7710 if (!W_ERROR_IS_OK(result)) {
7715 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7717 DEBUG(10,("Returning WERR_NOMEM\n"));
7718 result = WERR_NOMEM;
7722 for (i=0; i<numlines; i++) {
7723 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7724 result = fill_port_2(info, &info[i].info2, qlines[i]);
7725 if (!W_ERROR_IS_OK(result)) {
7730 TALLOC_FREE(qlines);
7733 if (!W_ERROR_IS_OK(result)) {
7735 TALLOC_FREE(qlines);
7747 /****************************************************************
7749 ****************************************************************/
7751 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7752 struct spoolss_EnumPorts *r)
7756 /* that's an [in out] buffer */
7758 if (!r->in.buffer && (r->in.offered != 0)) {
7759 return WERR_INVALID_PARAM;
7762 DEBUG(4,("_spoolss_EnumPorts\n"));
7766 *r->out.info = NULL;
7768 switch (r->in.level) {
7770 result = enumports_level_1(p->mem_ctx, r->out.info,
7774 result = enumports_level_2(p->mem_ctx, r->out.info,
7778 return WERR_UNKNOWN_LEVEL;
7781 if (!W_ERROR_IS_OK(result)) {
7785 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7787 *r->out.info, r->in.level,
7789 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7790 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7792 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7795 /****************************************************************************
7796 ****************************************************************************/
7798 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7800 struct spoolss_SetPrinterInfoCtr *info_ctr,
7801 struct spoolss_DeviceMode *devmode,
7802 struct security_descriptor *secdesc,
7803 struct spoolss_UserLevelCtr *user_ctr,
7804 struct policy_handle *handle)
7806 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7807 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7809 WERROR err = WERR_OK;
7811 /* samba does not have a concept of local, non-shared printers yet, so
7812 * make sure we always setup sharename - gd */
7813 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7814 (info2->printername != NULL && info2->printername[0] != '\0')) {
7815 DEBUG(5, ("spoolss_addprinterex_level_2: "
7816 "no sharename has been set, setting printername %s as sharename\n",
7817 info2->printername));
7818 info2->sharename = info2->printername;
7821 /* check to see if the printer already exists */
7822 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7823 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7825 return WERR_PRINTER_ALREADY_EXISTS;
7828 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7829 if ((snum = print_queue_snum(info2->printername)) != -1) {
7830 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7831 info2->printername));
7832 return WERR_PRINTER_ALREADY_EXISTS;
7836 /* validate printer info struct */
7837 if (!info2->printername || strlen(info2->printername) == 0) {
7838 return WERR_INVALID_PRINTER_NAME;
7840 if (!info2->portname || strlen(info2->portname) == 0) {
7841 return WERR_UNKNOWN_PORT;
7843 if (!info2->drivername || strlen(info2->drivername) == 0) {
7844 return WERR_UNKNOWN_PRINTER_DRIVER;
7846 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7847 return WERR_UNKNOWN_PRINTPROCESSOR;
7850 /* FIXME!!! smbd should check to see if the driver is installed before
7851 trying to add a printer like this --jerry */
7853 if (*lp_addprinter_cmd() ) {
7854 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7855 info2, p->client_id->addr,
7857 return WERR_ACCESS_DENIED;
7860 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7861 "smb.conf parameter \"addprinter command\" is defined. This"
7862 "parameter must exist for this call to succeed\n",
7863 info2->sharename ));
7866 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7867 return WERR_ACCESS_DENIED;
7870 /* you must be a printer admin to add a new printer */
7871 if (!print_access_check(p->session_info,
7874 PRINTER_ACCESS_ADMINISTER)) {
7875 return WERR_ACCESS_DENIED;
7879 * Do sanity check on the requested changes for Samba.
7882 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7883 return WERR_INVALID_PARAM;
7886 if (devmode == NULL) {
7887 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7890 update_dsspooler(p->mem_ctx,
7891 get_session_info_system(),
7897 err = winreg_update_printer(p->mem_ctx,
7898 get_session_info_system(),
7905 if (!W_ERROR_IS_OK(err)) {
7909 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7910 if (!W_ERROR_IS_OK(err)) {
7911 /* Handle open failed - remove addition. */
7912 ZERO_STRUCTP(handle);
7919 /****************************************************************
7920 _spoolss_AddPrinterEx
7921 ****************************************************************/
7923 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7924 struct spoolss_AddPrinterEx *r)
7926 switch (r->in.info_ctr->level) {
7928 /* we don't handle yet */
7929 /* but I know what to do ... */
7930 return WERR_UNKNOWN_LEVEL;
7932 return spoolss_addprinterex_level_2(p, r->in.server,
7934 r->in.devmode_ctr->devmode,
7935 r->in.secdesc_ctr->sd,
7936 r->in.userlevel_ctr,
7939 return WERR_UNKNOWN_LEVEL;
7943 /****************************************************************
7945 ****************************************************************/
7947 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7948 struct spoolss_AddPrinter *r)
7950 struct spoolss_AddPrinterEx a;
7951 struct spoolss_UserLevelCtr userlevel_ctr;
7953 ZERO_STRUCT(userlevel_ctr);
7955 userlevel_ctr.level = 1;
7957 a.in.server = r->in.server;
7958 a.in.info_ctr = r->in.info_ctr;
7959 a.in.devmode_ctr = r->in.devmode_ctr;
7960 a.in.secdesc_ctr = r->in.secdesc_ctr;
7961 a.in.userlevel_ctr = &userlevel_ctr;
7962 a.out.handle = r->out.handle;
7964 return _spoolss_AddPrinterEx(p, &a);
7967 /****************************************************************
7968 _spoolss_AddPrinterDriverEx
7969 ****************************************************************/
7971 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7972 struct spoolss_AddPrinterDriverEx *r)
7974 WERROR err = WERR_OK;
7975 const char *driver_name = NULL;
7980 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7981 fn = "_spoolss_AddPrinterDriver";
7983 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7984 fn = "_spoolss_AddPrinterDriverEx";
7987 return WERR_INVALID_PARAM;
7991 * we only support the semantics of AddPrinterDriver()
7992 * i.e. only copy files that are newer than existing ones
7995 if (r->in.flags == 0) {
7996 return WERR_INVALID_PARAM;
7999 if (r->in.flags != APD_COPY_NEW_FILES) {
8000 return WERR_ACCESS_DENIED;
8004 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8005 /* Clever hack from Martin Zielinski <mz@seh.de>
8006 * to allow downgrade from level 8 (Vista).
8008 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8009 r->in.info_ctr->level));
8010 return WERR_UNKNOWN_LEVEL;
8013 DEBUG(5,("Cleaning driver's information\n"));
8014 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8015 if (!W_ERROR_IS_OK(err))
8018 DEBUG(5,("Moving driver to final destination\n"));
8019 err = move_driver_to_download_area(p, r->in.info_ctr);
8020 if (!W_ERROR_IS_OK(err)) {
8024 err = winreg_add_driver(p->mem_ctx,
8025 get_session_info_system(),
8030 if (!W_ERROR_IS_OK(err)) {
8035 * I think this is where he DrvUpgradePrinter() hook would be
8036 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8037 * server. Right now, we just need to send ourselves a message
8038 * to update each printer bound to this driver. --jerry
8041 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8042 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8050 /****************************************************************
8051 _spoolss_AddPrinterDriver
8052 ****************************************************************/
8054 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8055 struct spoolss_AddPrinterDriver *r)
8057 struct spoolss_AddPrinterDriverEx a;
8059 switch (r->in.info_ctr->level) {
8066 return WERR_UNKNOWN_LEVEL;
8069 a.in.servername = r->in.servername;
8070 a.in.info_ctr = r->in.info_ctr;
8071 a.in.flags = APD_COPY_NEW_FILES;
8073 return _spoolss_AddPrinterDriverEx(p, &a);
8076 /****************************************************************************
8077 ****************************************************************************/
8079 struct _spoolss_paths {
8085 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8087 static const struct _spoolss_paths spoolss_paths[]= {
8088 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8089 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8092 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8093 const char *servername,
8094 const char *environment,
8098 const char *pservername = NULL;
8099 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8100 const char *short_archi;
8104 /* environment may be empty */
8105 if (environment && strlen(environment)) {
8106 long_archi = environment;
8109 /* servername may be empty */
8110 if (servername && strlen(servername)) {
8111 pservername = canon_servername(servername);
8113 if (!is_myname_or_ipaddr(pservername)) {
8114 return WERR_INVALID_PARAM;
8118 if (!(short_archi = get_short_archi(long_archi))) {
8119 return WERR_INVALID_ENVIRONMENT;
8122 switch (component) {
8123 case SPOOLSS_PRTPROCS_PATH:
8124 case SPOOLSS_DRIVER_PATH:
8126 *path = talloc_asprintf(mem_ctx,
8129 spoolss_paths[component].share,
8132 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8133 SPOOLSS_DEFAULT_SERVER_PATH,
8134 spoolss_paths[component].dir,
8139 return WERR_INVALID_PARAM;
8149 /****************************************************************************
8150 ****************************************************************************/
8152 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8153 const char *servername,
8154 const char *environment,
8155 struct spoolss_DriverDirectoryInfo1 *r)
8160 werr = compose_spoolss_server_path(mem_ctx,
8163 SPOOLSS_DRIVER_PATH,
8165 if (!W_ERROR_IS_OK(werr)) {
8169 DEBUG(4,("printer driver directory: [%s]\n", path));
8171 r->directory_name = path;
8176 /****************************************************************
8177 _spoolss_GetPrinterDriverDirectory
8178 ****************************************************************/
8180 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8181 struct spoolss_GetPrinterDriverDirectory *r)
8185 /* that's an [in out] buffer */
8187 if (!r->in.buffer && (r->in.offered != 0)) {
8188 return WERR_INVALID_PARAM;
8191 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8196 /* r->in.level is ignored */
8198 werror = getprinterdriverdir_level_1(p->mem_ctx,
8201 &r->out.info->info1);
8202 if (!W_ERROR_IS_OK(werror)) {
8203 TALLOC_FREE(r->out.info);
8207 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8208 r->out.info, r->in.level);
8209 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8211 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8214 /****************************************************************
8215 _spoolss_EnumPrinterData
8216 ****************************************************************/
8218 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8219 struct spoolss_EnumPrinterData *r)
8222 struct spoolss_EnumPrinterDataEx r2;
8224 struct spoolss_PrinterEnumValues *info, *val = NULL;
8227 r2.in.handle = r->in.handle;
8228 r2.in.key_name = "PrinterDriverData";
8230 r2.out.count = &count;
8231 r2.out.info = &info;
8232 r2.out.needed = &needed;
8234 result = _spoolss_EnumPrinterDataEx(p, &r2);
8235 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8236 r2.in.offered = needed;
8237 result = _spoolss_EnumPrinterDataEx(p, &r2);
8239 if (!W_ERROR_IS_OK(result)) {
8244 * The NT machine wants to know the biggest size of value and data
8246 * cf: MSDN EnumPrinterData remark section
8249 if (!r->in.value_offered && !r->in.data_offered) {
8250 uint32_t biggest_valuesize = 0;
8251 uint32_t biggest_datasize = 0;
8254 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8256 for (i=0; i<count; i++) {
8258 name_length = strlen(info[i].value_name);
8259 if (strlen(info[i].value_name) > biggest_valuesize) {
8260 biggest_valuesize = name_length;
8263 if (info[i].data_length > biggest_datasize) {
8264 biggest_datasize = info[i].data_length;
8267 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8271 /* the value is an UNICODE string but real_value_size is the length
8272 in bytes including the trailing 0 */
8274 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8275 *r->out.data_needed = biggest_datasize;
8277 DEBUG(6,("final values: [%d], [%d]\n",
8278 *r->out.value_needed, *r->out.data_needed));
8283 if (r->in.enum_index < count) {
8284 val = &info[r->in.enum_index];
8288 /* out_value should default to "" or else NT4 has
8289 problems unmarshalling the response */
8291 if (r->in.value_offered) {
8292 *r->out.value_needed = 1;
8293 r->out.value_name = talloc_strdup(r, "");
8294 if (!r->out.value_name) {
8298 r->out.value_name = NULL;
8299 *r->out.value_needed = 0;
8302 /* the data is counted in bytes */
8304 *r->out.data_needed = r->in.data_offered;
8306 result = WERR_NO_MORE_ITEMS;
8310 * - counted in bytes in the request
8311 * - counted in UNICODE chars in the max reply
8312 * - counted in bytes in the real size
8314 * take a pause *before* coding not *during* coding
8318 if (r->in.value_offered) {
8319 r->out.value_name = talloc_strdup(r, val->value_name);
8320 if (!r->out.value_name) {
8323 *r->out.value_needed = val->value_name_len;
8325 r->out.value_name = NULL;
8326 *r->out.value_needed = 0;
8331 *r->out.type = val->type;
8333 /* data - counted in bytes */
8336 * See the section "Dynamically Typed Query Parameters"
8340 if (r->out.data && val->data && val->data->data &&
8341 val->data_length && r->in.data_offered) {
8342 memcpy(r->out.data, val->data->data,
8343 MIN(val->data_length,r->in.data_offered));
8346 *r->out.data_needed = val->data_length;
8354 /****************************************************************
8355 _spoolss_SetPrinterData
8356 ****************************************************************/
8358 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8359 struct spoolss_SetPrinterData *r)
8361 struct spoolss_SetPrinterDataEx r2;
8363 r2.in.handle = r->in.handle;
8364 r2.in.key_name = "PrinterDriverData";
8365 r2.in.value_name = r->in.value_name;
8366 r2.in.type = r->in.type;
8367 r2.in.data = r->in.data;
8368 r2.in.offered = r->in.offered;
8370 return _spoolss_SetPrinterDataEx(p, &r2);
8373 /****************************************************************
8374 _spoolss_ResetPrinter
8375 ****************************************************************/
8377 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8378 struct spoolss_ResetPrinter *r)
8380 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8383 DEBUG(5,("_spoolss_ResetPrinter\n"));
8386 * All we do is to check to see if the handle and queue is valid.
8387 * This call really doesn't mean anything to us because we only
8388 * support RAW printing. --jerry
8392 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8393 OUR_HANDLE(r->in.handle)));
8397 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8401 /* blindly return success */
8405 /****************************************************************
8406 _spoolss_DeletePrinterData
8407 ****************************************************************/
8409 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8410 struct spoolss_DeletePrinterData *r)
8412 struct spoolss_DeletePrinterDataEx r2;
8414 r2.in.handle = r->in.handle;
8415 r2.in.key_name = "PrinterDriverData";
8416 r2.in.value_name = r->in.value_name;
8418 return _spoolss_DeletePrinterDataEx(p, &r2);
8421 /****************************************************************
8423 ****************************************************************/
8425 WERROR _spoolss_AddForm(struct pipes_struct *p,
8426 struct spoolss_AddForm *r)
8428 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8430 WERROR status = WERR_OK;
8432 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8434 DEBUG(5,("_spoolss_AddForm\n"));
8437 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8438 OUR_HANDLE(r->in.handle)));
8442 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8443 and not a printer admin, then fail */
8445 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8446 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8447 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8448 p->session_info->info3->base.domain.string,
8450 p->session_info->security_token,
8451 lp_printer_admin(snum))) {
8452 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8453 return WERR_ACCESS_DENIED;
8456 switch (form->flags) {
8457 case SPOOLSS_FORM_USER:
8458 case SPOOLSS_FORM_BUILTIN:
8459 case SPOOLSS_FORM_PRINTER:
8462 return WERR_INVALID_PARAM;
8465 status = winreg_printer_addform1(p->mem_ctx,
8466 get_session_info_system(),
8469 if (!W_ERROR_IS_OK(status)) {
8474 * ChangeID must always be set if this is a printer
8476 if (Printer->printer_type == SPLHND_PRINTER) {
8477 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8481 status = winreg_printer_update_changeid(p->mem_ctx,
8482 get_session_info_system(),
8484 lp_const_servicename(snum));
8485 if (!W_ERROR_IS_OK(status)) {
8493 /****************************************************************
8495 ****************************************************************/
8497 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8498 struct spoolss_DeleteForm *r)
8500 const char *form_name = r->in.form_name;
8501 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8503 WERROR status = WERR_OK;
8505 DEBUG(5,("_spoolss_DeleteForm\n"));
8508 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8509 OUR_HANDLE(r->in.handle)));
8513 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8514 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8515 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8516 p->session_info->info3->base.domain.string,
8518 p->session_info->security_token,
8519 lp_printer_admin(snum))) {
8520 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8521 return WERR_ACCESS_DENIED;
8524 status = winreg_printer_deleteform1(p->mem_ctx,
8525 get_session_info_system(),
8528 if (!W_ERROR_IS_OK(status)) {
8533 * ChangeID must always be set if this is a printer
8535 if (Printer->printer_type == SPLHND_PRINTER) {
8536 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8540 status = winreg_printer_update_changeid(p->mem_ctx,
8541 get_session_info_system(),
8543 lp_const_servicename(snum));
8544 if (!W_ERROR_IS_OK(status)) {
8552 /****************************************************************
8554 ****************************************************************/
8556 WERROR _spoolss_SetForm(struct pipes_struct *p,
8557 struct spoolss_SetForm *r)
8559 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8560 const char *form_name = r->in.form_name;
8562 WERROR status = WERR_OK;
8564 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8566 DEBUG(5,("_spoolss_SetForm\n"));
8569 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8570 OUR_HANDLE(r->in.handle)));
8574 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8575 and not a printer admin, then fail */
8577 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8578 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8579 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8580 p->session_info->info3->base.domain.string,
8582 p->session_info->security_token,
8583 lp_printer_admin(snum))) {
8584 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8585 return WERR_ACCESS_DENIED;
8588 status = winreg_printer_setform1(p->mem_ctx,
8589 get_session_info_system(),
8593 if (!W_ERROR_IS_OK(status)) {
8598 * ChangeID must always be set if this is a printer
8600 if (Printer->printer_type == SPLHND_PRINTER) {
8601 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8605 status = winreg_printer_update_changeid(p->mem_ctx,
8606 get_session_info_system(),
8608 lp_const_servicename(snum));
8609 if (!W_ERROR_IS_OK(status)) {
8617 /****************************************************************************
8618 fill_print_processor1
8619 ****************************************************************************/
8621 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8622 struct spoolss_PrintProcessorInfo1 *r,
8623 const char *print_processor_name)
8625 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8626 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8631 /****************************************************************************
8632 enumprintprocessors level 1.
8633 ****************************************************************************/
8635 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8636 union spoolss_PrintProcessorInfo **info_p,
8639 union spoolss_PrintProcessorInfo *info;
8642 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8643 W_ERROR_HAVE_NO_MEMORY(info);
8647 result = fill_print_processor1(info, &info[0].info1, "winprint");
8648 if (!W_ERROR_IS_OK(result)) {
8653 if (!W_ERROR_IS_OK(result)) {
8664 /****************************************************************
8665 _spoolss_EnumPrintProcessors
8666 ****************************************************************/
8668 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8669 struct spoolss_EnumPrintProcessors *r)
8673 /* that's an [in out] buffer */
8675 if (!r->in.buffer && (r->in.offered != 0)) {
8676 return WERR_INVALID_PARAM;
8679 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8682 * Enumerate the print processors ...
8684 * Just reply with "winprint", to keep NT happy
8685 * and I can use my nice printer checker.
8690 *r->out.info = NULL;
8692 if (!get_short_archi(r->in.environment)) {
8693 return WERR_INVALID_ENVIRONMENT;
8696 switch (r->in.level) {
8698 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8702 return WERR_UNKNOWN_LEVEL;
8705 if (!W_ERROR_IS_OK(result)) {
8709 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8710 spoolss_EnumPrintProcessors,
8711 *r->out.info, r->in.level,
8713 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8714 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8716 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8719 /****************************************************************************
8720 fill_printprocdatatype1
8721 ****************************************************************************/
8723 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8724 struct spoolss_PrintProcDataTypesInfo1 *r,
8725 const char *name_array)
8727 r->name_array = talloc_strdup(mem_ctx, name_array);
8728 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8733 /****************************************************************************
8734 enumprintprocdatatypes level 1.
8735 ****************************************************************************/
8737 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8738 union spoolss_PrintProcDataTypesInfo **info_p,
8742 union spoolss_PrintProcDataTypesInfo *info;
8744 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8745 W_ERROR_HAVE_NO_MEMORY(info);
8749 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8750 if (!W_ERROR_IS_OK(result)) {
8755 if (!W_ERROR_IS_OK(result)) {
8766 /****************************************************************
8767 _spoolss_EnumPrintProcDataTypes
8768 ****************************************************************/
8770 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8771 struct spoolss_EnumPrintProcDataTypes *r)
8775 /* that's an [in out] buffer */
8777 if (!r->in.buffer && (r->in.offered != 0)) {
8778 return WERR_INVALID_PARAM;
8781 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8785 *r->out.info = NULL;
8787 if (r->in.print_processor_name == NULL ||
8788 !strequal(r->in.print_processor_name, "winprint")) {
8789 return WERR_UNKNOWN_PRINTPROCESSOR;
8792 switch (r->in.level) {
8794 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8798 return WERR_UNKNOWN_LEVEL;
8801 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8802 spoolss_EnumPrintProcDataTypes,
8803 *r->out.info, r->in.level,
8805 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8806 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8808 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8811 /****************************************************************************
8813 ****************************************************************************/
8815 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8816 struct spoolss_MonitorInfo1 *r,
8817 const char *monitor_name)
8819 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8820 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8825 /****************************************************************************
8827 ****************************************************************************/
8829 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8830 struct spoolss_MonitorInfo2 *r,
8831 const char *monitor_name,
8832 const char *environment,
8833 const char *dll_name)
8835 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8836 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8837 r->environment = talloc_strdup(mem_ctx, environment);
8838 W_ERROR_HAVE_NO_MEMORY(r->environment);
8839 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8840 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8845 /****************************************************************************
8846 enumprintmonitors level 1.
8847 ****************************************************************************/
8849 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8850 union spoolss_MonitorInfo **info_p,
8853 union spoolss_MonitorInfo *info;
8854 WERROR result = WERR_OK;
8856 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8857 W_ERROR_HAVE_NO_MEMORY(info);
8861 result = fill_monitor_1(info, &info[0].info1,
8863 if (!W_ERROR_IS_OK(result)) {
8867 result = fill_monitor_1(info, &info[1].info1,
8869 if (!W_ERROR_IS_OK(result)) {
8874 if (!W_ERROR_IS_OK(result)) {
8885 /****************************************************************************
8886 enumprintmonitors level 2.
8887 ****************************************************************************/
8889 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8890 union spoolss_MonitorInfo **info_p,
8893 union spoolss_MonitorInfo *info;
8894 WERROR result = WERR_OK;
8896 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8897 W_ERROR_HAVE_NO_MEMORY(info);
8901 result = fill_monitor_2(info, &info[0].info2,
8903 "Windows NT X86", /* FIXME */
8905 if (!W_ERROR_IS_OK(result)) {
8909 result = fill_monitor_2(info, &info[1].info2,
8911 "Windows NT X86", /* FIXME */
8913 if (!W_ERROR_IS_OK(result)) {
8918 if (!W_ERROR_IS_OK(result)) {
8929 /****************************************************************
8930 _spoolss_EnumMonitors
8931 ****************************************************************/
8933 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8934 struct spoolss_EnumMonitors *r)
8938 /* that's an [in out] buffer */
8940 if (!r->in.buffer && (r->in.offered != 0)) {
8941 return WERR_INVALID_PARAM;
8944 DEBUG(5,("_spoolss_EnumMonitors\n"));
8947 * Enumerate the print monitors ...
8949 * Just reply with "Local Port", to keep NT happy
8950 * and I can use my nice printer checker.
8955 *r->out.info = NULL;
8957 switch (r->in.level) {
8959 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8963 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8967 return WERR_UNKNOWN_LEVEL;
8970 if (!W_ERROR_IS_OK(result)) {
8974 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8975 spoolss_EnumMonitors,
8976 *r->out.info, r->in.level,
8978 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8979 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8981 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8984 /****************************************************************************
8985 ****************************************************************************/
8987 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8988 const print_queue_struct *queue,
8989 int count, int snum,
8990 struct spoolss_PrinterInfo2 *pinfo2,
8992 struct spoolss_JobInfo1 *r)
8997 for (i=0; i<count; i++) {
8998 if (queue[i].job == (int)jobid) {
9004 if (found == false) {
9005 /* NT treats not found as bad param... yet another bad choice */
9006 return WERR_INVALID_PARAM;
9009 return fill_job_info1(mem_ctx,
9017 /****************************************************************************
9018 ****************************************************************************/
9020 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9021 const print_queue_struct *queue,
9022 int count, int snum,
9023 struct spoolss_PrinterInfo2 *pinfo2,
9025 struct spoolss_JobInfo2 *r)
9029 struct spoolss_DeviceMode *devmode;
9032 for (i=0; i<count; i++) {
9033 if (queue[i].job == (int)jobid) {
9039 if (found == false) {
9040 /* NT treats not found as bad param... yet another bad
9042 return WERR_INVALID_PARAM;
9046 * if the print job does not have a DEVMODE associated with it,
9047 * just use the one for the printer. A NULL devicemode is not
9048 * a failure condition
9051 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9053 result = spoolss_create_default_devmode(mem_ctx,
9054 pinfo2->printername,
9056 if (!W_ERROR_IS_OK(result)) {
9057 DEBUG(3, ("Can't proceed w/o a devmode!"));
9062 return fill_job_info2(mem_ctx,
9071 /****************************************************************
9073 ****************************************************************/
9075 WERROR _spoolss_GetJob(struct pipes_struct *p,
9076 struct spoolss_GetJob *r)
9078 WERROR result = WERR_OK;
9079 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9082 print_queue_struct *queue = NULL;
9083 print_status_struct prt_status;
9085 /* that's an [in out] buffer */
9087 if (!r->in.buffer && (r->in.offered != 0)) {
9088 return WERR_INVALID_PARAM;
9091 DEBUG(5,("_spoolss_GetJob\n"));
9095 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9099 result = winreg_get_printer(p->mem_ctx,
9100 get_session_info_system(),
9102 lp_const_servicename(snum),
9104 if (!W_ERROR_IS_OK(result)) {
9108 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9110 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9111 count, prt_status.status, prt_status.message));
9113 switch (r->in.level) {
9115 result = getjob_level_1(p->mem_ctx,
9116 queue, count, snum, pinfo2,
9117 r->in.job_id, &r->out.info->info1);
9120 result = getjob_level_2(p->mem_ctx,
9121 queue, count, snum, pinfo2,
9122 r->in.job_id, &r->out.info->info2);
9125 result = WERR_UNKNOWN_LEVEL;
9130 TALLOC_FREE(pinfo2);
9132 if (!W_ERROR_IS_OK(result)) {
9133 TALLOC_FREE(r->out.info);
9137 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9139 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9141 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9144 /****************************************************************
9145 _spoolss_GetPrinterDataEx
9146 ****************************************************************/
9148 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9149 struct spoolss_GetPrinterDataEx *r)
9152 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9153 const char *printer;
9155 WERROR result = WERR_OK;
9157 enum winreg_Type val_type;
9162 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9164 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9165 r->in.key_name, r->in.value_name));
9167 /* in case of problem, return some default values */
9170 *r->out.type = REG_NONE;
9173 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9174 OUR_HANDLE(r->in.handle)));
9175 result = WERR_BADFID;
9179 /* Is the handle to a printer or to the server? */
9181 if (Printer->printer_type == SPLHND_SERVER) {
9183 union spoolss_PrinterData data;
9185 result = getprinterdata_printer_server(p->mem_ctx,
9189 if (!W_ERROR_IS_OK(result)) {
9193 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9194 *r->out.type, &data);
9195 if (!W_ERROR_IS_OK(result)) {
9199 *r->out.needed = blob.length;
9201 if (r->in.offered >= *r->out.needed) {
9202 memcpy(r->out.data, blob.data, blob.length);
9205 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9208 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9211 printer = lp_const_servicename(snum);
9213 /* check to see if the keyname is valid */
9214 if (!strlen(r->in.key_name)) {
9215 return WERR_INVALID_PARAM;
9218 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9219 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9220 strequal(r->in.value_name, "ChangeId")) {
9221 *r->out.type = REG_DWORD;
9223 if (r->in.offered >= *r->out.needed) {
9224 uint32_t changeid = 0;
9226 result = winreg_printer_get_changeid(p->mem_ctx,
9227 get_session_info_system(),
9231 if (!W_ERROR_IS_OK(result)) {
9235 SIVAL(r->out.data, 0, changeid);
9241 result = winreg_get_printer_dataex(p->mem_ctx,
9242 get_session_info_system(),
9250 if (!W_ERROR_IS_OK(result)) {
9254 *r->out.needed = val_size;
9255 *r->out.type = val_type;
9257 if (r->in.offered >= *r->out.needed) {
9258 memcpy(r->out.data, val_data, val_size);
9262 /* retain type when returning WERR_MORE_DATA */
9263 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9265 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9268 /****************************************************************
9269 _spoolss_SetPrinterDataEx
9270 ****************************************************************/
9272 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9273 struct spoolss_SetPrinterDataEx *r)
9275 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9277 WERROR result = WERR_OK;
9278 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9281 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9283 /* From MSDN documentation of SetPrinterDataEx: pass request to
9284 SetPrinterData if key is "PrinterDriverData" */
9287 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9288 OUR_HANDLE(r->in.handle)));
9292 if (Printer->printer_type == SPLHND_SERVER) {
9293 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9294 "Not implemented for server handles yet\n"));
9295 return WERR_INVALID_PARAM;
9298 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9303 * Access check : NT returns "access denied" if you make a
9304 * SetPrinterData call without the necessary privildge.
9305 * we were originally returning OK if nothing changed
9306 * which made Win2k issue **a lot** of SetPrinterData
9307 * when connecting to a printer --jerry
9310 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9311 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9312 "change denied by handle access permissions\n"));
9313 return WERR_ACCESS_DENIED;
9316 result = winreg_get_printer(Printer,
9317 get_session_info_system(),
9319 lp_servicename(snum),
9321 if (!W_ERROR_IS_OK(result)) {
9325 /* check for OID in valuename */
9327 oid_string = strchr(r->in.value_name, ',');
9333 /* save the registry data */
9335 result = winreg_set_printer_dataex(p->mem_ctx,
9336 get_session_info_system(),
9345 if (W_ERROR_IS_OK(result)) {
9346 /* save the OID if one was specified */
9348 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9349 r->in.key_name, SPOOL_OID_KEY);
9351 result = WERR_NOMEM;
9356 * I'm not checking the status here on purpose. Don't know
9357 * if this is right, but I'm returning the status from the
9358 * previous set_printer_dataex() call. I have no idea if
9359 * this is right. --jerry
9361 winreg_set_printer_dataex(p->mem_ctx,
9362 get_session_info_system(),
9368 (uint8_t *) oid_string,
9369 strlen(oid_string) + 1);
9372 result = winreg_printer_update_changeid(p->mem_ctx,
9373 get_session_info_system(),
9375 lp_const_servicename(snum));
9380 talloc_free(pinfo2);
9384 /****************************************************************
9385 _spoolss_DeletePrinterDataEx
9386 ****************************************************************/
9388 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9389 struct spoolss_DeletePrinterDataEx *r)
9391 const char *printer;
9393 WERROR status = WERR_OK;
9394 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9396 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9399 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9400 "Invalid handle (%s:%u:%u).\n",
9401 OUR_HANDLE(r->in.handle)));
9405 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9406 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9407 "printer properties change denied by handle\n"));
9408 return WERR_ACCESS_DENIED;
9411 if (!r->in.value_name || !r->in.key_name) {
9415 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9418 printer = lp_const_servicename(snum);
9420 status = winreg_delete_printer_dataex(p->mem_ctx,
9421 get_session_info_system(),
9426 if (W_ERROR_IS_OK(status)) {
9427 status = winreg_printer_update_changeid(p->mem_ctx,
9428 get_session_info_system(),
9436 /****************************************************************
9437 _spoolss_EnumPrinterKey
9438 ****************************************************************/
9440 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9441 struct spoolss_EnumPrinterKey *r)
9444 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9446 WERROR result = WERR_BADFILE;
9447 const char **array = NULL;
9450 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9453 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9454 OUR_HANDLE(r->in.handle)));
9458 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9462 result = winreg_enum_printer_key(p->mem_ctx,
9463 get_session_info_system(),
9465 lp_const_servicename(snum),
9469 if (!W_ERROR_IS_OK(result)) {
9473 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9474 result = WERR_NOMEM;
9478 *r->out._ndr_size = r->in.offered / 2;
9479 *r->out.needed = blob.length;
9481 if (r->in.offered < *r->out.needed) {
9482 result = WERR_MORE_DATA;
9485 r->out.key_buffer->string_array = array;
9489 if (!W_ERROR_IS_OK(result)) {
9491 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9499 /****************************************************************
9500 _spoolss_DeletePrinterKey
9501 ****************************************************************/
9503 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9504 struct spoolss_DeletePrinterKey *r)
9506 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9509 const char *printer;
9511 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9514 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9515 OUR_HANDLE(r->in.handle)));
9519 /* if keyname == NULL, return error */
9520 if ( !r->in.key_name )
9521 return WERR_INVALID_PARAM;
9523 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9527 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9528 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9529 "printer properties change denied by handle\n"));
9530 return WERR_ACCESS_DENIED;
9533 printer = lp_const_servicename(snum);
9535 /* delete the key and all subkeys */
9536 status = winreg_delete_printer_key(p->mem_ctx,
9537 get_session_info_system(),
9541 if (W_ERROR_IS_OK(status)) {
9542 status = winreg_printer_update_changeid(p->mem_ctx,
9543 get_session_info_system(),
9551 /****************************************************************
9552 _spoolss_EnumPrinterDataEx
9553 ****************************************************************/
9555 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9556 struct spoolss_EnumPrinterDataEx *r)
9559 struct spoolss_PrinterEnumValues *info = NULL;
9560 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9564 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9568 *r->out.info = NULL;
9571 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9572 OUR_HANDLE(r->in.handle)));
9577 * first check for a keyname of NULL or "". Win2k seems to send
9578 * this a lot and we should send back WERR_INVALID_PARAM
9579 * no need to spend time looking up the printer in this case.
9583 if (!strlen(r->in.key_name)) {
9584 result = WERR_INVALID_PARAM;
9588 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9592 /* now look for a match on the key name */
9593 result = winreg_enum_printer_dataex(p->mem_ctx,
9594 get_session_info_system(),
9596 lp_const_servicename(snum),
9600 if (!W_ERROR_IS_OK(result)) {
9604 #if 0 /* FIXME - gd */
9605 /* housekeeping information in the reply */
9607 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9608 * the hand marshalled container size is a multiple
9609 * of 4 bytes for RPC alignment.
9613 needed += 4-(needed % 4);
9616 *r->out.count = count;
9617 *r->out.info = info;
9620 if (!W_ERROR_IS_OK(result)) {
9624 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9625 spoolss_EnumPrinterDataEx,
9628 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9629 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9631 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9634 /****************************************************************************
9635 ****************************************************************************/
9637 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9638 const char *servername,
9639 const char *environment,
9640 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9645 werr = compose_spoolss_server_path(mem_ctx,
9648 SPOOLSS_PRTPROCS_PATH,
9650 if (!W_ERROR_IS_OK(werr)) {
9654 DEBUG(4,("print processor directory: [%s]\n", path));
9656 r->directory_name = path;
9661 /****************************************************************
9662 _spoolss_GetPrintProcessorDirectory
9663 ****************************************************************/
9665 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9666 struct spoolss_GetPrintProcessorDirectory *r)
9669 char *prnproc_share = NULL;
9670 bool prnproc_share_exists = false;
9673 /* that's an [in out] buffer */
9675 if (!r->in.buffer && (r->in.offered != 0)) {
9676 return WERR_INVALID_PARAM;
9679 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9684 /* r->in.level is ignored */
9686 /* We always should reply with a local print processor directory so that
9687 * users are not forced to have a [prnproc$] share on the Samba spoolss
9688 * server, if users decide to do so, lets announce it though - Guenther */
9690 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9691 if (!prnproc_share) {
9695 prnproc_share_exists = true;
9698 result = getprintprocessordirectory_level_1(p->mem_ctx,
9699 prnproc_share_exists ? r->in.server : NULL,
9701 &r->out.info->info1);
9702 if (!W_ERROR_IS_OK(result)) {
9703 TALLOC_FREE(r->out.info);
9707 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9708 r->out.info, r->in.level);
9709 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9711 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9714 /*******************************************************************
9715 ********************************************************************/
9717 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9718 const char *dllname)
9720 enum ndr_err_code ndr_err;
9721 struct spoolss_MonitorUi ui;
9723 ui.dll_name = dllname;
9725 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9726 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9727 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9728 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9730 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9733 /*******************************************************************
9734 Streams the monitor UI DLL name in UNICODE
9735 *******************************************************************/
9737 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9738 struct security_token *token, DATA_BLOB *in,
9739 DATA_BLOB *out, uint32_t *needed)
9741 const char *dllname = "tcpmonui.dll";
9743 *needed = (strlen(dllname)+1) * 2;
9745 if (out->length < *needed) {
9746 return WERR_INSUFFICIENT_BUFFER;
9749 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9756 /*******************************************************************
9757 ********************************************************************/
9759 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9760 struct spoolss_PortData1 *port1,
9761 const DATA_BLOB *buf)
9763 enum ndr_err_code ndr_err;
9764 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9765 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9766 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9767 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9769 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9772 /*******************************************************************
9773 ********************************************************************/
9775 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9776 struct spoolss_PortData2 *port2,
9777 const DATA_BLOB *buf)
9779 enum ndr_err_code ndr_err;
9780 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9781 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9782 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9783 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9785 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9788 /*******************************************************************
9789 Create a new TCP/IP port
9790 *******************************************************************/
9792 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9793 struct security_token *token, DATA_BLOB *in,
9794 DATA_BLOB *out, uint32_t *needed)
9796 struct spoolss_PortData1 port1;
9797 struct spoolss_PortData2 port2;
9798 char *device_uri = NULL;
9801 const char *portname;
9802 const char *hostaddress;
9804 uint32_t port_number;
9807 /* peek for spoolss_PortData version */
9809 if (!in || (in->length < (128 + 4))) {
9810 return WERR_GENERAL_FAILURE;
9813 version = IVAL(in->data, 128);
9819 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9823 portname = port1.portname;
9824 hostaddress = port1.hostaddress;
9825 queue = port1.queue;
9826 protocol = port1.protocol;
9827 port_number = port1.port_number;
9833 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9837 portname = port2.portname;
9838 hostaddress = port2.hostaddress;
9839 queue = port2.queue;
9840 protocol = port2.protocol;
9841 port_number = port2.port_number;
9845 DEBUG(1,("xcvtcp_addport: "
9846 "unknown version of port_data: %d\n", version));
9847 return WERR_UNKNOWN_PORT;
9850 /* create the device URI and call the add_port_hook() */
9853 case PROTOCOL_RAWTCP_TYPE:
9854 device_uri = talloc_asprintf(mem_ctx,
9855 "socket://%s:%d/", hostaddress,
9859 case PROTOCOL_LPR_TYPE:
9860 device_uri = talloc_asprintf(mem_ctx,
9861 "lpr://%s/%s", hostaddress, queue );
9865 return WERR_UNKNOWN_PORT;
9872 return add_port_hook(mem_ctx, token, portname, device_uri);
9875 /*******************************************************************
9876 *******************************************************************/
9878 struct xcv_api_table xcvtcp_cmds[] = {
9879 { "MonitorUI", xcvtcp_monitorui },
9880 { "AddPort", xcvtcp_addport},
9884 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9885 struct security_token *token, const char *command,
9892 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9894 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9895 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9896 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9899 return WERR_BADFUNC;
9902 /*******************************************************************
9903 *******************************************************************/
9904 #if 0 /* don't support management using the "Local Port" monitor */
9906 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9907 struct security_token *token, DATA_BLOB *in,
9908 DATA_BLOB *out, uint32_t *needed)
9910 const char *dllname = "localui.dll";
9912 *needed = (strlen(dllname)+1) * 2;
9914 if (out->length < *needed) {
9915 return WERR_INSUFFICIENT_BUFFER;
9918 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9925 /*******************************************************************
9926 *******************************************************************/
9928 struct xcv_api_table xcvlocal_cmds[] = {
9929 { "MonitorUI", xcvlocal_monitorui },
9933 struct xcv_api_table xcvlocal_cmds[] = {
9940 /*******************************************************************
9941 *******************************************************************/
9943 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9944 struct security_token *token, const char *command,
9945 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9950 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9952 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9953 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9954 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9956 return WERR_BADFUNC;
9959 /****************************************************************
9961 ****************************************************************/
9963 WERROR _spoolss_XcvData(struct pipes_struct *p,
9964 struct spoolss_XcvData *r)
9966 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9967 DATA_BLOB out_data = data_blob_null;
9971 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9972 OUR_HANDLE(r->in.handle)));
9976 /* Has to be a handle to the TCP/IP port monitor */
9978 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9979 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9983 /* requires administrative access to the server */
9985 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9986 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9987 return WERR_ACCESS_DENIED;
9990 /* Allocate the outgoing buffer */
9992 if (r->in.out_data_size) {
9993 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9994 if (out_data.data == NULL) {
9999 switch ( Printer->printer_type ) {
10000 case SPLHND_PORTMON_TCP:
10001 werror = process_xcvtcp_command(p->mem_ctx,
10002 p->session_info->security_token,
10003 r->in.function_name,
10004 &r->in.in_data, &out_data,
10007 case SPLHND_PORTMON_LOCAL:
10008 werror = process_xcvlocal_command(p->mem_ctx,
10009 p->session_info->security_token,
10010 r->in.function_name,
10011 &r->in.in_data, &out_data,
10015 werror = WERR_INVALID_PRINT_MONITOR;
10018 if (!W_ERROR_IS_OK(werror)) {
10022 *r->out.status_code = 0;
10024 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10025 memcpy(r->out.out_data, out_data.data,
10026 MIN(r->in.out_data_size, out_data.length));
10032 /****************************************************************
10033 _spoolss_AddPrintProcessor
10034 ****************************************************************/
10036 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10037 struct spoolss_AddPrintProcessor *r)
10039 /* for now, just indicate success and ignore the add. We'll
10040 automatically set the winprint processor for printer
10041 entries later. Used to debug the LexMark Optra S 1855 PCL
10047 /****************************************************************
10049 ****************************************************************/
10051 WERROR _spoolss_AddPort(struct pipes_struct *p,
10052 struct spoolss_AddPort *r)
10054 /* do what w2k3 does */
10056 return WERR_NOT_SUPPORTED;
10059 /****************************************************************
10060 _spoolss_GetPrinterDriver
10061 ****************************************************************/
10063 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10064 struct spoolss_GetPrinterDriver *r)
10066 p->rng_fault_state = true;
10067 return WERR_NOT_SUPPORTED;
10070 /****************************************************************
10071 _spoolss_ReadPrinter
10072 ****************************************************************/
10074 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10075 struct spoolss_ReadPrinter *r)
10077 p->rng_fault_state = true;
10078 return WERR_NOT_SUPPORTED;
10081 /****************************************************************
10082 _spoolss_WaitForPrinterChange
10083 ****************************************************************/
10085 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10086 struct spoolss_WaitForPrinterChange *r)
10088 p->rng_fault_state = true;
10089 return WERR_NOT_SUPPORTED;
10092 /****************************************************************
10093 _spoolss_ConfigurePort
10094 ****************************************************************/
10096 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10097 struct spoolss_ConfigurePort *r)
10099 p->rng_fault_state = true;
10100 return WERR_NOT_SUPPORTED;
10103 /****************************************************************
10104 _spoolss_DeletePort
10105 ****************************************************************/
10107 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10108 struct spoolss_DeletePort *r)
10110 p->rng_fault_state = true;
10111 return WERR_NOT_SUPPORTED;
10114 /****************************************************************
10115 _spoolss_CreatePrinterIC
10116 ****************************************************************/
10118 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10119 struct spoolss_CreatePrinterIC *r)
10121 p->rng_fault_state = true;
10122 return WERR_NOT_SUPPORTED;
10125 /****************************************************************
10126 _spoolss_PlayGDIScriptOnPrinterIC
10127 ****************************************************************/
10129 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10130 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10132 p->rng_fault_state = true;
10133 return WERR_NOT_SUPPORTED;
10136 /****************************************************************
10137 _spoolss_DeletePrinterIC
10138 ****************************************************************/
10140 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10141 struct spoolss_DeletePrinterIC *r)
10143 p->rng_fault_state = true;
10144 return WERR_NOT_SUPPORTED;
10147 /****************************************************************
10148 _spoolss_AddPrinterConnection
10149 ****************************************************************/
10151 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10152 struct spoolss_AddPrinterConnection *r)
10154 p->rng_fault_state = true;
10155 return WERR_NOT_SUPPORTED;
10158 /****************************************************************
10159 _spoolss_DeletePrinterConnection
10160 ****************************************************************/
10162 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10163 struct spoolss_DeletePrinterConnection *r)
10165 p->rng_fault_state = true;
10166 return WERR_NOT_SUPPORTED;
10169 /****************************************************************
10170 _spoolss_PrinterMessageBox
10171 ****************************************************************/
10173 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10174 struct spoolss_PrinterMessageBox *r)
10176 p->rng_fault_state = true;
10177 return WERR_NOT_SUPPORTED;
10180 /****************************************************************
10181 _spoolss_AddMonitor
10182 ****************************************************************/
10184 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10185 struct spoolss_AddMonitor *r)
10187 p->rng_fault_state = true;
10188 return WERR_NOT_SUPPORTED;
10191 /****************************************************************
10192 _spoolss_DeleteMonitor
10193 ****************************************************************/
10195 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10196 struct spoolss_DeleteMonitor *r)
10198 p->rng_fault_state = true;
10199 return WERR_NOT_SUPPORTED;
10202 /****************************************************************
10203 _spoolss_DeletePrintProcessor
10204 ****************************************************************/
10206 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10207 struct spoolss_DeletePrintProcessor *r)
10209 p->rng_fault_state = true;
10210 return WERR_NOT_SUPPORTED;
10213 /****************************************************************
10214 _spoolss_AddPrintProvidor
10215 ****************************************************************/
10217 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10218 struct spoolss_AddPrintProvidor *r)
10220 p->rng_fault_state = true;
10221 return WERR_NOT_SUPPORTED;
10224 /****************************************************************
10225 _spoolss_DeletePrintProvidor
10226 ****************************************************************/
10228 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10229 struct spoolss_DeletePrintProvidor *r)
10231 p->rng_fault_state = true;
10232 return WERR_NOT_SUPPORTED;
10235 /****************************************************************
10236 _spoolss_FindFirstPrinterChangeNotification
10237 ****************************************************************/
10239 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10240 struct spoolss_FindFirstPrinterChangeNotification *r)
10242 p->rng_fault_state = true;
10243 return WERR_NOT_SUPPORTED;
10246 /****************************************************************
10247 _spoolss_FindNextPrinterChangeNotification
10248 ****************************************************************/
10250 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10251 struct spoolss_FindNextPrinterChangeNotification *r)
10253 p->rng_fault_state = true;
10254 return WERR_NOT_SUPPORTED;
10257 /****************************************************************
10258 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10259 ****************************************************************/
10261 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10262 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10264 p->rng_fault_state = true;
10265 return WERR_NOT_SUPPORTED;
10268 /****************************************************************
10269 _spoolss_ReplyOpenPrinter
10270 ****************************************************************/
10272 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10273 struct spoolss_ReplyOpenPrinter *r)
10275 p->rng_fault_state = true;
10276 return WERR_NOT_SUPPORTED;
10279 /****************************************************************
10280 _spoolss_RouterReplyPrinter
10281 ****************************************************************/
10283 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10284 struct spoolss_RouterReplyPrinter *r)
10286 p->rng_fault_state = true;
10287 return WERR_NOT_SUPPORTED;
10290 /****************************************************************
10291 _spoolss_ReplyClosePrinter
10292 ****************************************************************/
10294 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10295 struct spoolss_ReplyClosePrinter *r)
10297 p->rng_fault_state = true;
10298 return WERR_NOT_SUPPORTED;
10301 /****************************************************************
10303 ****************************************************************/
10305 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10306 struct spoolss_AddPortEx *r)
10308 p->rng_fault_state = true;
10309 return WERR_NOT_SUPPORTED;
10312 /****************************************************************
10313 _spoolss_RouterFindFirstPrinterChangeNotification
10314 ****************************************************************/
10316 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10317 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10319 p->rng_fault_state = true;
10320 return WERR_NOT_SUPPORTED;
10323 /****************************************************************
10324 _spoolss_SpoolerInit
10325 ****************************************************************/
10327 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10328 struct spoolss_SpoolerInit *r)
10330 p->rng_fault_state = true;
10331 return WERR_NOT_SUPPORTED;
10334 /****************************************************************
10335 _spoolss_ResetPrinterEx
10336 ****************************************************************/
10338 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10339 struct spoolss_ResetPrinterEx *r)
10341 p->rng_fault_state = true;
10342 return WERR_NOT_SUPPORTED;
10345 /****************************************************************
10346 _spoolss_RouterReplyPrinterEx
10347 ****************************************************************/
10349 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10350 struct spoolss_RouterReplyPrinterEx *r)
10352 p->rng_fault_state = true;
10353 return WERR_NOT_SUPPORTED;
10356 /****************************************************************
10358 ****************************************************************/
10360 WERROR _spoolss_44(struct pipes_struct *p,
10361 struct spoolss_44 *r)
10363 p->rng_fault_state = true;
10364 return WERR_NOT_SUPPORTED;
10367 /****************************************************************
10369 ****************************************************************/
10371 WERROR _spoolss_SetPort(struct pipes_struct *p,
10372 struct spoolss_SetPort *r)
10374 p->rng_fault_state = true;
10375 return WERR_NOT_SUPPORTED;
10378 /****************************************************************
10380 ****************************************************************/
10382 WERROR _spoolss_4a(struct pipes_struct *p,
10383 struct spoolss_4a *r)
10385 p->rng_fault_state = true;
10386 return WERR_NOT_SUPPORTED;
10389 /****************************************************************
10391 ****************************************************************/
10393 WERROR _spoolss_4b(struct pipes_struct *p,
10394 struct spoolss_4b *r)
10396 p->rng_fault_state = true;
10397 return WERR_NOT_SUPPORTED;
10400 /****************************************************************
10402 ****************************************************************/
10404 WERROR _spoolss_4c(struct pipes_struct *p,
10405 struct spoolss_4c *r)
10407 p->rng_fault_state = true;
10408 return WERR_NOT_SUPPORTED;
10411 /****************************************************************
10413 ****************************************************************/
10415 WERROR _spoolss_53(struct pipes_struct *p,
10416 struct spoolss_53 *r)
10418 p->rng_fault_state = true;
10419 return WERR_NOT_SUPPORTED;
10422 /****************************************************************
10423 _spoolss_AddPerMachineConnection
10424 ****************************************************************/
10426 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10427 struct spoolss_AddPerMachineConnection *r)
10429 p->rng_fault_state = true;
10430 return WERR_NOT_SUPPORTED;
10433 /****************************************************************
10434 _spoolss_DeletePerMachineConnection
10435 ****************************************************************/
10437 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10438 struct spoolss_DeletePerMachineConnection *r)
10440 p->rng_fault_state = true;
10441 return WERR_NOT_SUPPORTED;
10444 /****************************************************************
10445 _spoolss_EnumPerMachineConnections
10446 ****************************************************************/
10448 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10449 struct spoolss_EnumPerMachineConnections *r)
10451 p->rng_fault_state = true;
10452 return WERR_NOT_SUPPORTED;
10455 /****************************************************************
10457 ****************************************************************/
10459 WERROR _spoolss_5a(struct pipes_struct *p,
10460 struct spoolss_5a *r)
10462 p->rng_fault_state = true;
10463 return WERR_NOT_SUPPORTED;
10466 /****************************************************************
10468 ****************************************************************/
10470 WERROR _spoolss_5b(struct pipes_struct *p,
10471 struct spoolss_5b *r)
10473 p->rng_fault_state = true;
10474 return WERR_NOT_SUPPORTED;
10477 /****************************************************************
10479 ****************************************************************/
10481 WERROR _spoolss_5c(struct pipes_struct *p,
10482 struct spoolss_5c *r)
10484 p->rng_fault_state = true;
10485 return WERR_NOT_SUPPORTED;
10488 /****************************************************************
10490 ****************************************************************/
10492 WERROR _spoolss_5d(struct pipes_struct *p,
10493 struct spoolss_5d *r)
10495 p->rng_fault_state = true;
10496 return WERR_NOT_SUPPORTED;
10499 /****************************************************************
10501 ****************************************************************/
10503 WERROR _spoolss_5e(struct pipes_struct *p,
10504 struct spoolss_5e *r)
10506 p->rng_fault_state = true;
10507 return WERR_NOT_SUPPORTED;
10510 /****************************************************************
10512 ****************************************************************/
10514 WERROR _spoolss_5f(struct pipes_struct *p,
10515 struct spoolss_5f *r)
10517 p->rng_fault_state = true;
10518 return WERR_NOT_SUPPORTED;
10521 /****************************************************************
10523 ****************************************************************/
10525 WERROR _spoolss_60(struct pipes_struct *p,
10526 struct spoolss_60 *r)
10528 p->rng_fault_state = true;
10529 return WERR_NOT_SUPPORTED;
10532 /****************************************************************
10534 ****************************************************************/
10536 WERROR _spoolss_61(struct pipes_struct *p,
10537 struct spoolss_61 *r)
10539 p->rng_fault_state = true;
10540 return WERR_NOT_SUPPORTED;
10543 /****************************************************************
10545 ****************************************************************/
10547 WERROR _spoolss_62(struct pipes_struct *p,
10548 struct spoolss_62 *r)
10550 p->rng_fault_state = true;
10551 return WERR_NOT_SUPPORTED;
10554 /****************************************************************
10556 ****************************************************************/
10558 WERROR _spoolss_63(struct pipes_struct *p,
10559 struct spoolss_63 *r)
10561 p->rng_fault_state = true;
10562 return WERR_NOT_SUPPORTED;
10565 /****************************************************************
10567 ****************************************************************/
10569 WERROR _spoolss_64(struct pipes_struct *p,
10570 struct spoolss_64 *r)
10572 p->rng_fault_state = true;
10573 return WERR_NOT_SUPPORTED;
10576 /****************************************************************
10578 ****************************************************************/
10580 WERROR _spoolss_65(struct pipes_struct *p,
10581 struct spoolss_65 *r)
10583 p->rng_fault_state = true;
10584 return WERR_NOT_SUPPORTED;
10587 /****************************************************************
10588 _spoolss_GetCorePrinterDrivers
10589 ****************************************************************/
10591 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10592 struct spoolss_GetCorePrinterDrivers *r)
10594 p->rng_fault_state = true;
10595 return WERR_NOT_SUPPORTED;
10598 /****************************************************************
10600 ****************************************************************/
10602 WERROR _spoolss_67(struct pipes_struct *p,
10603 struct spoolss_67 *r)
10605 p->rng_fault_state = true;
10606 return WERR_NOT_SUPPORTED;
10609 /****************************************************************
10610 _spoolss_GetPrinterDriverPackagePath
10611 ****************************************************************/
10613 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10614 struct spoolss_GetPrinterDriverPackagePath *r)
10616 p->rng_fault_state = true;
10617 return WERR_NOT_SUPPORTED;
10620 /****************************************************************
10622 ****************************************************************/
10624 WERROR _spoolss_69(struct pipes_struct *p,
10625 struct spoolss_69 *r)
10627 p->rng_fault_state = true;
10628 return WERR_NOT_SUPPORTED;
10631 /****************************************************************
10633 ****************************************************************/
10635 WERROR _spoolss_6a(struct pipes_struct *p,
10636 struct spoolss_6a *r)
10638 p->rng_fault_state = true;
10639 return WERR_NOT_SUPPORTED;
10642 /****************************************************************
10644 ****************************************************************/
10646 WERROR _spoolss_6b(struct pipes_struct *p,
10647 struct spoolss_6b *r)
10649 p->rng_fault_state = true;
10650 return WERR_NOT_SUPPORTED;
10653 /****************************************************************
10655 ****************************************************************/
10657 WERROR _spoolss_6c(struct pipes_struct *p,
10658 struct spoolss_6c *r)
10660 p->rng_fault_state = true;
10661 return WERR_NOT_SUPPORTED;
10664 /****************************************************************
10666 ****************************************************************/
10668 WERROR _spoolss_6d(struct pipes_struct *p,
10669 struct spoolss_6d *r)
10671 p->rng_fault_state = true;
10672 return WERR_NOT_SUPPORTED;