2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "librpc/gen_ndr/messaging.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
44 #include "../librpc/gen_ndr/netlogon.h"
46 #include "printing/notify.h"
48 #include "../libcli/registry/util_reg.h"
50 /* macros stolen from s4 spoolss server */
51 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
52 ((info)?ndr_size_##fn(info, level, 0):0)
54 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
55 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
57 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
58 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
60 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
63 #define DBGC_CLASS DBGC_RPC_SRV
65 #ifndef MAX_OPEN_PRINTER_EXS
66 #define MAX_OPEN_PRINTER_EXS 50
69 struct notify_back_channel;
71 /* structure to store the printer handles */
72 /* and a reference to what it's pointing to */
73 /* and the notify info asked about */
74 /* that's the central struct */
75 struct printer_handle {
76 struct printer_handle *prev, *next;
77 bool document_started;
79 uint32 jobid; /* jobid in printing backend */
81 const char *servername;
84 uint32 access_granted;
90 struct spoolss_NotifyOption *option;
91 struct policy_handle cli_hnd;
92 struct notify_back_channel *cli_chan;
94 /* are we in a FindNextPrinterChangeNotify() call? */
96 struct messaging_context *msg_ctx;
103 /* devmode sent in the OpenPrinter() call */
104 struct spoolss_DeviceMode *devmode;
106 /* TODO cache the printer info2 structure */
107 struct spoolss_PrinterInfo2 *info2;
111 static struct printer_handle *printers_list;
113 struct printer_session_counter {
114 struct printer_session_counter *next;
115 struct printer_session_counter *prev;
121 static struct printer_session_counter *counter_list;
123 struct notify_back_channel {
124 struct notify_back_channel *prev, *next;
126 /* associated client */
127 struct sockaddr_storage client_address;
129 /* print notify back-channel pipe handle*/
130 struct rpc_pipe_client *cli_pipe;
131 struct dcerpc_binding_handle *binding_handle;
132 uint32_t active_connections;
135 static struct notify_back_channel *back_channels;
137 /* Map generic permissions to printer object specific permissions */
139 const struct standard_mapping printer_std_mapping = {
146 /* Map generic permissions to print server object specific permissions */
148 const struct standard_mapping printserver_std_mapping = {
155 /* API table for Xcv Monitor functions */
157 struct xcv_api_table {
159 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
162 static void prune_printername_cache(void);
164 /********************************************************************
165 * Canonicalize servername.
166 ********************************************************************/
168 static const char *canon_servername(const char *servername)
170 const char *pservername = servername;
171 while (*pservername == '\\') {
177 /* translate between internal status numbers and NT status numbers */
178 static int nt_printj_status(int v)
184 return JOB_STATUS_PAUSED;
186 return JOB_STATUS_SPOOLING;
188 return JOB_STATUS_PRINTING;
190 return JOB_STATUS_ERROR;
192 return JOB_STATUS_DELETING;
194 return JOB_STATUS_OFFLINE;
196 return JOB_STATUS_PAPEROUT;
198 return JOB_STATUS_PRINTED;
200 return JOB_STATUS_DELETED;
202 return JOB_STATUS_BLOCKED_DEVQ;
203 case LPQ_USER_INTERVENTION:
204 return JOB_STATUS_USER_INTERVENTION;
209 static int nt_printq_status(int v)
213 return PRINTER_STATUS_PAUSED;
222 /***************************************************************************
223 Disconnect from the client
224 ****************************************************************************/
226 static void srv_spoolss_replycloseprinter(int snum,
227 struct printer_handle *prn_hnd)
233 * Tell the specific printing tdb we no longer want messages for this printer
234 * by deregistering our PID.
237 if (!print_notify_deregister_pid(snum)) {
238 DEBUG(0, ("Failed to register our pid for printer %s\n",
239 lp_const_servicename(snum)));
242 /* weird if the test succeeds !!! */
243 if (prn_hnd->notify.cli_chan == NULL ||
244 prn_hnd->notify.cli_chan->active_connections == 0) {
245 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
246 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
247 TALLOC_FREE(prn_hnd->notify.cli_chan);
251 status = dcerpc_spoolss_ReplyClosePrinter(
252 prn_hnd->notify.cli_chan->binding_handle,
254 &prn_hnd->notify.cli_hnd,
256 if (!NT_STATUS_IS_OK(status)) {
257 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
259 result = ntstatus_to_werror(status);
260 } else if (!W_ERROR_IS_OK(result)) {
261 DEBUG(0, ("reply_close_printer failed [%s].\n",
262 win_errstr(result)));
265 /* if it's the last connection, deconnect the IPC$ share */
266 if (prn_hnd->notify.cli_chan->active_connections == 1) {
268 prn_hnd->notify.cli_chan->binding_handle = NULL;
269 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
270 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
271 TALLOC_FREE(prn_hnd->notify.cli_chan);
273 if (prn_hnd->notify.msg_ctx != NULL) {
274 messaging_deregister(prn_hnd->notify.msg_ctx,
275 MSG_PRINTER_NOTIFY2, NULL);
278 * Tell the serverid.tdb we're no longer
279 * interested in printer notify messages.
282 serverid_register_msg_flags(
283 messaging_server_id(prn_hnd->notify.msg_ctx),
284 false, FLAG_MSG_PRINT_NOTIFY);
288 if (prn_hnd->notify.cli_chan) {
289 prn_hnd->notify.cli_chan->active_connections--;
293 /****************************************************************************
294 Functions to free a printer entry datastruct.
295 ****************************************************************************/
297 static int printer_entry_destructor(struct printer_handle *Printer)
299 if (Printer->notify.cli_chan != NULL &&
300 Printer->notify.cli_chan->active_connections > 0) {
303 switch(Printer->printer_type) {
305 srv_spoolss_replycloseprinter(snum, Printer);
309 snum = print_queue_snum(Printer->sharename);
311 srv_spoolss_replycloseprinter(snum, Printer);
319 Printer->notify.flags=0;
320 Printer->notify.options=0;
321 Printer->notify.localmachine[0]='\0';
322 Printer->notify.printerlocal=0;
323 TALLOC_FREE(Printer->notify.option);
324 TALLOC_FREE(Printer->devmode);
326 /* Remove from the internal list. */
327 DLIST_REMOVE(printers_list, Printer);
331 /****************************************************************************
332 find printer index by handle
333 ****************************************************************************/
335 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
336 struct policy_handle *hnd)
338 struct printer_handle *find_printer = NULL;
340 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
341 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
348 /****************************************************************************
349 Close printer index by handle.
350 ****************************************************************************/
352 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
354 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
362 close_policy_hnd(p, hnd);
367 /****************************************************************************
368 Delete a printer given a handle.
369 ****************************************************************************/
371 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
372 const char *sharename,
373 struct messaging_context *msg_ctx)
375 char *cmd = lp_deleteprinter_cmd();
376 char *command = NULL;
378 bool is_print_op = false;
380 /* can't fail if we don't try */
385 command = talloc_asprintf(ctx,
392 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
394 DEBUG(10,("Running [%s]\n", command));
396 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
401 if ( (ret = smbrun(command, NULL)) == 0 ) {
402 /* Tell everyone we updated smb.conf. */
403 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
409 /********** END SePrintOperatorPrivlege BLOCK **********/
411 DEBUGADD(10,("returned [%d]\n", ret));
413 TALLOC_FREE(command);
416 return WERR_BADFID; /* What to return here? */
418 /* go ahead and re-read the services immediately */
420 reload_services(msg_ctx, -1, false);
423 if ( lp_servicenumber( sharename ) >= 0 )
424 return WERR_ACCESS_DENIED;
429 /****************************************************************************
430 Delete a printer given a handle.
431 ****************************************************************************/
433 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
435 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
439 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
445 * It turns out that Windows allows delete printer on a handle
446 * opened by an admin user, then used on a pipe handle created
447 * by an anonymous user..... but they're working on security.... riiight !
451 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
452 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
453 return WERR_ACCESS_DENIED;
456 /* this does not need a become root since the access check has been
457 done on the handle already */
459 result = winreg_delete_printer_key(p->mem_ctx,
460 get_session_info_system(),
464 if (!W_ERROR_IS_OK(result)) {
465 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
469 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
470 Printer->sharename, p->msg_ctx);
471 if (!W_ERROR_IS_OK(result)) {
474 prune_printername_cache();
478 /****************************************************************************
479 Return the snum of a printer corresponding to an handle.
480 ****************************************************************************/
482 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
483 int *number, struct share_params **params)
485 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
488 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
493 switch (Printer->printer_type) {
495 DEBUG(4,("short name:%s\n", Printer->sharename));
496 *number = print_queue_snum(Printer->sharename);
497 return (*number != -1);
505 /****************************************************************************
506 Set printer handle type.
507 Check if it's \\server or \\server\printer
508 ****************************************************************************/
510 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
512 DEBUG(3,("Setting printer type=%s\n", handlename));
514 /* it's a print server */
515 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
516 DEBUGADD(4,("Printer is a print server\n"));
517 Printer->printer_type = SPLHND_SERVER;
519 /* it's a printer (set_printer_hnd_name() will handle port monitors */
521 DEBUGADD(4,("Printer is a printer\n"));
522 Printer->printer_type = SPLHND_PRINTER;
528 static void prune_printername_cache_fn(const char *key, const char *value,
529 time_t timeout, void *private_data)
534 static void prune_printername_cache(void)
536 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
539 /****************************************************************************
540 Set printer handle name.. Accept names like \\server, \\server\printer,
541 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
542 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
543 XcvDataPort() interface.
544 ****************************************************************************/
546 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
547 const struct auth_serversupplied_info *session_info,
548 struct messaging_context *msg_ctx,
549 struct printer_handle *Printer,
550 const char *handlename)
553 int n_services=lp_numservices();
555 const char *printername;
556 const char *servername = NULL;
559 struct spoolss_PrinterInfo2 *info2 = NULL;
564 * Hopefully nobody names his printers like this. Maybe \ or ,
565 * are illegal in printer names even?
567 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
571 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
572 (unsigned long)strlen(handlename)));
574 aprinter = CONST_DISCARD(char *, handlename);
575 if ( *handlename == '\\' ) {
576 servername = canon_servername(handlename);
577 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
581 if (!is_myname_or_ipaddr(servername)) {
582 return WERR_INVALID_PRINTER_NAME;
584 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
585 if (Printer->servername == NULL) {
590 if (Printer->printer_type == SPLHND_SERVER) {
594 if (Printer->printer_type != SPLHND_PRINTER) {
595 return WERR_INVALID_HANDLE;
598 DEBUGADD(5, ("searching for [%s]\n", aprinter));
600 p = strchr(aprinter, ',');
607 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
609 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
615 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
618 /* check for the Port Monitor Interface */
619 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
620 Printer->printer_type = SPLHND_PORTMON_TCP;
621 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
624 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
625 Printer->printer_type = SPLHND_PORTMON_LOCAL;
626 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
631 * With hundreds of printers, the "for" loop iterating all
632 * shares can be quite expensive, as it is done on every
633 * OpenPrinter. The loop maps "aprinter" to "sname", the
634 * result of which we cache in gencache.
637 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
639 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
641 found = (strcmp(tmp, printer_not_found) != 0);
643 DEBUG(4, ("Printer %s not found\n", aprinter));
645 return WERR_INVALID_PRINTER_NAME;
651 /* Search all sharenames first as this is easier than pulling
652 the printer_info_2 off of disk. Don't use find_service() since
653 that calls out to map_username() */
655 /* do another loop to look for printernames */
656 for (snum = 0; !found && snum < n_services; snum++) {
657 const char *printer = lp_const_servicename(snum);
659 /* no point going on if this is not a printer */
660 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
664 /* ignore [printers] share */
665 if (strequal(printer, "printers")) {
669 fstrcpy(sname, printer);
670 if (strequal(aprinter, printer)) {
675 /* no point looking up the printer object if
676 we aren't allowing printername != sharename */
677 if (lp_force_printername(snum)) {
681 result = winreg_get_printer(mem_ctx,
686 if ( !W_ERROR_IS_OK(result) ) {
687 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
688 sname, win_errstr(result)));
692 printername = strrchr(info2->printername, '\\');
693 if (printername == NULL) {
694 printername = info2->printername;
699 if (strequal(printername, aprinter)) {
704 DEBUGADD(10, ("printername: %s\n", printername));
710 if (cache_key != NULL) {
711 gencache_set(cache_key, printer_not_found,
713 TALLOC_FREE(cache_key);
715 DEBUGADD(4,("Printer not found\n"));
716 return WERR_INVALID_PRINTER_NAME;
719 if (cache_key != NULL) {
720 gencache_set(cache_key, sname, time(NULL)+300);
721 TALLOC_FREE(cache_key);
724 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
726 fstrcpy(Printer->sharename, sname);
731 /****************************************************************************
732 Find first available printer slot. creates a printer handle for you.
733 ****************************************************************************/
735 static WERROR open_printer_hnd(struct pipes_struct *p,
736 struct policy_handle *hnd,
738 uint32_t access_granted)
740 struct printer_handle *new_printer;
743 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
745 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
746 if (new_printer == NULL) {
749 talloc_set_destructor(new_printer, printer_entry_destructor);
751 /* This also steals the printer_handle on the policy_handle */
752 if (!create_policy_hnd(p, hnd, new_printer)) {
753 TALLOC_FREE(new_printer);
754 return WERR_INVALID_HANDLE;
757 /* Add to the internal list. */
758 DLIST_ADD(printers_list, new_printer);
760 new_printer->notify.option=NULL;
762 if (!set_printer_hnd_printertype(new_printer, name)) {
763 close_printer_handle(p, hnd);
764 return WERR_INVALID_HANDLE;
767 result = set_printer_hnd_name(p->mem_ctx,
768 get_session_info_system(),
771 if (!W_ERROR_IS_OK(result)) {
772 close_printer_handle(p, hnd);
776 new_printer->access_granted = access_granted;
778 DEBUG(5, ("%d printer handles active\n",
779 (int)num_pipe_handles(p)));
784 /***************************************************************************
785 check to see if the client motify handle is monitoring the notification
786 given by (notify_type, notify_field).
787 **************************************************************************/
789 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
790 uint16_t notify_field)
795 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
796 uint16_t notify_field)
798 struct spoolss_NotifyOption *option = p->notify.option;
802 * Flags should always be zero when the change notify
803 * is registered by the client's spooler. A user Win32 app
804 * might use the flags though instead of the NOTIFY_OPTION_INFO
813 return is_monitoring_event_flags(
814 p->notify.flags, notify_type, notify_field);
816 for (i = 0; i < option->count; i++) {
818 /* Check match for notify_type */
820 if (option->types[i].type != notify_type)
823 /* Check match for field */
825 for (j = 0; j < option->types[i].count; j++) {
826 if (option->types[i].fields[j].field == notify_field) {
832 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
833 p->servername, p->sharename, notify_type, notify_field));
838 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
839 _data->data.integer[0] = _integer; \
840 _data->data.integer[1] = 0;
843 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
844 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
845 if (!_data->data.string.string) {\
846 _data->data.string.size = 0; \
848 _data->data.string.size = strlen_m_term(_p) * 2;
850 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
851 _data->data.devmode.devmode = _devmode;
853 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
854 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
855 if (!_data->data.sd.sd) { \
856 _data->data.sd.sd_size = 0; \
858 _data->data.sd.sd_size = \
859 ndr_size_security_descriptor(_data->data.sd.sd, 0);
861 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
866 struct spoolss_Time st;
870 if (!init_systemtime(&st, t)) {
874 p = talloc_array(mem_ctx, char, len);
880 * Systemtime must be linearized as a set of UINT16's.
881 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
884 SSVAL(p, 0, st.year);
885 SSVAL(p, 2, st.month);
886 SSVAL(p, 4, st.day_of_week);
888 SSVAL(p, 8, st.hour);
889 SSVAL(p, 10, st.minute);
890 SSVAL(p, 12, st.second);
891 SSVAL(p, 14, st.millisecond);
897 /* Convert a notification message to a struct spoolss_Notify */
899 static void notify_one_value(struct spoolss_notify_msg *msg,
900 struct spoolss_Notify *data,
903 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
906 static void notify_string(struct spoolss_notify_msg *msg,
907 struct spoolss_Notify *data,
910 /* The length of the message includes the trailing \0 */
912 data->data.string.size = msg->len * 2;
913 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
914 if (!data->data.string.string) {
915 data->data.string.size = 0;
920 static void notify_system_time(struct spoolss_notify_msg *msg,
921 struct spoolss_Notify *data,
924 data->data.string.string = NULL;
925 data->data.string.size = 0;
927 if (msg->len != sizeof(time_t)) {
928 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
933 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
934 &data->data.string.string,
935 &data->data.string.size);
938 struct notify2_message_table {
940 void (*fn)(struct spoolss_notify_msg *msg,
941 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
944 static struct notify2_message_table printer_notify_table[] = {
945 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
946 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
947 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
948 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
949 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
950 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
951 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
952 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
953 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
954 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
955 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
956 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
957 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
958 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
959 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
960 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
961 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
962 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
963 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
966 static struct notify2_message_table job_notify_table[] = {
967 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
968 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
969 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
970 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
971 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
972 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
973 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
974 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
975 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
976 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
977 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
978 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
979 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
980 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
981 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
982 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
983 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
984 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
985 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
986 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
987 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
988 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
989 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
990 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
994 /***********************************************************************
995 Allocate talloc context for container object
996 **********************************************************************/
998 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1003 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1008 /***********************************************************************
1009 release all allocated memory and zero out structure
1010 **********************************************************************/
1012 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1018 talloc_destroy(ctr->ctx);
1025 /***********************************************************************
1026 **********************************************************************/
1028 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1036 /***********************************************************************
1037 **********************************************************************/
1039 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1041 if ( !ctr || !ctr->msg_groups )
1044 if ( idx >= ctr->num_groups )
1047 return &ctr->msg_groups[idx];
1051 /***********************************************************************
1052 How many groups of change messages do we have ?
1053 **********************************************************************/
1055 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1060 return ctr->num_groups;
1063 /***********************************************************************
1064 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1065 **********************************************************************/
1067 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1069 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1070 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1071 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1077 /* loop over all groups looking for a matching printer name */
1079 for ( i=0; i<ctr->num_groups; i++ ) {
1080 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1084 /* add a new group? */
1086 if ( i == ctr->num_groups ) {
1089 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1090 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1093 ctr->msg_groups = groups;
1095 /* clear the new entry and set the printer name */
1097 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1098 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1101 /* add the change messages; 'i' is the correct index now regardless */
1103 msg_grp = &ctr->msg_groups[i];
1105 msg_grp->num_msgs++;
1107 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1108 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1111 msg_grp->msgs = msg_list;
1113 new_slot = msg_grp->num_msgs-1;
1114 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1116 /* need to allocate own copy of data */
1118 if ( msg->len != 0 )
1119 msg_grp->msgs[new_slot].notify.data = (char *)
1120 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1122 return ctr->num_groups;
1125 static void construct_info_data(struct spoolss_Notify *info_data,
1126 enum spoolss_NotifyType type,
1127 uint16_t field, int id);
1129 /***********************************************************************
1130 Send a change notication message on all handles which have a call
1132 **********************************************************************/
1134 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1135 struct printer_handle *prn_hnd,
1136 SPOOLSS_NOTIFY_MSG *messages,
1138 struct spoolss_Notify **_notifies,
1141 struct spoolss_Notify *notifies;
1142 SPOOLSS_NOTIFY_MSG *msg;
1147 notifies = talloc_zero_array(mem_ctx,
1148 struct spoolss_Notify, num_msgs);
1153 for (i = 0; i < num_msgs; i++) {
1157 /* Are we monitoring this event? */
1159 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1163 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1164 "for printer [%s]\n",
1165 msg->type, msg->field, prn_hnd->sharename));
1168 * if the is a printer notification handle and not a job
1169 * notification type, then set the id to 0.
1170 * Otherwise just use what was specified in the message.
1172 * When registering change notification on a print server
1173 * handle we always need to send back the id (snum) matching
1174 * the printer for which the change took place.
1175 * For change notify registered on a printer handle,
1176 * this does not matter and the id should be 0.
1181 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1182 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1188 /* Convert unix jobid to smb jobid */
1190 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1191 id = sysjob_to_jobid(msg->id);
1194 DEBUG(3, ("no such unix jobid %d\n",
1200 construct_info_data(¬ifies[count],
1201 msg->type, msg->field, id);
1204 case PRINTER_NOTIFY_TYPE:
1205 if (printer_notify_table[msg->field].fn) {
1206 printer_notify_table[msg->field].fn(msg,
1207 ¬ifies[count], mem_ctx);
1211 case JOB_NOTIFY_TYPE:
1212 if (job_notify_table[msg->field].fn) {
1213 job_notify_table[msg->field].fn(msg,
1214 ¬ifies[count], mem_ctx);
1219 DEBUG(5, ("Unknown notification type %d\n",
1227 *_notifies = notifies;
1233 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1234 struct printer_handle *prn_hnd,
1235 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1237 struct spoolss_Notify *notifies;
1239 union spoolss_ReplyPrinterInfo info;
1240 struct spoolss_NotifyInfo info0;
1241 uint32_t reply_result;
1246 /* Is there notification on this handle? */
1247 if (prn_hnd->notify.cli_chan == NULL ||
1248 prn_hnd->notify.cli_chan->active_connections == 0) {
1252 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1253 prn_hnd->servername, prn_hnd->sharename));
1255 /* For this printer? Print servers always receive notifications. */
1256 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1257 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1261 DEBUG(10,("Our printer\n"));
1263 /* build the array of change notifications */
1264 ret = build_notify2_messages(mem_ctx, prn_hnd,
1266 msg_group->num_msgs,
1272 info0.version = 0x2;
1273 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1274 info0.count = count;
1275 info0.notifies = notifies;
1277 info.info0 = &info0;
1279 status = dcerpc_spoolss_RouterReplyPrinterEx(
1280 prn_hnd->notify.cli_chan->binding_handle,
1282 &prn_hnd->notify.cli_hnd,
1283 prn_hnd->notify.change, /* color */
1284 prn_hnd->notify.flags,
1286 0, /* reply_type, must be 0 */
1288 if (!NT_STATUS_IS_OK(status)) {
1289 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1291 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1292 nt_errstr(status)));
1293 werr = ntstatus_to_werror(status);
1294 } else if (!W_ERROR_IS_OK(werr)) {
1295 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1297 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1300 switch (reply_result) {
1303 case PRINTER_NOTIFY_INFO_DISCARDED:
1304 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1305 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1314 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1316 struct printer_handle *p;
1317 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1318 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1322 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1326 if (!msg_group->msgs) {
1327 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1331 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1333 /* loop over all printers */
1335 for (p = printers_list; p; p = p->next) {
1336 ret = send_notify2_printer(mem_ctx, p, msg_group);
1343 DEBUG(8,("send_notify2_changes: Exit...\n"));
1347 /***********************************************************************
1348 **********************************************************************/
1350 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1353 uint32_t tv_sec, tv_usec;
1356 /* Unpack message */
1358 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1361 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1363 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1366 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1367 &msg->notify.value[0], &msg->notify.value[1]);
1369 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1370 &msg->len, &msg->notify.data);
1372 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1373 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1375 tv->tv_sec = tv_sec;
1376 tv->tv_usec = tv_usec;
1379 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1380 msg->notify.value[1]));
1382 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1387 /********************************************************************
1388 Receive a notify2 message list
1389 ********************************************************************/
1391 static void receive_notify2_message_list(struct messaging_context *msg,
1394 struct server_id server_id,
1397 size_t msg_count, i;
1398 char *buf = (char *)data->data;
1401 SPOOLSS_NOTIFY_MSG notify;
1402 SPOOLSS_NOTIFY_MSG_CTR messages;
1405 if (data->length < 4) {
1406 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1410 msg_count = IVAL(buf, 0);
1413 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1415 if (msg_count == 0) {
1416 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1420 /* initialize the container */
1422 ZERO_STRUCT( messages );
1423 notify_msg_ctr_init( &messages );
1426 * build message groups for each printer identified
1427 * in a change_notify msg. Remember that a PCN message
1428 * includes the handle returned for the srv_spoolss_replyopenprinter()
1429 * call. Therefore messages are grouped according to printer handle.
1432 for ( i=0; i<msg_count; i++ ) {
1433 struct timeval msg_tv;
1435 if (msg_ptr + 4 - buf > data->length) {
1436 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1440 msg_len = IVAL(msg_ptr,0);
1443 if (msg_ptr + msg_len - buf > data->length) {
1444 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1448 /* unpack messages */
1450 ZERO_STRUCT( notify );
1451 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1454 /* add to correct list in container */
1456 notify_msg_ctr_addmsg( &messages, ¬ify );
1458 /* free memory that might have been allocated by notify2_unpack_msg() */
1460 if ( notify.len != 0 )
1461 SAFE_FREE( notify.notify.data );
1464 /* process each group of messages */
1466 num_groups = notify_msg_ctr_numgroups( &messages );
1467 for ( i=0; i<num_groups; i++ )
1468 send_notify2_changes( &messages, i );
1473 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1474 (uint32_t)msg_count ));
1476 notify_msg_ctr_destroy( &messages );
1481 /********************************************************************
1482 Send a message to ourself about new driver being installed
1483 so we can upgrade the information for each printer bound to this
1485 ********************************************************************/
1487 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1488 struct messaging_context *msg_ctx)
1490 int len = strlen(drivername);
1495 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1498 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1499 MSG_PRINTER_DRVUPGRADE,
1500 (uint8_t *)drivername, len+1);
1505 void srv_spoolss_cleanup(void)
1507 struct printer_session_counter *session_counter;
1509 for (session_counter = counter_list;
1510 session_counter != NULL;
1511 session_counter = counter_list) {
1512 DLIST_REMOVE(counter_list, session_counter);
1513 TALLOC_FREE(session_counter);
1517 /**********************************************************************
1518 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1519 over all printers, upgrading ones as necessary
1520 **********************************************************************/
1522 void do_drv_upgrade_printer(struct messaging_context *msg,
1525 struct server_id server_id,
1528 TALLOC_CTX *tmp_ctx;
1529 struct auth_serversupplied_info *session_info = NULL;
1530 struct spoolss_PrinterInfo2 *pinfo2;
1533 const char *drivername;
1535 int n_services = lp_numservices();
1537 tmp_ctx = talloc_new(NULL);
1538 if (!tmp_ctx) return;
1540 status = make_session_info_system(tmp_ctx, &session_info);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 DEBUG(0, ("do_drv_upgrade_printer: "
1543 "Could not create system session_info\n"));
1547 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1549 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1553 DEBUG(10, ("do_drv_upgrade_printer: "
1554 "Got message for new driver [%s]\n", drivername));
1556 /* Iterate the printer list */
1558 for (snum = 0; snum < n_services; snum++) {
1559 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1563 /* ignore [printers] share */
1564 if (strequal(lp_const_servicename(snum), "printers")) {
1568 result = winreg_get_printer(tmp_ctx, session_info, msg,
1569 lp_const_servicename(snum),
1572 if (!W_ERROR_IS_OK(result)) {
1576 if (!pinfo2->drivername) {
1580 if (strcmp(drivername, pinfo2->drivername) != 0) {
1584 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1586 /* all we care about currently is the change_id */
1587 result = winreg_printer_update_changeid(tmp_ctx,
1590 pinfo2->printername);
1592 if (!W_ERROR_IS_OK(result)) {
1593 DEBUG(3, ("do_drv_upgrade_printer: "
1594 "Failed to update changeid [%s]\n",
1595 win_errstr(result)));
1601 talloc_free(tmp_ctx);
1604 /********************************************************************
1605 Update the cache for all printq's with a registered client
1607 ********************************************************************/
1609 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1611 struct printer_handle *printer = printers_list;
1614 /* loop through all printers and update the cache where
1615 a client is connected */
1617 if ((printer->printer_type == SPLHND_PRINTER) &&
1618 ((printer->notify.cli_chan != NULL) &&
1619 (printer->notify.cli_chan->active_connections > 0))) {
1620 snum = print_queue_snum(printer->sharename);
1621 print_queue_status(msg_ctx, snum, NULL, NULL);
1624 printer = printer->next;
1630 /****************************************************************
1631 _spoolss_OpenPrinter
1632 ****************************************************************/
1634 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1635 struct spoolss_OpenPrinter *r)
1637 struct spoolss_OpenPrinterEx e;
1640 ZERO_STRUCT(e.in.userlevel);
1642 e.in.printername = r->in.printername;
1643 e.in.datatype = r->in.datatype;
1644 e.in.devmode_ctr = r->in.devmode_ctr;
1645 e.in.access_mask = r->in.access_mask;
1648 e.out.handle = r->out.handle;
1650 werr = _spoolss_OpenPrinterEx(p, &e);
1652 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1653 /* OpenPrinterEx returns this for a bad
1654 * printer name. We must return WERR_INVALID_PRINTER_NAME
1657 werr = WERR_INVALID_PRINTER_NAME;
1663 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1664 struct spoolss_DeviceMode *orig,
1665 struct spoolss_DeviceMode **dest)
1667 struct spoolss_DeviceMode *dm;
1669 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1674 /* copy all values, then duplicate strings and structs */
1677 dm->devicename = talloc_strdup(dm, orig->devicename);
1678 if (!dm->devicename) {
1681 dm->formname = talloc_strdup(dm, orig->formname);
1682 if (!dm->formname) {
1685 if (orig->driverextra_data.data) {
1686 dm->driverextra_data.data =
1687 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1688 orig->driverextra_data.length);
1689 if (!dm->driverextra_data.data) {
1698 /****************************************************************
1699 _spoolss_OpenPrinterEx
1700 ****************************************************************/
1702 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1703 struct spoolss_OpenPrinterEx *r)
1706 struct printer_handle *Printer=NULL;
1709 if (!r->in.printername) {
1710 return WERR_INVALID_PARAM;
1713 if (r->in.level > 3) {
1714 return WERR_INVALID_PARAM;
1716 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1717 (r->in.level == 2 && !r->in.userlevel.level2) ||
1718 (r->in.level == 3 && !r->in.userlevel.level3)) {
1719 return WERR_INVALID_PARAM;
1722 /* some sanity check because you can open a printer or a print server */
1723 /* aka: \\server\printer or \\server */
1725 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1727 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1728 if (!W_ERROR_IS_OK(result)) {
1729 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1730 "for printer %s\n", r->in.printername));
1731 ZERO_STRUCTP(r->out.handle);
1735 Printer = find_printer_index_by_hnd(p, r->out.handle);
1737 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1738 "handle we created for printer %s\n", r->in.printername));
1739 close_printer_handle(p, r->out.handle);
1740 ZERO_STRUCTP(r->out.handle);
1741 return WERR_INVALID_PARAM;
1745 * First case: the user is opening the print server:
1747 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1748 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1750 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1751 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1752 * or if the user is listed in the smb.conf printer admin parameter.
1754 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1755 * client view printer folder, but does not show the MSAPW.
1757 * Note: this test needs code to check access rights here too. Jeremy
1758 * could you look at this?
1760 * Second case: the user is opening a printer:
1761 * NT doesn't let us connect to a printer if the connecting user
1762 * doesn't have print permission.
1764 * Third case: user is opening a Port Monitor
1765 * access checks same as opening a handle to the print server.
1768 switch (Printer->printer_type )
1771 case SPLHND_PORTMON_TCP:
1772 case SPLHND_PORTMON_LOCAL:
1773 /* Printserver handles use global struct... */
1777 /* Map standard access rights to object specific access rights */
1779 se_map_standard(&r->in.access_mask,
1780 &printserver_std_mapping);
1782 /* Deny any object specific bits that don't apply to print
1783 servers (i.e printer and job specific bits) */
1785 r->in.access_mask &= SEC_MASK_SPECIFIC;
1787 if (r->in.access_mask &
1788 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1789 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1790 close_printer_handle(p, r->out.handle);
1791 ZERO_STRUCTP(r->out.handle);
1792 return WERR_ACCESS_DENIED;
1795 /* Allow admin access */
1797 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1799 if (!lp_ms_add_printer_wizard()) {
1800 close_printer_handle(p, r->out.handle);
1801 ZERO_STRUCTP(r->out.handle);
1802 return WERR_ACCESS_DENIED;
1805 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1806 and not a printer admin, then fail */
1808 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1809 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1810 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1811 !token_contains_name_in_list(
1812 uidtoname(p->session_info->utok.uid),
1813 p->session_info->info3->base.domain.string,
1815 p->session_info->security_token,
1816 lp_printer_admin(snum))) {
1817 close_printer_handle(p, r->out.handle);
1818 ZERO_STRUCTP(r->out.handle);
1819 DEBUG(3,("access DENIED as user is not root, "
1820 "has no printoperator privilege, "
1821 "not a member of the printoperator builtin group and "
1822 "is not in printer admin list"));
1823 return WERR_ACCESS_DENIED;
1826 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1833 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1834 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1836 /* We fall through to return WERR_OK */
1839 case SPLHND_PRINTER:
1840 /* NT doesn't let us connect to a printer if the connecting user
1841 doesn't have print permission. */
1843 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1844 close_printer_handle(p, r->out.handle);
1845 ZERO_STRUCTP(r->out.handle);
1849 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1850 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1853 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1855 /* map an empty access mask to the minimum access mask */
1856 if (r->in.access_mask == 0x0)
1857 r->in.access_mask = PRINTER_ACCESS_USE;
1860 * If we are not serving the printer driver for this printer,
1861 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1862 * will keep NT clients happy --jerry
1865 if (lp_use_client_driver(snum)
1866 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1868 r->in.access_mask = PRINTER_ACCESS_USE;
1871 /* check smb.conf parameters and the the sec_desc */
1873 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1874 p->client_id->name, p->client_id->addr)) {
1875 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1876 ZERO_STRUCTP(r->out.handle);
1877 return WERR_ACCESS_DENIED;
1880 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1881 p->session_info->security_token, snum) ||
1882 !print_access_check(p->session_info,
1885 r->in.access_mask)) {
1886 DEBUG(3, ("access DENIED for printer open\n"));
1887 close_printer_handle(p, r->out.handle);
1888 ZERO_STRUCTP(r->out.handle);
1889 return WERR_ACCESS_DENIED;
1892 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1893 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1894 close_printer_handle(p, r->out.handle);
1895 ZERO_STRUCTP(r->out.handle);
1896 return WERR_ACCESS_DENIED;
1899 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1900 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1902 r->in.access_mask = PRINTER_ACCESS_USE;
1904 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1905 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1907 winreg_create_printer(p->mem_ctx,
1908 get_session_info_system(),
1910 lp_const_servicename(snum));
1915 /* sanity check to prevent programmer error */
1916 ZERO_STRUCTP(r->out.handle);
1920 Printer->access_granted = r->in.access_mask;
1923 * If the client sent a devmode in the OpenPrinter() call, then
1924 * save it here in case we get a job submission on this handle
1927 if ((Printer->printer_type != SPLHND_SERVER) &&
1928 r->in.devmode_ctr.devmode) {
1929 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1933 #if 0 /* JERRY -- I'm doubtful this is really effective */
1934 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1935 optimization in Windows 2000 clients --jerry */
1937 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1938 && (RA_WIN2K == get_remote_arch()) )
1940 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1941 sys_usleep( 500000 );
1948 /****************************************************************
1949 _spoolss_ClosePrinter
1950 ****************************************************************/
1952 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1953 struct spoolss_ClosePrinter *r)
1955 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1957 if (Printer && Printer->document_started) {
1958 struct spoolss_EndDocPrinter e;
1960 e.in.handle = r->in.handle;
1962 _spoolss_EndDocPrinter(p, &e);
1965 if (!close_printer_handle(p, r->in.handle))
1968 /* clear the returned printer handle. Observed behavior
1969 from Win2k server. Don't think this really matters.
1970 Previous code just copied the value of the closed
1973 ZERO_STRUCTP(r->out.handle);
1978 /****************************************************************
1979 _spoolss_DeletePrinter
1980 ****************************************************************/
1982 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1983 struct spoolss_DeletePrinter *r)
1985 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1989 if (Printer && Printer->document_started) {
1990 struct spoolss_EndDocPrinter e;
1992 e.in.handle = r->in.handle;
1994 _spoolss_EndDocPrinter(p, &e);
1997 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1998 winreg_delete_printer_key(p->mem_ctx,
1999 get_session_info_system(),
2001 lp_const_servicename(snum),
2005 result = delete_printer_handle(p, r->in.handle);
2010 /*******************************************************************
2011 * static function to lookup the version id corresponding to an
2012 * long architecture string
2013 ******************************************************************/
2015 static const struct print_architecture_table_node archi_table[]= {
2017 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2018 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2019 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2020 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2021 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2022 {"Windows IA64", SPL_ARCH_IA64, 3 },
2023 {"Windows x64", SPL_ARCH_X64, 3 },
2027 static int get_version_id(const char *arch)
2031 for (i=0; archi_table[i].long_archi != NULL; i++)
2033 if (strcmp(arch, archi_table[i].long_archi) == 0)
2034 return (archi_table[i].version);
2040 /****************************************************************
2041 _spoolss_DeletePrinterDriver
2042 ****************************************************************/
2044 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2045 struct spoolss_DeletePrinterDriver *r)
2048 struct spoolss_DriverInfo8 *info = NULL;
2049 struct spoolss_DriverInfo8 *info_win2k = NULL;
2053 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2054 and not a printer admin, then fail */
2056 if ( (p->session_info->utok.uid != sec_initial_uid())
2057 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2058 && !token_contains_name_in_list(
2059 uidtoname(p->session_info->utok.uid),
2060 p->session_info->info3->base.domain.string,
2062 p->session_info->security_token,
2063 lp_printer_admin(-1)) )
2065 return WERR_ACCESS_DENIED;
2068 /* check that we have a valid driver name first */
2070 if ((version = get_version_id(r->in.architecture)) == -1)
2071 return WERR_INVALID_ENVIRONMENT;
2073 status = winreg_get_driver(p->mem_ctx,
2074 get_session_info_system(),
2076 r->in.architecture, r->in.driver,
2078 if (!W_ERROR_IS_OK(status)) {
2079 /* try for Win2k driver if "Windows NT x86" */
2081 if ( version == 2 ) {
2084 status = winreg_get_driver(p->mem_ctx,
2085 get_session_info_system(),
2090 if (!W_ERROR_IS_OK(status)) {
2091 status = WERR_UNKNOWN_PRINTER_DRIVER;
2095 /* otherwise it was a failure */
2097 status = WERR_UNKNOWN_PRINTER_DRIVER;
2103 if (printer_driver_in_use(p->mem_ctx,
2104 get_session_info_system(),
2107 status = WERR_PRINTER_DRIVER_IN_USE;
2112 status = winreg_get_driver(p->mem_ctx,
2113 get_session_info_system(),
2116 r->in.driver, 3, &info_win2k);
2117 if (W_ERROR_IS_OK(status)) {
2118 /* if we get to here, we now have 2 driver info structures to remove */
2119 /* remove the Win2k driver first*/
2121 status = winreg_del_driver(p->mem_ctx,
2122 get_session_info_system(),
2125 talloc_free(info_win2k);
2127 /* this should not have failed---if it did, report to client */
2128 if (!W_ERROR_IS_OK(status)) {
2134 status = winreg_del_driver(p->mem_ctx,
2135 get_session_info_system(),
2145 /****************************************************************
2146 _spoolss_DeletePrinterDriverEx
2147 ****************************************************************/
2149 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2150 struct spoolss_DeletePrinterDriverEx *r)
2152 struct spoolss_DriverInfo8 *info = NULL;
2153 struct spoolss_DriverInfo8 *info_win2k = NULL;
2158 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2159 and not a printer admin, then fail */
2161 if ( (p->session_info->utok.uid != sec_initial_uid())
2162 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2163 && !token_contains_name_in_list(
2164 uidtoname(p->session_info->utok.uid),
2165 p->session_info->info3->base.domain.string,
2167 p->session_info->security_token, lp_printer_admin(-1)) )
2169 return WERR_ACCESS_DENIED;
2172 /* check that we have a valid driver name first */
2173 if ((version = get_version_id(r->in.architecture)) == -1) {
2174 /* this is what NT returns */
2175 return WERR_INVALID_ENVIRONMENT;
2178 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2179 version = r->in.version;
2181 status = winreg_get_driver(p->mem_ctx,
2182 get_session_info_system(),
2188 if (!W_ERROR_IS_OK(status)) {
2189 status = WERR_UNKNOWN_PRINTER_DRIVER;
2192 * if the client asked for a specific version,
2193 * or this is something other than Windows NT x86,
2197 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2200 /* try for Win2k driver if "Windows NT x86" */
2203 status = winreg_get_driver(info,
2204 get_session_info_system(),
2209 if (!W_ERROR_IS_OK(status)) {
2210 status = WERR_UNKNOWN_PRINTER_DRIVER;
2215 if (printer_driver_in_use(info,
2216 get_session_info_system(),
2219 status = WERR_PRINTER_DRIVER_IN_USE;
2224 * we have a couple of cases to consider.
2225 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2226 * then the delete should fail if **any** files overlap with
2228 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2229 * non-overlapping files
2230 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2231 * is set, the do not delete any files
2232 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2235 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2237 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2240 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2241 printer_driver_files_in_use(info,
2242 get_session_info_system(),
2245 /* no idea of the correct error here */
2246 status = WERR_ACCESS_DENIED;
2251 /* also check for W32X86/3 if necessary; maybe we already have? */
2253 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2254 status = winreg_get_driver(info,
2255 get_session_info_system(),
2258 r->in.driver, 3, &info_win2k);
2259 if (W_ERROR_IS_OK(status)) {
2262 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2263 printer_driver_files_in_use(info,
2264 get_session_info_system(),
2267 /* no idea of the correct error here */
2268 talloc_free(info_win2k);
2269 status = WERR_ACCESS_DENIED;
2273 /* if we get to here, we now have 2 driver info structures to remove */
2274 /* remove the Win2k driver first*/
2276 status = winreg_del_driver(info,
2277 get_session_info_system(),
2282 /* this should not have failed---if it did, report to client */
2284 if (!W_ERROR_IS_OK(status)) {
2289 * now delete any associated files if delete_files is
2290 * true. Even if this part failes, we return succes
2291 * because the driver doesn not exist any more
2294 delete_driver_files(get_session_info_system(),
2300 status = winreg_del_driver(info,
2301 get_session_info_system(),
2305 if (!W_ERROR_IS_OK(status)) {
2310 * now delete any associated files if delete_files is
2311 * true. Even if this part failes, we return succes
2312 * because the driver doesn not exist any more
2315 delete_driver_files(get_session_info_system(), info);
2324 /********************************************************************
2325 GetPrinterData on a printer server Handle.
2326 ********************************************************************/
2328 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2330 enum winreg_Type *type,
2331 union spoolss_PrinterData *data)
2333 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2335 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2341 if (!StrCaseCmp(value, "BeepEnabled")) {
2347 if (!StrCaseCmp(value, "EventLog")) {
2349 /* formally was 0x1b */
2354 if (!StrCaseCmp(value, "NetPopup")) {
2360 if (!StrCaseCmp(value, "MajorVersion")) {
2363 /* Windows NT 4.0 seems to not allow uploading of drivers
2364 to a server that reports 0x3 as the MajorVersion.
2365 need to investigate more how Win2k gets around this .
2368 if (RA_WINNT == get_remote_arch()) {
2377 if (!StrCaseCmp(value, "MinorVersion")) {
2384 * uint32_t size = 0x114
2385 * uint32_t major = 5
2386 * uint32_t minor = [0|1]
2387 * uint32_t build = [2195|2600]
2388 * extra unicode string = e.g. "Service Pack 3"
2390 if (!StrCaseCmp(value, "OSVersion")) {
2392 enum ndr_err_code ndr_err;
2393 struct spoolss_OSVersion os;
2395 os.major = 5; /* Windows 2000 == 5.0 */
2397 os.build = 2195; /* build */
2398 os.extra_string = ""; /* leave extra string empty */
2400 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2401 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2402 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2403 return WERR_GENERAL_FAILURE;
2407 data->binary = blob;
2413 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2416 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2417 W_ERROR_HAVE_NO_MEMORY(data->string);
2422 if (!StrCaseCmp(value, "Architecture")) {
2424 data->string = talloc_strdup(mem_ctx,
2425 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2426 W_ERROR_HAVE_NO_MEMORY(data->string);
2431 if (!StrCaseCmp(value, "DsPresent")) {
2434 /* only show the publish check box if we are a
2435 member of a AD domain */
2437 if (lp_security() == SEC_ADS) {
2445 if (!StrCaseCmp(value, "DNSMachineName")) {
2446 const char *hostname = get_mydnsfullname();
2449 return WERR_BADFILE;
2453 data->string = talloc_strdup(mem_ctx, hostname);
2454 W_ERROR_HAVE_NO_MEMORY(data->string);
2461 return WERR_INVALID_PARAM;
2464 /****************************************************************
2465 _spoolss_GetPrinterData
2466 ****************************************************************/
2468 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2469 struct spoolss_GetPrinterData *r)
2471 struct spoolss_GetPrinterDataEx r2;
2473 r2.in.handle = r->in.handle;
2474 r2.in.key_name = "PrinterDriverData";
2475 r2.in.value_name = r->in.value_name;
2476 r2.in.offered = r->in.offered;
2477 r2.out.type = r->out.type;
2478 r2.out.data = r->out.data;
2479 r2.out.needed = r->out.needed;
2481 return _spoolss_GetPrinterDataEx(p, &r2);
2484 /*********************************************************
2485 Connect to the client machine.
2486 **********************************************************/
2488 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2489 struct sockaddr_storage *client_ss, const char *remote_machine)
2492 struct cli_state *the_cli;
2493 struct sockaddr_storage rm_addr;
2494 char addr[INET6_ADDRSTRLEN];
2496 if ( is_zero_addr(client_ss) ) {
2497 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2499 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2500 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2503 print_sockaddr(addr, sizeof(addr), &rm_addr);
2505 rm_addr = *client_ss;
2506 print_sockaddr(addr, sizeof(addr), &rm_addr);
2507 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2511 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2512 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2517 /* setup the connection */
2518 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2519 &rm_addr, 0, "IPC$", "IPC",
2523 0, lp_client_signing());
2525 if ( !NT_STATUS_IS_OK( ret ) ) {
2526 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2531 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2532 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2533 cli_shutdown(the_cli);
2538 * Ok - we have an anonymous connection to the IPC$ share.
2539 * Now start the NT Domain stuff :-).
2542 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2543 if (!NT_STATUS_IS_OK(ret)) {
2544 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2545 remote_machine, nt_errstr(ret)));
2546 cli_shutdown(the_cli);
2553 /***************************************************************************
2554 Connect to the client.
2555 ****************************************************************************/
2557 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2558 uint32_t localprinter,
2559 enum winreg_Type type,
2560 struct policy_handle *handle,
2561 struct notify_back_channel **_chan,
2562 struct sockaddr_storage *client_ss,
2563 struct messaging_context *msg_ctx)
2567 struct notify_back_channel *chan;
2569 for (chan = back_channels; chan; chan = chan->next) {
2570 if (memcmp(&chan->client_address, client_ss,
2571 sizeof(struct sockaddr_storage)) == 0) {
2577 * If it's the first connection, contact the client
2578 * and connect to the IPC$ share anonymously
2581 fstring unix_printer;
2583 /* the +2 is to strip the leading 2 backslashs */
2584 fstrcpy(unix_printer, printer + 2);
2586 chan = talloc_zero(back_channels, struct notify_back_channel);
2590 chan->client_address = *client_ss;
2592 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2596 chan->binding_handle = chan->cli_pipe->binding_handle;
2598 DLIST_ADD(back_channels, chan);
2600 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2601 receive_notify2_message_list);
2602 /* Tell the connections db we're now interested in printer
2603 * notify messages. */
2604 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2605 true, FLAG_MSG_PRINT_NOTIFY);
2609 * Tell the specific printing tdb we want messages for this printer
2610 * by registering our PID.
2613 if (!print_notify_register_pid(snum)) {
2614 DEBUG(0, ("Failed to register our pid for printer %s\n",
2618 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2627 if (!NT_STATUS_IS_OK(status)) {
2628 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2629 result = ntstatus_to_werror(status);
2630 } else if (!W_ERROR_IS_OK(result)) {
2631 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2634 chan->active_connections++;
2637 return (W_ERROR_IS_OK(result));
2640 /****************************************************************
2641 ****************************************************************/
2643 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2644 const struct spoolss_NotifyOption *r)
2646 struct spoolss_NotifyOption *option;
2653 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2660 if (!option->count) {
2664 option->types = talloc_zero_array(option,
2665 struct spoolss_NotifyOptionType, option->count);
2666 if (!option->types) {
2667 talloc_free(option);
2671 for (i=0; i < option->count; i++) {
2672 option->types[i] = r->types[i];
2674 if (option->types[i].count) {
2675 option->types[i].fields = talloc_zero_array(option,
2676 union spoolss_Field, option->types[i].count);
2677 if (!option->types[i].fields) {
2678 talloc_free(option);
2681 for (k=0; k<option->types[i].count; k++) {
2682 option->types[i].fields[k] =
2683 r->types[i].fields[k];
2691 /****************************************************************
2692 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2694 * before replying OK: status=0 a rpc call is made to the workstation
2695 * asking ReplyOpenPrinter
2697 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2698 * called from api_spoolss_rffpcnex
2699 ****************************************************************/
2701 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2702 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2705 struct spoolss_NotifyOption *option = r->in.notify_options;
2706 struct sockaddr_storage client_ss;
2708 /* store the notify value in the printer struct */
2710 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2713 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2714 "Invalid handle (%s:%u:%u).\n",
2715 OUR_HANDLE(r->in.handle)));
2719 Printer->notify.flags = r->in.flags;
2720 Printer->notify.options = r->in.options;
2721 Printer->notify.printerlocal = r->in.printer_local;
2722 Printer->notify.msg_ctx = p->msg_ctx;
2724 TALLOC_FREE(Printer->notify.option);
2725 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2727 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2729 /* Connect to the client machine and send a ReplyOpenPrinter */
2731 if ( Printer->printer_type == SPLHND_SERVER)
2733 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2734 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2737 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2738 "client_address is %s\n", p->client_id->addr));
2740 if (!lp_print_notify_backchannel(snum)) {
2741 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2742 "backchannel disabled\n"));
2743 return WERR_SERVER_UNAVAILABLE;
2746 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2748 return WERR_SERVER_UNAVAILABLE;
2751 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2752 Printer->notify.printerlocal, REG_SZ,
2753 &Printer->notify.cli_hnd,
2754 &Printer->notify.cli_chan,
2755 &client_ss, p->msg_ctx)) {
2756 return WERR_SERVER_UNAVAILABLE;
2762 /*******************************************************************
2763 * fill a notify_info_data with the servername
2764 ********************************************************************/
2766 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2768 struct spoolss_Notify *data,
2769 print_queue_struct *queue,
2770 struct spoolss_PrinterInfo2 *pinfo2,
2771 TALLOC_CTX *mem_ctx)
2773 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2776 /*******************************************************************
2777 * fill a notify_info_data with the printername (not including the servername).
2778 ********************************************************************/
2780 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2782 struct spoolss_Notify *data,
2783 print_queue_struct *queue,
2784 struct spoolss_PrinterInfo2 *pinfo2,
2785 TALLOC_CTX *mem_ctx)
2787 /* the notify name should not contain the \\server\ part */
2788 const char *p = strrchr(pinfo2->printername, '\\');
2791 p = pinfo2->printername;
2796 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2799 /*******************************************************************
2800 * fill a notify_info_data with the servicename
2801 ********************************************************************/
2803 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2805 struct spoolss_Notify *data,
2806 print_queue_struct *queue,
2807 struct spoolss_PrinterInfo2 *pinfo2,
2808 TALLOC_CTX *mem_ctx)
2810 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2813 /*******************************************************************
2814 * fill a notify_info_data with the port name
2815 ********************************************************************/
2817 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2819 struct spoolss_Notify *data,
2820 print_queue_struct *queue,
2821 struct spoolss_PrinterInfo2 *pinfo2,
2822 TALLOC_CTX *mem_ctx)
2824 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2827 /*******************************************************************
2828 * fill a notify_info_data with the printername
2829 * but it doesn't exist, have to see what to do
2830 ********************************************************************/
2832 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2834 struct spoolss_Notify *data,
2835 print_queue_struct *queue,
2836 struct spoolss_PrinterInfo2 *pinfo2,
2837 TALLOC_CTX *mem_ctx)
2839 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2842 /*******************************************************************
2843 * fill a notify_info_data with the comment
2844 ********************************************************************/
2846 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2848 struct spoolss_Notify *data,
2849 print_queue_struct *queue,
2850 struct spoolss_PrinterInfo2 *pinfo2,
2851 TALLOC_CTX *mem_ctx)
2855 if (*pinfo2->comment == '\0') {
2856 p = lp_comment(snum);
2858 p = pinfo2->comment;
2861 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2864 /*******************************************************************
2865 * fill a notify_info_data with the comment
2866 * location = "Room 1, floor 2, building 3"
2867 ********************************************************************/
2869 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2871 struct spoolss_Notify *data,
2872 print_queue_struct *queue,
2873 struct spoolss_PrinterInfo2 *pinfo2,
2874 TALLOC_CTX *mem_ctx)
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2879 /*******************************************************************
2880 * fill a notify_info_data with the device mode
2881 * jfm:xxxx don't to it for know but that's a real problem !!!
2882 ********************************************************************/
2884 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2886 struct spoolss_Notify *data,
2887 print_queue_struct *queue,
2888 struct spoolss_PrinterInfo2 *pinfo2,
2889 TALLOC_CTX *mem_ctx)
2891 /* for a dummy implementation we have to zero the fields */
2892 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2895 /*******************************************************************
2896 * fill a notify_info_data with the separator file name
2897 ********************************************************************/
2899 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2901 struct spoolss_Notify *data,
2902 print_queue_struct *queue,
2903 struct spoolss_PrinterInfo2 *pinfo2,
2904 TALLOC_CTX *mem_ctx)
2906 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2909 /*******************************************************************
2910 * fill a notify_info_data with the print processor
2911 * jfm:xxxx return always winprint to indicate we don't do anything to it
2912 ********************************************************************/
2914 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2916 struct spoolss_Notify *data,
2917 print_queue_struct *queue,
2918 struct spoolss_PrinterInfo2 *pinfo2,
2919 TALLOC_CTX *mem_ctx)
2921 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2924 /*******************************************************************
2925 * fill a notify_info_data with the print processor options
2926 * jfm:xxxx send an empty string
2927 ********************************************************************/
2929 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2931 struct spoolss_Notify *data,
2932 print_queue_struct *queue,
2933 struct spoolss_PrinterInfo2 *pinfo2,
2934 TALLOC_CTX *mem_ctx)
2936 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2939 /*******************************************************************
2940 * fill a notify_info_data with the data type
2941 * jfm:xxxx always send RAW as data type
2942 ********************************************************************/
2944 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2946 struct spoolss_Notify *data,
2947 print_queue_struct *queue,
2948 struct spoolss_PrinterInfo2 *pinfo2,
2949 TALLOC_CTX *mem_ctx)
2951 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2954 /*******************************************************************
2955 * fill a notify_info_data with the security descriptor
2956 * jfm:xxxx send an null pointer to say no security desc
2957 * have to implement security before !
2958 ********************************************************************/
2960 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2962 struct spoolss_Notify *data,
2963 print_queue_struct *queue,
2964 struct spoolss_PrinterInfo2 *pinfo2,
2965 TALLOC_CTX *mem_ctx)
2967 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2970 /*******************************************************************
2971 * fill a notify_info_data with the attributes
2972 * jfm:xxxx a samba printer is always shared
2973 ********************************************************************/
2975 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2977 struct spoolss_Notify *data,
2978 print_queue_struct *queue,
2979 struct spoolss_PrinterInfo2 *pinfo2,
2980 TALLOC_CTX *mem_ctx)
2982 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2985 /*******************************************************************
2986 * fill a notify_info_data with the priority
2987 ********************************************************************/
2989 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2991 struct spoolss_Notify *data,
2992 print_queue_struct *queue,
2993 struct spoolss_PrinterInfo2 *pinfo2,
2994 TALLOC_CTX *mem_ctx)
2996 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2999 /*******************************************************************
3000 * fill a notify_info_data with the default priority
3001 ********************************************************************/
3003 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3005 struct spoolss_Notify *data,
3006 print_queue_struct *queue,
3007 struct spoolss_PrinterInfo2 *pinfo2,
3008 TALLOC_CTX *mem_ctx)
3010 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3013 /*******************************************************************
3014 * fill a notify_info_data with the start time
3015 ********************************************************************/
3017 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3019 struct spoolss_Notify *data,
3020 print_queue_struct *queue,
3021 struct spoolss_PrinterInfo2 *pinfo2,
3022 TALLOC_CTX *mem_ctx)
3024 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3027 /*******************************************************************
3028 * fill a notify_info_data with the until time
3029 ********************************************************************/
3031 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 struct spoolss_PrinterInfo2 *pinfo2,
3036 TALLOC_CTX *mem_ctx)
3038 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3041 /*******************************************************************
3042 * fill a notify_info_data with the status
3043 ********************************************************************/
3045 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3047 struct spoolss_Notify *data,
3048 print_queue_struct *queue,
3049 struct spoolss_PrinterInfo2 *pinfo2,
3050 TALLOC_CTX *mem_ctx)
3052 print_status_struct status;
3054 print_queue_length(msg_ctx, snum, &status);
3055 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3058 /*******************************************************************
3059 * fill a notify_info_data with the number of jobs queued
3060 ********************************************************************/
3062 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3064 struct spoolss_Notify *data,
3065 print_queue_struct *queue,
3066 struct spoolss_PrinterInfo2 *pinfo2,
3067 TALLOC_CTX *mem_ctx)
3069 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3070 data, print_queue_length(msg_ctx, snum, NULL));
3073 /*******************************************************************
3074 * fill a notify_info_data with the average ppm
3075 ********************************************************************/
3077 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3079 struct spoolss_Notify *data,
3080 print_queue_struct *queue,
3081 struct spoolss_PrinterInfo2 *pinfo2,
3082 TALLOC_CTX *mem_ctx)
3084 /* always respond 8 pages per minutes */
3085 /* a little hard ! */
3086 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3089 /*******************************************************************
3090 * fill a notify_info_data with username
3091 ********************************************************************/
3093 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3095 struct spoolss_Notify *data,
3096 print_queue_struct *queue,
3097 struct spoolss_PrinterInfo2 *pinfo2,
3098 TALLOC_CTX *mem_ctx)
3100 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3103 /*******************************************************************
3104 * fill a notify_info_data with job status
3105 ********************************************************************/
3107 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3109 struct spoolss_Notify *data,
3110 print_queue_struct *queue,
3111 struct spoolss_PrinterInfo2 *pinfo2,
3112 TALLOC_CTX *mem_ctx)
3114 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3117 /*******************************************************************
3118 * fill a notify_info_data with job name
3119 ********************************************************************/
3121 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3123 struct spoolss_Notify *data,
3124 print_queue_struct *queue,
3125 struct spoolss_PrinterInfo2 *pinfo2,
3126 TALLOC_CTX *mem_ctx)
3128 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3131 /*******************************************************************
3132 * fill a notify_info_data with job status
3133 ********************************************************************/
3135 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3137 struct spoolss_Notify *data,
3138 print_queue_struct *queue,
3139 struct spoolss_PrinterInfo2 *pinfo2,
3140 TALLOC_CTX *mem_ctx)
3143 * Now we're returning job status codes we just return a "" here. JRA.
3148 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3151 switch (queue->status) {
3156 p = ""; /* NT provides the paused string */
3165 #endif /* NO LONGER NEEDED. */
3167 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3170 /*******************************************************************
3171 * fill a notify_info_data with job time
3172 ********************************************************************/
3174 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3176 struct spoolss_Notify *data,
3177 print_queue_struct *queue,
3178 struct spoolss_PrinterInfo2 *pinfo2,
3179 TALLOC_CTX *mem_ctx)
3181 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3184 /*******************************************************************
3185 * fill a notify_info_data with job size
3186 ********************************************************************/
3188 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3190 struct spoolss_Notify *data,
3191 print_queue_struct *queue,
3192 struct spoolss_PrinterInfo2 *pinfo2,
3193 TALLOC_CTX *mem_ctx)
3195 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3198 /*******************************************************************
3199 * fill a notify_info_data with page info
3200 ********************************************************************/
3201 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3203 struct spoolss_Notify *data,
3204 print_queue_struct *queue,
3205 struct spoolss_PrinterInfo2 *pinfo2,
3206 TALLOC_CTX *mem_ctx)
3208 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3211 /*******************************************************************
3212 * fill a notify_info_data with pages printed info.
3213 ********************************************************************/
3214 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3216 struct spoolss_Notify *data,
3217 print_queue_struct *queue,
3218 struct spoolss_PrinterInfo2 *pinfo2,
3219 TALLOC_CTX *mem_ctx)
3221 /* Add code when back-end tracks this */
3222 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3225 /*******************************************************************
3226 Fill a notify_info_data with job position.
3227 ********************************************************************/
3229 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3231 struct spoolss_Notify *data,
3232 print_queue_struct *queue,
3233 struct spoolss_PrinterInfo2 *pinfo2,
3234 TALLOC_CTX *mem_ctx)
3236 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3239 /*******************************************************************
3240 Fill a notify_info_data with submitted time.
3241 ********************************************************************/
3243 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3245 struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 struct spoolss_PrinterInfo2 *pinfo2,
3248 TALLOC_CTX *mem_ctx)
3250 data->data.string.string = NULL;
3251 data->data.string.size = 0;
3253 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3254 &data->data.string.string,
3255 &data->data.string.size);
3259 struct s_notify_info_data_table
3261 enum spoolss_NotifyType type;
3264 enum spoolss_NotifyTable variable_type;
3265 void (*fn) (struct messaging_context *msg_ctx,
3266 int snum, struct spoolss_Notify *data,
3267 print_queue_struct *queue,
3268 struct spoolss_PrinterInfo2 *pinfo2,
3269 TALLOC_CTX *mem_ctx);
3272 /* A table describing the various print notification constants and
3273 whether the notification data is a pointer to a variable sized
3274 buffer, a one value uint32_t or a two value uint32_t. */
3276 static const struct s_notify_info_data_table notify_info_data_table[] =
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3329 /*******************************************************************
3330 Return the variable_type of info_data structure.
3331 ********************************************************************/
3333 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3338 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3339 if ( (notify_info_data_table[i].type == type) &&
3340 (notify_info_data_table[i].field == field) ) {
3341 return notify_info_data_table[i].variable_type;
3345 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3347 return (enum spoolss_NotifyTable) 0;
3350 /****************************************************************************
3351 ****************************************************************************/
3353 static bool search_notify(enum spoolss_NotifyType type,
3359 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3360 if (notify_info_data_table[i].type == type &&
3361 notify_info_data_table[i].field == field &&
3362 notify_info_data_table[i].fn != NULL) {
3371 /****************************************************************************
3372 ****************************************************************************/
3374 static void construct_info_data(struct spoolss_Notify *info_data,
3375 enum spoolss_NotifyType type,
3376 uint16_t field, int id)
3378 info_data->type = type;
3379 info_data->field.field = field;
3380 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3381 info_data->job_id = id;
3384 /*******************************************************************
3386 * fill a notify_info struct with info asked
3388 ********************************************************************/
3390 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3391 struct printer_handle *print_hnd,
3392 struct spoolss_NotifyInfo *info,
3393 struct spoolss_PrinterInfo2 *pinfo2,
3395 const struct spoolss_NotifyOptionType *option_type,
3397 TALLOC_CTX *mem_ctx)
3400 enum spoolss_NotifyType type;
3403 struct spoolss_Notify *current_data;
3404 print_queue_struct *queue=NULL;
3406 type = option_type->type;
3408 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3409 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3410 option_type->count, lp_servicename(snum)));
3412 for(field_num=0; field_num < option_type->count; field_num++) {
3413 field = option_type->fields[field_num].field;
3415 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3417 if (!search_notify(type, field, &j) )
3420 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3421 struct spoolss_Notify,
3423 if (info->notifies == NULL) {
3424 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3428 current_data = &info->notifies[info->count];
3430 construct_info_data(current_data, type, field, id);
3432 DEBUG(10, ("construct_notify_printer_info: "
3433 "calling [%s] snum=%d printername=[%s])\n",
3434 notify_info_data_table[j].name, snum,
3435 pinfo2->printername));
3437 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3438 queue, pinfo2, mem_ctx);
3446 /*******************************************************************
3448 * fill a notify_info struct with info asked
3450 ********************************************************************/
3452 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3453 print_queue_struct *queue,
3454 struct spoolss_NotifyInfo *info,
3455 struct spoolss_PrinterInfo2 *pinfo2,
3457 const struct spoolss_NotifyOptionType *option_type,
3459 TALLOC_CTX *mem_ctx)
3462 enum spoolss_NotifyType type;
3464 struct spoolss_Notify *current_data;
3466 DEBUG(4,("construct_notify_jobs_info\n"));
3468 type = option_type->type;
3470 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3471 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3472 option_type->count));
3474 for(field_num=0; field_num<option_type->count; field_num++) {
3475 field = option_type->fields[field_num].field;
3477 if (!search_notify(type, field, &j) )
3480 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3481 struct spoolss_Notify,
3483 if (info->notifies == NULL) {
3484 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3488 current_data=&(info->notifies[info->count]);
3490 construct_info_data(current_data, type, field, id);
3491 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3492 queue, pinfo2, mem_ctx);
3500 * JFM: The enumeration is not that simple, it's even non obvious.
3502 * let's take an example: I want to monitor the PRINTER SERVER for
3503 * the printer's name and the number of jobs currently queued.
3504 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3505 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3507 * I have 3 printers on the back of my server.
3509 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3512 * 1 printer 1 name 1
3513 * 2 printer 1 cjob 1
3514 * 3 printer 2 name 2
3515 * 4 printer 2 cjob 2
3516 * 5 printer 3 name 3
3517 * 6 printer 3 name 3
3519 * that's the print server case, the printer case is even worse.
3522 /*******************************************************************
3524 * enumerate all printers on the printserver
3525 * fill a notify_info struct with info asked
3527 ********************************************************************/
3529 static WERROR printserver_notify_info(struct pipes_struct *p,
3530 struct policy_handle *hnd,
3531 struct spoolss_NotifyInfo *info,
3532 TALLOC_CTX *mem_ctx)
3535 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3536 int n_services=lp_numservices();
3538 struct spoolss_NotifyOption *option;
3539 struct spoolss_NotifyOptionType option_type;
3540 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3543 DEBUG(4,("printserver_notify_info\n"));
3548 option = Printer->notify.option;
3551 info->notifies = NULL;
3554 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3555 sending a ffpcn() request first */
3560 for (i=0; i<option->count; i++) {
3561 option_type = option->types[i];
3563 if (option_type.type != PRINTER_NOTIFY_TYPE)
3566 for (snum = 0; snum < n_services; snum++) {
3567 if (!lp_browseable(snum) ||
3568 !lp_snum_ok(snum) ||
3569 !lp_print_ok(snum)) {
3570 continue; /* skip */
3573 /* Maybe we should use the SYSTEM session_info here... */
3574 result = winreg_get_printer(mem_ctx,
3575 get_session_info_system(),
3577 lp_servicename(snum),
3579 if (!W_ERROR_IS_OK(result)) {
3580 DEBUG(4, ("printserver_notify_info: "
3581 "Failed to get printer [%s]\n",
3582 lp_servicename(snum)));
3587 construct_notify_printer_info(p->msg_ctx,
3593 TALLOC_FREE(pinfo2);
3599 * Debugging information, don't delete.
3602 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3603 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3604 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3606 for (i=0; i<info->count; i++) {
3607 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3608 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3609 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3616 /*******************************************************************
3618 * fill a notify_info struct with info asked
3620 ********************************************************************/
3622 static WERROR printer_notify_info(struct pipes_struct *p,
3623 struct policy_handle *hnd,
3624 struct spoolss_NotifyInfo *info,
3625 TALLOC_CTX *mem_ctx)
3628 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3631 struct spoolss_NotifyOption *option;
3632 struct spoolss_NotifyOptionType option_type;
3634 print_queue_struct *queue=NULL;
3635 print_status_struct status;
3636 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3639 DEBUG(4,("printer_notify_info\n"));
3644 option = Printer->notify.option;
3648 info->notifies = NULL;
3651 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3652 sending a ffpcn() request first */
3657 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3661 /* Maybe we should use the SYSTEM session_info here... */
3662 result = winreg_get_printer(mem_ctx,
3663 get_session_info_system(),
3665 lp_servicename(snum), &pinfo2);
3666 if (!W_ERROR_IS_OK(result)) {
3670 for (i=0; i<option->count; i++) {
3671 option_type = option->types[i];
3673 switch (option_type.type) {
3674 case PRINTER_NOTIFY_TYPE:
3675 if (construct_notify_printer_info(p->msg_ctx,
3684 case JOB_NOTIFY_TYPE:
3686 count = print_queue_status(p->msg_ctx, snum, &queue,
3689 for (j=0; j<count; j++) {
3690 construct_notify_jobs_info(p->msg_ctx,
3704 * Debugging information, don't delete.
3707 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3708 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3709 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3711 for (i=0; i<info->count; i++) {
3712 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3713 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3714 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3718 talloc_free(pinfo2);
3722 /****************************************************************
3723 _spoolss_RouterRefreshPrinterChangeNotify
3724 ****************************************************************/
3726 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3727 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3729 struct spoolss_NotifyInfo *info;
3731 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3732 WERROR result = WERR_BADFID;
3734 /* we always have a spoolss_NotifyInfo struct */
3735 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3737 result = WERR_NOMEM;
3741 *r->out.info = info;
3744 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3745 "Invalid handle (%s:%u:%u).\n",
3746 OUR_HANDLE(r->in.handle)));
3750 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3753 * We are now using the change value, and
3754 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3755 * I don't have a global notification system, I'm sending back all the
3756 * information even when _NOTHING_ has changed.
3759 /* We need to keep track of the change value to send back in
3760 RRPCN replies otherwise our updates are ignored. */
3762 Printer->notify.fnpcn = true;
3764 if (Printer->notify.cli_chan != NULL &&
3765 Printer->notify.cli_chan->active_connections > 0) {
3766 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3767 "Saving change value in request [%x]\n",
3769 Printer->notify.change = r->in.change_low;
3772 /* just ignore the spoolss_NotifyOption */
3774 switch (Printer->printer_type) {
3776 result = printserver_notify_info(p, r->in.handle,
3780 case SPLHND_PRINTER:
3781 result = printer_notify_info(p, r->in.handle,
3786 Printer->notify.fnpcn = false;
3792 /********************************************************************
3793 ********************************************************************/
3795 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3796 const char *servername,
3797 const char *printername,
3798 const char **printername_p)
3800 /* FIXME: add lp_force_printername() */
3802 if (servername == NULL) {
3803 *printername_p = talloc_strdup(mem_ctx, printername);
3804 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3808 if (servername[0] == '\\' && servername[1] == '\\') {
3812 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3813 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3818 /********************************************************************
3819 ********************************************************************/
3821 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3822 const char *printername)
3828 dm->devicename = talloc_strndup(dm, printername,
3829 MIN(strlen(printername), 31));
3832 /********************************************************************
3833 * construct_printer_info_0
3834 * fill a printer_info_0 struct
3835 ********************************************************************/
3837 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3838 const struct auth_serversupplied_info *session_info,
3839 struct messaging_context *msg_ctx,
3840 struct spoolss_PrinterInfo2 *info2,
3841 const char *servername,
3842 struct spoolss_PrinterInfo0 *r,
3846 struct printer_session_counter *session_counter;
3847 struct timeval setuptime;
3848 print_status_struct status;
3851 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3852 if (!W_ERROR_IS_OK(result)) {
3857 r->servername = talloc_strdup(mem_ctx, servername);
3858 W_ERROR_HAVE_NO_MEMORY(r->servername);
3860 r->servername = NULL;
3863 count = print_queue_length(msg_ctx, snum, &status);
3865 /* check if we already have a counter for this printer */
3866 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3867 if (session_counter->snum == snum)
3871 /* it's the first time, add it to the list */
3872 if (session_counter == NULL) {
3873 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3874 W_ERROR_HAVE_NO_MEMORY(session_counter);
3875 session_counter->snum = snum;
3876 session_counter->counter = 0;
3877 DLIST_ADD(counter_list, session_counter);
3881 session_counter->counter++;
3887 get_startup_time(&setuptime);
3888 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3891 * the global_counter should be stored in a TDB as it's common to all the clients
3892 * and should be zeroed on samba startup
3894 r->global_counter = session_counter->counter;
3896 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3897 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3898 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3899 r->free_build = SPOOLSS_RELEASE_BUILD;
3901 r->max_spooling = 0;
3902 r->session_counter = session_counter->counter;
3903 r->num_error_out_of_paper = 0x0;
3904 r->num_error_not_ready = 0x0; /* number of print failure */
3906 r->number_of_processors = 0x1;
3907 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3908 r->high_part_total_bytes = 0x0;
3910 /* ChangeID in milliseconds*/
3911 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3912 info2->sharename, &r->change_id);
3914 r->last_error = WERR_OK;
3915 r->status = nt_printq_status(status.status);
3916 r->enumerate_network_printers = 0x0;
3917 r->c_setprinter = 0x0;
3918 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3919 r->processor_level = 0x6; /* 6 ???*/
3928 /********************************************************************
3929 * construct_printer_info1
3930 * fill a spoolss_PrinterInfo1 struct
3931 ********************************************************************/
3933 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3934 const struct spoolss_PrinterInfo2 *info2,
3936 const char *servername,
3937 struct spoolss_PrinterInfo1 *r,
3944 if (info2->comment == NULL || info2->comment[0] == '\0') {
3945 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3947 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3949 W_ERROR_HAVE_NO_MEMORY(r->comment);
3951 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3952 if (!W_ERROR_IS_OK(result)) {
3956 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3960 W_ERROR_HAVE_NO_MEMORY(r->description);
3965 /********************************************************************
3966 * construct_printer_info2
3967 * fill a spoolss_PrinterInfo2 struct
3968 ********************************************************************/
3970 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3971 struct messaging_context *msg_ctx,
3972 const struct spoolss_PrinterInfo2 *info2,
3973 const char *servername,
3974 struct spoolss_PrinterInfo2 *r,
3978 print_status_struct status;
3981 count = print_queue_length(msg_ctx, snum, &status);
3984 r->servername = talloc_strdup(mem_ctx, servername);
3985 W_ERROR_HAVE_NO_MEMORY(r->servername);
3987 r->servername = NULL;
3990 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3991 if (!W_ERROR_IS_OK(result)) {
3995 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3996 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3997 r->portname = talloc_strdup(mem_ctx, info2->portname);
3998 W_ERROR_HAVE_NO_MEMORY(r->portname);
3999 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4000 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4002 if (info2->comment[0] == '\0') {
4003 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4005 r->comment = talloc_strdup(mem_ctx, info2->comment);
4007 W_ERROR_HAVE_NO_MEMORY(r->comment);
4009 r->location = talloc_strdup(mem_ctx, info2->location);
4010 W_ERROR_HAVE_NO_MEMORY(r->location);
4011 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4012 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4013 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4014 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4015 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4016 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4017 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4018 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4020 r->attributes = info2->attributes;
4022 r->priority = info2->priority;
4023 r->defaultpriority = info2->defaultpriority;
4024 r->starttime = info2->starttime;
4025 r->untiltime = info2->untiltime;
4026 r->status = nt_printq_status(status.status);
4028 r->averageppm = info2->averageppm;
4030 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4032 DEBUG(8,("Returning NULL Devicemode!\n"));
4035 compose_devicemode_devicename(r->devmode, r->printername);
4039 if (info2->secdesc != NULL) {
4040 /* don't use talloc_steal() here unless you do a deep steal of all
4041 the SEC_DESC members */
4043 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4049 /********************************************************************
4050 * construct_printer_info3
4051 * fill a spoolss_PrinterInfo3 struct
4052 ********************************************************************/
4054 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4055 const struct spoolss_PrinterInfo2 *info2,
4056 const char *servername,
4057 struct spoolss_PrinterInfo3 *r,
4060 /* These are the components of the SD we are returning. */
4062 if (info2->secdesc != NULL) {
4063 /* don't use talloc_steal() here unless you do a deep steal of all
4064 the SEC_DESC members */
4066 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4067 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4073 /********************************************************************
4074 * construct_printer_info4
4075 * fill a spoolss_PrinterInfo4 struct
4076 ********************************************************************/
4078 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4079 const struct spoolss_PrinterInfo2 *info2,
4080 const char *servername,
4081 struct spoolss_PrinterInfo4 *r,
4086 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4087 if (!W_ERROR_IS_OK(result)) {
4092 r->servername = talloc_strdup(mem_ctx, servername);
4093 W_ERROR_HAVE_NO_MEMORY(r->servername);
4095 r->servername = NULL;
4098 r->attributes = info2->attributes;
4103 /********************************************************************
4104 * construct_printer_info5
4105 * fill a spoolss_PrinterInfo5 struct
4106 ********************************************************************/
4108 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4109 const struct spoolss_PrinterInfo2 *info2,
4110 const char *servername,
4111 struct spoolss_PrinterInfo5 *r,
4116 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4117 if (!W_ERROR_IS_OK(result)) {
4121 r->portname = talloc_strdup(mem_ctx, info2->portname);
4122 W_ERROR_HAVE_NO_MEMORY(r->portname);
4124 r->attributes = info2->attributes;
4126 /* these two are not used by NT+ according to MSDN */
4127 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4128 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4133 /********************************************************************
4134 * construct_printer_info_6
4135 * fill a spoolss_PrinterInfo6 struct
4136 ********************************************************************/
4138 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4139 struct messaging_context *msg_ctx,
4140 const struct spoolss_PrinterInfo2 *info2,
4141 const char *servername,
4142 struct spoolss_PrinterInfo6 *r,
4146 print_status_struct status;
4148 count = print_queue_length(msg_ctx, snum, &status);
4150 r->status = nt_printq_status(status.status);
4155 /********************************************************************
4156 * construct_printer_info7
4157 * fill a spoolss_PrinterInfo7 struct
4158 ********************************************************************/
4160 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4161 struct messaging_context *msg_ctx,
4162 const char *servername,
4163 struct spoolss_PrinterInfo7 *r,
4166 struct auth_serversupplied_info *session_info;
4170 status = make_session_info_system(mem_ctx, &session_info);
4171 if (!NT_STATUS_IS_OK(status)) {
4172 DEBUG(0, ("construct_printer_info7: "
4173 "Could not create system session_info\n"));
4177 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4179 lp_servicename(snum), &guid, NULL)) {
4180 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4181 r->action = DSPRINT_PUBLISH;
4183 r->guid = talloc_strdup(mem_ctx, "");
4184 r->action = DSPRINT_UNPUBLISH;
4186 W_ERROR_HAVE_NO_MEMORY(r->guid);
4188 TALLOC_FREE(session_info);
4192 /********************************************************************
4193 * construct_printer_info8
4194 * fill a spoolss_PrinterInfo8 struct
4195 ********************************************************************/
4197 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4198 const struct spoolss_PrinterInfo2 *info2,
4199 const char *servername,
4200 struct spoolss_DeviceModeInfo *r,
4204 const char *printername;
4206 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4207 if (!W_ERROR_IS_OK(result)) {
4211 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4213 DEBUG(8,("Returning NULL Devicemode!\n"));
4216 compose_devicemode_devicename(r->devmode, printername);
4222 /********************************************************************
4223 ********************************************************************/
4225 static bool snum_is_shared_printer(int snum)
4227 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4230 /********************************************************************
4231 Spoolss_enumprinters.
4232 ********************************************************************/
4234 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4235 const struct auth_serversupplied_info *session_info,
4236 struct messaging_context *msg_ctx,
4237 const char *servername,
4240 union spoolss_PrinterInfo **info_p,
4244 int n_services = lp_numservices();
4245 union spoolss_PrinterInfo *info = NULL;
4247 WERROR result = WERR_OK;
4252 for (snum = 0; snum < n_services; snum++) {
4254 const char *printer;
4255 struct spoolss_PrinterInfo2 *info2;
4257 if (!snum_is_shared_printer(snum)) {
4261 printer = lp_const_servicename(snum);
4263 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4266 result = winreg_create_printer(mem_ctx,
4270 if (!W_ERROR_IS_OK(result)) {
4274 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4275 union spoolss_PrinterInfo,
4278 result = WERR_NOMEM;
4282 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4284 if (!W_ERROR_IS_OK(result)) {
4290 result = construct_printer_info0(info, session_info,
4293 &info[count].info0, snum);
4296 result = construct_printer_info1(info, info2, flags,
4298 &info[count].info1, snum);
4301 result = construct_printer_info2(info, msg_ctx, info2,
4303 &info[count].info2, snum);
4306 result = construct_printer_info4(info, info2,
4308 &info[count].info4, snum);
4311 result = construct_printer_info5(info, info2,
4313 &info[count].info5, snum);
4317 result = WERR_UNKNOWN_LEVEL;
4321 if (!W_ERROR_IS_OK(result)) {
4332 if (!W_ERROR_IS_OK(result)) {
4342 /********************************************************************
4343 * handle enumeration of printers at level 0
4344 ********************************************************************/
4346 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4347 const struct auth_serversupplied_info *session_info,
4348 struct messaging_context *msg_ctx,
4350 const char *servername,
4351 union spoolss_PrinterInfo **info,
4354 DEBUG(4,("enum_all_printers_info_0\n"));
4356 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4357 servername, 0, flags, info, count);
4361 /********************************************************************
4362 ********************************************************************/
4364 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4365 const struct auth_serversupplied_info *session_info,
4366 struct messaging_context *msg_ctx,
4367 const char *servername,
4369 union spoolss_PrinterInfo **info,
4372 DEBUG(4,("enum_all_printers_info_1\n"));
4374 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4375 servername, 1, flags, info, count);
4378 /********************************************************************
4379 enum_all_printers_info_1_local.
4380 *********************************************************************/
4382 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4383 const struct auth_serversupplied_info *session_info,
4384 struct messaging_context *msg_ctx,
4385 const char *servername,
4386 union spoolss_PrinterInfo **info,
4389 DEBUG(4,("enum_all_printers_info_1_local\n"));
4391 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4392 servername, PRINTER_ENUM_ICON8, info, count);
4395 /********************************************************************
4396 enum_all_printers_info_1_name.
4397 *********************************************************************/
4399 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4400 const struct auth_serversupplied_info *session_info,
4401 struct messaging_context *msg_ctx,
4402 const char *servername,
4403 union spoolss_PrinterInfo **info,
4406 const char *s = servername;
4408 DEBUG(4,("enum_all_printers_info_1_name\n"));
4410 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4414 if (!is_myname_or_ipaddr(s)) {
4415 return WERR_INVALID_NAME;
4418 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4419 servername, PRINTER_ENUM_ICON8, info, count);
4422 /********************************************************************
4423 enum_all_printers_info_1_network.
4424 *********************************************************************/
4426 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4427 const struct auth_serversupplied_info *session_info,
4428 struct messaging_context *msg_ctx,
4429 const char *servername,
4430 union spoolss_PrinterInfo **info,
4433 const char *s = servername;
4435 DEBUG(4,("enum_all_printers_info_1_network\n"));
4437 /* If we respond to a enum_printers level 1 on our name with flags
4438 set to PRINTER_ENUM_REMOTE with a list of printers then these
4439 printers incorrectly appear in the APW browse list.
4440 Specifically the printers for the server appear at the workgroup
4441 level where all the other servers in the domain are
4442 listed. Windows responds to this call with a
4443 WERR_CAN_NOT_COMPLETE so we should do the same. */
4445 if (servername[0] == '\\' && servername[1] == '\\') {
4449 if (is_myname_or_ipaddr(s)) {
4450 return WERR_CAN_NOT_COMPLETE;
4453 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4454 servername, PRINTER_ENUM_NAME, info, count);
4457 /********************************************************************
4458 * api_spoolss_enumprinters
4460 * called from api_spoolss_enumprinters (see this to understand)
4461 ********************************************************************/
4463 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4464 const struct auth_serversupplied_info *session_info,
4465 struct messaging_context *msg_ctx,
4466 const char *servername,
4467 union spoolss_PrinterInfo **info,
4470 DEBUG(4,("enum_all_printers_info_2\n"));
4472 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4473 servername, 2, 0, info, count);
4476 /********************************************************************
4477 * handle enumeration of printers at level 1
4478 ********************************************************************/
4480 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4481 const struct auth_serversupplied_info *session_info,
4482 struct messaging_context *msg_ctx,
4484 const char *servername,
4485 union spoolss_PrinterInfo **info,
4488 /* Not all the flags are equals */
4490 if (flags & PRINTER_ENUM_LOCAL) {
4491 return enum_all_printers_info_1_local(mem_ctx, session_info,
4492 msg_ctx, servername, info, count);
4495 if (flags & PRINTER_ENUM_NAME) {
4496 return enum_all_printers_info_1_name(mem_ctx, session_info,
4497 msg_ctx, servername, info,
4501 if (flags & PRINTER_ENUM_NETWORK) {
4502 return enum_all_printers_info_1_network(mem_ctx, session_info,
4503 msg_ctx, servername, info,
4507 return WERR_OK; /* NT4sp5 does that */
4510 /********************************************************************
4511 * handle enumeration of printers at level 2
4512 ********************************************************************/
4514 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4515 const struct auth_serversupplied_info *session_info,
4516 struct messaging_context *msg_ctx,
4518 const char *servername,
4519 union spoolss_PrinterInfo **info,
4522 if (flags & PRINTER_ENUM_LOCAL) {
4524 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4529 if (flags & PRINTER_ENUM_NAME) {
4530 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4531 return WERR_INVALID_NAME;
4534 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4539 if (flags & PRINTER_ENUM_REMOTE) {
4540 return WERR_UNKNOWN_LEVEL;
4546 /********************************************************************
4547 * handle enumeration of printers at level 4
4548 ********************************************************************/
4550 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4551 const struct auth_serversupplied_info *session_info,
4552 struct messaging_context *msg_ctx,
4554 const char *servername,
4555 union spoolss_PrinterInfo **info,
4558 DEBUG(4,("enum_all_printers_info_4\n"));
4560 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4561 servername, 4, flags, info, count);
4565 /********************************************************************
4566 * handle enumeration of printers at level 5
4567 ********************************************************************/
4569 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4570 const struct auth_serversupplied_info *session_info,
4571 struct messaging_context *msg_ctx,
4573 const char *servername,
4574 union spoolss_PrinterInfo **info,
4577 DEBUG(4,("enum_all_printers_info_5\n"));
4579 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4580 servername, 5, flags, info, count);
4583 /****************************************************************
4584 _spoolss_EnumPrinters
4585 ****************************************************************/
4587 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4588 struct spoolss_EnumPrinters *r)
4590 const struct auth_serversupplied_info *session_info = get_session_info_system();
4593 /* that's an [in out] buffer */
4595 if (!r->in.buffer && (r->in.offered != 0)) {
4596 return WERR_INVALID_PARAM;
4599 DEBUG(4,("_spoolss_EnumPrinters\n"));
4603 *r->out.info = NULL;
4607 * flags==PRINTER_ENUM_NAME
4608 * if name=="" then enumerates all printers
4609 * if name!="" then enumerate the printer
4610 * flags==PRINTER_ENUM_REMOTE
4611 * name is NULL, enumerate printers
4612 * Level 2: name!="" enumerates printers, name can't be NULL
4613 * Level 3: doesn't exist
4614 * Level 4: does a local registry lookup
4615 * Level 5: same as Level 2
4618 if (r->in.server && r->in.server[0] == '\0') {
4619 r->in.server = NULL;
4622 switch (r->in.level) {
4624 result = enumprinters_level0(p->mem_ctx, session_info,
4625 p->msg_ctx, r->in.flags,
4627 r->out.info, r->out.count);
4630 result = enumprinters_level1(p->mem_ctx, session_info,
4631 p->msg_ctx, r->in.flags,
4633 r->out.info, r->out.count);
4636 result = enumprinters_level2(p->mem_ctx, session_info,
4637 p->msg_ctx, r->in.flags,
4639 r->out.info, r->out.count);
4642 result = enumprinters_level4(p->mem_ctx, session_info,
4643 p->msg_ctx, r->in.flags,
4645 r->out.info, r->out.count);
4648 result = enumprinters_level5(p->mem_ctx, session_info,
4649 p->msg_ctx, r->in.flags,
4651 r->out.info, r->out.count);
4654 return WERR_UNKNOWN_LEVEL;
4657 if (!W_ERROR_IS_OK(result)) {
4661 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4662 spoolss_EnumPrinters,
4663 *r->out.info, r->in.level,
4665 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4666 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4668 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4671 /****************************************************************
4673 ****************************************************************/
4675 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4676 struct spoolss_GetPrinter *r)
4678 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4679 struct spoolss_PrinterInfo2 *info2 = NULL;
4680 WERROR result = WERR_OK;
4683 /* that's an [in out] buffer */
4685 if (!r->in.buffer && (r->in.offered != 0)) {
4686 return WERR_INVALID_PARAM;
4691 if (Printer == NULL) {
4695 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4699 result = winreg_get_printer(p->mem_ctx,
4700 get_session_info_system(),
4702 lp_const_servicename(snum),
4704 if (!W_ERROR_IS_OK(result)) {
4708 switch (r->in.level) {
4710 result = construct_printer_info0(p->mem_ctx,
4711 get_session_info_system(),
4714 Printer->servername,
4715 &r->out.info->info0,
4719 result = construct_printer_info1(p->mem_ctx, info2,
4721 Printer->servername,
4722 &r->out.info->info1, snum);
4725 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4726 Printer->servername,
4727 &r->out.info->info2, snum);
4730 result = construct_printer_info3(p->mem_ctx, info2,
4731 Printer->servername,
4732 &r->out.info->info3, snum);
4735 result = construct_printer_info4(p->mem_ctx, info2,
4736 Printer->servername,
4737 &r->out.info->info4, snum);
4740 result = construct_printer_info5(p->mem_ctx, info2,
4741 Printer->servername,
4742 &r->out.info->info5, snum);
4745 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4746 Printer->servername,
4747 &r->out.info->info6, snum);
4750 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4751 Printer->servername,
4752 &r->out.info->info7, snum);
4755 result = construct_printer_info8(p->mem_ctx, info2,
4756 Printer->servername,
4757 &r->out.info->info8, snum);
4760 result = WERR_UNKNOWN_LEVEL;
4765 if (!W_ERROR_IS_OK(result)) {
4766 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4767 r->in.level, win_errstr(result)));
4768 TALLOC_FREE(r->out.info);
4772 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4773 r->out.info, r->in.level);
4774 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4776 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4779 /********************************************************************
4780 ********************************************************************/
4782 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4784 if (in && strlen(in)) { \
4785 out = talloc_strdup(mem_ctx, in); \
4787 out = talloc_strdup(mem_ctx, ""); \
4789 W_ERROR_HAVE_NO_MEMORY(out); \
4792 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4794 if (in && strlen(in)) { \
4795 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4797 out = talloc_strdup(mem_ctx, ""); \
4799 W_ERROR_HAVE_NO_MEMORY(out); \
4802 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4803 const char **string_array,
4804 const char ***presult,
4805 const char *cservername,
4809 int i, num_strings = 0;
4810 const char **array = NULL;
4812 if (string_array == NULL) {
4813 return WERR_INVALID_PARAMETER;
4816 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4817 const char *str = NULL;
4819 if (cservername == NULL || arch == NULL) {
4820 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4822 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4825 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4832 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4833 &array, &num_strings);
4843 /********************************************************************
4844 * fill a spoolss_DriverInfo1 struct
4845 ********************************************************************/
4847 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4848 struct spoolss_DriverInfo1 *r,
4849 const struct spoolss_DriverInfo8 *driver,
4850 const char *servername)
4852 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4853 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4858 /********************************************************************
4859 * fill a spoolss_DriverInfo2 struct
4860 ********************************************************************/
4862 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4863 struct spoolss_DriverInfo2 *r,
4864 const struct spoolss_DriverInfo8 *driver,
4865 const char *servername)
4868 const char *cservername = canon_servername(servername);
4870 r->version = driver->version;
4872 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4873 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4874 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4875 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4877 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4878 driver->architecture,
4880 driver->driver_path,
4883 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4884 driver->architecture,
4889 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4890 driver->architecture,
4892 driver->config_file,
4898 /********************************************************************
4899 * fill a spoolss_DriverInfo3 struct
4900 ********************************************************************/
4902 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4903 struct spoolss_DriverInfo3 *r,
4904 const struct spoolss_DriverInfo8 *driver,
4905 const char *servername)
4907 const char *cservername = canon_servername(servername);
4909 r->version = driver->version;
4911 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4912 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4913 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4914 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4916 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4917 driver->architecture,
4919 driver->driver_path,
4922 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923 driver->architecture,
4928 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4929 driver->architecture,
4931 driver->config_file,
4934 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4935 driver->architecture,
4940 FILL_DRIVER_STRING(mem_ctx,
4941 driver->monitor_name,
4944 FILL_DRIVER_STRING(mem_ctx,
4945 driver->default_datatype,
4946 r->default_datatype);
4948 return string_array_from_driver_info(mem_ctx,
4949 driver->dependent_files,
4950 &r->dependent_files,
4952 driver->architecture,
4956 /********************************************************************
4957 * fill a spoolss_DriverInfo4 struct
4958 ********************************************************************/
4960 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4961 struct spoolss_DriverInfo4 *r,
4962 const struct spoolss_DriverInfo8 *driver,
4963 const char *servername)
4965 const char *cservername = canon_servername(servername);
4968 r->version = driver->version;
4970 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4971 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4972 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4973 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4975 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4976 driver->architecture,
4978 driver->driver_path,
4981 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4982 driver->architecture,
4987 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4988 driver->architecture,
4990 driver->config_file,
4993 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994 driver->architecture,
4999 result = string_array_from_driver_info(mem_ctx,
5000 driver->dependent_files,
5001 &r->dependent_files,
5003 driver->architecture,
5005 if (!W_ERROR_IS_OK(result)) {
5009 FILL_DRIVER_STRING(mem_ctx,
5010 driver->monitor_name,
5013 FILL_DRIVER_STRING(mem_ctx,
5014 driver->default_datatype,
5015 r->default_datatype);
5018 result = string_array_from_driver_info(mem_ctx,
5019 driver->previous_names,
5026 /********************************************************************
5027 * fill a spoolss_DriverInfo5 struct
5028 ********************************************************************/
5030 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5031 struct spoolss_DriverInfo5 *r,
5032 const struct spoolss_DriverInfo8 *driver,
5033 const char *servername)
5035 const char *cservername = canon_servername(servername);
5037 r->version = driver->version;
5039 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5040 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5041 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5042 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5044 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5045 driver->architecture,
5047 driver->driver_path,
5050 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051 driver->architecture,
5056 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057 driver->architecture,
5059 driver->config_file,
5062 r->driver_attributes = 0;
5063 r->config_version = 0;
5064 r->driver_version = 0;
5068 /********************************************************************
5069 * fill a spoolss_DriverInfo6 struct
5070 ********************************************************************/
5072 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5073 struct spoolss_DriverInfo6 *r,
5074 const struct spoolss_DriverInfo8 *driver,
5075 const char *servername)
5077 const char *cservername = canon_servername(servername);
5080 r->version = driver->version;
5082 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5083 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5084 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5085 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5087 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5088 driver->architecture,
5090 driver->driver_path,
5093 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094 driver->architecture,
5099 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5100 driver->architecture,
5102 driver->config_file,
5105 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5106 driver->architecture,
5111 FILL_DRIVER_STRING(mem_ctx,
5112 driver->monitor_name,
5115 FILL_DRIVER_STRING(mem_ctx,
5116 driver->default_datatype,
5117 r->default_datatype);
5119 result = string_array_from_driver_info(mem_ctx,
5120 driver->dependent_files,
5121 &r->dependent_files,
5123 driver->architecture,
5125 if (!W_ERROR_IS_OK(result)) {
5129 result = string_array_from_driver_info(mem_ctx,
5130 driver->previous_names,
5133 if (!W_ERROR_IS_OK(result)) {
5137 r->driver_date = driver->driver_date;
5138 r->driver_version = driver->driver_version;
5140 FILL_DRIVER_STRING(mem_ctx,
5141 driver->manufacturer_name,
5142 r->manufacturer_name);
5143 FILL_DRIVER_STRING(mem_ctx,
5144 driver->manufacturer_url,
5145 r->manufacturer_url);
5146 FILL_DRIVER_STRING(mem_ctx,
5147 driver->hardware_id,
5149 FILL_DRIVER_STRING(mem_ctx,
5156 /********************************************************************
5157 * fill a spoolss_DriverInfo8 struct
5158 ********************************************************************/
5160 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5161 struct spoolss_DriverInfo8 *r,
5162 const struct spoolss_DriverInfo8 *driver,
5163 const char *servername)
5165 const char *cservername = canon_servername(servername);
5168 r->version = driver->version;
5170 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5171 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5172 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5173 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5175 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5176 driver->architecture,
5178 driver->driver_path,
5181 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182 driver->architecture,
5187 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5188 driver->architecture,
5190 driver->config_file,
5193 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5194 driver->architecture,
5199 FILL_DRIVER_STRING(mem_ctx,
5200 driver->monitor_name,
5203 FILL_DRIVER_STRING(mem_ctx,
5204 driver->default_datatype,
5205 r->default_datatype);
5207 result = string_array_from_driver_info(mem_ctx,
5208 driver->dependent_files,
5209 &r->dependent_files,
5211 driver->architecture,
5213 if (!W_ERROR_IS_OK(result)) {
5217 result = string_array_from_driver_info(mem_ctx,
5218 driver->previous_names,
5221 if (!W_ERROR_IS_OK(result)) {
5225 r->driver_date = driver->driver_date;
5226 r->driver_version = driver->driver_version;
5228 FILL_DRIVER_STRING(mem_ctx,
5229 driver->manufacturer_name,
5230 r->manufacturer_name);
5231 FILL_DRIVER_STRING(mem_ctx,
5232 driver->manufacturer_url,
5233 r->manufacturer_url);
5234 FILL_DRIVER_STRING(mem_ctx,
5235 driver->hardware_id,
5237 FILL_DRIVER_STRING(mem_ctx,
5241 FILL_DRIVER_STRING(mem_ctx,
5242 driver->print_processor,
5243 r->print_processor);
5244 FILL_DRIVER_STRING(mem_ctx,
5245 driver->vendor_setup,
5248 result = string_array_from_driver_info(mem_ctx,
5249 driver->color_profiles,
5252 if (!W_ERROR_IS_OK(result)) {
5256 FILL_DRIVER_STRING(mem_ctx,
5260 r->printer_driver_attributes = driver->printer_driver_attributes;
5262 result = string_array_from_driver_info(mem_ctx,
5263 driver->core_driver_dependencies,
5264 &r->core_driver_dependencies,
5266 if (!W_ERROR_IS_OK(result)) {
5270 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5271 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5276 #if 0 /* disabled until marshalling issues are resolved - gd */
5277 /********************************************************************
5278 ********************************************************************/
5280 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5281 struct spoolss_DriverFileInfo *r,
5282 const char *cservername,
5283 const char *file_name,
5284 enum spoolss_DriverFileType file_type,
5285 uint32_t file_version)
5287 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5288 cservername, file_name);
5289 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5290 r->file_type = file_type;
5291 r->file_version = file_version;
5296 /********************************************************************
5297 ********************************************************************/
5299 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5300 const struct spoolss_DriverInfo8 *driver,
5301 const char *cservername,
5302 struct spoolss_DriverFileInfo **info_p,
5305 struct spoolss_DriverFileInfo *info = NULL;
5313 if (strlen(driver->driver_path)) {
5314 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5315 struct spoolss_DriverFileInfo,
5317 W_ERROR_HAVE_NO_MEMORY(info);
5318 result = fill_spoolss_DriverFileInfo(info,
5321 driver->driver_path,
5322 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5324 W_ERROR_NOT_OK_RETURN(result);
5328 if (strlen(driver->config_file)) {
5329 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5330 struct spoolss_DriverFileInfo,
5332 W_ERROR_HAVE_NO_MEMORY(info);
5333 result = fill_spoolss_DriverFileInfo(info,
5336 driver->config_file,
5337 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5339 W_ERROR_NOT_OK_RETURN(result);
5343 if (strlen(driver->data_file)) {
5344 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5345 struct spoolss_DriverFileInfo,
5347 W_ERROR_HAVE_NO_MEMORY(info);
5348 result = fill_spoolss_DriverFileInfo(info,
5352 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5354 W_ERROR_NOT_OK_RETURN(result);
5358 if (strlen(driver->help_file)) {
5359 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5360 struct spoolss_DriverFileInfo,
5362 W_ERROR_HAVE_NO_MEMORY(info);
5363 result = fill_spoolss_DriverFileInfo(info,
5367 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5369 W_ERROR_NOT_OK_RETURN(result);
5373 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5374 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5375 struct spoolss_DriverFileInfo,
5377 W_ERROR_HAVE_NO_MEMORY(info);
5378 result = fill_spoolss_DriverFileInfo(info,
5381 driver->dependent_files[i],
5382 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5384 W_ERROR_NOT_OK_RETURN(result);
5394 /********************************************************************
5395 * fill a spoolss_DriverInfo101 struct
5396 ********************************************************************/
5398 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5399 struct spoolss_DriverInfo101 *r,
5400 const struct spoolss_DriverInfo8 *driver,
5401 const char *servername)
5403 const char *cservername = canon_servername(servername);
5406 r->version = driver->version;
5408 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5409 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5410 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5411 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5413 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5417 if (!W_ERROR_IS_OK(result)) {
5421 FILL_DRIVER_STRING(mem_ctx,
5422 driver->monitor_name,
5425 FILL_DRIVER_STRING(mem_ctx,
5426 driver->default_datatype,
5427 r->default_datatype);
5429 result = string_array_from_driver_info(mem_ctx,
5430 driver->previous_names,
5433 if (!W_ERROR_IS_OK(result)) {
5437 r->driver_date = driver->driver_date;
5438 r->driver_version = driver->driver_version;
5440 FILL_DRIVER_STRING(mem_ctx,
5441 driver->manufacturer_name,
5442 r->manufacturer_name);
5443 FILL_DRIVER_STRING(mem_ctx,
5444 driver->manufacturer_url,
5445 r->manufacturer_url);
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->hardware_id,
5449 FILL_DRIVER_STRING(mem_ctx,
5456 /********************************************************************
5457 ********************************************************************/
5459 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5460 const struct auth_serversupplied_info *session_info,
5461 struct messaging_context *msg_ctx,
5463 union spoolss_DriverInfo *r,
5465 const char *servername,
5466 const char *architecture,
5469 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5470 struct spoolss_DriverInfo8 *driver;
5474 return WERR_UNKNOWN_LEVEL;
5477 result = winreg_get_printer(mem_ctx,
5480 lp_const_servicename(snum),
5483 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5484 win_errstr(result)));
5486 if (!W_ERROR_IS_OK(result)) {
5487 return WERR_INVALID_PRINTER_NAME;
5490 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5492 pinfo2->drivername, version, &driver);
5494 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5495 win_errstr(result)));
5497 if (!W_ERROR_IS_OK(result)) {
5499 * Is this a W2k client ?
5503 talloc_free(pinfo2);
5504 return WERR_UNKNOWN_PRINTER_DRIVER;
5507 /* Yes - try again with a WinNT driver. */
5509 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5513 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5514 win_errstr(result)));
5515 if (!W_ERROR_IS_OK(result)) {
5516 talloc_free(pinfo2);
5517 return WERR_UNKNOWN_PRINTER_DRIVER;
5523 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5526 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5529 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5532 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5535 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5538 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5541 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5543 #if 0 /* disabled until marshalling issues are resolved - gd */
5545 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5549 result = WERR_UNKNOWN_LEVEL;
5553 talloc_free(pinfo2);
5554 talloc_free(driver);
5559 /****************************************************************
5560 _spoolss_GetPrinterDriver2
5561 ****************************************************************/
5563 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5564 struct spoolss_GetPrinterDriver2 *r)
5566 struct printer_handle *printer;
5571 /* that's an [in out] buffer */
5573 if (!r->in.buffer && (r->in.offered != 0)) {
5574 return WERR_INVALID_PARAM;
5577 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5579 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5580 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5581 return WERR_INVALID_PRINTER_NAME;
5585 *r->out.server_major_version = 0;
5586 *r->out.server_minor_version = 0;
5588 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5592 result = construct_printer_driver_info_level(p->mem_ctx,
5593 get_session_info_system(),
5595 r->in.level, r->out.info,
5596 snum, printer->servername,
5598 r->in.client_major_version);
5599 if (!W_ERROR_IS_OK(result)) {
5600 TALLOC_FREE(r->out.info);
5604 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5605 r->out.info, r->in.level);
5606 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5608 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5612 /****************************************************************
5613 _spoolss_StartPagePrinter
5614 ****************************************************************/
5616 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5617 struct spoolss_StartPagePrinter *r)
5619 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5622 DEBUG(3,("_spoolss_StartPagePrinter: "
5623 "Error in startpageprinter printer handle\n"));
5627 Printer->page_started = true;
5631 /****************************************************************
5632 _spoolss_EndPagePrinter
5633 ****************************************************************/
5635 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5636 struct spoolss_EndPagePrinter *r)
5640 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5643 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5644 OUR_HANDLE(r->in.handle)));
5648 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5651 Printer->page_started = false;
5652 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5657 /****************************************************************
5658 _spoolss_StartDocPrinter
5659 ****************************************************************/
5661 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5662 struct spoolss_StartDocPrinter *r)
5664 struct spoolss_DocumentInfo1 *info_1;
5666 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5670 DEBUG(2,("_spoolss_StartDocPrinter: "
5671 "Invalid handle (%s:%u:%u)\n",
5672 OUR_HANDLE(r->in.handle)));
5676 if (Printer->jobid) {
5677 DEBUG(2, ("_spoolss_StartDocPrinter: "
5678 "StartDocPrinter called twice! "
5679 "(existing jobid = %d)\n", Printer->jobid));
5680 return WERR_INVALID_HANDLE;
5683 if (r->in.level != 1) {
5684 return WERR_UNKNOWN_LEVEL;
5687 info_1 = r->in.info.info1;
5690 * a nice thing with NT is it doesn't listen to what you tell it.
5691 * when asked to send _only_ RAW datas, it tries to send datas
5694 * So I add checks like in NT Server ...
5697 if (info_1->datatype) {
5698 if (strcmp(info_1->datatype, "RAW") != 0) {
5700 return WERR_INVALID_DATATYPE;
5704 /* get the share number of the printer */
5705 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5709 werr = print_job_start(p->session_info,
5713 info_1->document_name,
5714 info_1->output_file,
5718 /* An error occured in print_job_start() so return an appropriate
5721 if (!W_ERROR_IS_OK(werr)) {
5725 Printer->document_started = true;
5726 *r->out.job_id = Printer->jobid;
5731 /****************************************************************
5732 _spoolss_EndDocPrinter
5733 ****************************************************************/
5735 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5736 struct spoolss_EndDocPrinter *r)
5738 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5743 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5744 OUR_HANDLE(r->in.handle)));
5748 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5752 Printer->document_started = false;
5753 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5754 if (!NT_STATUS_IS_OK(status)) {
5755 DEBUG(2, ("_spoolss_EndDocPrinter: "
5756 "print_job_end failed [%s]\n",
5757 nt_errstr(status)));
5761 return ntstatus_to_werror(status);
5764 /****************************************************************
5765 _spoolss_WritePrinter
5766 ****************************************************************/
5768 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5769 struct spoolss_WritePrinter *r)
5771 ssize_t buffer_written;
5773 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5776 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5777 OUR_HANDLE(r->in.handle)));
5778 *r->out.num_written = r->in._data_size;
5782 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5785 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5786 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5787 snum, Printer->jobid,
5788 (const char *)r->in.data.data,
5789 (size_t)r->in._data_size);
5790 if (buffer_written == (ssize_t)-1) {
5791 *r->out.num_written = 0;
5792 if (errno == ENOSPC)
5793 return WERR_NO_SPOOL_SPACE;
5795 return WERR_ACCESS_DENIED;
5798 *r->out.num_written = r->in._data_size;
5803 /********************************************************************
5804 * api_spoolss_getprinter
5805 * called from the spoolss dispatcher
5807 ********************************************************************/
5809 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5810 struct pipes_struct *p)
5812 const struct auth_serversupplied_info *session_info = p->session_info;
5814 WERROR errcode = WERR_BADFUNC;
5815 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5818 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5819 OUR_HANDLE(handle)));
5823 if (!get_printer_snum(p, handle, &snum, NULL))
5827 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5828 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5830 case SPOOLSS_PRINTER_CONTROL_RESUME:
5831 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5832 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5834 case SPOOLSS_PRINTER_CONTROL_PURGE:
5835 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5838 return WERR_UNKNOWN_LEVEL;
5845 /****************************************************************
5846 _spoolss_AbortPrinter
5847 * From MSDN: "Deletes printer's spool file if printer is configured
5849 ****************************************************************/
5851 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5852 struct spoolss_AbortPrinter *r)
5854 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5856 WERROR errcode = WERR_OK;
5859 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5860 OUR_HANDLE(r->in.handle)));
5864 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5867 if (!Printer->document_started) {
5868 return WERR_SPL_NO_STARTDOC;
5871 errcode = print_job_delete(p->session_info,
5879 /********************************************************************
5880 * called by spoolss_api_setprinter
5881 * when updating a printer description
5882 ********************************************************************/
5884 static WERROR update_printer_sec(struct policy_handle *handle,
5885 struct pipes_struct *p,
5886 struct sec_desc_buf *secdesc_ctr)
5888 struct spoolss_security_descriptor *new_secdesc = NULL;
5889 struct spoolss_security_descriptor *old_secdesc = NULL;
5890 const char *printer;
5894 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5896 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5897 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5898 OUR_HANDLE(handle)));
5900 result = WERR_BADFID;
5904 if (secdesc_ctr == NULL) {
5905 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5906 result = WERR_INVALID_PARAM;
5909 printer = lp_const_servicename(snum);
5911 /* Check the user has permissions to change the security
5912 descriptor. By experimentation with two NT machines, the user
5913 requires Full Access to the printer to change security
5916 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5917 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5918 result = WERR_ACCESS_DENIED;
5922 /* NT seems to like setting the security descriptor even though
5923 nothing may have actually changed. */
5924 result = winreg_get_printer_secdesc(p->mem_ctx,
5925 get_session_info_system(),
5929 if (!W_ERROR_IS_OK(result)) {
5930 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5931 result = WERR_BADFID;
5935 if (DEBUGLEVEL >= 10) {
5936 struct security_acl *the_acl;
5939 the_acl = old_secdesc->dacl;
5940 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5941 printer, the_acl->num_aces));
5943 for (i = 0; i < the_acl->num_aces; i++) {
5944 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5945 &the_acl->aces[i].trustee),
5946 the_acl->aces[i].access_mask));
5949 the_acl = secdesc_ctr->sd->dacl;
5952 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5953 printer, the_acl->num_aces));
5955 for (i = 0; i < the_acl->num_aces; i++) {
5956 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5957 &the_acl->aces[i].trustee),
5958 the_acl->aces[i].access_mask));
5961 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5965 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5966 if (new_secdesc == NULL) {
5967 result = WERR_NOMEM;
5971 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5976 result = winreg_set_printer_secdesc(p->mem_ctx,
5977 get_session_info_system(),
5986 /********************************************************************
5987 Canonicalize printer info from a client
5988 ********************************************************************/
5990 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5991 struct spoolss_SetPrinterInfo2 *info2,
5994 fstring printername;
5997 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5998 "portname=%s drivername=%s comment=%s location=%s\n",
5999 info2->servername, info2->printername, info2->sharename,
6000 info2->portname, info2->drivername, info2->comment,
6003 /* we force some elements to "correct" values */
6004 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6005 if (info2->servername == NULL) {
6008 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6009 if (info2->sharename == NULL) {
6013 /* check to see if we allow printername != sharename */
6014 if (lp_force_printername(snum)) {
6015 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6016 global_myname(), info2->sharename);
6018 /* make sure printername is in \\server\printername format */
6019 fstrcpy(printername, info2->printername);
6021 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6022 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6026 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6027 global_myname(), p);
6029 if (info2->printername == NULL) {
6033 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6034 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6039 /****************************************************************************
6040 ****************************************************************************/
6042 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6044 char *cmd = lp_addport_cmd();
6045 char *command = NULL;
6047 bool is_print_op = false;
6050 return WERR_ACCESS_DENIED;
6053 command = talloc_asprintf(ctx,
6054 "%s \"%s\" \"%s\"", cmd, portname, uri );
6060 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6062 DEBUG(10,("Running [%s]\n", command));
6064 /********* BEGIN SePrintOperatorPrivilege **********/
6069 ret = smbrun(command, NULL);
6074 /********* END SePrintOperatorPrivilege **********/
6076 DEBUGADD(10,("returned [%d]\n", ret));
6078 TALLOC_FREE(command);
6081 return WERR_ACCESS_DENIED;
6087 /****************************************************************************
6088 ****************************************************************************/
6090 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6091 struct spoolss_SetPrinterInfo2 *info2,
6092 const char *remote_machine,
6093 struct messaging_context *msg_ctx)
6095 char *cmd = lp_addprinter_cmd();
6097 char *command = NULL;
6101 bool is_print_op = false;
6103 if (!remote_machine) {
6107 command = talloc_asprintf(ctx,
6108 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6109 cmd, info2->printername, info2->sharename,
6110 info2->portname, info2->drivername,
6111 info2->location, info2->comment, remote_machine);
6117 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6119 DEBUG(10,("Running [%s]\n", command));
6121 /********* BEGIN SePrintOperatorPrivilege **********/
6126 if ( (ret = smbrun(command, &fd)) == 0 ) {
6127 /* Tell everyone we updated smb.conf. */
6128 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6134 /********* END SePrintOperatorPrivilege **********/
6136 DEBUGADD(10,("returned [%d]\n", ret));
6138 TALLOC_FREE(command);
6146 /* reload our services immediately */
6148 reload_services(msg_ctx, -1, false);
6152 /* Get lines and convert them back to dos-codepage */
6153 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6154 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6157 /* Set the portname to what the script says the portname should be. */
6158 /* but don't require anything to be return from the script exit a good error code */
6161 /* Set the portname to what the script says the portname should be. */
6162 info2->portname = talloc_strdup(ctx, qlines[0]);
6163 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6166 TALLOC_FREE(qlines);
6170 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6171 const struct auth_serversupplied_info *session_info,
6172 struct messaging_context *msg_ctx,
6174 struct spoolss_SetPrinterInfo2 *printer,
6175 struct spoolss_PrinterInfo2 *old_printer)
6177 bool force_update = (old_printer == NULL);
6178 const char *dnsdomname;
6179 const char *longname;
6180 const char *uncname;
6181 const char *spooling;
6183 WERROR result = WERR_OK;
6185 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6186 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6187 winreg_set_printer_dataex(mem_ctx,
6191 SPOOL_DSSPOOLER_KEY,
6192 SPOOL_REG_DRIVERNAME,
6197 if (!force_update) {
6198 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6199 printer->drivername));
6201 notify_printer_driver(server_event_context(), msg_ctx,
6202 snum, printer->drivername ?
6203 printer->drivername : "");
6207 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6208 push_reg_sz(mem_ctx, &buffer, printer->comment);
6209 winreg_set_printer_dataex(mem_ctx,
6213 SPOOL_DSSPOOLER_KEY,
6214 SPOOL_REG_DESCRIPTION,
6219 if (!force_update) {
6220 notify_printer_comment(server_event_context(), msg_ctx,
6221 snum, printer->comment ?
6222 printer->comment : "");
6226 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6227 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6228 winreg_set_printer_dataex(mem_ctx,
6232 SPOOL_DSSPOOLER_KEY,
6233 SPOOL_REG_PRINTSHARENAME,
6238 if (!force_update) {
6239 notify_printer_sharename(server_event_context(),
6241 snum, printer->sharename ?
6242 printer->sharename : "");
6246 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6249 p = strrchr(printer->printername, '\\' );
6253 p = printer->printername;
6256 push_reg_sz(mem_ctx, &buffer, p);
6257 winreg_set_printer_dataex(mem_ctx,
6261 SPOOL_DSSPOOLER_KEY,
6262 SPOOL_REG_PRINTERNAME,
6267 if (!force_update) {
6268 notify_printer_printername(server_event_context(),
6269 msg_ctx, snum, p ? p : "");
6273 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6274 push_reg_sz(mem_ctx, &buffer, printer->portname);
6275 winreg_set_printer_dataex(mem_ctx,
6279 SPOOL_DSSPOOLER_KEY,
6285 if (!force_update) {
6286 notify_printer_port(server_event_context(),
6287 msg_ctx, snum, printer->portname ?
6288 printer->portname : "");
6292 if (force_update || !strequal(printer->location, old_printer->location)) {
6293 push_reg_sz(mem_ctx, &buffer, printer->location);
6294 winreg_set_printer_dataex(mem_ctx,
6298 SPOOL_DSSPOOLER_KEY,
6304 if (!force_update) {
6305 notify_printer_location(server_event_context(),
6308 printer->location : "");
6312 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6313 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6314 winreg_set_printer_dataex(mem_ctx,
6318 SPOOL_DSSPOOLER_KEY,
6319 SPOOL_REG_PRINTSEPARATORFILE,
6324 if (!force_update) {
6325 notify_printer_sepfile(server_event_context(),
6328 printer->sepfile : "");
6332 if (force_update || printer->starttime != old_printer->starttime) {
6333 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6334 SIVAL(buffer.data, 0, printer->starttime);
6335 winreg_set_printer_dataex(mem_ctx,
6339 SPOOL_DSSPOOLER_KEY,
6340 SPOOL_REG_PRINTSTARTTIME,
6346 if (force_update || printer->untiltime != old_printer->untiltime) {
6347 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6348 SIVAL(buffer.data, 0, printer->untiltime);
6349 winreg_set_printer_dataex(mem_ctx,
6353 SPOOL_DSSPOOLER_KEY,
6354 SPOOL_REG_PRINTENDTIME,
6360 if (force_update || printer->priority != old_printer->priority) {
6361 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6362 SIVAL(buffer.data, 0, printer->priority);
6363 winreg_set_printer_dataex(mem_ctx,
6367 SPOOL_DSSPOOLER_KEY,
6374 if (force_update || printer->attributes != old_printer->attributes) {
6375 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6376 SIVAL(buffer.data, 0, (printer->attributes &
6377 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6378 winreg_set_printer_dataex(mem_ctx,
6382 SPOOL_DSSPOOLER_KEY,
6383 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6388 switch (printer->attributes & 0x3) {
6390 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6393 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6396 spooling = SPOOL_REGVAL_PRINTDIRECT;
6399 spooling = "unknown";
6401 push_reg_sz(mem_ctx, &buffer, spooling);
6402 winreg_set_printer_dataex(mem_ctx,
6406 SPOOL_DSSPOOLER_KEY,
6407 SPOOL_REG_PRINTSPOOLING,
6413 push_reg_sz(mem_ctx, &buffer, global_myname());
6414 winreg_set_printer_dataex(mem_ctx,
6418 SPOOL_DSSPOOLER_KEY,
6419 SPOOL_REG_SHORTSERVERNAME,
6424 dnsdomname = get_mydnsfullname();
6425 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6426 longname = talloc_strdup(mem_ctx, dnsdomname);
6428 longname = talloc_strdup(mem_ctx, global_myname());
6430 if (longname == NULL) {
6431 result = WERR_NOMEM;
6435 push_reg_sz(mem_ctx, &buffer, longname);
6436 winreg_set_printer_dataex(mem_ctx,
6440 SPOOL_DSSPOOLER_KEY,
6441 SPOOL_REG_SERVERNAME,
6446 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6447 global_myname(), printer->sharename);
6448 push_reg_sz(mem_ctx, &buffer, uncname);
6449 winreg_set_printer_dataex(mem_ctx,
6453 SPOOL_DSSPOOLER_KEY,
6463 /********************************************************************
6464 * Called by spoolss_api_setprinter
6465 * when updating a printer description.
6466 ********************************************************************/
6468 static WERROR update_printer(struct pipes_struct *p,
6469 struct policy_handle *handle,
6470 struct spoolss_SetPrinterInfoCtr *info_ctr,
6471 struct spoolss_DeviceMode *devmode)
6473 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6474 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6475 struct spoolss_PrinterInfo2 *old_printer;
6476 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6478 WERROR result = WERR_OK;
6479 TALLOC_CTX *tmp_ctx;
6481 DEBUG(8,("update_printer\n"));
6483 tmp_ctx = talloc_new(p->mem_ctx);
6484 if (tmp_ctx == NULL) {
6489 result = WERR_BADFID;
6493 if (!get_printer_snum(p, handle, &snum, NULL)) {
6494 result = WERR_BADFID;
6498 result = winreg_get_printer(tmp_ctx,
6499 get_session_info_system(),
6501 lp_const_servicename(snum),
6503 if (!W_ERROR_IS_OK(result)) {
6504 result = WERR_BADFID;
6508 /* Do sanity check on the requested changes for Samba */
6509 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6510 result = WERR_INVALID_PARAM;
6514 /* FIXME!!! If the driver has changed we really should verify that
6515 it is installed before doing much else --jerry */
6517 /* Check calling user has permission to update printer description */
6518 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6519 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6520 result = WERR_ACCESS_DENIED;
6524 /* Call addprinter hook */
6525 /* Check changes to see if this is really needed */
6527 if (*lp_addprinter_cmd() &&
6528 (!strequal(printer->drivername, old_printer->drivername) ||
6529 !strequal(printer->comment, old_printer->comment) ||
6530 !strequal(printer->portname, old_printer->portname) ||
6531 !strequal(printer->location, old_printer->location)) )
6533 /* add_printer_hook() will call reload_services() */
6534 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6535 printer, p->client_id->addr,
6537 result = WERR_ACCESS_DENIED;
6542 update_dsspooler(tmp_ctx,
6543 get_session_info_system(),
6549 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6551 if (devmode == NULL) {
6552 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6554 result = winreg_update_printer(tmp_ctx,
6555 get_session_info_system(),
6564 talloc_free(tmp_ctx);
6569 /****************************************************************************
6570 ****************************************************************************/
6571 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6572 struct policy_handle *handle,
6573 struct spoolss_SetPrinterInfo7 *info7)
6576 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6579 struct printer_handle *Printer;
6581 if ( lp_security() != SEC_ADS ) {
6582 return WERR_UNKNOWN_LEVEL;
6585 Printer = find_printer_index_by_hnd(p, handle);
6587 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6592 if (!get_printer_snum(p, handle, &snum, NULL))
6595 result = winreg_get_printer(p->mem_ctx,
6596 get_session_info_system(),
6598 lp_servicename(snum),
6600 if (!W_ERROR_IS_OK(result)) {
6604 nt_printer_publish(pinfo2,
6605 get_session_info_system(),
6610 TALLOC_FREE(pinfo2);
6613 return WERR_UNKNOWN_LEVEL;
6617 /********************************************************************
6618 ********************************************************************/
6620 static WERROR update_printer_devmode(struct pipes_struct *p,
6621 struct policy_handle *handle,
6622 struct spoolss_DeviceMode *devmode)
6625 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6626 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6628 DEBUG(8,("update_printer_devmode\n"));
6634 if (!get_printer_snum(p, handle, &snum, NULL)) {
6638 /* Check calling user has permission to update printer description */
6639 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6640 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6641 return WERR_ACCESS_DENIED;
6644 return winreg_update_printer(p->mem_ctx,
6645 get_session_info_system(),
6647 lp_const_servicename(snum),
6655 /****************************************************************
6657 ****************************************************************/
6659 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6660 struct spoolss_SetPrinter *r)
6664 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6667 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6668 OUR_HANDLE(r->in.handle)));
6672 /* check the level */
6673 switch (r->in.info_ctr->level) {
6675 return control_printer(r->in.handle, r->in.command, p);
6677 result = update_printer(p, r->in.handle,
6679 r->in.devmode_ctr->devmode);
6680 if (!W_ERROR_IS_OK(result))
6682 if (r->in.secdesc_ctr->sd)
6683 result = update_printer_sec(r->in.handle, p,
6687 return update_printer_sec(r->in.handle, p,
6690 return publish_or_unpublish_printer(p, r->in.handle,
6691 r->in.info_ctr->info.info7);
6693 return update_printer_devmode(p, r->in.handle,
6694 r->in.devmode_ctr->devmode);
6696 return WERR_UNKNOWN_LEVEL;
6700 /****************************************************************
6701 _spoolss_FindClosePrinterNotify
6702 ****************************************************************/
6704 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6705 struct spoolss_FindClosePrinterNotify *r)
6707 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6710 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6711 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6715 if (Printer->notify.cli_chan != NULL &&
6716 Printer->notify.cli_chan->active_connections > 0) {
6719 if (Printer->printer_type == SPLHND_PRINTER) {
6720 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6725 srv_spoolss_replycloseprinter(snum, Printer);
6728 Printer->notify.flags=0;
6729 Printer->notify.options=0;
6730 Printer->notify.localmachine[0]='\0';
6731 Printer->notify.printerlocal=0;
6732 TALLOC_FREE(Printer->notify.option);
6737 /****************************************************************
6739 ****************************************************************/
6741 WERROR _spoolss_AddJob(struct pipes_struct *p,
6742 struct spoolss_AddJob *r)
6744 if (!r->in.buffer && (r->in.offered != 0)) {
6745 return WERR_INVALID_PARAM;
6748 /* this is what a NT server returns for AddJob. AddJob must fail on
6749 * non-local printers */
6751 if (r->in.level != 1) {
6752 return WERR_UNKNOWN_LEVEL;
6755 return WERR_INVALID_PARAM;
6758 /****************************************************************************
6760 ****************************************************************************/
6762 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6763 struct spoolss_JobInfo1 *r,
6764 const print_queue_struct *queue,
6765 int position, int snum,
6766 struct spoolss_PrinterInfo2 *pinfo2)
6770 t = gmtime(&queue->time);
6772 r->job_id = queue->job;
6774 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6775 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6776 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6777 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6778 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6779 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6780 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6781 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6782 r->data_type = talloc_strdup(mem_ctx, "RAW");
6783 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6784 r->text_status = talloc_strdup(mem_ctx, "");
6785 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6787 r->status = nt_printj_status(queue->status);
6788 r->priority = queue->priority;
6789 r->position = position;
6790 r->total_pages = queue->page_count;
6791 r->pages_printed = 0; /* ??? */
6793 init_systemtime(&r->submitted, t);
6798 /****************************************************************************
6800 ****************************************************************************/
6802 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6803 struct spoolss_JobInfo2 *r,
6804 const print_queue_struct *queue,
6805 int position, int snum,
6806 struct spoolss_PrinterInfo2 *pinfo2,
6807 struct spoolss_DeviceMode *devmode)
6811 t = gmtime(&queue->time);
6813 r->job_id = queue->job;
6815 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6816 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6817 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6818 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6819 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6820 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6821 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6822 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6823 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6824 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6825 r->data_type = talloc_strdup(mem_ctx, "RAW");
6826 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6827 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6828 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6829 r->parameters = talloc_strdup(mem_ctx, "");
6830 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6831 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6832 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6834 r->devmode = devmode;
6836 r->text_status = talloc_strdup(mem_ctx, "");
6837 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6841 r->status = nt_printj_status(queue->status);
6842 r->priority = queue->priority;
6843 r->position = position;
6846 r->total_pages = queue->page_count;
6847 r->size = queue->size;
6848 init_systemtime(&r->submitted, t);
6850 r->pages_printed = 0; /* ??? */
6855 /****************************************************************************
6857 ****************************************************************************/
6859 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6860 struct spoolss_JobInfo3 *r,
6861 const print_queue_struct *queue,
6862 const print_queue_struct *next_queue,
6863 int position, int snum,
6864 struct spoolss_PrinterInfo2 *pinfo2)
6866 r->job_id = queue->job;
6869 r->next_job_id = next_queue->job;
6876 /****************************************************************************
6877 Enumjobs at level 1.
6878 ****************************************************************************/
6880 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6881 const print_queue_struct *queue,
6882 uint32_t num_queues, int snum,
6883 struct spoolss_PrinterInfo2 *pinfo2,
6884 union spoolss_JobInfo **info_p,
6887 union spoolss_JobInfo *info;
6889 WERROR result = WERR_OK;
6891 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6892 W_ERROR_HAVE_NO_MEMORY(info);
6894 *count = num_queues;
6896 for (i=0; i<*count; i++) {
6897 result = fill_job_info1(info,
6903 if (!W_ERROR_IS_OK(result)) {
6909 if (!W_ERROR_IS_OK(result)) {
6920 /****************************************************************************
6921 Enumjobs at level 2.
6922 ****************************************************************************/
6924 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6925 const print_queue_struct *queue,
6926 uint32_t num_queues, int snum,
6927 struct spoolss_PrinterInfo2 *pinfo2,
6928 union spoolss_JobInfo **info_p,
6931 union spoolss_JobInfo *info;
6933 WERROR result = WERR_OK;
6935 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6936 W_ERROR_HAVE_NO_MEMORY(info);
6938 *count = num_queues;
6940 for (i=0; i<*count; i++) {
6941 struct spoolss_DeviceMode *devmode;
6943 result = spoolss_create_default_devmode(info,
6944 pinfo2->printername,
6946 if (!W_ERROR_IS_OK(result)) {
6947 DEBUG(3, ("Can't proceed w/o a devmode!"));
6951 result = fill_job_info2(info,
6958 if (!W_ERROR_IS_OK(result)) {
6964 if (!W_ERROR_IS_OK(result)) {
6975 /****************************************************************************
6976 Enumjobs at level 3.
6977 ****************************************************************************/
6979 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6980 const print_queue_struct *queue,
6981 uint32_t num_queues, int snum,
6982 struct spoolss_PrinterInfo2 *pinfo2,
6983 union spoolss_JobInfo **info_p,
6986 union spoolss_JobInfo *info;
6988 WERROR result = WERR_OK;
6990 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6991 W_ERROR_HAVE_NO_MEMORY(info);
6993 *count = num_queues;
6995 for (i=0; i<*count; i++) {
6996 const print_queue_struct *next_queue = NULL;
6999 next_queue = &queue[i+1];
7002 result = fill_job_info3(info,
7009 if (!W_ERROR_IS_OK(result)) {
7015 if (!W_ERROR_IS_OK(result)) {
7026 /****************************************************************
7028 ****************************************************************/
7030 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7031 struct spoolss_EnumJobs *r)
7034 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7036 print_status_struct prt_status;
7037 print_queue_struct *queue = NULL;
7040 /* that's an [in out] buffer */
7042 if (!r->in.buffer && (r->in.offered != 0)) {
7043 return WERR_INVALID_PARAM;
7046 DEBUG(4,("_spoolss_EnumJobs\n"));
7050 *r->out.info = NULL;
7052 /* lookup the printer snum and tdb entry */
7054 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7058 result = winreg_get_printer(p->mem_ctx,
7059 get_session_info_system(),
7061 lp_const_servicename(snum),
7063 if (!W_ERROR_IS_OK(result)) {
7067 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7068 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7069 count, prt_status.status, prt_status.message));
7073 TALLOC_FREE(pinfo2);
7077 switch (r->in.level) {
7079 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7080 pinfo2, r->out.info, r->out.count);
7083 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7084 pinfo2, r->out.info, r->out.count);
7087 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7088 pinfo2, r->out.info, r->out.count);
7091 result = WERR_UNKNOWN_LEVEL;
7096 TALLOC_FREE(pinfo2);
7098 if (!W_ERROR_IS_OK(result)) {
7102 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7104 *r->out.info, r->in.level,
7106 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7107 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7109 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7112 /****************************************************************
7113 _spoolss_ScheduleJob
7114 ****************************************************************/
7116 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7117 struct spoolss_ScheduleJob *r)
7122 /****************************************************************
7123 ****************************************************************/
7125 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7126 struct messaging_context *msg_ctx,
7127 const char *printer_name,
7129 struct spoolss_SetJobInfo1 *r)
7133 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7137 if (strequal(old_doc_name, r->document_name)) {
7141 if (!print_job_set_name(server_event_context(), msg_ctx,
7142 printer_name, job_id, r->document_name)) {
7149 /****************************************************************
7151 ****************************************************************/
7153 WERROR _spoolss_SetJob(struct pipes_struct *p,
7154 struct spoolss_SetJob *r)
7156 const struct auth_serversupplied_info *session_info = p->session_info;
7158 WERROR errcode = WERR_BADFUNC;
7160 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7164 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7165 return WERR_INVALID_PRINTER_NAME;
7168 switch (r->in.command) {
7169 case SPOOLSS_JOB_CONTROL_CANCEL:
7170 case SPOOLSS_JOB_CONTROL_DELETE:
7171 errcode = print_job_delete(session_info, p->msg_ctx,
7172 snum, r->in.job_id);
7173 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7177 case SPOOLSS_JOB_CONTROL_PAUSE:
7178 if (print_job_pause(session_info, p->msg_ctx,
7179 snum, r->in.job_id, &errcode)) {
7183 case SPOOLSS_JOB_CONTROL_RESTART:
7184 case SPOOLSS_JOB_CONTROL_RESUME:
7185 if (print_job_resume(session_info, p->msg_ctx,
7186 snum, r->in.job_id, &errcode)) {
7194 return WERR_UNKNOWN_LEVEL;
7197 if (!W_ERROR_IS_OK(errcode)) {
7201 if (r->in.ctr == NULL) {
7205 switch (r->in.ctr->level) {
7207 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7208 lp_const_servicename(snum),
7210 r->in.ctr->info.info1);
7216 return WERR_UNKNOWN_LEVEL;
7222 /****************************************************************************
7223 Enumerates all printer drivers by level and architecture.
7224 ****************************************************************************/
7226 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7227 const struct auth_serversupplied_info *session_info,
7228 struct messaging_context *msg_ctx,
7229 const char *servername,
7230 const char *architecture,
7232 union spoolss_DriverInfo **info_p,
7237 struct spoolss_DriverInfo8 *driver;
7238 union spoolss_DriverInfo *info = NULL;
7240 WERROR result = WERR_OK;
7241 uint32_t num_drivers;
7242 const char **drivers;
7247 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7248 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7249 architecture, version,
7250 &num_drivers, &drivers);
7251 if (!W_ERROR_IS_OK(result)) {
7254 DEBUG(4, ("we have:[%d] drivers in environment"
7255 " [%s] and version [%d]\n",
7256 num_drivers, architecture, version));
7258 if (num_drivers != 0) {
7259 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7260 union spoolss_DriverInfo,
7261 count + num_drivers);
7263 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7264 "failed to enlarge driver info buffer!\n"));
7265 result = WERR_NOMEM;
7270 for (i = 0; i < num_drivers; i++) {
7271 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7273 result = winreg_get_driver(mem_ctx, session_info,
7275 architecture, drivers[i],
7277 if (!W_ERROR_IS_OK(result)) {
7283 result = fill_printer_driver_info1(info, &info[count+i].info1,
7284 driver, servername);
7287 result = fill_printer_driver_info2(info, &info[count+i].info2,
7288 driver, servername);
7291 result = fill_printer_driver_info3(info, &info[count+i].info3,
7292 driver, servername);
7295 result = fill_printer_driver_info4(info, &info[count+i].info4,
7296 driver, servername);
7299 result = fill_printer_driver_info5(info, &info[count+i].info5,
7300 driver, servername);
7303 result = fill_printer_driver_info6(info, &info[count+i].info6,
7304 driver, servername);
7307 result = fill_printer_driver_info8(info, &info[count+i].info8,
7308 driver, servername);
7311 result = WERR_UNKNOWN_LEVEL;
7315 TALLOC_FREE(driver);
7317 if (!W_ERROR_IS_OK(result)) {
7322 count += num_drivers;
7323 TALLOC_FREE(drivers);
7327 TALLOC_FREE(drivers);
7329 if (!W_ERROR_IS_OK(result)) {
7340 /****************************************************************************
7341 Enumerates all printer drivers by level.
7342 ****************************************************************************/
7344 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7345 const struct auth_serversupplied_info *session_info,
7346 struct messaging_context *msg_ctx,
7347 const char *servername,
7348 const char *architecture,
7350 union spoolss_DriverInfo **info_p,
7354 WERROR result = WERR_OK;
7356 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7358 for (a=0; archi_table[a].long_archi != NULL; a++) {
7360 union spoolss_DriverInfo *info = NULL;
7363 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7367 archi_table[a].long_archi,
7371 if (!W_ERROR_IS_OK(result)) {
7375 for (i=0; i < count; i++) {
7376 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7377 info[i], info_p, count_p);
7384 return enumprinterdrivers_level_by_architecture(mem_ctx,
7394 /****************************************************************
7395 _spoolss_EnumPrinterDrivers
7396 ****************************************************************/
7398 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7399 struct spoolss_EnumPrinterDrivers *r)
7401 const char *cservername;
7404 /* that's an [in out] buffer */
7406 if (!r->in.buffer && (r->in.offered != 0)) {
7407 return WERR_INVALID_PARAM;
7410 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7414 *r->out.info = NULL;
7416 cservername = canon_servername(r->in.server);
7418 if (!is_myname_or_ipaddr(cservername)) {
7419 return WERR_UNKNOWN_PRINTER_DRIVER;
7422 result = enumprinterdrivers_level(p->mem_ctx,
7423 get_session_info_system(),
7430 if (!W_ERROR_IS_OK(result)) {
7434 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7435 spoolss_EnumPrinterDrivers,
7436 *r->out.info, r->in.level,
7438 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7439 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7441 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7444 /****************************************************************
7446 ****************************************************************/
7448 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7449 struct spoolss_EnumForms *r)
7455 *r->out.info = NULL;
7457 /* that's an [in out] buffer */
7459 if (!r->in.buffer && (r->in.offered != 0) ) {
7460 return WERR_INVALID_PARAM;
7463 DEBUG(4,("_spoolss_EnumForms\n"));
7464 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7465 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7467 switch (r->in.level) {
7469 result = winreg_printer_enumforms1(p->mem_ctx,
7470 get_session_info_system(),
7476 result = WERR_UNKNOWN_LEVEL;
7480 if (!W_ERROR_IS_OK(result)) {
7484 if (*r->out.count == 0) {
7485 return WERR_NO_MORE_ITEMS;
7488 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7490 *r->out.info, r->in.level,
7492 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7493 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7495 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7498 /****************************************************************
7500 ****************************************************************/
7502 WERROR _spoolss_GetForm(struct pipes_struct *p,
7503 struct spoolss_GetForm *r)
7507 /* that's an [in out] buffer */
7509 if (!r->in.buffer && (r->in.offered != 0)) {
7510 return WERR_INVALID_PARAM;
7513 DEBUG(4,("_spoolss_GetForm\n"));
7514 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7515 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7517 switch (r->in.level) {
7519 result = winreg_printer_getform1(p->mem_ctx,
7520 get_session_info_system(),
7523 &r->out.info->info1);
7526 result = WERR_UNKNOWN_LEVEL;
7530 if (!W_ERROR_IS_OK(result)) {
7531 TALLOC_FREE(r->out.info);
7535 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7536 r->out.info, r->in.level);
7537 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7539 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7542 /****************************************************************************
7543 ****************************************************************************/
7545 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7546 struct spoolss_PortInfo1 *r,
7549 r->port_name = talloc_strdup(mem_ctx, name);
7550 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7555 /****************************************************************************
7556 TODO: This probably needs distinguish between TCP/IP and Local ports
7558 ****************************************************************************/
7560 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7561 struct spoolss_PortInfo2 *r,
7564 r->port_name = talloc_strdup(mem_ctx, name);
7565 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7567 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7568 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7570 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7571 W_ERROR_HAVE_NO_MEMORY(r->description);
7573 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7580 /****************************************************************************
7581 wrapper around the enumer ports command
7582 ****************************************************************************/
7584 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7586 char *cmd = lp_enumports_cmd();
7587 char **qlines = NULL;
7588 char *command = NULL;
7596 /* if no hook then just fill in the default port */
7599 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7602 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7603 TALLOC_FREE(qlines);
7610 /* we have a valid enumport command */
7612 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7617 DEBUG(10,("Running [%s]\n", command));
7618 ret = smbrun(command, &fd);
7619 DEBUG(10,("Returned [%d]\n", ret));
7620 TALLOC_FREE(command);
7625 return WERR_ACCESS_DENIED;
7629 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7630 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7640 /****************************************************************************
7642 ****************************************************************************/
7644 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7645 union spoolss_PortInfo **info_p,
7648 union spoolss_PortInfo *info = NULL;
7650 WERROR result = WERR_OK;
7651 char **qlines = NULL;
7654 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7655 if (!W_ERROR_IS_OK(result)) {
7660 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7662 DEBUG(10,("Returning WERR_NOMEM\n"));
7663 result = WERR_NOMEM;
7667 for (i=0; i<numlines; i++) {
7668 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7669 result = fill_port_1(info, &info[i].info1, qlines[i]);
7670 if (!W_ERROR_IS_OK(result)) {
7675 TALLOC_FREE(qlines);
7678 if (!W_ERROR_IS_OK(result)) {
7680 TALLOC_FREE(qlines);
7692 /****************************************************************************
7694 ****************************************************************************/
7696 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7697 union spoolss_PortInfo **info_p,
7700 union spoolss_PortInfo *info = NULL;
7702 WERROR result = WERR_OK;
7703 char **qlines = NULL;
7706 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7707 if (!W_ERROR_IS_OK(result)) {
7712 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7714 DEBUG(10,("Returning WERR_NOMEM\n"));
7715 result = WERR_NOMEM;
7719 for (i=0; i<numlines; i++) {
7720 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7721 result = fill_port_2(info, &info[i].info2, qlines[i]);
7722 if (!W_ERROR_IS_OK(result)) {
7727 TALLOC_FREE(qlines);
7730 if (!W_ERROR_IS_OK(result)) {
7732 TALLOC_FREE(qlines);
7744 /****************************************************************
7746 ****************************************************************/
7748 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7749 struct spoolss_EnumPorts *r)
7753 /* that's an [in out] buffer */
7755 if (!r->in.buffer && (r->in.offered != 0)) {
7756 return WERR_INVALID_PARAM;
7759 DEBUG(4,("_spoolss_EnumPorts\n"));
7763 *r->out.info = NULL;
7765 switch (r->in.level) {
7767 result = enumports_level_1(p->mem_ctx, r->out.info,
7771 result = enumports_level_2(p->mem_ctx, r->out.info,
7775 return WERR_UNKNOWN_LEVEL;
7778 if (!W_ERROR_IS_OK(result)) {
7782 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7784 *r->out.info, r->in.level,
7786 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7787 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7789 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7792 /****************************************************************************
7793 ****************************************************************************/
7795 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7797 struct spoolss_SetPrinterInfoCtr *info_ctr,
7798 struct spoolss_DeviceMode *devmode,
7799 struct security_descriptor *secdesc,
7800 struct spoolss_UserLevelCtr *user_ctr,
7801 struct policy_handle *handle)
7803 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7804 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7806 WERROR err = WERR_OK;
7808 /* samba does not have a concept of local, non-shared printers yet, so
7809 * make sure we always setup sharename - gd */
7810 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7811 (info2->printername != NULL && info2->printername[0] != '\0')) {
7812 DEBUG(5, ("spoolss_addprinterex_level_2: "
7813 "no sharename has been set, setting printername %s as sharename\n",
7814 info2->printername));
7815 info2->sharename = info2->printername;
7818 /* check to see if the printer already exists */
7819 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7820 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7822 return WERR_PRINTER_ALREADY_EXISTS;
7825 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7826 if ((snum = print_queue_snum(info2->printername)) != -1) {
7827 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7828 info2->printername));
7829 return WERR_PRINTER_ALREADY_EXISTS;
7833 /* validate printer info struct */
7834 if (!info2->printername || strlen(info2->printername) == 0) {
7835 return WERR_INVALID_PRINTER_NAME;
7837 if (!info2->portname || strlen(info2->portname) == 0) {
7838 return WERR_UNKNOWN_PORT;
7840 if (!info2->drivername || strlen(info2->drivername) == 0) {
7841 return WERR_UNKNOWN_PRINTER_DRIVER;
7843 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7844 return WERR_UNKNOWN_PRINTPROCESSOR;
7847 /* FIXME!!! smbd should check to see if the driver is installed before
7848 trying to add a printer like this --jerry */
7850 if (*lp_addprinter_cmd() ) {
7851 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7852 info2, p->client_id->addr,
7854 return WERR_ACCESS_DENIED;
7857 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7858 "smb.conf parameter \"addprinter command\" is defined. This"
7859 "parameter must exist for this call to succeed\n",
7860 info2->sharename ));
7863 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7864 return WERR_ACCESS_DENIED;
7867 /* you must be a printer admin to add a new printer */
7868 if (!print_access_check(p->session_info,
7871 PRINTER_ACCESS_ADMINISTER)) {
7872 return WERR_ACCESS_DENIED;
7876 * Do sanity check on the requested changes for Samba.
7879 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7880 return WERR_INVALID_PARAM;
7883 if (devmode == NULL) {
7884 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7887 update_dsspooler(p->mem_ctx,
7888 get_session_info_system(),
7894 err = winreg_update_printer(p->mem_ctx,
7895 get_session_info_system(),
7902 if (!W_ERROR_IS_OK(err)) {
7906 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7907 if (!W_ERROR_IS_OK(err)) {
7908 /* Handle open failed - remove addition. */
7909 ZERO_STRUCTP(handle);
7916 /****************************************************************
7917 _spoolss_AddPrinterEx
7918 ****************************************************************/
7920 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7921 struct spoolss_AddPrinterEx *r)
7923 switch (r->in.info_ctr->level) {
7925 /* we don't handle yet */
7926 /* but I know what to do ... */
7927 return WERR_UNKNOWN_LEVEL;
7929 return spoolss_addprinterex_level_2(p, r->in.server,
7931 r->in.devmode_ctr->devmode,
7932 r->in.secdesc_ctr->sd,
7933 r->in.userlevel_ctr,
7936 return WERR_UNKNOWN_LEVEL;
7940 /****************************************************************
7942 ****************************************************************/
7944 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7945 struct spoolss_AddPrinter *r)
7947 struct spoolss_AddPrinterEx a;
7948 struct spoolss_UserLevelCtr userlevel_ctr;
7950 ZERO_STRUCT(userlevel_ctr);
7952 userlevel_ctr.level = 1;
7954 a.in.server = r->in.server;
7955 a.in.info_ctr = r->in.info_ctr;
7956 a.in.devmode_ctr = r->in.devmode_ctr;
7957 a.in.secdesc_ctr = r->in.secdesc_ctr;
7958 a.in.userlevel_ctr = &userlevel_ctr;
7959 a.out.handle = r->out.handle;
7961 return _spoolss_AddPrinterEx(p, &a);
7964 /****************************************************************
7965 _spoolss_AddPrinterDriverEx
7966 ****************************************************************/
7968 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7969 struct spoolss_AddPrinterDriverEx *r)
7971 WERROR err = WERR_OK;
7972 const char *driver_name = NULL;
7977 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7978 fn = "_spoolss_AddPrinterDriver";
7980 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7981 fn = "_spoolss_AddPrinterDriverEx";
7984 return WERR_INVALID_PARAM;
7988 * we only support the semantics of AddPrinterDriver()
7989 * i.e. only copy files that are newer than existing ones
7992 if (r->in.flags == 0) {
7993 return WERR_INVALID_PARAM;
7996 if (r->in.flags != APD_COPY_NEW_FILES) {
7997 return WERR_ACCESS_DENIED;
8001 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8002 /* Clever hack from Martin Zielinski <mz@seh.de>
8003 * to allow downgrade from level 8 (Vista).
8005 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8006 r->in.info_ctr->level));
8007 return WERR_UNKNOWN_LEVEL;
8010 DEBUG(5,("Cleaning driver's information\n"));
8011 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8012 if (!W_ERROR_IS_OK(err))
8015 DEBUG(5,("Moving driver to final destination\n"));
8016 err = move_driver_to_download_area(p, r->in.info_ctr);
8017 if (!W_ERROR_IS_OK(err)) {
8021 err = winreg_add_driver(p->mem_ctx,
8022 get_session_info_system(),
8027 if (!W_ERROR_IS_OK(err)) {
8032 * I think this is where he DrvUpgradePrinter() hook would be
8033 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8034 * server. Right now, we just need to send ourselves a message
8035 * to update each printer bound to this driver. --jerry
8038 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8039 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8047 /****************************************************************
8048 _spoolss_AddPrinterDriver
8049 ****************************************************************/
8051 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8052 struct spoolss_AddPrinterDriver *r)
8054 struct spoolss_AddPrinterDriverEx a;
8056 switch (r->in.info_ctr->level) {
8063 return WERR_UNKNOWN_LEVEL;
8066 a.in.servername = r->in.servername;
8067 a.in.info_ctr = r->in.info_ctr;
8068 a.in.flags = APD_COPY_NEW_FILES;
8070 return _spoolss_AddPrinterDriverEx(p, &a);
8073 /****************************************************************************
8074 ****************************************************************************/
8076 struct _spoolss_paths {
8082 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8084 static const struct _spoolss_paths spoolss_paths[]= {
8085 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8086 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8089 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8090 const char *servername,
8091 const char *environment,
8095 const char *pservername = NULL;
8096 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8097 const char *short_archi;
8101 /* environment may be empty */
8102 if (environment && strlen(environment)) {
8103 long_archi = environment;
8106 /* servername may be empty */
8107 if (servername && strlen(servername)) {
8108 pservername = canon_servername(servername);
8110 if (!is_myname_or_ipaddr(pservername)) {
8111 return WERR_INVALID_PARAM;
8115 if (!(short_archi = get_short_archi(long_archi))) {
8116 return WERR_INVALID_ENVIRONMENT;
8119 switch (component) {
8120 case SPOOLSS_PRTPROCS_PATH:
8121 case SPOOLSS_DRIVER_PATH:
8123 *path = talloc_asprintf(mem_ctx,
8126 spoolss_paths[component].share,
8129 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8130 SPOOLSS_DEFAULT_SERVER_PATH,
8131 spoolss_paths[component].dir,
8136 return WERR_INVALID_PARAM;
8146 /****************************************************************************
8147 ****************************************************************************/
8149 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8150 const char *servername,
8151 const char *environment,
8152 struct spoolss_DriverDirectoryInfo1 *r)
8157 werr = compose_spoolss_server_path(mem_ctx,
8160 SPOOLSS_DRIVER_PATH,
8162 if (!W_ERROR_IS_OK(werr)) {
8166 DEBUG(4,("printer driver directory: [%s]\n", path));
8168 r->directory_name = path;
8173 /****************************************************************
8174 _spoolss_GetPrinterDriverDirectory
8175 ****************************************************************/
8177 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8178 struct spoolss_GetPrinterDriverDirectory *r)
8182 /* that's an [in out] buffer */
8184 if (!r->in.buffer && (r->in.offered != 0)) {
8185 return WERR_INVALID_PARAM;
8188 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8193 /* r->in.level is ignored */
8195 werror = getprinterdriverdir_level_1(p->mem_ctx,
8198 &r->out.info->info1);
8199 if (!W_ERROR_IS_OK(werror)) {
8200 TALLOC_FREE(r->out.info);
8204 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8205 r->out.info, r->in.level);
8206 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8208 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8211 /****************************************************************
8212 _spoolss_EnumPrinterData
8213 ****************************************************************/
8215 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8216 struct spoolss_EnumPrinterData *r)
8219 struct spoolss_EnumPrinterDataEx r2;
8221 struct spoolss_PrinterEnumValues *info, *val = NULL;
8224 r2.in.handle = r->in.handle;
8225 r2.in.key_name = "PrinterDriverData";
8227 r2.out.count = &count;
8228 r2.out.info = &info;
8229 r2.out.needed = &needed;
8231 result = _spoolss_EnumPrinterDataEx(p, &r2);
8232 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8233 r2.in.offered = needed;
8234 result = _spoolss_EnumPrinterDataEx(p, &r2);
8236 if (!W_ERROR_IS_OK(result)) {
8241 * The NT machine wants to know the biggest size of value and data
8243 * cf: MSDN EnumPrinterData remark section
8246 if (!r->in.value_offered && !r->in.data_offered) {
8247 uint32_t biggest_valuesize = 0;
8248 uint32_t biggest_datasize = 0;
8251 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8253 for (i=0; i<count; i++) {
8255 name_length = strlen(info[i].value_name);
8256 if (strlen(info[i].value_name) > biggest_valuesize) {
8257 biggest_valuesize = name_length;
8260 if (info[i].data_length > biggest_datasize) {
8261 biggest_datasize = info[i].data_length;
8264 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8268 /* the value is an UNICODE string but real_value_size is the length
8269 in bytes including the trailing 0 */
8271 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8272 *r->out.data_needed = biggest_datasize;
8274 DEBUG(6,("final values: [%d], [%d]\n",
8275 *r->out.value_needed, *r->out.data_needed));
8280 if (r->in.enum_index < count) {
8281 val = &info[r->in.enum_index];
8285 /* out_value should default to "" or else NT4 has
8286 problems unmarshalling the response */
8288 if (r->in.value_offered) {
8289 *r->out.value_needed = 1;
8290 r->out.value_name = talloc_strdup(r, "");
8291 if (!r->out.value_name) {
8295 r->out.value_name = NULL;
8296 *r->out.value_needed = 0;
8299 /* the data is counted in bytes */
8301 *r->out.data_needed = r->in.data_offered;
8303 result = WERR_NO_MORE_ITEMS;
8307 * - counted in bytes in the request
8308 * - counted in UNICODE chars in the max reply
8309 * - counted in bytes in the real size
8311 * take a pause *before* coding not *during* coding
8315 if (r->in.value_offered) {
8316 r->out.value_name = talloc_strdup(r, val->value_name);
8317 if (!r->out.value_name) {
8320 *r->out.value_needed = val->value_name_len;
8322 r->out.value_name = NULL;
8323 *r->out.value_needed = 0;
8328 *r->out.type = val->type;
8330 /* data - counted in bytes */
8333 * See the section "Dynamically Typed Query Parameters"
8337 if (r->out.data && val->data && val->data->data &&
8338 val->data_length && r->in.data_offered) {
8339 memcpy(r->out.data, val->data->data,
8340 MIN(val->data_length,r->in.data_offered));
8343 *r->out.data_needed = val->data_length;
8351 /****************************************************************
8352 _spoolss_SetPrinterData
8353 ****************************************************************/
8355 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8356 struct spoolss_SetPrinterData *r)
8358 struct spoolss_SetPrinterDataEx r2;
8360 r2.in.handle = r->in.handle;
8361 r2.in.key_name = "PrinterDriverData";
8362 r2.in.value_name = r->in.value_name;
8363 r2.in.type = r->in.type;
8364 r2.in.data = r->in.data;
8365 r2.in.offered = r->in.offered;
8367 return _spoolss_SetPrinterDataEx(p, &r2);
8370 /****************************************************************
8371 _spoolss_ResetPrinter
8372 ****************************************************************/
8374 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8375 struct spoolss_ResetPrinter *r)
8377 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8380 DEBUG(5,("_spoolss_ResetPrinter\n"));
8383 * All we do is to check to see if the handle and queue is valid.
8384 * This call really doesn't mean anything to us because we only
8385 * support RAW printing. --jerry
8389 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8390 OUR_HANDLE(r->in.handle)));
8394 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8398 /* blindly return success */
8402 /****************************************************************
8403 _spoolss_DeletePrinterData
8404 ****************************************************************/
8406 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8407 struct spoolss_DeletePrinterData *r)
8409 struct spoolss_DeletePrinterDataEx r2;
8411 r2.in.handle = r->in.handle;
8412 r2.in.key_name = "PrinterDriverData";
8413 r2.in.value_name = r->in.value_name;
8415 return _spoolss_DeletePrinterDataEx(p, &r2);
8418 /****************************************************************
8420 ****************************************************************/
8422 WERROR _spoolss_AddForm(struct pipes_struct *p,
8423 struct spoolss_AddForm *r)
8425 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8427 WERROR status = WERR_OK;
8429 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8431 DEBUG(5,("_spoolss_AddForm\n"));
8434 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8435 OUR_HANDLE(r->in.handle)));
8439 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8440 and not a printer admin, then fail */
8442 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8443 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8444 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8445 p->session_info->info3->base.domain.string,
8447 p->session_info->security_token,
8448 lp_printer_admin(snum))) {
8449 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8450 return WERR_ACCESS_DENIED;
8453 switch (form->flags) {
8454 case SPOOLSS_FORM_USER:
8455 case SPOOLSS_FORM_BUILTIN:
8456 case SPOOLSS_FORM_PRINTER:
8459 return WERR_INVALID_PARAM;
8462 status = winreg_printer_addform1(p->mem_ctx,
8463 get_session_info_system(),
8466 if (!W_ERROR_IS_OK(status)) {
8471 * ChangeID must always be set if this is a printer
8473 if (Printer->printer_type == SPLHND_PRINTER) {
8474 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8478 status = winreg_printer_update_changeid(p->mem_ctx,
8479 get_session_info_system(),
8481 lp_const_servicename(snum));
8482 if (!W_ERROR_IS_OK(status)) {
8490 /****************************************************************
8492 ****************************************************************/
8494 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8495 struct spoolss_DeleteForm *r)
8497 const char *form_name = r->in.form_name;
8498 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8500 WERROR status = WERR_OK;
8502 DEBUG(5,("_spoolss_DeleteForm\n"));
8505 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8506 OUR_HANDLE(r->in.handle)));
8510 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8511 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8512 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8513 p->session_info->info3->base.domain.string,
8515 p->session_info->security_token,
8516 lp_printer_admin(snum))) {
8517 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8518 return WERR_ACCESS_DENIED;
8521 status = winreg_printer_deleteform1(p->mem_ctx,
8522 get_session_info_system(),
8525 if (!W_ERROR_IS_OK(status)) {
8530 * ChangeID must always be set if this is a printer
8532 if (Printer->printer_type == SPLHND_PRINTER) {
8533 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8537 status = winreg_printer_update_changeid(p->mem_ctx,
8538 get_session_info_system(),
8540 lp_const_servicename(snum));
8541 if (!W_ERROR_IS_OK(status)) {
8549 /****************************************************************
8551 ****************************************************************/
8553 WERROR _spoolss_SetForm(struct pipes_struct *p,
8554 struct spoolss_SetForm *r)
8556 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8557 const char *form_name = r->in.form_name;
8559 WERROR status = WERR_OK;
8561 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8563 DEBUG(5,("_spoolss_SetForm\n"));
8566 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8567 OUR_HANDLE(r->in.handle)));
8571 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8572 and not a printer admin, then fail */
8574 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8575 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8576 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8577 p->session_info->info3->base.domain.string,
8579 p->session_info->security_token,
8580 lp_printer_admin(snum))) {
8581 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8582 return WERR_ACCESS_DENIED;
8585 status = winreg_printer_setform1(p->mem_ctx,
8586 get_session_info_system(),
8590 if (!W_ERROR_IS_OK(status)) {
8595 * ChangeID must always be set if this is a printer
8597 if (Printer->printer_type == SPLHND_PRINTER) {
8598 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8602 status = winreg_printer_update_changeid(p->mem_ctx,
8603 get_session_info_system(),
8605 lp_const_servicename(snum));
8606 if (!W_ERROR_IS_OK(status)) {
8614 /****************************************************************************
8615 fill_print_processor1
8616 ****************************************************************************/
8618 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8619 struct spoolss_PrintProcessorInfo1 *r,
8620 const char *print_processor_name)
8622 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8623 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8628 /****************************************************************************
8629 enumprintprocessors level 1.
8630 ****************************************************************************/
8632 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8633 union spoolss_PrintProcessorInfo **info_p,
8636 union spoolss_PrintProcessorInfo *info;
8639 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8640 W_ERROR_HAVE_NO_MEMORY(info);
8644 result = fill_print_processor1(info, &info[0].info1, "winprint");
8645 if (!W_ERROR_IS_OK(result)) {
8650 if (!W_ERROR_IS_OK(result)) {
8661 /****************************************************************
8662 _spoolss_EnumPrintProcessors
8663 ****************************************************************/
8665 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8666 struct spoolss_EnumPrintProcessors *r)
8670 /* that's an [in out] buffer */
8672 if (!r->in.buffer && (r->in.offered != 0)) {
8673 return WERR_INVALID_PARAM;
8676 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8679 * Enumerate the print processors ...
8681 * Just reply with "winprint", to keep NT happy
8682 * and I can use my nice printer checker.
8687 *r->out.info = NULL;
8689 if (!get_short_archi(r->in.environment)) {
8690 return WERR_INVALID_ENVIRONMENT;
8693 switch (r->in.level) {
8695 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8699 return WERR_UNKNOWN_LEVEL;
8702 if (!W_ERROR_IS_OK(result)) {
8706 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8707 spoolss_EnumPrintProcessors,
8708 *r->out.info, r->in.level,
8710 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8711 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8713 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8716 /****************************************************************************
8717 fill_printprocdatatype1
8718 ****************************************************************************/
8720 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8721 struct spoolss_PrintProcDataTypesInfo1 *r,
8722 const char *name_array)
8724 r->name_array = talloc_strdup(mem_ctx, name_array);
8725 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8730 /****************************************************************************
8731 enumprintprocdatatypes level 1.
8732 ****************************************************************************/
8734 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8735 union spoolss_PrintProcDataTypesInfo **info_p,
8739 union spoolss_PrintProcDataTypesInfo *info;
8741 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8742 W_ERROR_HAVE_NO_MEMORY(info);
8746 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8747 if (!W_ERROR_IS_OK(result)) {
8752 if (!W_ERROR_IS_OK(result)) {
8763 /****************************************************************
8764 _spoolss_EnumPrintProcDataTypes
8765 ****************************************************************/
8767 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8768 struct spoolss_EnumPrintProcDataTypes *r)
8772 /* that's an [in out] buffer */
8774 if (!r->in.buffer && (r->in.offered != 0)) {
8775 return WERR_INVALID_PARAM;
8778 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8782 *r->out.info = NULL;
8784 if (r->in.print_processor_name == NULL ||
8785 !strequal(r->in.print_processor_name, "winprint")) {
8786 return WERR_UNKNOWN_PRINTPROCESSOR;
8789 switch (r->in.level) {
8791 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8795 return WERR_UNKNOWN_LEVEL;
8798 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8799 spoolss_EnumPrintProcDataTypes,
8800 *r->out.info, r->in.level,
8802 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8803 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8805 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8808 /****************************************************************************
8810 ****************************************************************************/
8812 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8813 struct spoolss_MonitorInfo1 *r,
8814 const char *monitor_name)
8816 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8817 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8822 /****************************************************************************
8824 ****************************************************************************/
8826 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8827 struct spoolss_MonitorInfo2 *r,
8828 const char *monitor_name,
8829 const char *environment,
8830 const char *dll_name)
8832 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8833 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8834 r->environment = talloc_strdup(mem_ctx, environment);
8835 W_ERROR_HAVE_NO_MEMORY(r->environment);
8836 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8837 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8842 /****************************************************************************
8843 enumprintmonitors level 1.
8844 ****************************************************************************/
8846 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8847 union spoolss_MonitorInfo **info_p,
8850 union spoolss_MonitorInfo *info;
8851 WERROR result = WERR_OK;
8853 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8854 W_ERROR_HAVE_NO_MEMORY(info);
8858 result = fill_monitor_1(info, &info[0].info1,
8860 if (!W_ERROR_IS_OK(result)) {
8864 result = fill_monitor_1(info, &info[1].info1,
8866 if (!W_ERROR_IS_OK(result)) {
8871 if (!W_ERROR_IS_OK(result)) {
8882 /****************************************************************************
8883 enumprintmonitors level 2.
8884 ****************************************************************************/
8886 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8887 union spoolss_MonitorInfo **info_p,
8890 union spoolss_MonitorInfo *info;
8891 WERROR result = WERR_OK;
8893 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8894 W_ERROR_HAVE_NO_MEMORY(info);
8898 result = fill_monitor_2(info, &info[0].info2,
8900 "Windows NT X86", /* FIXME */
8902 if (!W_ERROR_IS_OK(result)) {
8906 result = fill_monitor_2(info, &info[1].info2,
8908 "Windows NT X86", /* FIXME */
8910 if (!W_ERROR_IS_OK(result)) {
8915 if (!W_ERROR_IS_OK(result)) {
8926 /****************************************************************
8927 _spoolss_EnumMonitors
8928 ****************************************************************/
8930 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8931 struct spoolss_EnumMonitors *r)
8935 /* that's an [in out] buffer */
8937 if (!r->in.buffer && (r->in.offered != 0)) {
8938 return WERR_INVALID_PARAM;
8941 DEBUG(5,("_spoolss_EnumMonitors\n"));
8944 * Enumerate the print monitors ...
8946 * Just reply with "Local Port", to keep NT happy
8947 * and I can use my nice printer checker.
8952 *r->out.info = NULL;
8954 switch (r->in.level) {
8956 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8960 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8964 return WERR_UNKNOWN_LEVEL;
8967 if (!W_ERROR_IS_OK(result)) {
8971 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8972 spoolss_EnumMonitors,
8973 *r->out.info, r->in.level,
8975 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8976 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8978 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8981 /****************************************************************************
8982 ****************************************************************************/
8984 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8985 const print_queue_struct *queue,
8986 int count, int snum,
8987 struct spoolss_PrinterInfo2 *pinfo2,
8989 struct spoolss_JobInfo1 *r)
8994 for (i=0; i<count; i++) {
8995 if (queue[i].job == (int)jobid) {
9001 if (found == false) {
9002 /* NT treats not found as bad param... yet another bad choice */
9003 return WERR_INVALID_PARAM;
9006 return fill_job_info1(mem_ctx,
9014 /****************************************************************************
9015 ****************************************************************************/
9017 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9018 const print_queue_struct *queue,
9019 int count, int snum,
9020 struct spoolss_PrinterInfo2 *pinfo2,
9022 struct spoolss_JobInfo2 *r)
9026 struct spoolss_DeviceMode *devmode;
9029 for (i=0; i<count; i++) {
9030 if (queue[i].job == (int)jobid) {
9036 if (found == false) {
9037 /* NT treats not found as bad param... yet another bad
9039 return WERR_INVALID_PARAM;
9043 * if the print job does not have a DEVMODE associated with it,
9044 * just use the one for the printer. A NULL devicemode is not
9045 * a failure condition
9048 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9050 result = spoolss_create_default_devmode(mem_ctx,
9051 pinfo2->printername,
9053 if (!W_ERROR_IS_OK(result)) {
9054 DEBUG(3, ("Can't proceed w/o a devmode!"));
9059 return fill_job_info2(mem_ctx,
9068 /****************************************************************
9070 ****************************************************************/
9072 WERROR _spoolss_GetJob(struct pipes_struct *p,
9073 struct spoolss_GetJob *r)
9075 WERROR result = WERR_OK;
9076 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9079 print_queue_struct *queue = NULL;
9080 print_status_struct prt_status;
9082 /* that's an [in out] buffer */
9084 if (!r->in.buffer && (r->in.offered != 0)) {
9085 return WERR_INVALID_PARAM;
9088 DEBUG(5,("_spoolss_GetJob\n"));
9092 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9096 result = winreg_get_printer(p->mem_ctx,
9097 get_session_info_system(),
9099 lp_const_servicename(snum),
9101 if (!W_ERROR_IS_OK(result)) {
9105 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9107 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9108 count, prt_status.status, prt_status.message));
9110 switch (r->in.level) {
9112 result = getjob_level_1(p->mem_ctx,
9113 queue, count, snum, pinfo2,
9114 r->in.job_id, &r->out.info->info1);
9117 result = getjob_level_2(p->mem_ctx,
9118 queue, count, snum, pinfo2,
9119 r->in.job_id, &r->out.info->info2);
9122 result = WERR_UNKNOWN_LEVEL;
9127 TALLOC_FREE(pinfo2);
9129 if (!W_ERROR_IS_OK(result)) {
9130 TALLOC_FREE(r->out.info);
9134 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9136 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9138 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9141 /****************************************************************
9142 _spoolss_GetPrinterDataEx
9143 ****************************************************************/
9145 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9146 struct spoolss_GetPrinterDataEx *r)
9149 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9150 const char *printer;
9152 WERROR result = WERR_OK;
9154 enum winreg_Type val_type;
9159 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9161 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9162 r->in.key_name, r->in.value_name));
9164 /* in case of problem, return some default values */
9167 *r->out.type = REG_NONE;
9170 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9171 OUR_HANDLE(r->in.handle)));
9172 result = WERR_BADFID;
9176 /* Is the handle to a printer or to the server? */
9178 if (Printer->printer_type == SPLHND_SERVER) {
9180 union spoolss_PrinterData data;
9182 result = getprinterdata_printer_server(p->mem_ctx,
9186 if (!W_ERROR_IS_OK(result)) {
9190 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9191 *r->out.type, &data);
9192 if (!W_ERROR_IS_OK(result)) {
9196 *r->out.needed = blob.length;
9198 if (r->in.offered >= *r->out.needed) {
9199 memcpy(r->out.data, blob.data, blob.length);
9202 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9205 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9208 printer = lp_const_servicename(snum);
9210 /* check to see if the keyname is valid */
9211 if (!strlen(r->in.key_name)) {
9212 return WERR_INVALID_PARAM;
9215 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9216 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9217 strequal(r->in.value_name, "ChangeId")) {
9218 *r->out.type = REG_DWORD;
9220 if (r->in.offered >= *r->out.needed) {
9221 uint32_t changeid = 0;
9223 result = winreg_printer_get_changeid(p->mem_ctx,
9224 get_session_info_system(),
9228 if (!W_ERROR_IS_OK(result)) {
9232 SIVAL(r->out.data, 0, changeid);
9238 result = winreg_get_printer_dataex(p->mem_ctx,
9239 get_session_info_system(),
9247 if (!W_ERROR_IS_OK(result)) {
9251 *r->out.needed = val_size;
9252 *r->out.type = val_type;
9254 if (r->in.offered >= *r->out.needed) {
9255 memcpy(r->out.data, val_data, val_size);
9259 /* retain type when returning WERR_MORE_DATA */
9260 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9262 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9265 /****************************************************************
9266 _spoolss_SetPrinterDataEx
9267 ****************************************************************/
9269 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9270 struct spoolss_SetPrinterDataEx *r)
9272 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9274 WERROR result = WERR_OK;
9275 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9278 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9280 /* From MSDN documentation of SetPrinterDataEx: pass request to
9281 SetPrinterData if key is "PrinterDriverData" */
9284 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9285 OUR_HANDLE(r->in.handle)));
9289 if (Printer->printer_type == SPLHND_SERVER) {
9290 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9291 "Not implemented for server handles yet\n"));
9292 return WERR_INVALID_PARAM;
9295 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9300 * Access check : NT returns "access denied" if you make a
9301 * SetPrinterData call without the necessary privildge.
9302 * we were originally returning OK if nothing changed
9303 * which made Win2k issue **a lot** of SetPrinterData
9304 * when connecting to a printer --jerry
9307 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9308 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9309 "change denied by handle access permissions\n"));
9310 return WERR_ACCESS_DENIED;
9313 result = winreg_get_printer(Printer,
9314 get_session_info_system(),
9316 lp_servicename(snum),
9318 if (!W_ERROR_IS_OK(result)) {
9322 /* check for OID in valuename */
9324 oid_string = strchr(r->in.value_name, ',');
9330 /* save the registry data */
9332 result = winreg_set_printer_dataex(p->mem_ctx,
9333 get_session_info_system(),
9342 if (W_ERROR_IS_OK(result)) {
9343 /* save the OID if one was specified */
9345 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9346 r->in.key_name, SPOOL_OID_KEY);
9348 result = WERR_NOMEM;
9353 * I'm not checking the status here on purpose. Don't know
9354 * if this is right, but I'm returning the status from the
9355 * previous set_printer_dataex() call. I have no idea if
9356 * this is right. --jerry
9358 winreg_set_printer_dataex(p->mem_ctx,
9359 get_session_info_system(),
9365 (uint8_t *) oid_string,
9366 strlen(oid_string) + 1);
9369 result = winreg_printer_update_changeid(p->mem_ctx,
9370 get_session_info_system(),
9372 lp_const_servicename(snum));
9377 talloc_free(pinfo2);
9381 /****************************************************************
9382 _spoolss_DeletePrinterDataEx
9383 ****************************************************************/
9385 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9386 struct spoolss_DeletePrinterDataEx *r)
9388 const char *printer;
9390 WERROR status = WERR_OK;
9391 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9393 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9396 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9397 "Invalid handle (%s:%u:%u).\n",
9398 OUR_HANDLE(r->in.handle)));
9402 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9403 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9404 "printer properties change denied by handle\n"));
9405 return WERR_ACCESS_DENIED;
9408 if (!r->in.value_name || !r->in.key_name) {
9412 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9415 printer = lp_const_servicename(snum);
9417 status = winreg_delete_printer_dataex(p->mem_ctx,
9418 get_session_info_system(),
9423 if (W_ERROR_IS_OK(status)) {
9424 status = winreg_printer_update_changeid(p->mem_ctx,
9425 get_session_info_system(),
9433 /****************************************************************
9434 _spoolss_EnumPrinterKey
9435 ****************************************************************/
9437 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9438 struct spoolss_EnumPrinterKey *r)
9441 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9443 WERROR result = WERR_BADFILE;
9444 const char **array = NULL;
9447 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9450 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9451 OUR_HANDLE(r->in.handle)));
9455 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9459 result = winreg_enum_printer_key(p->mem_ctx,
9460 get_session_info_system(),
9462 lp_const_servicename(snum),
9466 if (!W_ERROR_IS_OK(result)) {
9470 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9471 result = WERR_NOMEM;
9475 *r->out._ndr_size = r->in.offered / 2;
9476 *r->out.needed = blob.length;
9478 if (r->in.offered < *r->out.needed) {
9479 result = WERR_MORE_DATA;
9482 r->out.key_buffer->string_array = array;
9486 if (!W_ERROR_IS_OK(result)) {
9488 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9496 /****************************************************************
9497 _spoolss_DeletePrinterKey
9498 ****************************************************************/
9500 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9501 struct spoolss_DeletePrinterKey *r)
9503 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9506 const char *printer;
9508 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9511 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9512 OUR_HANDLE(r->in.handle)));
9516 /* if keyname == NULL, return error */
9517 if ( !r->in.key_name )
9518 return WERR_INVALID_PARAM;
9520 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9524 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9525 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9526 "printer properties change denied by handle\n"));
9527 return WERR_ACCESS_DENIED;
9530 printer = lp_const_servicename(snum);
9532 /* delete the key and all subkeys */
9533 status = winreg_delete_printer_key(p->mem_ctx,
9534 get_session_info_system(),
9538 if (W_ERROR_IS_OK(status)) {
9539 status = winreg_printer_update_changeid(p->mem_ctx,
9540 get_session_info_system(),
9548 /****************************************************************
9549 _spoolss_EnumPrinterDataEx
9550 ****************************************************************/
9552 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9553 struct spoolss_EnumPrinterDataEx *r)
9556 struct spoolss_PrinterEnumValues *info = NULL;
9557 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9561 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9565 *r->out.info = NULL;
9568 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9569 OUR_HANDLE(r->in.handle)));
9574 * first check for a keyname of NULL or "". Win2k seems to send
9575 * this a lot and we should send back WERR_INVALID_PARAM
9576 * no need to spend time looking up the printer in this case.
9580 if (!strlen(r->in.key_name)) {
9581 result = WERR_INVALID_PARAM;
9585 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9589 /* now look for a match on the key name */
9590 result = winreg_enum_printer_dataex(p->mem_ctx,
9591 get_session_info_system(),
9593 lp_const_servicename(snum),
9597 if (!W_ERROR_IS_OK(result)) {
9601 #if 0 /* FIXME - gd */
9602 /* housekeeping information in the reply */
9604 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9605 * the hand marshalled container size is a multiple
9606 * of 4 bytes for RPC alignment.
9610 needed += 4-(needed % 4);
9613 *r->out.count = count;
9614 *r->out.info = info;
9617 if (!W_ERROR_IS_OK(result)) {
9621 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9622 spoolss_EnumPrinterDataEx,
9625 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9626 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9628 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9631 /****************************************************************************
9632 ****************************************************************************/
9634 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9635 const char *servername,
9636 const char *environment,
9637 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9642 werr = compose_spoolss_server_path(mem_ctx,
9645 SPOOLSS_PRTPROCS_PATH,
9647 if (!W_ERROR_IS_OK(werr)) {
9651 DEBUG(4,("print processor directory: [%s]\n", path));
9653 r->directory_name = path;
9658 /****************************************************************
9659 _spoolss_GetPrintProcessorDirectory
9660 ****************************************************************/
9662 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9663 struct spoolss_GetPrintProcessorDirectory *r)
9666 char *prnproc_share = NULL;
9667 bool prnproc_share_exists = false;
9670 /* that's an [in out] buffer */
9672 if (!r->in.buffer && (r->in.offered != 0)) {
9673 return WERR_INVALID_PARAM;
9676 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9681 /* r->in.level is ignored */
9683 /* We always should reply with a local print processor directory so that
9684 * users are not forced to have a [prnproc$] share on the Samba spoolss
9685 * server, if users decide to do so, lets announce it though - Guenther */
9687 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9688 if (!prnproc_share) {
9692 prnproc_share_exists = true;
9695 result = getprintprocessordirectory_level_1(p->mem_ctx,
9696 prnproc_share_exists ? r->in.server : NULL,
9698 &r->out.info->info1);
9699 if (!W_ERROR_IS_OK(result)) {
9700 TALLOC_FREE(r->out.info);
9704 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9705 r->out.info, r->in.level);
9706 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9708 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9711 /*******************************************************************
9712 ********************************************************************/
9714 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9715 const char *dllname)
9717 enum ndr_err_code ndr_err;
9718 struct spoolss_MonitorUi ui;
9720 ui.dll_name = dllname;
9722 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9723 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9724 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9725 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9727 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9730 /*******************************************************************
9731 Streams the monitor UI DLL name in UNICODE
9732 *******************************************************************/
9734 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9735 struct security_token *token, DATA_BLOB *in,
9736 DATA_BLOB *out, uint32_t *needed)
9738 const char *dllname = "tcpmonui.dll";
9740 *needed = (strlen(dllname)+1) * 2;
9742 if (out->length < *needed) {
9743 return WERR_INSUFFICIENT_BUFFER;
9746 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9753 /*******************************************************************
9754 ********************************************************************/
9756 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9757 struct spoolss_PortData1 *port1,
9758 const DATA_BLOB *buf)
9760 enum ndr_err_code ndr_err;
9761 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9762 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9763 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9764 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9766 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9769 /*******************************************************************
9770 ********************************************************************/
9772 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9773 struct spoolss_PortData2 *port2,
9774 const DATA_BLOB *buf)
9776 enum ndr_err_code ndr_err;
9777 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9778 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9779 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9780 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9782 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9785 /*******************************************************************
9786 Create a new TCP/IP port
9787 *******************************************************************/
9789 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9790 struct security_token *token, DATA_BLOB *in,
9791 DATA_BLOB *out, uint32_t *needed)
9793 struct spoolss_PortData1 port1;
9794 struct spoolss_PortData2 port2;
9795 char *device_uri = NULL;
9798 const char *portname;
9799 const char *hostaddress;
9801 uint32_t port_number;
9804 /* peek for spoolss_PortData version */
9806 if (!in || (in->length < (128 + 4))) {
9807 return WERR_GENERAL_FAILURE;
9810 version = IVAL(in->data, 128);
9816 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9820 portname = port1.portname;
9821 hostaddress = port1.hostaddress;
9822 queue = port1.queue;
9823 protocol = port1.protocol;
9824 port_number = port1.port_number;
9830 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9834 portname = port2.portname;
9835 hostaddress = port2.hostaddress;
9836 queue = port2.queue;
9837 protocol = port2.protocol;
9838 port_number = port2.port_number;
9842 DEBUG(1,("xcvtcp_addport: "
9843 "unknown version of port_data: %d\n", version));
9844 return WERR_UNKNOWN_PORT;
9847 /* create the device URI and call the add_port_hook() */
9850 case PROTOCOL_RAWTCP_TYPE:
9851 device_uri = talloc_asprintf(mem_ctx,
9852 "socket://%s:%d/", hostaddress,
9856 case PROTOCOL_LPR_TYPE:
9857 device_uri = talloc_asprintf(mem_ctx,
9858 "lpr://%s/%s", hostaddress, queue );
9862 return WERR_UNKNOWN_PORT;
9869 return add_port_hook(mem_ctx, token, portname, device_uri);
9872 /*******************************************************************
9873 *******************************************************************/
9875 struct xcv_api_table xcvtcp_cmds[] = {
9876 { "MonitorUI", xcvtcp_monitorui },
9877 { "AddPort", xcvtcp_addport},
9881 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9882 struct security_token *token, const char *command,
9889 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9891 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9892 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9893 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9896 return WERR_BADFUNC;
9899 /*******************************************************************
9900 *******************************************************************/
9901 #if 0 /* don't support management using the "Local Port" monitor */
9903 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9904 struct security_token *token, DATA_BLOB *in,
9905 DATA_BLOB *out, uint32_t *needed)
9907 const char *dllname = "localui.dll";
9909 *needed = (strlen(dllname)+1) * 2;
9911 if (out->length < *needed) {
9912 return WERR_INSUFFICIENT_BUFFER;
9915 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9922 /*******************************************************************
9923 *******************************************************************/
9925 struct xcv_api_table xcvlocal_cmds[] = {
9926 { "MonitorUI", xcvlocal_monitorui },
9930 struct xcv_api_table xcvlocal_cmds[] = {
9937 /*******************************************************************
9938 *******************************************************************/
9940 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9941 struct security_token *token, const char *command,
9942 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9947 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9949 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9950 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9951 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9953 return WERR_BADFUNC;
9956 /****************************************************************
9958 ****************************************************************/
9960 WERROR _spoolss_XcvData(struct pipes_struct *p,
9961 struct spoolss_XcvData *r)
9963 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9964 DATA_BLOB out_data = data_blob_null;
9968 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9969 OUR_HANDLE(r->in.handle)));
9973 /* Has to be a handle to the TCP/IP port monitor */
9975 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9976 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9980 /* requires administrative access to the server */
9982 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9983 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9984 return WERR_ACCESS_DENIED;
9987 /* Allocate the outgoing buffer */
9989 if (r->in.out_data_size) {
9990 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9991 if (out_data.data == NULL) {
9996 switch ( Printer->printer_type ) {
9997 case SPLHND_PORTMON_TCP:
9998 werror = process_xcvtcp_command(p->mem_ctx,
9999 p->session_info->security_token,
10000 r->in.function_name,
10001 &r->in.in_data, &out_data,
10004 case SPLHND_PORTMON_LOCAL:
10005 werror = process_xcvlocal_command(p->mem_ctx,
10006 p->session_info->security_token,
10007 r->in.function_name,
10008 &r->in.in_data, &out_data,
10012 werror = WERR_INVALID_PRINT_MONITOR;
10015 if (!W_ERROR_IS_OK(werror)) {
10019 *r->out.status_code = 0;
10021 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10022 memcpy(r->out.out_data, out_data.data,
10023 MIN(r->in.out_data_size, out_data.length));
10029 /****************************************************************
10030 _spoolss_AddPrintProcessor
10031 ****************************************************************/
10033 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10034 struct spoolss_AddPrintProcessor *r)
10036 /* for now, just indicate success and ignore the add. We'll
10037 automatically set the winprint processor for printer
10038 entries later. Used to debug the LexMark Optra S 1855 PCL
10044 /****************************************************************
10046 ****************************************************************/
10048 WERROR _spoolss_AddPort(struct pipes_struct *p,
10049 struct spoolss_AddPort *r)
10051 /* do what w2k3 does */
10053 return WERR_NOT_SUPPORTED;
10056 /****************************************************************
10057 _spoolss_GetPrinterDriver
10058 ****************************************************************/
10060 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10061 struct spoolss_GetPrinterDriver *r)
10063 p->rng_fault_state = true;
10064 return WERR_NOT_SUPPORTED;
10067 /****************************************************************
10068 _spoolss_ReadPrinter
10069 ****************************************************************/
10071 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10072 struct spoolss_ReadPrinter *r)
10074 p->rng_fault_state = true;
10075 return WERR_NOT_SUPPORTED;
10078 /****************************************************************
10079 _spoolss_WaitForPrinterChange
10080 ****************************************************************/
10082 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10083 struct spoolss_WaitForPrinterChange *r)
10085 p->rng_fault_state = true;
10086 return WERR_NOT_SUPPORTED;
10089 /****************************************************************
10090 _spoolss_ConfigurePort
10091 ****************************************************************/
10093 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10094 struct spoolss_ConfigurePort *r)
10096 p->rng_fault_state = true;
10097 return WERR_NOT_SUPPORTED;
10100 /****************************************************************
10101 _spoolss_DeletePort
10102 ****************************************************************/
10104 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10105 struct spoolss_DeletePort *r)
10107 p->rng_fault_state = true;
10108 return WERR_NOT_SUPPORTED;
10111 /****************************************************************
10112 _spoolss_CreatePrinterIC
10113 ****************************************************************/
10115 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10116 struct spoolss_CreatePrinterIC *r)
10118 p->rng_fault_state = true;
10119 return WERR_NOT_SUPPORTED;
10122 /****************************************************************
10123 _spoolss_PlayGDIScriptOnPrinterIC
10124 ****************************************************************/
10126 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10127 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10129 p->rng_fault_state = true;
10130 return WERR_NOT_SUPPORTED;
10133 /****************************************************************
10134 _spoolss_DeletePrinterIC
10135 ****************************************************************/
10137 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10138 struct spoolss_DeletePrinterIC *r)
10140 p->rng_fault_state = true;
10141 return WERR_NOT_SUPPORTED;
10144 /****************************************************************
10145 _spoolss_AddPrinterConnection
10146 ****************************************************************/
10148 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10149 struct spoolss_AddPrinterConnection *r)
10151 p->rng_fault_state = true;
10152 return WERR_NOT_SUPPORTED;
10155 /****************************************************************
10156 _spoolss_DeletePrinterConnection
10157 ****************************************************************/
10159 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10160 struct spoolss_DeletePrinterConnection *r)
10162 p->rng_fault_state = true;
10163 return WERR_NOT_SUPPORTED;
10166 /****************************************************************
10167 _spoolss_PrinterMessageBox
10168 ****************************************************************/
10170 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10171 struct spoolss_PrinterMessageBox *r)
10173 p->rng_fault_state = true;
10174 return WERR_NOT_SUPPORTED;
10177 /****************************************************************
10178 _spoolss_AddMonitor
10179 ****************************************************************/
10181 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10182 struct spoolss_AddMonitor *r)
10184 p->rng_fault_state = true;
10185 return WERR_NOT_SUPPORTED;
10188 /****************************************************************
10189 _spoolss_DeleteMonitor
10190 ****************************************************************/
10192 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10193 struct spoolss_DeleteMonitor *r)
10195 p->rng_fault_state = true;
10196 return WERR_NOT_SUPPORTED;
10199 /****************************************************************
10200 _spoolss_DeletePrintProcessor
10201 ****************************************************************/
10203 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10204 struct spoolss_DeletePrintProcessor *r)
10206 p->rng_fault_state = true;
10207 return WERR_NOT_SUPPORTED;
10210 /****************************************************************
10211 _spoolss_AddPrintProvidor
10212 ****************************************************************/
10214 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10215 struct spoolss_AddPrintProvidor *r)
10217 p->rng_fault_state = true;
10218 return WERR_NOT_SUPPORTED;
10221 /****************************************************************
10222 _spoolss_DeletePrintProvidor
10223 ****************************************************************/
10225 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10226 struct spoolss_DeletePrintProvidor *r)
10228 p->rng_fault_state = true;
10229 return WERR_NOT_SUPPORTED;
10232 /****************************************************************
10233 _spoolss_FindFirstPrinterChangeNotification
10234 ****************************************************************/
10236 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10237 struct spoolss_FindFirstPrinterChangeNotification *r)
10239 p->rng_fault_state = true;
10240 return WERR_NOT_SUPPORTED;
10243 /****************************************************************
10244 _spoolss_FindNextPrinterChangeNotification
10245 ****************************************************************/
10247 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10248 struct spoolss_FindNextPrinterChangeNotification *r)
10250 p->rng_fault_state = true;
10251 return WERR_NOT_SUPPORTED;
10254 /****************************************************************
10255 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10256 ****************************************************************/
10258 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10259 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10261 p->rng_fault_state = true;
10262 return WERR_NOT_SUPPORTED;
10265 /****************************************************************
10266 _spoolss_ReplyOpenPrinter
10267 ****************************************************************/
10269 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10270 struct spoolss_ReplyOpenPrinter *r)
10272 p->rng_fault_state = true;
10273 return WERR_NOT_SUPPORTED;
10276 /****************************************************************
10277 _spoolss_RouterReplyPrinter
10278 ****************************************************************/
10280 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10281 struct spoolss_RouterReplyPrinter *r)
10283 p->rng_fault_state = true;
10284 return WERR_NOT_SUPPORTED;
10287 /****************************************************************
10288 _spoolss_ReplyClosePrinter
10289 ****************************************************************/
10291 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10292 struct spoolss_ReplyClosePrinter *r)
10294 p->rng_fault_state = true;
10295 return WERR_NOT_SUPPORTED;
10298 /****************************************************************
10300 ****************************************************************/
10302 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10303 struct spoolss_AddPortEx *r)
10305 p->rng_fault_state = true;
10306 return WERR_NOT_SUPPORTED;
10309 /****************************************************************
10310 _spoolss_RouterFindFirstPrinterChangeNotification
10311 ****************************************************************/
10313 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10314 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10316 p->rng_fault_state = true;
10317 return WERR_NOT_SUPPORTED;
10320 /****************************************************************
10321 _spoolss_SpoolerInit
10322 ****************************************************************/
10324 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10325 struct spoolss_SpoolerInit *r)
10327 p->rng_fault_state = true;
10328 return WERR_NOT_SUPPORTED;
10331 /****************************************************************
10332 _spoolss_ResetPrinterEx
10333 ****************************************************************/
10335 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10336 struct spoolss_ResetPrinterEx *r)
10338 p->rng_fault_state = true;
10339 return WERR_NOT_SUPPORTED;
10342 /****************************************************************
10343 _spoolss_RouterReplyPrinterEx
10344 ****************************************************************/
10346 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10347 struct spoolss_RouterReplyPrinterEx *r)
10349 p->rng_fault_state = true;
10350 return WERR_NOT_SUPPORTED;
10353 /****************************************************************
10355 ****************************************************************/
10357 WERROR _spoolss_44(struct pipes_struct *p,
10358 struct spoolss_44 *r)
10360 p->rng_fault_state = true;
10361 return WERR_NOT_SUPPORTED;
10364 /****************************************************************
10366 ****************************************************************/
10368 WERROR _spoolss_SetPort(struct pipes_struct *p,
10369 struct spoolss_SetPort *r)
10371 p->rng_fault_state = true;
10372 return WERR_NOT_SUPPORTED;
10375 /****************************************************************
10377 ****************************************************************/
10379 WERROR _spoolss_4a(struct pipes_struct *p,
10380 struct spoolss_4a *r)
10382 p->rng_fault_state = true;
10383 return WERR_NOT_SUPPORTED;
10386 /****************************************************************
10388 ****************************************************************/
10390 WERROR _spoolss_4b(struct pipes_struct *p,
10391 struct spoolss_4b *r)
10393 p->rng_fault_state = true;
10394 return WERR_NOT_SUPPORTED;
10397 /****************************************************************
10399 ****************************************************************/
10401 WERROR _spoolss_4c(struct pipes_struct *p,
10402 struct spoolss_4c *r)
10404 p->rng_fault_state = true;
10405 return WERR_NOT_SUPPORTED;
10408 /****************************************************************
10410 ****************************************************************/
10412 WERROR _spoolss_53(struct pipes_struct *p,
10413 struct spoolss_53 *r)
10415 p->rng_fault_state = true;
10416 return WERR_NOT_SUPPORTED;
10419 /****************************************************************
10420 _spoolss_AddPerMachineConnection
10421 ****************************************************************/
10423 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10424 struct spoolss_AddPerMachineConnection *r)
10426 p->rng_fault_state = true;
10427 return WERR_NOT_SUPPORTED;
10430 /****************************************************************
10431 _spoolss_DeletePerMachineConnection
10432 ****************************************************************/
10434 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10435 struct spoolss_DeletePerMachineConnection *r)
10437 p->rng_fault_state = true;
10438 return WERR_NOT_SUPPORTED;
10441 /****************************************************************
10442 _spoolss_EnumPerMachineConnections
10443 ****************************************************************/
10445 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10446 struct spoolss_EnumPerMachineConnections *r)
10448 p->rng_fault_state = true;
10449 return WERR_NOT_SUPPORTED;
10452 /****************************************************************
10454 ****************************************************************/
10456 WERROR _spoolss_5a(struct pipes_struct *p,
10457 struct spoolss_5a *r)
10459 p->rng_fault_state = true;
10460 return WERR_NOT_SUPPORTED;
10463 /****************************************************************
10465 ****************************************************************/
10467 WERROR _spoolss_5b(struct pipes_struct *p,
10468 struct spoolss_5b *r)
10470 p->rng_fault_state = true;
10471 return WERR_NOT_SUPPORTED;
10474 /****************************************************************
10476 ****************************************************************/
10478 WERROR _spoolss_5c(struct pipes_struct *p,
10479 struct spoolss_5c *r)
10481 p->rng_fault_state = true;
10482 return WERR_NOT_SUPPORTED;
10485 /****************************************************************
10487 ****************************************************************/
10489 WERROR _spoolss_5d(struct pipes_struct *p,
10490 struct spoolss_5d *r)
10492 p->rng_fault_state = true;
10493 return WERR_NOT_SUPPORTED;
10496 /****************************************************************
10498 ****************************************************************/
10500 WERROR _spoolss_5e(struct pipes_struct *p,
10501 struct spoolss_5e *r)
10503 p->rng_fault_state = true;
10504 return WERR_NOT_SUPPORTED;
10507 /****************************************************************
10509 ****************************************************************/
10511 WERROR _spoolss_5f(struct pipes_struct *p,
10512 struct spoolss_5f *r)
10514 p->rng_fault_state = true;
10515 return WERR_NOT_SUPPORTED;
10518 /****************************************************************
10520 ****************************************************************/
10522 WERROR _spoolss_60(struct pipes_struct *p,
10523 struct spoolss_60 *r)
10525 p->rng_fault_state = true;
10526 return WERR_NOT_SUPPORTED;
10529 /****************************************************************
10531 ****************************************************************/
10533 WERROR _spoolss_61(struct pipes_struct *p,
10534 struct spoolss_61 *r)
10536 p->rng_fault_state = true;
10537 return WERR_NOT_SUPPORTED;
10540 /****************************************************************
10542 ****************************************************************/
10544 WERROR _spoolss_62(struct pipes_struct *p,
10545 struct spoolss_62 *r)
10547 p->rng_fault_state = true;
10548 return WERR_NOT_SUPPORTED;
10551 /****************************************************************
10553 ****************************************************************/
10555 WERROR _spoolss_63(struct pipes_struct *p,
10556 struct spoolss_63 *r)
10558 p->rng_fault_state = true;
10559 return WERR_NOT_SUPPORTED;
10562 /****************************************************************
10564 ****************************************************************/
10566 WERROR _spoolss_64(struct pipes_struct *p,
10567 struct spoolss_64 *r)
10569 p->rng_fault_state = true;
10570 return WERR_NOT_SUPPORTED;
10573 /****************************************************************
10575 ****************************************************************/
10577 WERROR _spoolss_65(struct pipes_struct *p,
10578 struct spoolss_65 *r)
10580 p->rng_fault_state = true;
10581 return WERR_NOT_SUPPORTED;
10584 /****************************************************************
10585 _spoolss_GetCorePrinterDrivers
10586 ****************************************************************/
10588 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10589 struct spoolss_GetCorePrinterDrivers *r)
10591 p->rng_fault_state = true;
10592 return WERR_NOT_SUPPORTED;
10595 /****************************************************************
10597 ****************************************************************/
10599 WERROR _spoolss_67(struct pipes_struct *p,
10600 struct spoolss_67 *r)
10602 p->rng_fault_state = true;
10603 return WERR_NOT_SUPPORTED;
10606 /****************************************************************
10607 _spoolss_GetPrinterDriverPackagePath
10608 ****************************************************************/
10610 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10611 struct spoolss_GetPrinterDriverPackagePath *r)
10613 p->rng_fault_state = true;
10614 return WERR_NOT_SUPPORTED;
10617 /****************************************************************
10619 ****************************************************************/
10621 WERROR _spoolss_69(struct pipes_struct *p,
10622 struct spoolss_69 *r)
10624 p->rng_fault_state = true;
10625 return WERR_NOT_SUPPORTED;
10628 /****************************************************************
10630 ****************************************************************/
10632 WERROR _spoolss_6a(struct pipes_struct *p,
10633 struct spoolss_6a *r)
10635 p->rng_fault_state = true;
10636 return WERR_NOT_SUPPORTED;
10639 /****************************************************************
10641 ****************************************************************/
10643 WERROR _spoolss_6b(struct pipes_struct *p,
10644 struct spoolss_6b *r)
10646 p->rng_fault_state = true;
10647 return WERR_NOT_SUPPORTED;
10650 /****************************************************************
10652 ****************************************************************/
10654 WERROR _spoolss_6c(struct pipes_struct *p,
10655 struct spoolss_6c *r)
10657 p->rng_fault_state = true;
10658 return WERR_NOT_SUPPORTED;
10661 /****************************************************************
10663 ****************************************************************/
10665 WERROR _spoolss_6d(struct pipes_struct *p,
10666 struct spoolss_6d *r)
10668 p->rng_fault_state = true;
10669 return WERR_NOT_SUPPORTED;