2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "../libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry/reg_objects.h"
41 #include "include/printing.h"
43 #include "../librpc/gen_ndr/netlogon.h"
45 #include "printing/notify.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
52 /* macros stolen from s4 spoolss server */
53 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
54 ((info)?ndr_size_##fn(info, level, 0):0)
56 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
57 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
59 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
60 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
62 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
65 #define DBGC_CLASS DBGC_RPC_SRV
67 #ifndef MAX_OPEN_PRINTER_EXS
68 #define MAX_OPEN_PRINTER_EXS 50
71 struct notify_back_channel;
73 /* structure to store the printer handles */
74 /* and a reference to what it's pointing to */
75 /* and the notify info asked about */
76 /* that's the central struct */
77 struct printer_handle {
78 struct printer_handle *prev, *next;
79 bool document_started;
81 uint32 jobid; /* jobid in printing backend */
83 const char *servername;
86 uint32 access_granted;
92 struct spoolss_NotifyOption *option;
93 struct policy_handle cli_hnd;
94 struct notify_back_channel *cli_chan;
96 /* are we in a FindNextPrinterChangeNotify() call? */
98 struct messaging_context *msg_ctx;
105 /* devmode sent in the OpenPrinter() call */
106 struct spoolss_DeviceMode *devmode;
108 /* TODO cache the printer info2 structure */
109 struct spoolss_PrinterInfo2 *info2;
113 static struct printer_handle *printers_list;
115 struct printer_session_counter {
116 struct printer_session_counter *next;
117 struct printer_session_counter *prev;
123 static struct printer_session_counter *counter_list;
125 struct notify_back_channel {
126 struct notify_back_channel *prev, *next;
128 /* associated client */
129 struct sockaddr_storage client_address;
131 /* print notify back-channel pipe handle*/
132 struct rpc_pipe_client *cli_pipe;
133 struct dcerpc_binding_handle *binding_handle;
134 uint32_t active_connections;
137 static struct notify_back_channel *back_channels;
139 /* Map generic permissions to printer object specific permissions */
141 const struct standard_mapping printer_std_mapping = {
148 /* Map generic permissions to print server object specific permissions */
150 const struct standard_mapping printserver_std_mapping = {
157 /* API table for Xcv Monitor functions */
159 struct xcv_api_table {
161 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
164 static void prune_printername_cache(void);
166 /********************************************************************
167 * Canonicalize servername.
168 ********************************************************************/
170 static const char *canon_servername(const char *servername)
172 const char *pservername = servername;
173 while (*pservername == '\\') {
179 /* translate between internal status numbers and NT status numbers */
180 static int nt_printj_status(int v)
186 return JOB_STATUS_PAUSED;
188 return JOB_STATUS_SPOOLING;
190 return JOB_STATUS_PRINTING;
192 return JOB_STATUS_ERROR;
194 return JOB_STATUS_DELETING;
196 return JOB_STATUS_OFFLINE;
198 return JOB_STATUS_PAPEROUT;
200 return JOB_STATUS_PRINTED;
202 return JOB_STATUS_DELETED;
204 return JOB_STATUS_BLOCKED_DEVQ;
205 case LPQ_USER_INTERVENTION:
206 return JOB_STATUS_USER_INTERVENTION;
211 static int nt_printq_status(int v)
215 return PRINTER_STATUS_PAUSED;
224 /***************************************************************************
225 Disconnect from the client
226 ****************************************************************************/
228 static void srv_spoolss_replycloseprinter(int snum,
229 struct printer_handle *prn_hnd)
235 * Tell the specific printing tdb we no longer want messages for this printer
236 * by deregistering our PID.
239 if (!print_notify_deregister_pid(snum)) {
240 DEBUG(0, ("Failed to register our pid for printer %s\n",
241 lp_const_servicename(snum)));
244 /* weird if the test succeeds !!! */
245 if (prn_hnd->notify.cli_chan == NULL ||
246 prn_hnd->notify.cli_chan->active_connections == 0) {
247 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
248 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
249 TALLOC_FREE(prn_hnd->notify.cli_chan);
253 status = dcerpc_spoolss_ReplyClosePrinter(
254 prn_hnd->notify.cli_chan->binding_handle,
256 &prn_hnd->notify.cli_hnd,
258 if (!NT_STATUS_IS_OK(status)) {
259 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
261 result = ntstatus_to_werror(status);
262 } else if (!W_ERROR_IS_OK(result)) {
263 DEBUG(0, ("reply_close_printer failed [%s].\n",
264 win_errstr(result)));
267 /* if it's the last connection, deconnect the IPC$ share */
268 if (prn_hnd->notify.cli_chan->active_connections == 1) {
270 prn_hnd->notify.cli_chan->binding_handle = NULL;
271 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
272 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
273 TALLOC_FREE(prn_hnd->notify.cli_chan);
275 if (prn_hnd->notify.msg_ctx != NULL) {
276 messaging_deregister(prn_hnd->notify.msg_ctx,
277 MSG_PRINTER_NOTIFY2, NULL);
280 * Tell the serverid.tdb we're no longer
281 * interested in printer notify messages.
284 serverid_register_msg_flags(
285 messaging_server_id(prn_hnd->notify.msg_ctx),
286 false, FLAG_MSG_PRINT_NOTIFY);
290 if (prn_hnd->notify.cli_chan) {
291 prn_hnd->notify.cli_chan->active_connections--;
295 /****************************************************************************
296 Functions to free a printer entry datastruct.
297 ****************************************************************************/
299 static int printer_entry_destructor(struct printer_handle *Printer)
301 if (Printer->notify.cli_chan != NULL &&
302 Printer->notify.cli_chan->active_connections > 0) {
305 switch(Printer->printer_type) {
307 srv_spoolss_replycloseprinter(snum, Printer);
311 snum = print_queue_snum(Printer->sharename);
313 srv_spoolss_replycloseprinter(snum, Printer);
321 Printer->notify.flags=0;
322 Printer->notify.options=0;
323 Printer->notify.localmachine[0]='\0';
324 Printer->notify.printerlocal=0;
325 TALLOC_FREE(Printer->notify.option);
326 TALLOC_FREE(Printer->devmode);
328 /* Remove from the internal list. */
329 DLIST_REMOVE(printers_list, Printer);
333 /****************************************************************************
334 find printer index by handle
335 ****************************************************************************/
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338 struct policy_handle *hnd)
340 struct printer_handle *find_printer = NULL;
342 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
350 /****************************************************************************
351 Close printer index by handle.
352 ****************************************************************************/
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
359 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
364 close_policy_hnd(p, hnd);
369 /****************************************************************************
370 Delete a printer given a handle.
371 ****************************************************************************/
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374 const char *sharename,
375 struct messaging_context *msg_ctx)
377 char *cmd = lp_deleteprinter_cmd();
378 char *command = NULL;
380 bool is_print_op = false;
382 /* can't fail if we don't try */
387 command = talloc_asprintf(ctx,
394 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396 DEBUG(10,("Running [%s]\n", command));
398 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
403 if ( (ret = smbrun(command, NULL)) == 0 ) {
404 /* Tell everyone we updated smb.conf. */
405 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
411 /********** END SePrintOperatorPrivlege BLOCK **********/
413 DEBUGADD(10,("returned [%d]\n", ret));
415 TALLOC_FREE(command);
418 return WERR_BADFID; /* What to return here? */
420 /* go ahead and re-read the services immediately */
422 reload_services(msg_ctx, -1, false);
425 if ( lp_servicenumber( sharename ) >= 0 )
426 return WERR_ACCESS_DENIED;
431 /****************************************************************************
432 Delete a printer given a handle.
433 ****************************************************************************/
435 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
437 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
441 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
447 * It turns out that Windows allows delete printer on a handle
448 * opened by an admin user, then used on a pipe handle created
449 * by an anonymous user..... but they're working on security.... riiight !
453 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
454 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
455 return WERR_ACCESS_DENIED;
458 /* this does not need a become root since the access check has been
459 done on the handle already */
461 result = winreg_delete_printer_key(p->mem_ctx,
462 get_session_info_system(),
466 if (!W_ERROR_IS_OK(result)) {
467 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
471 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
472 Printer->sharename, p->msg_ctx);
473 if (!W_ERROR_IS_OK(result)) {
476 prune_printername_cache();
480 /****************************************************************************
481 Return the snum of a printer corresponding to an handle.
482 ****************************************************************************/
484 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
485 int *number, struct share_params **params)
487 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
490 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
495 switch (Printer->printer_type) {
497 DEBUG(4,("short name:%s\n", Printer->sharename));
498 *number = print_queue_snum(Printer->sharename);
499 return (*number != -1);
507 /****************************************************************************
508 Set printer handle type.
509 Check if it's \\server or \\server\printer
510 ****************************************************************************/
512 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
514 DEBUG(3,("Setting printer type=%s\n", handlename));
516 /* it's a print server */
517 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
518 DEBUGADD(4,("Printer is a print server\n"));
519 Printer->printer_type = SPLHND_SERVER;
521 /* it's a printer (set_printer_hnd_name() will handle port monitors */
523 DEBUGADD(4,("Printer is a printer\n"));
524 Printer->printer_type = SPLHND_PRINTER;
530 static void prune_printername_cache_fn(const char *key, const char *value,
531 time_t timeout, void *private_data)
536 static void prune_printername_cache(void)
538 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
541 /****************************************************************************
542 Set printer handle name.. Accept names like \\server, \\server\printer,
543 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
544 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
545 XcvDataPort() interface.
546 ****************************************************************************/
548 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
549 const struct auth_serversupplied_info *session_info,
550 struct messaging_context *msg_ctx,
551 struct printer_handle *Printer,
552 const char *handlename)
555 int n_services=lp_numservices();
557 const char *printername;
558 const char *servername = NULL;
561 struct spoolss_PrinterInfo2 *info2 = NULL;
566 * Hopefully nobody names his printers like this. Maybe \ or ,
567 * are illegal in printer names even?
569 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
573 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
574 (unsigned long)strlen(handlename)));
576 aprinter = CONST_DISCARD(char *, handlename);
577 if ( *handlename == '\\' ) {
578 servername = canon_servername(handlename);
579 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
583 if (!is_myname_or_ipaddr(servername)) {
584 return WERR_INVALID_PRINTER_NAME;
586 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
587 if (Printer->servername == NULL) {
592 if (Printer->printer_type == SPLHND_SERVER) {
596 if (Printer->printer_type != SPLHND_PRINTER) {
597 return WERR_INVALID_HANDLE;
600 DEBUGADD(5, ("searching for [%s]\n", aprinter));
602 p = strchr(aprinter, ',');
609 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
611 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
617 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
620 /* check for the Port Monitor Interface */
621 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
622 Printer->printer_type = SPLHND_PORTMON_TCP;
623 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
626 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
627 Printer->printer_type = SPLHND_PORTMON_LOCAL;
628 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
633 * With hundreds of printers, the "for" loop iterating all
634 * shares can be quite expensive, as it is done on every
635 * OpenPrinter. The loop maps "aprinter" to "sname", the
636 * result of which we cache in gencache.
639 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
641 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
643 found = (strcmp(tmp, printer_not_found) != 0);
645 DEBUG(4, ("Printer %s not found\n", aprinter));
647 return WERR_INVALID_PRINTER_NAME;
653 /* Search all sharenames first as this is easier than pulling
654 the printer_info_2 off of disk. Don't use find_service() since
655 that calls out to map_username() */
657 /* do another loop to look for printernames */
658 for (snum = 0; !found && snum < n_services; snum++) {
659 const char *printer = lp_const_servicename(snum);
661 /* no point going on if this is not a printer */
662 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
666 /* ignore [printers] share */
667 if (strequal(printer, "printers")) {
671 fstrcpy(sname, printer);
672 if (strequal(aprinter, printer)) {
677 /* no point looking up the printer object if
678 we aren't allowing printername != sharename */
679 if (lp_force_printername(snum)) {
683 result = winreg_get_printer(mem_ctx,
688 if ( !W_ERROR_IS_OK(result) ) {
689 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
690 sname, win_errstr(result)));
694 printername = strrchr(info2->printername, '\\');
695 if (printername == NULL) {
696 printername = info2->printername;
701 if (strequal(printername, aprinter)) {
706 DEBUGADD(10, ("printername: %s\n", printername));
712 if (cache_key != NULL) {
713 gencache_set(cache_key, printer_not_found,
715 TALLOC_FREE(cache_key);
717 DEBUGADD(4,("Printer not found\n"));
718 return WERR_INVALID_PRINTER_NAME;
721 if (cache_key != NULL) {
722 gencache_set(cache_key, sname, time(NULL)+300);
723 TALLOC_FREE(cache_key);
726 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
728 fstrcpy(Printer->sharename, sname);
733 /****************************************************************************
734 Find first available printer slot. creates a printer handle for you.
735 ****************************************************************************/
737 static WERROR open_printer_hnd(struct pipes_struct *p,
738 struct policy_handle *hnd,
740 uint32_t access_granted)
742 struct printer_handle *new_printer;
745 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
747 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
748 if (new_printer == NULL) {
751 talloc_set_destructor(new_printer, printer_entry_destructor);
753 /* This also steals the printer_handle on the policy_handle */
754 if (!create_policy_hnd(p, hnd, new_printer)) {
755 TALLOC_FREE(new_printer);
756 return WERR_INVALID_HANDLE;
759 /* Add to the internal list. */
760 DLIST_ADD(printers_list, new_printer);
762 new_printer->notify.option=NULL;
764 if (!set_printer_hnd_printertype(new_printer, name)) {
765 close_printer_handle(p, hnd);
766 return WERR_INVALID_HANDLE;
769 result = set_printer_hnd_name(p->mem_ctx,
770 get_session_info_system(),
773 if (!W_ERROR_IS_OK(result)) {
774 close_printer_handle(p, hnd);
778 new_printer->access_granted = access_granted;
780 DEBUG(5, ("%d printer handles active\n",
781 (int)num_pipe_handles(p)));
786 /***************************************************************************
787 check to see if the client motify handle is monitoring the notification
788 given by (notify_type, notify_field).
789 **************************************************************************/
791 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
792 uint16_t notify_field)
797 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
798 uint16_t notify_field)
800 struct spoolss_NotifyOption *option = p->notify.option;
804 * Flags should always be zero when the change notify
805 * is registered by the client's spooler. A user Win32 app
806 * might use the flags though instead of the NOTIFY_OPTION_INFO
815 return is_monitoring_event_flags(
816 p->notify.flags, notify_type, notify_field);
818 for (i = 0; i < option->count; i++) {
820 /* Check match for notify_type */
822 if (option->types[i].type != notify_type)
825 /* Check match for field */
827 for (j = 0; j < option->types[i].count; j++) {
828 if (option->types[i].fields[j].field == notify_field) {
834 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
835 p->servername, p->sharename, notify_type, notify_field));
840 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
841 _data->data.integer[0] = _integer; \
842 _data->data.integer[1] = 0;
845 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
846 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
847 if (!_data->data.string.string) {\
848 _data->data.string.size = 0; \
850 _data->data.string.size = strlen_m_term(_p) * 2;
852 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
853 _data->data.devmode.devmode = _devmode;
855 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
856 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
857 if (!_data->data.sd.sd) { \
858 _data->data.sd.sd_size = 0; \
860 _data->data.sd.sd_size = \
861 ndr_size_security_descriptor(_data->data.sd.sd, 0);
863 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
868 struct spoolss_Time st;
872 if (!init_systemtime(&st, t)) {
876 p = talloc_array(mem_ctx, char, len);
882 * Systemtime must be linearized as a set of UINT16's.
883 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
886 SSVAL(p, 0, st.year);
887 SSVAL(p, 2, st.month);
888 SSVAL(p, 4, st.day_of_week);
890 SSVAL(p, 8, st.hour);
891 SSVAL(p, 10, st.minute);
892 SSVAL(p, 12, st.second);
893 SSVAL(p, 14, st.millisecond);
899 /* Convert a notification message to a struct spoolss_Notify */
901 static void notify_one_value(struct spoolss_notify_msg *msg,
902 struct spoolss_Notify *data,
905 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
908 static void notify_string(struct spoolss_notify_msg *msg,
909 struct spoolss_Notify *data,
912 /* The length of the message includes the trailing \0 */
914 data->data.string.size = msg->len * 2;
915 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
916 if (!data->data.string.string) {
917 data->data.string.size = 0;
922 static void notify_system_time(struct spoolss_notify_msg *msg,
923 struct spoolss_Notify *data,
926 data->data.string.string = NULL;
927 data->data.string.size = 0;
929 if (msg->len != sizeof(time_t)) {
930 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
935 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
936 &data->data.string.string,
937 &data->data.string.size);
940 struct notify2_message_table {
942 void (*fn)(struct spoolss_notify_msg *msg,
943 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
946 static struct notify2_message_table printer_notify_table[] = {
947 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
948 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
949 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
950 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
951 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
952 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
953 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
954 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
955 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
956 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
957 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
958 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
959 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
960 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
961 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
962 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
963 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
964 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
965 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
968 static struct notify2_message_table job_notify_table[] = {
969 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
970 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
971 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
972 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
973 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
974 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
975 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
976 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
977 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
978 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
979 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
980 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
981 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
982 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
983 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
984 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
985 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
986 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
987 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
988 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
989 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
990 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
991 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
992 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
996 /***********************************************************************
997 Allocate talloc context for container object
998 **********************************************************************/
1000 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1005 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1010 /***********************************************************************
1011 release all allocated memory and zero out structure
1012 **********************************************************************/
1014 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1020 talloc_destroy(ctr->ctx);
1027 /***********************************************************************
1028 **********************************************************************/
1030 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1038 /***********************************************************************
1039 **********************************************************************/
1041 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1043 if ( !ctr || !ctr->msg_groups )
1046 if ( idx >= ctr->num_groups )
1049 return &ctr->msg_groups[idx];
1053 /***********************************************************************
1054 How many groups of change messages do we have ?
1055 **********************************************************************/
1057 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1062 return ctr->num_groups;
1065 /***********************************************************************
1066 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1067 **********************************************************************/
1069 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1071 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1072 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1073 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1079 /* loop over all groups looking for a matching printer name */
1081 for ( i=0; i<ctr->num_groups; i++ ) {
1082 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1086 /* add a new group? */
1088 if ( i == ctr->num_groups ) {
1091 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1092 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1095 ctr->msg_groups = groups;
1097 /* clear the new entry and set the printer name */
1099 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1100 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1103 /* add the change messages; 'i' is the correct index now regardless */
1105 msg_grp = &ctr->msg_groups[i];
1107 msg_grp->num_msgs++;
1109 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1110 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1113 msg_grp->msgs = msg_list;
1115 new_slot = msg_grp->num_msgs-1;
1116 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1118 /* need to allocate own copy of data */
1120 if ( msg->len != 0 )
1121 msg_grp->msgs[new_slot].notify.data = (char *)
1122 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1124 return ctr->num_groups;
1127 static void construct_info_data(struct spoolss_Notify *info_data,
1128 enum spoolss_NotifyType type,
1129 uint16_t field, int id);
1131 /***********************************************************************
1132 Send a change notication message on all handles which have a call
1134 **********************************************************************/
1136 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1137 struct printer_handle *prn_hnd,
1138 SPOOLSS_NOTIFY_MSG *messages,
1140 struct spoolss_Notify **_notifies,
1143 struct spoolss_Notify *notifies;
1144 SPOOLSS_NOTIFY_MSG *msg;
1149 notifies = talloc_zero_array(mem_ctx,
1150 struct spoolss_Notify, num_msgs);
1155 for (i = 0; i < num_msgs; i++) {
1159 /* Are we monitoring this event? */
1161 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1165 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1166 "for printer [%s]\n",
1167 msg->type, msg->field, prn_hnd->sharename));
1170 * if the is a printer notification handle and not a job
1171 * notification type, then set the id to 0.
1172 * Otherwise just use what was specified in the message.
1174 * When registering change notification on a print server
1175 * handle we always need to send back the id (snum) matching
1176 * the printer for which the change took place.
1177 * For change notify registered on a printer handle,
1178 * this does not matter and the id should be 0.
1183 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1184 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1190 /* Convert unix jobid to smb jobid */
1192 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1193 id = sysjob_to_jobid(msg->id);
1196 DEBUG(3, ("no such unix jobid %d\n",
1202 construct_info_data(¬ifies[count],
1203 msg->type, msg->field, id);
1206 case PRINTER_NOTIFY_TYPE:
1207 if (printer_notify_table[msg->field].fn) {
1208 printer_notify_table[msg->field].fn(msg,
1209 ¬ifies[count], mem_ctx);
1213 case JOB_NOTIFY_TYPE:
1214 if (job_notify_table[msg->field].fn) {
1215 job_notify_table[msg->field].fn(msg,
1216 ¬ifies[count], mem_ctx);
1221 DEBUG(5, ("Unknown notification type %d\n",
1229 *_notifies = notifies;
1235 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1236 struct printer_handle *prn_hnd,
1237 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1239 struct spoolss_Notify *notifies;
1241 union spoolss_ReplyPrinterInfo info;
1242 struct spoolss_NotifyInfo info0;
1243 uint32_t reply_result;
1248 /* Is there notification on this handle? */
1249 if (prn_hnd->notify.cli_chan == NULL ||
1250 prn_hnd->notify.cli_chan->active_connections == 0) {
1254 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1255 prn_hnd->servername, prn_hnd->sharename));
1257 /* For this printer? Print servers always receive notifications. */
1258 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1259 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1263 DEBUG(10,("Our printer\n"));
1265 /* build the array of change notifications */
1266 ret = build_notify2_messages(mem_ctx, prn_hnd,
1268 msg_group->num_msgs,
1274 info0.version = 0x2;
1275 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1276 info0.count = count;
1277 info0.notifies = notifies;
1279 info.info0 = &info0;
1281 status = dcerpc_spoolss_RouterReplyPrinterEx(
1282 prn_hnd->notify.cli_chan->binding_handle,
1284 &prn_hnd->notify.cli_hnd,
1285 prn_hnd->notify.change, /* color */
1286 prn_hnd->notify.flags,
1288 0, /* reply_type, must be 0 */
1290 if (!NT_STATUS_IS_OK(status)) {
1291 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1293 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294 nt_errstr(status)));
1295 werr = ntstatus_to_werror(status);
1296 } else if (!W_ERROR_IS_OK(werr)) {
1297 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1299 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1302 switch (reply_result) {
1305 case PRINTER_NOTIFY_INFO_DISCARDED:
1306 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1307 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1316 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1318 struct printer_handle *p;
1319 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1320 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1324 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1328 if (!msg_group->msgs) {
1329 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1333 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1335 /* loop over all printers */
1337 for (p = printers_list; p; p = p->next) {
1338 ret = send_notify2_printer(mem_ctx, p, msg_group);
1345 DEBUG(8,("send_notify2_changes: Exit...\n"));
1349 /***********************************************************************
1350 **********************************************************************/
1352 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1355 uint32_t tv_sec, tv_usec;
1358 /* Unpack message */
1360 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1363 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1365 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1368 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1369 &msg->notify.value[0], &msg->notify.value[1]);
1371 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1372 &msg->len, &msg->notify.data);
1374 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1375 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1377 tv->tv_sec = tv_sec;
1378 tv->tv_usec = tv_usec;
1381 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1382 msg->notify.value[1]));
1384 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1389 /********************************************************************
1390 Receive a notify2 message list
1391 ********************************************************************/
1393 static void receive_notify2_message_list(struct messaging_context *msg,
1396 struct server_id server_id,
1399 size_t msg_count, i;
1400 char *buf = (char *)data->data;
1403 SPOOLSS_NOTIFY_MSG notify;
1404 SPOOLSS_NOTIFY_MSG_CTR messages;
1407 if (data->length < 4) {
1408 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1412 msg_count = IVAL(buf, 0);
1415 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1417 if (msg_count == 0) {
1418 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1422 /* initialize the container */
1424 ZERO_STRUCT( messages );
1425 notify_msg_ctr_init( &messages );
1428 * build message groups for each printer identified
1429 * in a change_notify msg. Remember that a PCN message
1430 * includes the handle returned for the srv_spoolss_replyopenprinter()
1431 * call. Therefore messages are grouped according to printer handle.
1434 for ( i=0; i<msg_count; i++ ) {
1435 struct timeval msg_tv;
1437 if (msg_ptr + 4 - buf > data->length) {
1438 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1442 msg_len = IVAL(msg_ptr,0);
1445 if (msg_ptr + msg_len - buf > data->length) {
1446 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1450 /* unpack messages */
1452 ZERO_STRUCT( notify );
1453 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1456 /* add to correct list in container */
1458 notify_msg_ctr_addmsg( &messages, ¬ify );
1460 /* free memory that might have been allocated by notify2_unpack_msg() */
1462 if ( notify.len != 0 )
1463 SAFE_FREE( notify.notify.data );
1466 /* process each group of messages */
1468 num_groups = notify_msg_ctr_numgroups( &messages );
1469 for ( i=0; i<num_groups; i++ )
1470 send_notify2_changes( &messages, i );
1475 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1476 (uint32_t)msg_count ));
1478 notify_msg_ctr_destroy( &messages );
1483 /********************************************************************
1484 Send a message to ourself about new driver being installed
1485 so we can upgrade the information for each printer bound to this
1487 ********************************************************************/
1489 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1490 struct messaging_context *msg_ctx)
1492 int len = strlen(drivername);
1497 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1500 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1501 MSG_PRINTER_DRVUPGRADE,
1502 (uint8_t *)drivername, len+1);
1507 void srv_spoolss_cleanup(void)
1509 struct printer_session_counter *session_counter;
1511 for (session_counter = counter_list;
1512 session_counter != NULL;
1513 session_counter = counter_list) {
1514 DLIST_REMOVE(counter_list, session_counter);
1515 TALLOC_FREE(session_counter);
1519 /**********************************************************************
1520 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1521 over all printers, upgrading ones as necessary
1522 **********************************************************************/
1524 void do_drv_upgrade_printer(struct messaging_context *msg,
1527 struct server_id server_id,
1530 TALLOC_CTX *tmp_ctx;
1531 struct auth_serversupplied_info *session_info = NULL;
1532 struct spoolss_PrinterInfo2 *pinfo2;
1535 const char *drivername;
1537 int n_services = lp_numservices();
1539 tmp_ctx = talloc_new(NULL);
1540 if (!tmp_ctx) return;
1542 status = make_session_info_system(tmp_ctx, &session_info);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 DEBUG(0, ("do_drv_upgrade_printer: "
1545 "Could not create system session_info\n"));
1549 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1551 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1555 DEBUG(10, ("do_drv_upgrade_printer: "
1556 "Got message for new driver [%s]\n", drivername));
1558 /* Iterate the printer list */
1560 for (snum = 0; snum < n_services; snum++) {
1561 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1565 /* ignore [printers] share */
1566 if (strequal(lp_const_servicename(snum), "printers")) {
1570 result = winreg_get_printer(tmp_ctx, session_info, msg,
1571 lp_const_servicename(snum),
1574 if (!W_ERROR_IS_OK(result)) {
1578 if (!pinfo2->drivername) {
1582 if (strcmp(drivername, pinfo2->drivername) != 0) {
1586 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1588 /* all we care about currently is the change_id */
1589 result = winreg_printer_update_changeid(tmp_ctx,
1592 pinfo2->printername);
1594 if (!W_ERROR_IS_OK(result)) {
1595 DEBUG(3, ("do_drv_upgrade_printer: "
1596 "Failed to update changeid [%s]\n",
1597 win_errstr(result)));
1603 talloc_free(tmp_ctx);
1606 /********************************************************************
1607 Update the cache for all printq's with a registered client
1609 ********************************************************************/
1611 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1613 struct printer_handle *printer = printers_list;
1616 /* loop through all printers and update the cache where
1617 a client is connected */
1619 if ((printer->printer_type == SPLHND_PRINTER) &&
1620 ((printer->notify.cli_chan != NULL) &&
1621 (printer->notify.cli_chan->active_connections > 0))) {
1622 snum = print_queue_snum(printer->sharename);
1623 print_queue_status(msg_ctx, snum, NULL, NULL);
1626 printer = printer->next;
1632 /****************************************************************
1633 _spoolss_OpenPrinter
1634 ****************************************************************/
1636 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1637 struct spoolss_OpenPrinter *r)
1639 struct spoolss_OpenPrinterEx e;
1642 ZERO_STRUCT(e.in.userlevel);
1644 e.in.printername = r->in.printername;
1645 e.in.datatype = r->in.datatype;
1646 e.in.devmode_ctr = r->in.devmode_ctr;
1647 e.in.access_mask = r->in.access_mask;
1650 e.out.handle = r->out.handle;
1652 werr = _spoolss_OpenPrinterEx(p, &e);
1654 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1655 /* OpenPrinterEx returns this for a bad
1656 * printer name. We must return WERR_INVALID_PRINTER_NAME
1659 werr = WERR_INVALID_PRINTER_NAME;
1665 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1666 struct spoolss_DeviceMode *orig,
1667 struct spoolss_DeviceMode **dest)
1669 struct spoolss_DeviceMode *dm;
1671 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1676 /* copy all values, then duplicate strings and structs */
1679 dm->devicename = talloc_strdup(dm, orig->devicename);
1680 if (!dm->devicename) {
1683 dm->formname = talloc_strdup(dm, orig->formname);
1684 if (!dm->formname) {
1687 if (orig->driverextra_data.data) {
1688 dm->driverextra_data.data =
1689 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1690 orig->driverextra_data.length);
1691 if (!dm->driverextra_data.data) {
1700 /****************************************************************
1701 _spoolss_OpenPrinterEx
1702 ****************************************************************/
1704 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1705 struct spoolss_OpenPrinterEx *r)
1708 struct printer_handle *Printer=NULL;
1711 if (!r->in.printername) {
1712 return WERR_INVALID_PARAM;
1715 if (r->in.level > 3) {
1716 return WERR_INVALID_PARAM;
1718 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1719 (r->in.level == 2 && !r->in.userlevel.level2) ||
1720 (r->in.level == 3 && !r->in.userlevel.level3)) {
1721 return WERR_INVALID_PARAM;
1724 /* some sanity check because you can open a printer or a print server */
1725 /* aka: \\server\printer or \\server */
1727 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1729 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1730 if (!W_ERROR_IS_OK(result)) {
1731 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1732 "for printer %s\n", r->in.printername));
1733 ZERO_STRUCTP(r->out.handle);
1737 Printer = find_printer_index_by_hnd(p, r->out.handle);
1739 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1740 "handle we created for printer %s\n", r->in.printername));
1741 close_printer_handle(p, r->out.handle);
1742 ZERO_STRUCTP(r->out.handle);
1743 return WERR_INVALID_PARAM;
1747 * First case: the user is opening the print server:
1749 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1750 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1752 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1753 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1754 * or if the user is listed in the smb.conf printer admin parameter.
1756 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1757 * client view printer folder, but does not show the MSAPW.
1759 * Note: this test needs code to check access rights here too. Jeremy
1760 * could you look at this?
1762 * Second case: the user is opening a printer:
1763 * NT doesn't let us connect to a printer if the connecting user
1764 * doesn't have print permission.
1766 * Third case: user is opening a Port Monitor
1767 * access checks same as opening a handle to the print server.
1770 switch (Printer->printer_type )
1773 case SPLHND_PORTMON_TCP:
1774 case SPLHND_PORTMON_LOCAL:
1775 /* Printserver handles use global struct... */
1779 /* Map standard access rights to object specific access rights */
1781 se_map_standard(&r->in.access_mask,
1782 &printserver_std_mapping);
1784 /* Deny any object specific bits that don't apply to print
1785 servers (i.e printer and job specific bits) */
1787 r->in.access_mask &= SEC_MASK_SPECIFIC;
1789 if (r->in.access_mask &
1790 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1791 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1792 close_printer_handle(p, r->out.handle);
1793 ZERO_STRUCTP(r->out.handle);
1794 return WERR_ACCESS_DENIED;
1797 /* Allow admin access */
1799 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1801 if (!lp_ms_add_printer_wizard()) {
1802 close_printer_handle(p, r->out.handle);
1803 ZERO_STRUCTP(r->out.handle);
1804 return WERR_ACCESS_DENIED;
1807 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1808 and not a printer admin, then fail */
1810 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1811 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1812 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1813 !token_contains_name_in_list(
1814 uidtoname(p->session_info->utok.uid),
1815 p->session_info->info3->base.domain.string,
1817 p->session_info->security_token,
1818 lp_printer_admin(snum))) {
1819 close_printer_handle(p, r->out.handle);
1820 ZERO_STRUCTP(r->out.handle);
1821 DEBUG(3,("access DENIED as user is not root, "
1822 "has no printoperator privilege, "
1823 "not a member of the printoperator builtin group and "
1824 "is not in printer admin list"));
1825 return WERR_ACCESS_DENIED;
1828 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1832 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1835 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1836 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838 /* We fall through to return WERR_OK */
1841 case SPLHND_PRINTER:
1842 /* NT doesn't let us connect to a printer if the connecting user
1843 doesn't have print permission. */
1845 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1846 close_printer_handle(p, r->out.handle);
1847 ZERO_STRUCTP(r->out.handle);
1851 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1852 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1855 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1857 /* map an empty access mask to the minimum access mask */
1858 if (r->in.access_mask == 0x0)
1859 r->in.access_mask = PRINTER_ACCESS_USE;
1862 * If we are not serving the printer driver for this printer,
1863 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1864 * will keep NT clients happy --jerry
1867 if (lp_use_client_driver(snum)
1868 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1870 r->in.access_mask = PRINTER_ACCESS_USE;
1873 /* check smb.conf parameters and the the sec_desc */
1875 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1876 p->client_id->name, p->client_id->addr)) {
1877 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1878 ZERO_STRUCTP(r->out.handle);
1879 return WERR_ACCESS_DENIED;
1882 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1883 p->session_info->security_token, snum) ||
1884 !print_access_check(p->session_info,
1887 r->in.access_mask)) {
1888 DEBUG(3, ("access DENIED for printer open\n"));
1889 close_printer_handle(p, r->out.handle);
1890 ZERO_STRUCTP(r->out.handle);
1891 return WERR_ACCESS_DENIED;
1894 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1895 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1896 close_printer_handle(p, r->out.handle);
1897 ZERO_STRUCTP(r->out.handle);
1898 return WERR_ACCESS_DENIED;
1901 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1902 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1904 r->in.access_mask = PRINTER_ACCESS_USE;
1906 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1907 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1909 winreg_create_printer(p->mem_ctx,
1910 get_session_info_system(),
1912 lp_const_servicename(snum));
1917 /* sanity check to prevent programmer error */
1918 ZERO_STRUCTP(r->out.handle);
1922 Printer->access_granted = r->in.access_mask;
1925 * If the client sent a devmode in the OpenPrinter() call, then
1926 * save it here in case we get a job submission on this handle
1929 if ((Printer->printer_type != SPLHND_SERVER) &&
1930 r->in.devmode_ctr.devmode) {
1931 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1935 #if 0 /* JERRY -- I'm doubtful this is really effective */
1936 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1937 optimization in Windows 2000 clients --jerry */
1939 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1940 && (RA_WIN2K == get_remote_arch()) )
1942 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1943 sys_usleep( 500000 );
1950 /****************************************************************
1951 _spoolss_ClosePrinter
1952 ****************************************************************/
1954 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1955 struct spoolss_ClosePrinter *r)
1957 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1959 if (Printer && Printer->document_started) {
1960 struct spoolss_EndDocPrinter e;
1962 e.in.handle = r->in.handle;
1964 _spoolss_EndDocPrinter(p, &e);
1967 if (!close_printer_handle(p, r->in.handle))
1970 /* clear the returned printer handle. Observed behavior
1971 from Win2k server. Don't think this really matters.
1972 Previous code just copied the value of the closed
1975 ZERO_STRUCTP(r->out.handle);
1980 /****************************************************************
1981 _spoolss_DeletePrinter
1982 ****************************************************************/
1984 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1985 struct spoolss_DeletePrinter *r)
1987 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1991 if (Printer && Printer->document_started) {
1992 struct spoolss_EndDocPrinter e;
1994 e.in.handle = r->in.handle;
1996 _spoolss_EndDocPrinter(p, &e);
1999 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2000 winreg_delete_printer_key(p->mem_ctx,
2001 get_session_info_system(),
2003 lp_const_servicename(snum),
2007 result = delete_printer_handle(p, r->in.handle);
2012 /*******************************************************************
2013 * static function to lookup the version id corresponding to an
2014 * long architecture string
2015 ******************************************************************/
2017 static const struct print_architecture_table_node archi_table[]= {
2019 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2020 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2021 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2022 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2023 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2024 {"Windows IA64", SPL_ARCH_IA64, 3 },
2025 {"Windows x64", SPL_ARCH_X64, 3 },
2029 static int get_version_id(const char *arch)
2033 for (i=0; archi_table[i].long_archi != NULL; i++)
2035 if (strcmp(arch, archi_table[i].long_archi) == 0)
2036 return (archi_table[i].version);
2042 /****************************************************************
2043 _spoolss_DeletePrinterDriver
2044 ****************************************************************/
2046 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2047 struct spoolss_DeletePrinterDriver *r)
2050 struct spoolss_DriverInfo8 *info = NULL;
2051 struct spoolss_DriverInfo8 *info_win2k = NULL;
2055 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2056 and not a printer admin, then fail */
2058 if ( (p->session_info->utok.uid != sec_initial_uid())
2059 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2060 && !token_contains_name_in_list(
2061 uidtoname(p->session_info->utok.uid),
2062 p->session_info->info3->base.domain.string,
2064 p->session_info->security_token,
2065 lp_printer_admin(-1)) )
2067 return WERR_ACCESS_DENIED;
2070 /* check that we have a valid driver name first */
2072 if ((version = get_version_id(r->in.architecture)) == -1)
2073 return WERR_INVALID_ENVIRONMENT;
2075 status = winreg_get_driver(p->mem_ctx,
2076 get_session_info_system(),
2078 r->in.architecture, r->in.driver,
2080 if (!W_ERROR_IS_OK(status)) {
2081 /* try for Win2k driver if "Windows NT x86" */
2083 if ( version == 2 ) {
2086 status = winreg_get_driver(p->mem_ctx,
2087 get_session_info_system(),
2092 if (!W_ERROR_IS_OK(status)) {
2093 status = WERR_UNKNOWN_PRINTER_DRIVER;
2097 /* otherwise it was a failure */
2099 status = WERR_UNKNOWN_PRINTER_DRIVER;
2105 if (printer_driver_in_use(p->mem_ctx,
2106 get_session_info_system(),
2109 status = WERR_PRINTER_DRIVER_IN_USE;
2114 status = winreg_get_driver(p->mem_ctx,
2115 get_session_info_system(),
2118 r->in.driver, 3, &info_win2k);
2119 if (W_ERROR_IS_OK(status)) {
2120 /* if we get to here, we now have 2 driver info structures to remove */
2121 /* remove the Win2k driver first*/
2123 status = winreg_del_driver(p->mem_ctx,
2124 get_session_info_system(),
2127 talloc_free(info_win2k);
2129 /* this should not have failed---if it did, report to client */
2130 if (!W_ERROR_IS_OK(status)) {
2136 status = winreg_del_driver(p->mem_ctx,
2137 get_session_info_system(),
2147 /****************************************************************
2148 _spoolss_DeletePrinterDriverEx
2149 ****************************************************************/
2151 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2152 struct spoolss_DeletePrinterDriverEx *r)
2154 struct spoolss_DriverInfo8 *info = NULL;
2155 struct spoolss_DriverInfo8 *info_win2k = NULL;
2160 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2161 and not a printer admin, then fail */
2163 if ( (p->session_info->utok.uid != sec_initial_uid())
2164 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2165 && !token_contains_name_in_list(
2166 uidtoname(p->session_info->utok.uid),
2167 p->session_info->info3->base.domain.string,
2169 p->session_info->security_token, lp_printer_admin(-1)) )
2171 return WERR_ACCESS_DENIED;
2174 /* check that we have a valid driver name first */
2175 if ((version = get_version_id(r->in.architecture)) == -1) {
2176 /* this is what NT returns */
2177 return WERR_INVALID_ENVIRONMENT;
2180 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2181 version = r->in.version;
2183 status = winreg_get_driver(p->mem_ctx,
2184 get_session_info_system(),
2190 if (!W_ERROR_IS_OK(status)) {
2191 status = WERR_UNKNOWN_PRINTER_DRIVER;
2194 * if the client asked for a specific version,
2195 * or this is something other than Windows NT x86,
2199 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2202 /* try for Win2k driver if "Windows NT x86" */
2205 status = winreg_get_driver(info,
2206 get_session_info_system(),
2211 if (!W_ERROR_IS_OK(status)) {
2212 status = WERR_UNKNOWN_PRINTER_DRIVER;
2217 if (printer_driver_in_use(info,
2218 get_session_info_system(),
2221 status = WERR_PRINTER_DRIVER_IN_USE;
2226 * we have a couple of cases to consider.
2227 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2228 * then the delete should fail if **any** files overlap with
2230 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2231 * non-overlapping files
2232 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2233 * is set, the do not delete any files
2234 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2237 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2239 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2242 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2243 printer_driver_files_in_use(info,
2244 get_session_info_system(),
2247 /* no idea of the correct error here */
2248 status = WERR_ACCESS_DENIED;
2253 /* also check for W32X86/3 if necessary; maybe we already have? */
2255 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2256 status = winreg_get_driver(info,
2257 get_session_info_system(),
2260 r->in.driver, 3, &info_win2k);
2261 if (W_ERROR_IS_OK(status)) {
2264 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2265 printer_driver_files_in_use(info,
2266 get_session_info_system(),
2269 /* no idea of the correct error here */
2270 talloc_free(info_win2k);
2271 status = WERR_ACCESS_DENIED;
2275 /* if we get to here, we now have 2 driver info structures to remove */
2276 /* remove the Win2k driver first*/
2278 status = winreg_del_driver(info,
2279 get_session_info_system(),
2284 /* this should not have failed---if it did, report to client */
2286 if (!W_ERROR_IS_OK(status)) {
2291 * now delete any associated files if delete_files is
2292 * true. Even if this part failes, we return succes
2293 * because the driver doesn not exist any more
2296 delete_driver_files(get_session_info_system(),
2302 status = winreg_del_driver(info,
2303 get_session_info_system(),
2307 if (!W_ERROR_IS_OK(status)) {
2312 * now delete any associated files if delete_files is
2313 * true. Even if this part failes, we return succes
2314 * because the driver doesn not exist any more
2317 delete_driver_files(get_session_info_system(), info);
2326 /********************************************************************
2327 GetPrinterData on a printer server Handle.
2328 ********************************************************************/
2330 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2332 enum winreg_Type *type,
2333 union spoolss_PrinterData *data)
2335 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2337 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2343 if (!StrCaseCmp(value, "BeepEnabled")) {
2349 if (!StrCaseCmp(value, "EventLog")) {
2351 /* formally was 0x1b */
2356 if (!StrCaseCmp(value, "NetPopup")) {
2362 if (!StrCaseCmp(value, "MajorVersion")) {
2365 /* Windows NT 4.0 seems to not allow uploading of drivers
2366 to a server that reports 0x3 as the MajorVersion.
2367 need to investigate more how Win2k gets around this .
2370 if (RA_WINNT == get_remote_arch()) {
2379 if (!StrCaseCmp(value, "MinorVersion")) {
2386 * uint32_t size = 0x114
2387 * uint32_t major = 5
2388 * uint32_t minor = [0|1]
2389 * uint32_t build = [2195|2600]
2390 * extra unicode string = e.g. "Service Pack 3"
2392 if (!StrCaseCmp(value, "OSVersion")) {
2394 enum ndr_err_code ndr_err;
2395 struct spoolss_OSVersion os;
2397 os.major = 5; /* Windows 2000 == 5.0 */
2399 os.build = 2195; /* build */
2400 os.extra_string = ""; /* leave extra string empty */
2402 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2403 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2404 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2405 return WERR_GENERAL_FAILURE;
2409 data->binary = blob;
2415 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2418 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2419 W_ERROR_HAVE_NO_MEMORY(data->string);
2424 if (!StrCaseCmp(value, "Architecture")) {
2426 data->string = talloc_strdup(mem_ctx,
2427 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2428 W_ERROR_HAVE_NO_MEMORY(data->string);
2433 if (!StrCaseCmp(value, "DsPresent")) {
2436 /* only show the publish check box if we are a
2437 member of a AD domain */
2439 if (lp_security() == SEC_ADS) {
2447 if (!StrCaseCmp(value, "DNSMachineName")) {
2448 const char *hostname = get_mydnsfullname();
2451 return WERR_BADFILE;
2455 data->string = talloc_strdup(mem_ctx, hostname);
2456 W_ERROR_HAVE_NO_MEMORY(data->string);
2463 return WERR_INVALID_PARAM;
2466 /****************************************************************
2467 _spoolss_GetPrinterData
2468 ****************************************************************/
2470 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2471 struct spoolss_GetPrinterData *r)
2473 struct spoolss_GetPrinterDataEx r2;
2475 r2.in.handle = r->in.handle;
2476 r2.in.key_name = "PrinterDriverData";
2477 r2.in.value_name = r->in.value_name;
2478 r2.in.offered = r->in.offered;
2479 r2.out.type = r->out.type;
2480 r2.out.data = r->out.data;
2481 r2.out.needed = r->out.needed;
2483 return _spoolss_GetPrinterDataEx(p, &r2);
2486 /*********************************************************
2487 Connect to the client machine.
2488 **********************************************************/
2490 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2491 struct sockaddr_storage *client_ss, const char *remote_machine)
2494 struct cli_state *the_cli;
2495 struct sockaddr_storage rm_addr;
2496 char addr[INET6_ADDRSTRLEN];
2498 if ( is_zero_addr(client_ss) ) {
2499 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2501 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2502 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2505 print_sockaddr(addr, sizeof(addr), &rm_addr);
2507 rm_addr = *client_ss;
2508 print_sockaddr(addr, sizeof(addr), &rm_addr);
2509 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2513 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2514 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2519 /* setup the connection */
2520 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2521 &rm_addr, 0, "IPC$", "IPC",
2525 0, lp_client_signing());
2527 if ( !NT_STATUS_IS_OK( ret ) ) {
2528 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2533 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2534 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2535 cli_shutdown(the_cli);
2540 * Ok - we have an anonymous connection to the IPC$ share.
2541 * Now start the NT Domain stuff :-).
2544 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2545 if (!NT_STATUS_IS_OK(ret)) {
2546 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2547 remote_machine, nt_errstr(ret)));
2548 cli_shutdown(the_cli);
2555 /***************************************************************************
2556 Connect to the client.
2557 ****************************************************************************/
2559 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2560 uint32_t localprinter,
2561 enum winreg_Type type,
2562 struct policy_handle *handle,
2563 struct notify_back_channel **_chan,
2564 struct sockaddr_storage *client_ss,
2565 struct messaging_context *msg_ctx)
2569 struct notify_back_channel *chan;
2571 for (chan = back_channels; chan; chan = chan->next) {
2572 if (memcmp(&chan->client_address, client_ss,
2573 sizeof(struct sockaddr_storage)) == 0) {
2579 * If it's the first connection, contact the client
2580 * and connect to the IPC$ share anonymously
2583 fstring unix_printer;
2585 /* the +2 is to strip the leading 2 backslashs */
2586 fstrcpy(unix_printer, printer + 2);
2588 chan = talloc_zero(back_channels, struct notify_back_channel);
2592 chan->client_address = *client_ss;
2594 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2598 chan->binding_handle = chan->cli_pipe->binding_handle;
2600 DLIST_ADD(back_channels, chan);
2602 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2603 receive_notify2_message_list);
2604 /* Tell the connections db we're now interested in printer
2605 * notify messages. */
2606 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2607 true, FLAG_MSG_PRINT_NOTIFY);
2611 * Tell the specific printing tdb we want messages for this printer
2612 * by registering our PID.
2615 if (!print_notify_register_pid(snum)) {
2616 DEBUG(0, ("Failed to register our pid for printer %s\n",
2620 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2629 if (!NT_STATUS_IS_OK(status)) {
2630 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2631 result = ntstatus_to_werror(status);
2632 } else if (!W_ERROR_IS_OK(result)) {
2633 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2636 chan->active_connections++;
2639 return (W_ERROR_IS_OK(result));
2642 /****************************************************************
2643 ****************************************************************/
2645 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2646 const struct spoolss_NotifyOption *r)
2648 struct spoolss_NotifyOption *option;
2655 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2662 if (!option->count) {
2666 option->types = talloc_zero_array(option,
2667 struct spoolss_NotifyOptionType, option->count);
2668 if (!option->types) {
2669 talloc_free(option);
2673 for (i=0; i < option->count; i++) {
2674 option->types[i] = r->types[i];
2676 if (option->types[i].count) {
2677 option->types[i].fields = talloc_zero_array(option,
2678 union spoolss_Field, option->types[i].count);
2679 if (!option->types[i].fields) {
2680 talloc_free(option);
2683 for (k=0; k<option->types[i].count; k++) {
2684 option->types[i].fields[k] =
2685 r->types[i].fields[k];
2693 /****************************************************************
2694 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2696 * before replying OK: status=0 a rpc call is made to the workstation
2697 * asking ReplyOpenPrinter
2699 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2700 * called from api_spoolss_rffpcnex
2701 ****************************************************************/
2703 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2704 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2707 struct spoolss_NotifyOption *option = r->in.notify_options;
2708 struct sockaddr_storage client_ss;
2710 /* store the notify value in the printer struct */
2712 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2715 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2716 "Invalid handle (%s:%u:%u).\n",
2717 OUR_HANDLE(r->in.handle)));
2721 Printer->notify.flags = r->in.flags;
2722 Printer->notify.options = r->in.options;
2723 Printer->notify.printerlocal = r->in.printer_local;
2724 Printer->notify.msg_ctx = p->msg_ctx;
2726 TALLOC_FREE(Printer->notify.option);
2727 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2729 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2731 /* Connect to the client machine and send a ReplyOpenPrinter */
2733 if ( Printer->printer_type == SPLHND_SERVER)
2735 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2736 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2739 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2740 "client_address is %s\n", p->client_id->addr));
2742 if (!lp_print_notify_backchannel(snum)) {
2743 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2744 "backchannel disabled\n"));
2745 return WERR_SERVER_UNAVAILABLE;
2748 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2750 return WERR_SERVER_UNAVAILABLE;
2753 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2754 Printer->notify.printerlocal, REG_SZ,
2755 &Printer->notify.cli_hnd,
2756 &Printer->notify.cli_chan,
2757 &client_ss, p->msg_ctx)) {
2758 return WERR_SERVER_UNAVAILABLE;
2764 /*******************************************************************
2765 * fill a notify_info_data with the servername
2766 ********************************************************************/
2768 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2770 struct spoolss_Notify *data,
2771 print_queue_struct *queue,
2772 struct spoolss_PrinterInfo2 *pinfo2,
2773 TALLOC_CTX *mem_ctx)
2775 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2778 /*******************************************************************
2779 * fill a notify_info_data with the printername (not including the servername).
2780 ********************************************************************/
2782 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2784 struct spoolss_Notify *data,
2785 print_queue_struct *queue,
2786 struct spoolss_PrinterInfo2 *pinfo2,
2787 TALLOC_CTX *mem_ctx)
2789 /* the notify name should not contain the \\server\ part */
2790 const char *p = strrchr(pinfo2->printername, '\\');
2793 p = pinfo2->printername;
2798 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2801 /*******************************************************************
2802 * fill a notify_info_data with the servicename
2803 ********************************************************************/
2805 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2807 struct spoolss_Notify *data,
2808 print_queue_struct *queue,
2809 struct spoolss_PrinterInfo2 *pinfo2,
2810 TALLOC_CTX *mem_ctx)
2812 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2815 /*******************************************************************
2816 * fill a notify_info_data with the port name
2817 ********************************************************************/
2819 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2821 struct spoolss_Notify *data,
2822 print_queue_struct *queue,
2823 struct spoolss_PrinterInfo2 *pinfo2,
2824 TALLOC_CTX *mem_ctx)
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2829 /*******************************************************************
2830 * fill a notify_info_data with the printername
2831 * but it doesn't exist, have to see what to do
2832 ********************************************************************/
2834 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 struct spoolss_PrinterInfo2 *pinfo2,
2839 TALLOC_CTX *mem_ctx)
2841 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2844 /*******************************************************************
2845 * fill a notify_info_data with the comment
2846 ********************************************************************/
2848 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2850 struct spoolss_Notify *data,
2851 print_queue_struct *queue,
2852 struct spoolss_PrinterInfo2 *pinfo2,
2853 TALLOC_CTX *mem_ctx)
2857 if (*pinfo2->comment == '\0') {
2858 p = lp_comment(snum);
2860 p = pinfo2->comment;
2863 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2866 /*******************************************************************
2867 * fill a notify_info_data with the comment
2868 * location = "Room 1, floor 2, building 3"
2869 ********************************************************************/
2871 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2873 struct spoolss_Notify *data,
2874 print_queue_struct *queue,
2875 struct spoolss_PrinterInfo2 *pinfo2,
2876 TALLOC_CTX *mem_ctx)
2878 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2881 /*******************************************************************
2882 * fill a notify_info_data with the device mode
2883 * jfm:xxxx don't to it for know but that's a real problem !!!
2884 ********************************************************************/
2886 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2888 struct spoolss_Notify *data,
2889 print_queue_struct *queue,
2890 struct spoolss_PrinterInfo2 *pinfo2,
2891 TALLOC_CTX *mem_ctx)
2893 /* for a dummy implementation we have to zero the fields */
2894 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2897 /*******************************************************************
2898 * fill a notify_info_data with the separator file name
2899 ********************************************************************/
2901 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2903 struct spoolss_Notify *data,
2904 print_queue_struct *queue,
2905 struct spoolss_PrinterInfo2 *pinfo2,
2906 TALLOC_CTX *mem_ctx)
2908 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2911 /*******************************************************************
2912 * fill a notify_info_data with the print processor
2913 * jfm:xxxx return always winprint to indicate we don't do anything to it
2914 ********************************************************************/
2916 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2918 struct spoolss_Notify *data,
2919 print_queue_struct *queue,
2920 struct spoolss_PrinterInfo2 *pinfo2,
2921 TALLOC_CTX *mem_ctx)
2923 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2926 /*******************************************************************
2927 * fill a notify_info_data with the print processor options
2928 * jfm:xxxx send an empty string
2929 ********************************************************************/
2931 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2933 struct spoolss_Notify *data,
2934 print_queue_struct *queue,
2935 struct spoolss_PrinterInfo2 *pinfo2,
2936 TALLOC_CTX *mem_ctx)
2938 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2941 /*******************************************************************
2942 * fill a notify_info_data with the data type
2943 * jfm:xxxx always send RAW as data type
2944 ********************************************************************/
2946 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 struct spoolss_PrinterInfo2 *pinfo2,
2951 TALLOC_CTX *mem_ctx)
2953 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2956 /*******************************************************************
2957 * fill a notify_info_data with the security descriptor
2958 * jfm:xxxx send an null pointer to say no security desc
2959 * have to implement security before !
2960 ********************************************************************/
2962 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2964 struct spoolss_Notify *data,
2965 print_queue_struct *queue,
2966 struct spoolss_PrinterInfo2 *pinfo2,
2967 TALLOC_CTX *mem_ctx)
2969 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2972 /*******************************************************************
2973 * fill a notify_info_data with the attributes
2974 * jfm:xxxx a samba printer is always shared
2975 ********************************************************************/
2977 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2979 struct spoolss_Notify *data,
2980 print_queue_struct *queue,
2981 struct spoolss_PrinterInfo2 *pinfo2,
2982 TALLOC_CTX *mem_ctx)
2984 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2987 /*******************************************************************
2988 * fill a notify_info_data with the priority
2989 ********************************************************************/
2991 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2993 struct spoolss_Notify *data,
2994 print_queue_struct *queue,
2995 struct spoolss_PrinterInfo2 *pinfo2,
2996 TALLOC_CTX *mem_ctx)
2998 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3001 /*******************************************************************
3002 * fill a notify_info_data with the default priority
3003 ********************************************************************/
3005 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 struct spoolss_PrinterInfo2 *pinfo2,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3015 /*******************************************************************
3016 * fill a notify_info_data with the start time
3017 ********************************************************************/
3019 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 struct spoolss_PrinterInfo2 *pinfo2,
3024 TALLOC_CTX *mem_ctx)
3026 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3029 /*******************************************************************
3030 * fill a notify_info_data with the until time
3031 ********************************************************************/
3033 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3035 struct spoolss_Notify *data,
3036 print_queue_struct *queue,
3037 struct spoolss_PrinterInfo2 *pinfo2,
3038 TALLOC_CTX *mem_ctx)
3040 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3043 /*******************************************************************
3044 * fill a notify_info_data with the status
3045 ********************************************************************/
3047 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3049 struct spoolss_Notify *data,
3050 print_queue_struct *queue,
3051 struct spoolss_PrinterInfo2 *pinfo2,
3052 TALLOC_CTX *mem_ctx)
3054 print_status_struct status;
3056 print_queue_length(msg_ctx, snum, &status);
3057 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3060 /*******************************************************************
3061 * fill a notify_info_data with the number of jobs queued
3062 ********************************************************************/
3064 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3066 struct spoolss_Notify *data,
3067 print_queue_struct *queue,
3068 struct spoolss_PrinterInfo2 *pinfo2,
3069 TALLOC_CTX *mem_ctx)
3071 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3072 data, print_queue_length(msg_ctx, snum, NULL));
3075 /*******************************************************************
3076 * fill a notify_info_data with the average ppm
3077 ********************************************************************/
3079 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3081 struct spoolss_Notify *data,
3082 print_queue_struct *queue,
3083 struct spoolss_PrinterInfo2 *pinfo2,
3084 TALLOC_CTX *mem_ctx)
3086 /* always respond 8 pages per minutes */
3087 /* a little hard ! */
3088 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3091 /*******************************************************************
3092 * fill a notify_info_data with username
3093 ********************************************************************/
3095 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3097 struct spoolss_Notify *data,
3098 print_queue_struct *queue,
3099 struct spoolss_PrinterInfo2 *pinfo2,
3100 TALLOC_CTX *mem_ctx)
3102 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3105 /*******************************************************************
3106 * fill a notify_info_data with job status
3107 ********************************************************************/
3109 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3111 struct spoolss_Notify *data,
3112 print_queue_struct *queue,
3113 struct spoolss_PrinterInfo2 *pinfo2,
3114 TALLOC_CTX *mem_ctx)
3116 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3119 /*******************************************************************
3120 * fill a notify_info_data with job name
3121 ********************************************************************/
3123 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3125 struct spoolss_Notify *data,
3126 print_queue_struct *queue,
3127 struct spoolss_PrinterInfo2 *pinfo2,
3128 TALLOC_CTX *mem_ctx)
3130 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3133 /*******************************************************************
3134 * fill a notify_info_data with job status
3135 ********************************************************************/
3137 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3139 struct spoolss_Notify *data,
3140 print_queue_struct *queue,
3141 struct spoolss_PrinterInfo2 *pinfo2,
3142 TALLOC_CTX *mem_ctx)
3145 * Now we're returning job status codes we just return a "" here. JRA.
3150 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3153 switch (queue->status) {
3158 p = ""; /* NT provides the paused string */
3167 #endif /* NO LONGER NEEDED. */
3169 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3172 /*******************************************************************
3173 * fill a notify_info_data with job time
3174 ********************************************************************/
3176 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3178 struct spoolss_Notify *data,
3179 print_queue_struct *queue,
3180 struct spoolss_PrinterInfo2 *pinfo2,
3181 TALLOC_CTX *mem_ctx)
3183 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3186 /*******************************************************************
3187 * fill a notify_info_data with job size
3188 ********************************************************************/
3190 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3192 struct spoolss_Notify *data,
3193 print_queue_struct *queue,
3194 struct spoolss_PrinterInfo2 *pinfo2,
3195 TALLOC_CTX *mem_ctx)
3197 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3200 /*******************************************************************
3201 * fill a notify_info_data with page info
3202 ********************************************************************/
3203 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3205 struct spoolss_Notify *data,
3206 print_queue_struct *queue,
3207 struct spoolss_PrinterInfo2 *pinfo2,
3208 TALLOC_CTX *mem_ctx)
3210 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3213 /*******************************************************************
3214 * fill a notify_info_data with pages printed info.
3215 ********************************************************************/
3216 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3218 struct spoolss_Notify *data,
3219 print_queue_struct *queue,
3220 struct spoolss_PrinterInfo2 *pinfo2,
3221 TALLOC_CTX *mem_ctx)
3223 /* Add code when back-end tracks this */
3224 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3227 /*******************************************************************
3228 Fill a notify_info_data with job position.
3229 ********************************************************************/
3231 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3233 struct spoolss_Notify *data,
3234 print_queue_struct *queue,
3235 struct spoolss_PrinterInfo2 *pinfo2,
3236 TALLOC_CTX *mem_ctx)
3238 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3241 /*******************************************************************
3242 Fill a notify_info_data with submitted time.
3243 ********************************************************************/
3245 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3247 struct spoolss_Notify *data,
3248 print_queue_struct *queue,
3249 struct spoolss_PrinterInfo2 *pinfo2,
3250 TALLOC_CTX *mem_ctx)
3252 data->data.string.string = NULL;
3253 data->data.string.size = 0;
3255 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3256 &data->data.string.string,
3257 &data->data.string.size);
3261 struct s_notify_info_data_table
3263 enum spoolss_NotifyType type;
3266 enum spoolss_NotifyTable variable_type;
3267 void (*fn) (struct messaging_context *msg_ctx,
3268 int snum, struct spoolss_Notify *data,
3269 print_queue_struct *queue,
3270 struct spoolss_PrinterInfo2 *pinfo2,
3271 TALLOC_CTX *mem_ctx);
3274 /* A table describing the various print notification constants and
3275 whether the notification data is a pointer to a variable sized
3276 buffer, a one value uint32_t or a two value uint32_t. */
3278 static const struct s_notify_info_data_table notify_info_data_table[] =
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3331 /*******************************************************************
3332 Return the variable_type of info_data structure.
3333 ********************************************************************/
3335 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3340 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3341 if ( (notify_info_data_table[i].type == type) &&
3342 (notify_info_data_table[i].field == field) ) {
3343 return notify_info_data_table[i].variable_type;
3347 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3349 return (enum spoolss_NotifyTable) 0;
3352 /****************************************************************************
3353 ****************************************************************************/
3355 static bool search_notify(enum spoolss_NotifyType type,
3361 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3362 if (notify_info_data_table[i].type == type &&
3363 notify_info_data_table[i].field == field &&
3364 notify_info_data_table[i].fn != NULL) {
3373 /****************************************************************************
3374 ****************************************************************************/
3376 static void construct_info_data(struct spoolss_Notify *info_data,
3377 enum spoolss_NotifyType type,
3378 uint16_t field, int id)
3380 info_data->type = type;
3381 info_data->field.field = field;
3382 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3383 info_data->job_id = id;
3386 /*******************************************************************
3388 * fill a notify_info struct with info asked
3390 ********************************************************************/
3392 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3393 struct printer_handle *print_hnd,
3394 struct spoolss_NotifyInfo *info,
3395 struct spoolss_PrinterInfo2 *pinfo2,
3397 const struct spoolss_NotifyOptionType *option_type,
3399 TALLOC_CTX *mem_ctx)
3402 enum spoolss_NotifyType type;
3405 struct spoolss_Notify *current_data;
3406 print_queue_struct *queue=NULL;
3408 type = option_type->type;
3410 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3411 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3412 option_type->count, lp_servicename(snum)));
3414 for(field_num=0; field_num < option_type->count; field_num++) {
3415 field = option_type->fields[field_num].field;
3417 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3419 if (!search_notify(type, field, &j) )
3422 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3423 struct spoolss_Notify,
3425 if (info->notifies == NULL) {
3426 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3430 current_data = &info->notifies[info->count];
3432 construct_info_data(current_data, type, field, id);
3434 DEBUG(10, ("construct_notify_printer_info: "
3435 "calling [%s] snum=%d printername=[%s])\n",
3436 notify_info_data_table[j].name, snum,
3437 pinfo2->printername));
3439 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3440 queue, pinfo2, mem_ctx);
3448 /*******************************************************************
3450 * fill a notify_info struct with info asked
3452 ********************************************************************/
3454 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3455 print_queue_struct *queue,
3456 struct spoolss_NotifyInfo *info,
3457 struct spoolss_PrinterInfo2 *pinfo2,
3459 const struct spoolss_NotifyOptionType *option_type,
3461 TALLOC_CTX *mem_ctx)
3464 enum spoolss_NotifyType type;
3466 struct spoolss_Notify *current_data;
3468 DEBUG(4,("construct_notify_jobs_info\n"));
3470 type = option_type->type;
3472 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3473 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3474 option_type->count));
3476 for(field_num=0; field_num<option_type->count; field_num++) {
3477 field = option_type->fields[field_num].field;
3479 if (!search_notify(type, field, &j) )
3482 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3483 struct spoolss_Notify,
3485 if (info->notifies == NULL) {
3486 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3490 current_data=&(info->notifies[info->count]);
3492 construct_info_data(current_data, type, field, id);
3493 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3494 queue, pinfo2, mem_ctx);
3502 * JFM: The enumeration is not that simple, it's even non obvious.
3504 * let's take an example: I want to monitor the PRINTER SERVER for
3505 * the printer's name and the number of jobs currently queued.
3506 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3507 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3509 * I have 3 printers on the back of my server.
3511 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3514 * 1 printer 1 name 1
3515 * 2 printer 1 cjob 1
3516 * 3 printer 2 name 2
3517 * 4 printer 2 cjob 2
3518 * 5 printer 3 name 3
3519 * 6 printer 3 name 3
3521 * that's the print server case, the printer case is even worse.
3524 /*******************************************************************
3526 * enumerate all printers on the printserver
3527 * fill a notify_info struct with info asked
3529 ********************************************************************/
3531 static WERROR printserver_notify_info(struct pipes_struct *p,
3532 struct policy_handle *hnd,
3533 struct spoolss_NotifyInfo *info,
3534 TALLOC_CTX *mem_ctx)
3537 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3538 int n_services=lp_numservices();
3540 struct spoolss_NotifyOption *option;
3541 struct spoolss_NotifyOptionType option_type;
3542 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3545 DEBUG(4,("printserver_notify_info\n"));
3550 option = Printer->notify.option;
3553 info->notifies = NULL;
3556 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3557 sending a ffpcn() request first */
3562 for (i=0; i<option->count; i++) {
3563 option_type = option->types[i];
3565 if (option_type.type != PRINTER_NOTIFY_TYPE)
3568 for (snum = 0; snum < n_services; snum++) {
3569 if (!lp_browseable(snum) ||
3570 !lp_snum_ok(snum) ||
3571 !lp_print_ok(snum)) {
3572 continue; /* skip */
3575 /* Maybe we should use the SYSTEM session_info here... */
3576 result = winreg_get_printer(mem_ctx,
3577 get_session_info_system(),
3579 lp_servicename(snum),
3581 if (!W_ERROR_IS_OK(result)) {
3582 DEBUG(4, ("printserver_notify_info: "
3583 "Failed to get printer [%s]\n",
3584 lp_servicename(snum)));
3589 construct_notify_printer_info(p->msg_ctx,
3595 TALLOC_FREE(pinfo2);
3601 * Debugging information, don't delete.
3604 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3605 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3606 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3608 for (i=0; i<info->count; i++) {
3609 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3610 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3611 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3618 /*******************************************************************
3620 * fill a notify_info struct with info asked
3622 ********************************************************************/
3624 static WERROR printer_notify_info(struct pipes_struct *p,
3625 struct policy_handle *hnd,
3626 struct spoolss_NotifyInfo *info,
3627 TALLOC_CTX *mem_ctx)
3630 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3633 struct spoolss_NotifyOption *option;
3634 struct spoolss_NotifyOptionType option_type;
3636 print_queue_struct *queue=NULL;
3637 print_status_struct status;
3638 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3641 DEBUG(4,("printer_notify_info\n"));
3646 option = Printer->notify.option;
3650 info->notifies = NULL;
3653 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3654 sending a ffpcn() request first */
3659 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3663 /* Maybe we should use the SYSTEM session_info here... */
3664 result = winreg_get_printer(mem_ctx,
3665 get_session_info_system(),
3667 lp_servicename(snum), &pinfo2);
3668 if (!W_ERROR_IS_OK(result)) {
3672 for (i=0; i<option->count; i++) {
3673 option_type = option->types[i];
3675 switch (option_type.type) {
3676 case PRINTER_NOTIFY_TYPE:
3677 if (construct_notify_printer_info(p->msg_ctx,
3686 case JOB_NOTIFY_TYPE:
3688 count = print_queue_status(p->msg_ctx, snum, &queue,
3691 for (j=0; j<count; j++) {
3692 construct_notify_jobs_info(p->msg_ctx,
3706 * Debugging information, don't delete.
3709 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3710 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3711 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3713 for (i=0; i<info->count; i++) {
3714 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3715 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3716 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3720 talloc_free(pinfo2);
3724 /****************************************************************
3725 _spoolss_RouterRefreshPrinterChangeNotify
3726 ****************************************************************/
3728 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3729 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3731 struct spoolss_NotifyInfo *info;
3733 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3734 WERROR result = WERR_BADFID;
3736 /* we always have a spoolss_NotifyInfo struct */
3737 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3739 result = WERR_NOMEM;
3743 *r->out.info = info;
3746 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3747 "Invalid handle (%s:%u:%u).\n",
3748 OUR_HANDLE(r->in.handle)));
3752 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3755 * We are now using the change value, and
3756 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3757 * I don't have a global notification system, I'm sending back all the
3758 * information even when _NOTHING_ has changed.
3761 /* We need to keep track of the change value to send back in
3762 RRPCN replies otherwise our updates are ignored. */
3764 Printer->notify.fnpcn = true;
3766 if (Printer->notify.cli_chan != NULL &&
3767 Printer->notify.cli_chan->active_connections > 0) {
3768 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3769 "Saving change value in request [%x]\n",
3771 Printer->notify.change = r->in.change_low;
3774 /* just ignore the spoolss_NotifyOption */
3776 switch (Printer->printer_type) {
3778 result = printserver_notify_info(p, r->in.handle,
3782 case SPLHND_PRINTER:
3783 result = printer_notify_info(p, r->in.handle,
3788 Printer->notify.fnpcn = false;
3794 /********************************************************************
3795 ********************************************************************/
3797 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3798 const char *servername,
3799 const char *printername,
3800 const char **printername_p)
3802 /* FIXME: add lp_force_printername() */
3804 if (servername == NULL) {
3805 *printername_p = talloc_strdup(mem_ctx, printername);
3806 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3810 if (servername[0] == '\\' && servername[1] == '\\') {
3814 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3815 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3820 /********************************************************************
3821 ********************************************************************/
3823 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3824 const char *printername)
3830 dm->devicename = talloc_strndup(dm, printername,
3831 MIN(strlen(printername), 31));
3834 /********************************************************************
3835 * construct_printer_info_0
3836 * fill a printer_info_0 struct
3837 ********************************************************************/
3839 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3840 const struct auth_serversupplied_info *session_info,
3841 struct messaging_context *msg_ctx,
3842 struct spoolss_PrinterInfo2 *info2,
3843 const char *servername,
3844 struct spoolss_PrinterInfo0 *r,
3848 struct printer_session_counter *session_counter;
3849 struct timeval setuptime;
3850 print_status_struct status;
3853 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3854 if (!W_ERROR_IS_OK(result)) {
3859 r->servername = talloc_strdup(mem_ctx, servername);
3860 W_ERROR_HAVE_NO_MEMORY(r->servername);
3862 r->servername = NULL;
3865 count = print_queue_length(msg_ctx, snum, &status);
3867 /* check if we already have a counter for this printer */
3868 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3869 if (session_counter->snum == snum)
3873 /* it's the first time, add it to the list */
3874 if (session_counter == NULL) {
3875 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3876 W_ERROR_HAVE_NO_MEMORY(session_counter);
3877 session_counter->snum = snum;
3878 session_counter->counter = 0;
3879 DLIST_ADD(counter_list, session_counter);
3883 session_counter->counter++;
3889 get_startup_time(&setuptime);
3890 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3893 * the global_counter should be stored in a TDB as it's common to all the clients
3894 * and should be zeroed on samba startup
3896 r->global_counter = session_counter->counter;
3898 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3899 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3900 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3901 r->free_build = SPOOLSS_RELEASE_BUILD;
3903 r->max_spooling = 0;
3904 r->session_counter = session_counter->counter;
3905 r->num_error_out_of_paper = 0x0;
3906 r->num_error_not_ready = 0x0; /* number of print failure */
3908 r->number_of_processors = 0x1;
3909 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3910 r->high_part_total_bytes = 0x0;
3912 /* ChangeID in milliseconds*/
3913 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3914 info2->sharename, &r->change_id);
3916 r->last_error = WERR_OK;
3917 r->status = nt_printq_status(status.status);
3918 r->enumerate_network_printers = 0x0;
3919 r->c_setprinter = 0x0;
3920 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3921 r->processor_level = 0x6; /* 6 ???*/
3930 /********************************************************************
3931 * construct_printer_info1
3932 * fill a spoolss_PrinterInfo1 struct
3933 ********************************************************************/
3935 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3936 const struct spoolss_PrinterInfo2 *info2,
3938 const char *servername,
3939 struct spoolss_PrinterInfo1 *r,
3946 if (info2->comment == NULL || info2->comment[0] == '\0') {
3947 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3949 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3951 W_ERROR_HAVE_NO_MEMORY(r->comment);
3953 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3954 if (!W_ERROR_IS_OK(result)) {
3958 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3962 W_ERROR_HAVE_NO_MEMORY(r->description);
3967 /********************************************************************
3968 * construct_printer_info2
3969 * fill a spoolss_PrinterInfo2 struct
3970 ********************************************************************/
3972 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3973 struct messaging_context *msg_ctx,
3974 const struct spoolss_PrinterInfo2 *info2,
3975 const char *servername,
3976 struct spoolss_PrinterInfo2 *r,
3980 print_status_struct status;
3983 count = print_queue_length(msg_ctx, snum, &status);
3986 r->servername = talloc_strdup(mem_ctx, servername);
3987 W_ERROR_HAVE_NO_MEMORY(r->servername);
3989 r->servername = NULL;
3992 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3993 if (!W_ERROR_IS_OK(result)) {
3997 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3998 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3999 r->portname = talloc_strdup(mem_ctx, info2->portname);
4000 W_ERROR_HAVE_NO_MEMORY(r->portname);
4001 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4002 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4004 if (info2->comment[0] == '\0') {
4005 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4007 r->comment = talloc_strdup(mem_ctx, info2->comment);
4009 W_ERROR_HAVE_NO_MEMORY(r->comment);
4011 r->location = talloc_strdup(mem_ctx, info2->location);
4012 W_ERROR_HAVE_NO_MEMORY(r->location);
4013 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4014 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4015 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4016 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4017 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4018 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4019 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4020 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4022 r->attributes = info2->attributes;
4024 r->priority = info2->priority;
4025 r->defaultpriority = info2->defaultpriority;
4026 r->starttime = info2->starttime;
4027 r->untiltime = info2->untiltime;
4028 r->status = nt_printq_status(status.status);
4030 r->averageppm = info2->averageppm;
4032 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4034 DEBUG(8,("Returning NULL Devicemode!\n"));
4037 compose_devicemode_devicename(r->devmode, r->printername);
4041 if (info2->secdesc != NULL) {
4042 /* don't use talloc_steal() here unless you do a deep steal of all
4043 the SEC_DESC members */
4045 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4051 /********************************************************************
4052 * construct_printer_info3
4053 * fill a spoolss_PrinterInfo3 struct
4054 ********************************************************************/
4056 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4057 const struct spoolss_PrinterInfo2 *info2,
4058 const char *servername,
4059 struct spoolss_PrinterInfo3 *r,
4062 /* These are the components of the SD we are returning. */
4064 if (info2->secdesc != NULL) {
4065 /* don't use talloc_steal() here unless you do a deep steal of all
4066 the SEC_DESC members */
4068 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4069 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4075 /********************************************************************
4076 * construct_printer_info4
4077 * fill a spoolss_PrinterInfo4 struct
4078 ********************************************************************/
4080 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4081 const struct spoolss_PrinterInfo2 *info2,
4082 const char *servername,
4083 struct spoolss_PrinterInfo4 *r,
4088 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4089 if (!W_ERROR_IS_OK(result)) {
4094 r->servername = talloc_strdup(mem_ctx, servername);
4095 W_ERROR_HAVE_NO_MEMORY(r->servername);
4097 r->servername = NULL;
4100 r->attributes = info2->attributes;
4105 /********************************************************************
4106 * construct_printer_info5
4107 * fill a spoolss_PrinterInfo5 struct
4108 ********************************************************************/
4110 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4111 const struct spoolss_PrinterInfo2 *info2,
4112 const char *servername,
4113 struct spoolss_PrinterInfo5 *r,
4118 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4119 if (!W_ERROR_IS_OK(result)) {
4123 r->portname = talloc_strdup(mem_ctx, info2->portname);
4124 W_ERROR_HAVE_NO_MEMORY(r->portname);
4126 r->attributes = info2->attributes;
4128 /* these two are not used by NT+ according to MSDN */
4129 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4130 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4135 /********************************************************************
4136 * construct_printer_info_6
4137 * fill a spoolss_PrinterInfo6 struct
4138 ********************************************************************/
4140 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4141 struct messaging_context *msg_ctx,
4142 const struct spoolss_PrinterInfo2 *info2,
4143 const char *servername,
4144 struct spoolss_PrinterInfo6 *r,
4148 print_status_struct status;
4150 count = print_queue_length(msg_ctx, snum, &status);
4152 r->status = nt_printq_status(status.status);
4157 /********************************************************************
4158 * construct_printer_info7
4159 * fill a spoolss_PrinterInfo7 struct
4160 ********************************************************************/
4162 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4163 struct messaging_context *msg_ctx,
4164 const char *servername,
4165 struct spoolss_PrinterInfo7 *r,
4168 struct auth_serversupplied_info *session_info;
4172 status = make_session_info_system(mem_ctx, &session_info);
4173 if (!NT_STATUS_IS_OK(status)) {
4174 DEBUG(0, ("construct_printer_info7: "
4175 "Could not create system session_info\n"));
4179 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4181 lp_servicename(snum), &guid, NULL)) {
4182 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4183 r->action = DSPRINT_PUBLISH;
4185 r->guid = talloc_strdup(mem_ctx, "");
4186 r->action = DSPRINT_UNPUBLISH;
4188 W_ERROR_HAVE_NO_MEMORY(r->guid);
4190 TALLOC_FREE(session_info);
4194 /********************************************************************
4195 * construct_printer_info8
4196 * fill a spoolss_PrinterInfo8 struct
4197 ********************************************************************/
4199 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4200 const struct spoolss_PrinterInfo2 *info2,
4201 const char *servername,
4202 struct spoolss_DeviceModeInfo *r,
4206 const char *printername;
4208 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4209 if (!W_ERROR_IS_OK(result)) {
4213 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4215 DEBUG(8,("Returning NULL Devicemode!\n"));
4218 compose_devicemode_devicename(r->devmode, printername);
4224 /********************************************************************
4225 ********************************************************************/
4227 static bool snum_is_shared_printer(int snum)
4229 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4232 /********************************************************************
4233 Spoolss_enumprinters.
4234 ********************************************************************/
4236 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4237 const struct auth_serversupplied_info *session_info,
4238 struct messaging_context *msg_ctx,
4239 const char *servername,
4242 union spoolss_PrinterInfo **info_p,
4246 int n_services = lp_numservices();
4247 union spoolss_PrinterInfo *info = NULL;
4249 WERROR result = WERR_OK;
4254 for (snum = 0; snum < n_services; snum++) {
4256 const char *printer;
4257 struct spoolss_PrinterInfo2 *info2;
4259 if (!snum_is_shared_printer(snum)) {
4263 printer = lp_const_servicename(snum);
4265 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4268 result = winreg_create_printer(mem_ctx,
4272 if (!W_ERROR_IS_OK(result)) {
4276 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4277 union spoolss_PrinterInfo,
4280 result = WERR_NOMEM;
4284 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4286 if (!W_ERROR_IS_OK(result)) {
4292 result = construct_printer_info0(info, session_info,
4295 &info[count].info0, snum);
4298 result = construct_printer_info1(info, info2, flags,
4300 &info[count].info1, snum);
4303 result = construct_printer_info2(info, msg_ctx, info2,
4305 &info[count].info2, snum);
4308 result = construct_printer_info4(info, info2,
4310 &info[count].info4, snum);
4313 result = construct_printer_info5(info, info2,
4315 &info[count].info5, snum);
4319 result = WERR_UNKNOWN_LEVEL;
4323 if (!W_ERROR_IS_OK(result)) {
4334 if (!W_ERROR_IS_OK(result)) {
4344 /********************************************************************
4345 * handle enumeration of printers at level 0
4346 ********************************************************************/
4348 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4349 const struct auth_serversupplied_info *session_info,
4350 struct messaging_context *msg_ctx,
4352 const char *servername,
4353 union spoolss_PrinterInfo **info,
4356 DEBUG(4,("enum_all_printers_info_0\n"));
4358 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4359 servername, 0, flags, info, count);
4363 /********************************************************************
4364 ********************************************************************/
4366 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4367 const struct auth_serversupplied_info *session_info,
4368 struct messaging_context *msg_ctx,
4369 const char *servername,
4371 union spoolss_PrinterInfo **info,
4374 DEBUG(4,("enum_all_printers_info_1\n"));
4376 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4377 servername, 1, flags, info, count);
4380 /********************************************************************
4381 enum_all_printers_info_1_local.
4382 *********************************************************************/
4384 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4385 const struct auth_serversupplied_info *session_info,
4386 struct messaging_context *msg_ctx,
4387 const char *servername,
4388 union spoolss_PrinterInfo **info,
4391 DEBUG(4,("enum_all_printers_info_1_local\n"));
4393 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4394 servername, PRINTER_ENUM_ICON8, info, count);
4397 /********************************************************************
4398 enum_all_printers_info_1_name.
4399 *********************************************************************/
4401 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4402 const struct auth_serversupplied_info *session_info,
4403 struct messaging_context *msg_ctx,
4404 const char *servername,
4405 union spoolss_PrinterInfo **info,
4408 const char *s = servername;
4410 DEBUG(4,("enum_all_printers_info_1_name\n"));
4412 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4416 if (!is_myname_or_ipaddr(s)) {
4417 return WERR_INVALID_NAME;
4420 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4421 servername, PRINTER_ENUM_ICON8, info, count);
4424 /********************************************************************
4425 enum_all_printers_info_1_network.
4426 *********************************************************************/
4428 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4429 const struct auth_serversupplied_info *session_info,
4430 struct messaging_context *msg_ctx,
4431 const char *servername,
4432 union spoolss_PrinterInfo **info,
4435 const char *s = servername;
4437 DEBUG(4,("enum_all_printers_info_1_network\n"));
4439 /* If we respond to a enum_printers level 1 on our name with flags
4440 set to PRINTER_ENUM_REMOTE with a list of printers then these
4441 printers incorrectly appear in the APW browse list.
4442 Specifically the printers for the server appear at the workgroup
4443 level where all the other servers in the domain are
4444 listed. Windows responds to this call with a
4445 WERR_CAN_NOT_COMPLETE so we should do the same. */
4447 if (servername[0] == '\\' && servername[1] == '\\') {
4451 if (is_myname_or_ipaddr(s)) {
4452 return WERR_CAN_NOT_COMPLETE;
4455 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4456 servername, PRINTER_ENUM_NAME, info, count);
4459 /********************************************************************
4460 * api_spoolss_enumprinters
4462 * called from api_spoolss_enumprinters (see this to understand)
4463 ********************************************************************/
4465 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4466 const struct auth_serversupplied_info *session_info,
4467 struct messaging_context *msg_ctx,
4468 const char *servername,
4469 union spoolss_PrinterInfo **info,
4472 DEBUG(4,("enum_all_printers_info_2\n"));
4474 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4475 servername, 2, 0, info, count);
4478 /********************************************************************
4479 * handle enumeration of printers at level 1
4480 ********************************************************************/
4482 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4483 const struct auth_serversupplied_info *session_info,
4484 struct messaging_context *msg_ctx,
4486 const char *servername,
4487 union spoolss_PrinterInfo **info,
4490 /* Not all the flags are equals */
4492 if (flags & PRINTER_ENUM_LOCAL) {
4493 return enum_all_printers_info_1_local(mem_ctx, session_info,
4494 msg_ctx, servername, info, count);
4497 if (flags & PRINTER_ENUM_NAME) {
4498 return enum_all_printers_info_1_name(mem_ctx, session_info,
4499 msg_ctx, servername, info,
4503 if (flags & PRINTER_ENUM_NETWORK) {
4504 return enum_all_printers_info_1_network(mem_ctx, session_info,
4505 msg_ctx, servername, info,
4509 return WERR_OK; /* NT4sp5 does that */
4512 /********************************************************************
4513 * handle enumeration of printers at level 2
4514 ********************************************************************/
4516 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4517 const struct auth_serversupplied_info *session_info,
4518 struct messaging_context *msg_ctx,
4520 const char *servername,
4521 union spoolss_PrinterInfo **info,
4524 if (flags & PRINTER_ENUM_LOCAL) {
4526 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4531 if (flags & PRINTER_ENUM_NAME) {
4532 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4533 return WERR_INVALID_NAME;
4536 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4541 if (flags & PRINTER_ENUM_REMOTE) {
4542 return WERR_UNKNOWN_LEVEL;
4548 /********************************************************************
4549 * handle enumeration of printers at level 4
4550 ********************************************************************/
4552 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4553 const struct auth_serversupplied_info *session_info,
4554 struct messaging_context *msg_ctx,
4556 const char *servername,
4557 union spoolss_PrinterInfo **info,
4560 DEBUG(4,("enum_all_printers_info_4\n"));
4562 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4563 servername, 4, flags, info, count);
4567 /********************************************************************
4568 * handle enumeration of printers at level 5
4569 ********************************************************************/
4571 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4572 const struct auth_serversupplied_info *session_info,
4573 struct messaging_context *msg_ctx,
4575 const char *servername,
4576 union spoolss_PrinterInfo **info,
4579 DEBUG(4,("enum_all_printers_info_5\n"));
4581 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4582 servername, 5, flags, info, count);
4585 /****************************************************************
4586 _spoolss_EnumPrinters
4587 ****************************************************************/
4589 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4590 struct spoolss_EnumPrinters *r)
4592 const struct auth_serversupplied_info *session_info = get_session_info_system();
4595 /* that's an [in out] buffer */
4597 if (!r->in.buffer && (r->in.offered != 0)) {
4598 return WERR_INVALID_PARAM;
4601 DEBUG(4,("_spoolss_EnumPrinters\n"));
4605 *r->out.info = NULL;
4609 * flags==PRINTER_ENUM_NAME
4610 * if name=="" then enumerates all printers
4611 * if name!="" then enumerate the printer
4612 * flags==PRINTER_ENUM_REMOTE
4613 * name is NULL, enumerate printers
4614 * Level 2: name!="" enumerates printers, name can't be NULL
4615 * Level 3: doesn't exist
4616 * Level 4: does a local registry lookup
4617 * Level 5: same as Level 2
4620 if (r->in.server && r->in.server[0] == '\0') {
4621 r->in.server = NULL;
4624 switch (r->in.level) {
4626 result = enumprinters_level0(p->mem_ctx, session_info,
4627 p->msg_ctx, r->in.flags,
4629 r->out.info, r->out.count);
4632 result = enumprinters_level1(p->mem_ctx, session_info,
4633 p->msg_ctx, r->in.flags,
4635 r->out.info, r->out.count);
4638 result = enumprinters_level2(p->mem_ctx, session_info,
4639 p->msg_ctx, r->in.flags,
4641 r->out.info, r->out.count);
4644 result = enumprinters_level4(p->mem_ctx, session_info,
4645 p->msg_ctx, r->in.flags,
4647 r->out.info, r->out.count);
4650 result = enumprinters_level5(p->mem_ctx, session_info,
4651 p->msg_ctx, r->in.flags,
4653 r->out.info, r->out.count);
4656 return WERR_UNKNOWN_LEVEL;
4659 if (!W_ERROR_IS_OK(result)) {
4663 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4664 spoolss_EnumPrinters,
4665 *r->out.info, r->in.level,
4667 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4668 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4670 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4673 /****************************************************************
4675 ****************************************************************/
4677 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4678 struct spoolss_GetPrinter *r)
4680 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4681 struct spoolss_PrinterInfo2 *info2 = NULL;
4682 WERROR result = WERR_OK;
4685 /* that's an [in out] buffer */
4687 if (!r->in.buffer && (r->in.offered != 0)) {
4688 return WERR_INVALID_PARAM;
4693 if (Printer == NULL) {
4697 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4701 result = winreg_get_printer(p->mem_ctx,
4702 get_session_info_system(),
4704 lp_const_servicename(snum),
4706 if (!W_ERROR_IS_OK(result)) {
4710 switch (r->in.level) {
4712 result = construct_printer_info0(p->mem_ctx,
4713 get_session_info_system(),
4716 Printer->servername,
4717 &r->out.info->info0,
4721 result = construct_printer_info1(p->mem_ctx, info2,
4723 Printer->servername,
4724 &r->out.info->info1, snum);
4727 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4728 Printer->servername,
4729 &r->out.info->info2, snum);
4732 result = construct_printer_info3(p->mem_ctx, info2,
4733 Printer->servername,
4734 &r->out.info->info3, snum);
4737 result = construct_printer_info4(p->mem_ctx, info2,
4738 Printer->servername,
4739 &r->out.info->info4, snum);
4742 result = construct_printer_info5(p->mem_ctx, info2,
4743 Printer->servername,
4744 &r->out.info->info5, snum);
4747 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4748 Printer->servername,
4749 &r->out.info->info6, snum);
4752 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4753 Printer->servername,
4754 &r->out.info->info7, snum);
4757 result = construct_printer_info8(p->mem_ctx, info2,
4758 Printer->servername,
4759 &r->out.info->info8, snum);
4762 result = WERR_UNKNOWN_LEVEL;
4767 if (!W_ERROR_IS_OK(result)) {
4768 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4769 r->in.level, win_errstr(result)));
4770 TALLOC_FREE(r->out.info);
4774 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4775 r->out.info, r->in.level);
4776 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4778 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4781 /********************************************************************
4782 ********************************************************************/
4784 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4786 if (in && strlen(in)) { \
4787 out = talloc_strdup(mem_ctx, in); \
4789 out = talloc_strdup(mem_ctx, ""); \
4791 W_ERROR_HAVE_NO_MEMORY(out); \
4794 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4796 if (in && strlen(in)) { \
4797 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4799 out = talloc_strdup(mem_ctx, ""); \
4801 W_ERROR_HAVE_NO_MEMORY(out); \
4804 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4805 const char **string_array,
4806 const char ***presult,
4807 const char *cservername,
4811 int i, num_strings = 0;
4812 const char **array = NULL;
4814 if (string_array == NULL) {
4815 return WERR_INVALID_PARAMETER;
4818 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4819 const char *str = NULL;
4821 if (cservername == NULL || arch == NULL) {
4822 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4824 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4827 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4834 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4835 &array, &num_strings);
4845 /********************************************************************
4846 * fill a spoolss_DriverInfo1 struct
4847 ********************************************************************/
4849 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4850 struct spoolss_DriverInfo1 *r,
4851 const struct spoolss_DriverInfo8 *driver,
4852 const char *servername)
4854 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4855 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4860 /********************************************************************
4861 * fill a spoolss_DriverInfo2 struct
4862 ********************************************************************/
4864 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4865 struct spoolss_DriverInfo2 *r,
4866 const struct spoolss_DriverInfo8 *driver,
4867 const char *servername)
4870 const char *cservername = canon_servername(servername);
4872 r->version = driver->version;
4874 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4875 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4876 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4877 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4879 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4880 driver->architecture,
4882 driver->driver_path,
4885 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4886 driver->architecture,
4891 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4892 driver->architecture,
4894 driver->config_file,
4900 /********************************************************************
4901 * fill a spoolss_DriverInfo3 struct
4902 ********************************************************************/
4904 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4905 struct spoolss_DriverInfo3 *r,
4906 const struct spoolss_DriverInfo8 *driver,
4907 const char *servername)
4909 const char *cservername = canon_servername(servername);
4911 r->version = driver->version;
4913 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4914 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4915 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4916 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4918 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4919 driver->architecture,
4921 driver->driver_path,
4924 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4925 driver->architecture,
4930 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4931 driver->architecture,
4933 driver->config_file,
4936 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4937 driver->architecture,
4942 FILL_DRIVER_STRING(mem_ctx,
4943 driver->monitor_name,
4946 FILL_DRIVER_STRING(mem_ctx,
4947 driver->default_datatype,
4948 r->default_datatype);
4950 return string_array_from_driver_info(mem_ctx,
4951 driver->dependent_files,
4952 &r->dependent_files,
4954 driver->architecture,
4958 /********************************************************************
4959 * fill a spoolss_DriverInfo4 struct
4960 ********************************************************************/
4962 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4963 struct spoolss_DriverInfo4 *r,
4964 const struct spoolss_DriverInfo8 *driver,
4965 const char *servername)
4967 const char *cservername = canon_servername(servername);
4970 r->version = driver->version;
4972 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4973 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4974 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4975 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4977 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4978 driver->architecture,
4980 driver->driver_path,
4983 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4984 driver->architecture,
4989 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4990 driver->architecture,
4992 driver->config_file,
4995 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4996 driver->architecture,
5001 result = string_array_from_driver_info(mem_ctx,
5002 driver->dependent_files,
5003 &r->dependent_files,
5005 driver->architecture,
5007 if (!W_ERROR_IS_OK(result)) {
5011 FILL_DRIVER_STRING(mem_ctx,
5012 driver->monitor_name,
5015 FILL_DRIVER_STRING(mem_ctx,
5016 driver->default_datatype,
5017 r->default_datatype);
5020 result = string_array_from_driver_info(mem_ctx,
5021 driver->previous_names,
5028 /********************************************************************
5029 * fill a spoolss_DriverInfo5 struct
5030 ********************************************************************/
5032 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5033 struct spoolss_DriverInfo5 *r,
5034 const struct spoolss_DriverInfo8 *driver,
5035 const char *servername)
5037 const char *cservername = canon_servername(servername);
5039 r->version = driver->version;
5041 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5042 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5043 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5044 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5046 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5047 driver->architecture,
5049 driver->driver_path,
5052 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5053 driver->architecture,
5058 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5059 driver->architecture,
5061 driver->config_file,
5064 r->driver_attributes = 0;
5065 r->config_version = 0;
5066 r->driver_version = 0;
5070 /********************************************************************
5071 * fill a spoolss_DriverInfo6 struct
5072 ********************************************************************/
5074 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5075 struct spoolss_DriverInfo6 *r,
5076 const struct spoolss_DriverInfo8 *driver,
5077 const char *servername)
5079 const char *cservername = canon_servername(servername);
5082 r->version = driver->version;
5084 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5085 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5086 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5087 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5089 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5090 driver->architecture,
5092 driver->driver_path,
5095 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5096 driver->architecture,
5101 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5102 driver->architecture,
5104 driver->config_file,
5107 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108 driver->architecture,
5113 FILL_DRIVER_STRING(mem_ctx,
5114 driver->monitor_name,
5117 FILL_DRIVER_STRING(mem_ctx,
5118 driver->default_datatype,
5119 r->default_datatype);
5121 result = string_array_from_driver_info(mem_ctx,
5122 driver->dependent_files,
5123 &r->dependent_files,
5125 driver->architecture,
5127 if (!W_ERROR_IS_OK(result)) {
5131 result = string_array_from_driver_info(mem_ctx,
5132 driver->previous_names,
5135 if (!W_ERROR_IS_OK(result)) {
5139 r->driver_date = driver->driver_date;
5140 r->driver_version = driver->driver_version;
5142 FILL_DRIVER_STRING(mem_ctx,
5143 driver->manufacturer_name,
5144 r->manufacturer_name);
5145 FILL_DRIVER_STRING(mem_ctx,
5146 driver->manufacturer_url,
5147 r->manufacturer_url);
5148 FILL_DRIVER_STRING(mem_ctx,
5149 driver->hardware_id,
5151 FILL_DRIVER_STRING(mem_ctx,
5158 /********************************************************************
5159 * fill a spoolss_DriverInfo8 struct
5160 ********************************************************************/
5162 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5163 struct spoolss_DriverInfo8 *r,
5164 const struct spoolss_DriverInfo8 *driver,
5165 const char *servername)
5167 const char *cservername = canon_servername(servername);
5170 r->version = driver->version;
5172 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5173 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5174 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5175 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5177 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5178 driver->architecture,
5180 driver->driver_path,
5183 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5184 driver->architecture,
5189 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5190 driver->architecture,
5192 driver->config_file,
5195 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5196 driver->architecture,
5201 FILL_DRIVER_STRING(mem_ctx,
5202 driver->monitor_name,
5205 FILL_DRIVER_STRING(mem_ctx,
5206 driver->default_datatype,
5207 r->default_datatype);
5209 result = string_array_from_driver_info(mem_ctx,
5210 driver->dependent_files,
5211 &r->dependent_files,
5213 driver->architecture,
5215 if (!W_ERROR_IS_OK(result)) {
5219 result = string_array_from_driver_info(mem_ctx,
5220 driver->previous_names,
5223 if (!W_ERROR_IS_OK(result)) {
5227 r->driver_date = driver->driver_date;
5228 r->driver_version = driver->driver_version;
5230 FILL_DRIVER_STRING(mem_ctx,
5231 driver->manufacturer_name,
5232 r->manufacturer_name);
5233 FILL_DRIVER_STRING(mem_ctx,
5234 driver->manufacturer_url,
5235 r->manufacturer_url);
5236 FILL_DRIVER_STRING(mem_ctx,
5237 driver->hardware_id,
5239 FILL_DRIVER_STRING(mem_ctx,
5243 FILL_DRIVER_STRING(mem_ctx,
5244 driver->print_processor,
5245 r->print_processor);
5246 FILL_DRIVER_STRING(mem_ctx,
5247 driver->vendor_setup,
5250 result = string_array_from_driver_info(mem_ctx,
5251 driver->color_profiles,
5254 if (!W_ERROR_IS_OK(result)) {
5258 FILL_DRIVER_STRING(mem_ctx,
5262 r->printer_driver_attributes = driver->printer_driver_attributes;
5264 result = string_array_from_driver_info(mem_ctx,
5265 driver->core_driver_dependencies,
5266 &r->core_driver_dependencies,
5268 if (!W_ERROR_IS_OK(result)) {
5272 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5273 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5278 #if 0 /* disabled until marshalling issues are resolved - gd */
5279 /********************************************************************
5280 ********************************************************************/
5282 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5283 struct spoolss_DriverFileInfo *r,
5284 const char *cservername,
5285 const char *file_name,
5286 enum spoolss_DriverFileType file_type,
5287 uint32_t file_version)
5289 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5290 cservername, file_name);
5291 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5292 r->file_type = file_type;
5293 r->file_version = file_version;
5298 /********************************************************************
5299 ********************************************************************/
5301 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5302 const struct spoolss_DriverInfo8 *driver,
5303 const char *cservername,
5304 struct spoolss_DriverFileInfo **info_p,
5307 struct spoolss_DriverFileInfo *info = NULL;
5315 if (strlen(driver->driver_path)) {
5316 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5317 struct spoolss_DriverFileInfo,
5319 W_ERROR_HAVE_NO_MEMORY(info);
5320 result = fill_spoolss_DriverFileInfo(info,
5323 driver->driver_path,
5324 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5326 W_ERROR_NOT_OK_RETURN(result);
5330 if (strlen(driver->config_file)) {
5331 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5332 struct spoolss_DriverFileInfo,
5334 W_ERROR_HAVE_NO_MEMORY(info);
5335 result = fill_spoolss_DriverFileInfo(info,
5338 driver->config_file,
5339 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5341 W_ERROR_NOT_OK_RETURN(result);
5345 if (strlen(driver->data_file)) {
5346 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5347 struct spoolss_DriverFileInfo,
5349 W_ERROR_HAVE_NO_MEMORY(info);
5350 result = fill_spoolss_DriverFileInfo(info,
5354 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5356 W_ERROR_NOT_OK_RETURN(result);
5360 if (strlen(driver->help_file)) {
5361 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5362 struct spoolss_DriverFileInfo,
5364 W_ERROR_HAVE_NO_MEMORY(info);
5365 result = fill_spoolss_DriverFileInfo(info,
5369 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5371 W_ERROR_NOT_OK_RETURN(result);
5375 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5376 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5377 struct spoolss_DriverFileInfo,
5379 W_ERROR_HAVE_NO_MEMORY(info);
5380 result = fill_spoolss_DriverFileInfo(info,
5383 driver->dependent_files[i],
5384 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5386 W_ERROR_NOT_OK_RETURN(result);
5396 /********************************************************************
5397 * fill a spoolss_DriverInfo101 struct
5398 ********************************************************************/
5400 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5401 struct spoolss_DriverInfo101 *r,
5402 const struct spoolss_DriverInfo8 *driver,
5403 const char *servername)
5405 const char *cservername = canon_servername(servername);
5408 r->version = driver->version;
5410 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5411 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5412 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5413 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5415 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5419 if (!W_ERROR_IS_OK(result)) {
5423 FILL_DRIVER_STRING(mem_ctx,
5424 driver->monitor_name,
5427 FILL_DRIVER_STRING(mem_ctx,
5428 driver->default_datatype,
5429 r->default_datatype);
5431 result = string_array_from_driver_info(mem_ctx,
5432 driver->previous_names,
5435 if (!W_ERROR_IS_OK(result)) {
5439 r->driver_date = driver->driver_date;
5440 r->driver_version = driver->driver_version;
5442 FILL_DRIVER_STRING(mem_ctx,
5443 driver->manufacturer_name,
5444 r->manufacturer_name);
5445 FILL_DRIVER_STRING(mem_ctx,
5446 driver->manufacturer_url,
5447 r->manufacturer_url);
5448 FILL_DRIVER_STRING(mem_ctx,
5449 driver->hardware_id,
5451 FILL_DRIVER_STRING(mem_ctx,
5458 /********************************************************************
5459 ********************************************************************/
5461 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5462 const struct auth_serversupplied_info *session_info,
5463 struct messaging_context *msg_ctx,
5465 union spoolss_DriverInfo *r,
5467 const char *servername,
5468 const char *architecture,
5471 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5472 struct spoolss_DriverInfo8 *driver;
5476 return WERR_UNKNOWN_LEVEL;
5479 result = winreg_get_printer(mem_ctx,
5482 lp_const_servicename(snum),
5485 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5486 win_errstr(result)));
5488 if (!W_ERROR_IS_OK(result)) {
5489 return WERR_INVALID_PRINTER_NAME;
5492 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5494 pinfo2->drivername, version, &driver);
5496 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5497 win_errstr(result)));
5499 if (!W_ERROR_IS_OK(result)) {
5501 * Is this a W2k client ?
5505 talloc_free(pinfo2);
5506 return WERR_UNKNOWN_PRINTER_DRIVER;
5509 /* Yes - try again with a WinNT driver. */
5511 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5515 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5516 win_errstr(result)));
5517 if (!W_ERROR_IS_OK(result)) {
5518 talloc_free(pinfo2);
5519 return WERR_UNKNOWN_PRINTER_DRIVER;
5525 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5528 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5531 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5534 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5537 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5540 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5543 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5545 #if 0 /* disabled until marshalling issues are resolved - gd */
5547 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5551 result = WERR_UNKNOWN_LEVEL;
5555 talloc_free(pinfo2);
5556 talloc_free(driver);
5561 /****************************************************************
5562 _spoolss_GetPrinterDriver2
5563 ****************************************************************/
5565 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5566 struct spoolss_GetPrinterDriver2 *r)
5568 struct printer_handle *printer;
5573 /* that's an [in out] buffer */
5575 if (!r->in.buffer && (r->in.offered != 0)) {
5576 return WERR_INVALID_PARAM;
5579 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5581 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5582 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5583 return WERR_INVALID_PRINTER_NAME;
5587 *r->out.server_major_version = 0;
5588 *r->out.server_minor_version = 0;
5590 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5594 result = construct_printer_driver_info_level(p->mem_ctx,
5595 get_session_info_system(),
5597 r->in.level, r->out.info,
5598 snum, printer->servername,
5600 r->in.client_major_version);
5601 if (!W_ERROR_IS_OK(result)) {
5602 TALLOC_FREE(r->out.info);
5606 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5607 r->out.info, r->in.level);
5608 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5610 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5614 /****************************************************************
5615 _spoolss_StartPagePrinter
5616 ****************************************************************/
5618 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5619 struct spoolss_StartPagePrinter *r)
5621 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5624 DEBUG(3,("_spoolss_StartPagePrinter: "
5625 "Error in startpageprinter printer handle\n"));
5629 Printer->page_started = true;
5633 /****************************************************************
5634 _spoolss_EndPagePrinter
5635 ****************************************************************/
5637 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5638 struct spoolss_EndPagePrinter *r)
5642 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5645 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5646 OUR_HANDLE(r->in.handle)));
5650 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5653 Printer->page_started = false;
5654 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5659 /****************************************************************
5660 _spoolss_StartDocPrinter
5661 ****************************************************************/
5663 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5664 struct spoolss_StartDocPrinter *r)
5666 struct spoolss_DocumentInfo1 *info_1;
5668 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5672 DEBUG(2,("_spoolss_StartDocPrinter: "
5673 "Invalid handle (%s:%u:%u)\n",
5674 OUR_HANDLE(r->in.handle)));
5678 if (Printer->jobid) {
5679 DEBUG(2, ("_spoolss_StartDocPrinter: "
5680 "StartDocPrinter called twice! "
5681 "(existing jobid = %d)\n", Printer->jobid));
5682 return WERR_INVALID_HANDLE;
5685 if (r->in.level != 1) {
5686 return WERR_UNKNOWN_LEVEL;
5689 info_1 = r->in.info.info1;
5692 * a nice thing with NT is it doesn't listen to what you tell it.
5693 * when asked to send _only_ RAW datas, it tries to send datas
5696 * So I add checks like in NT Server ...
5699 if (info_1->datatype) {
5700 if (strcmp(info_1->datatype, "RAW") != 0) {
5702 return WERR_INVALID_DATATYPE;
5706 /* get the share number of the printer */
5707 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5711 werr = print_job_start(p->session_info,
5715 info_1->document_name,
5716 info_1->output_file,
5720 /* An error occured in print_job_start() so return an appropriate
5723 if (!W_ERROR_IS_OK(werr)) {
5727 Printer->document_started = true;
5728 *r->out.job_id = Printer->jobid;
5733 /****************************************************************
5734 _spoolss_EndDocPrinter
5735 ****************************************************************/
5737 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5738 struct spoolss_EndDocPrinter *r)
5740 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5745 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5746 OUR_HANDLE(r->in.handle)));
5750 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5754 Printer->document_started = false;
5755 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5756 if (!NT_STATUS_IS_OK(status)) {
5757 DEBUG(2, ("_spoolss_EndDocPrinter: "
5758 "print_job_end failed [%s]\n",
5759 nt_errstr(status)));
5763 return ntstatus_to_werror(status);
5766 /****************************************************************
5767 _spoolss_WritePrinter
5768 ****************************************************************/
5770 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5771 struct spoolss_WritePrinter *r)
5773 ssize_t buffer_written;
5775 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5778 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5779 OUR_HANDLE(r->in.handle)));
5780 *r->out.num_written = r->in._data_size;
5784 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5787 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5788 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5789 snum, Printer->jobid,
5790 (const char *)r->in.data.data,
5791 (size_t)r->in._data_size);
5792 if (buffer_written == (ssize_t)-1) {
5793 *r->out.num_written = 0;
5794 if (errno == ENOSPC)
5795 return WERR_NO_SPOOL_SPACE;
5797 return WERR_ACCESS_DENIED;
5800 *r->out.num_written = r->in._data_size;
5805 /********************************************************************
5806 * api_spoolss_getprinter
5807 * called from the spoolss dispatcher
5809 ********************************************************************/
5811 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5812 struct pipes_struct *p)
5814 const struct auth_serversupplied_info *session_info = p->session_info;
5816 WERROR errcode = WERR_BADFUNC;
5817 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5820 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5821 OUR_HANDLE(handle)));
5825 if (!get_printer_snum(p, handle, &snum, NULL))
5829 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5830 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5832 case SPOOLSS_PRINTER_CONTROL_RESUME:
5833 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5834 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5836 case SPOOLSS_PRINTER_CONTROL_PURGE:
5837 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5840 return WERR_UNKNOWN_LEVEL;
5847 /****************************************************************
5848 _spoolss_AbortPrinter
5849 * From MSDN: "Deletes printer's spool file if printer is configured
5851 ****************************************************************/
5853 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5854 struct spoolss_AbortPrinter *r)
5856 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5858 WERROR errcode = WERR_OK;
5861 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5862 OUR_HANDLE(r->in.handle)));
5866 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5869 if (!Printer->document_started) {
5870 return WERR_SPL_NO_STARTDOC;
5873 errcode = print_job_delete(p->session_info,
5881 /********************************************************************
5882 * called by spoolss_api_setprinter
5883 * when updating a printer description
5884 ********************************************************************/
5886 static WERROR update_printer_sec(struct policy_handle *handle,
5887 struct pipes_struct *p,
5888 struct sec_desc_buf *secdesc_ctr)
5890 struct spoolss_security_descriptor *new_secdesc = NULL;
5891 struct spoolss_security_descriptor *old_secdesc = NULL;
5892 const char *printer;
5896 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5898 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5899 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5900 OUR_HANDLE(handle)));
5902 result = WERR_BADFID;
5906 if (secdesc_ctr == NULL) {
5907 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5908 result = WERR_INVALID_PARAM;
5911 printer = lp_const_servicename(snum);
5913 /* Check the user has permissions to change the security
5914 descriptor. By experimentation with two NT machines, the user
5915 requires Full Access to the printer to change security
5918 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5919 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5920 result = WERR_ACCESS_DENIED;
5924 /* NT seems to like setting the security descriptor even though
5925 nothing may have actually changed. */
5926 result = winreg_get_printer_secdesc(p->mem_ctx,
5927 get_session_info_system(),
5931 if (!W_ERROR_IS_OK(result)) {
5932 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5933 result = WERR_BADFID;
5937 if (DEBUGLEVEL >= 10) {
5938 struct security_acl *the_acl;
5941 the_acl = old_secdesc->dacl;
5942 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5943 printer, the_acl->num_aces));
5945 for (i = 0; i < the_acl->num_aces; i++) {
5946 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5947 &the_acl->aces[i].trustee),
5948 the_acl->aces[i].access_mask));
5951 the_acl = secdesc_ctr->sd->dacl;
5954 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5955 printer, the_acl->num_aces));
5957 for (i = 0; i < the_acl->num_aces; i++) {
5958 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5959 &the_acl->aces[i].trustee),
5960 the_acl->aces[i].access_mask));
5963 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5967 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5968 if (new_secdesc == NULL) {
5969 result = WERR_NOMEM;
5973 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5978 result = winreg_set_printer_secdesc(p->mem_ctx,
5979 get_session_info_system(),
5988 /********************************************************************
5989 Canonicalize printer info from a client
5990 ********************************************************************/
5992 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5993 struct spoolss_SetPrinterInfo2 *info2,
5996 fstring printername;
5999 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6000 "portname=%s drivername=%s comment=%s location=%s\n",
6001 info2->servername, info2->printername, info2->sharename,
6002 info2->portname, info2->drivername, info2->comment,
6005 /* we force some elements to "correct" values */
6006 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6007 if (info2->servername == NULL) {
6010 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6011 if (info2->sharename == NULL) {
6015 /* check to see if we allow printername != sharename */
6016 if (lp_force_printername(snum)) {
6017 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6018 global_myname(), info2->sharename);
6020 /* make sure printername is in \\server\printername format */
6021 fstrcpy(printername, info2->printername);
6023 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6024 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6028 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6029 global_myname(), p);
6031 if (info2->printername == NULL) {
6035 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6036 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6041 /****************************************************************************
6042 ****************************************************************************/
6044 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6046 char *cmd = lp_addport_cmd();
6047 char *command = NULL;
6049 bool is_print_op = false;
6052 return WERR_ACCESS_DENIED;
6055 command = talloc_asprintf(ctx,
6056 "%s \"%s\" \"%s\"", cmd, portname, uri );
6062 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6064 DEBUG(10,("Running [%s]\n", command));
6066 /********* BEGIN SePrintOperatorPrivilege **********/
6071 ret = smbrun(command, NULL);
6076 /********* END SePrintOperatorPrivilege **********/
6078 DEBUGADD(10,("returned [%d]\n", ret));
6080 TALLOC_FREE(command);
6083 return WERR_ACCESS_DENIED;
6089 /****************************************************************************
6090 ****************************************************************************/
6092 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6093 struct spoolss_SetPrinterInfo2 *info2,
6094 const char *remote_machine,
6095 struct messaging_context *msg_ctx)
6097 char *cmd = lp_addprinter_cmd();
6099 char *command = NULL;
6103 bool is_print_op = false;
6105 if (!remote_machine) {
6109 command = talloc_asprintf(ctx,
6110 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6111 cmd, info2->printername, info2->sharename,
6112 info2->portname, info2->drivername,
6113 info2->location, info2->comment, remote_machine);
6119 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6121 DEBUG(10,("Running [%s]\n", command));
6123 /********* BEGIN SePrintOperatorPrivilege **********/
6128 if ( (ret = smbrun(command, &fd)) == 0 ) {
6129 /* Tell everyone we updated smb.conf. */
6130 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6136 /********* END SePrintOperatorPrivilege **********/
6138 DEBUGADD(10,("returned [%d]\n", ret));
6140 TALLOC_FREE(command);
6148 /* reload our services immediately */
6150 reload_services(msg_ctx, -1, false);
6154 /* Get lines and convert them back to dos-codepage */
6155 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6156 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6159 /* Set the portname to what the script says the portname should be. */
6160 /* but don't require anything to be return from the script exit a good error code */
6163 /* Set the portname to what the script says the portname should be. */
6164 info2->portname = talloc_strdup(ctx, qlines[0]);
6165 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6168 TALLOC_FREE(qlines);
6172 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6173 const struct auth_serversupplied_info *session_info,
6174 struct messaging_context *msg_ctx,
6176 struct spoolss_SetPrinterInfo2 *printer,
6177 struct spoolss_PrinterInfo2 *old_printer)
6179 bool force_update = (old_printer == NULL);
6180 const char *dnsdomname;
6181 const char *longname;
6182 const char *uncname;
6183 const char *spooling;
6185 WERROR result = WERR_OK;
6187 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6188 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6189 winreg_set_printer_dataex(mem_ctx,
6193 SPOOL_DSSPOOLER_KEY,
6194 SPOOL_REG_DRIVERNAME,
6199 if (!force_update) {
6200 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6201 printer->drivername));
6203 notify_printer_driver(server_event_context(), msg_ctx,
6204 snum, printer->drivername ?
6205 printer->drivername : "");
6209 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6210 push_reg_sz(mem_ctx, &buffer, printer->comment);
6211 winreg_set_printer_dataex(mem_ctx,
6215 SPOOL_DSSPOOLER_KEY,
6216 SPOOL_REG_DESCRIPTION,
6221 if (!force_update) {
6222 notify_printer_comment(server_event_context(), msg_ctx,
6223 snum, printer->comment ?
6224 printer->comment : "");
6228 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6229 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6230 winreg_set_printer_dataex(mem_ctx,
6234 SPOOL_DSSPOOLER_KEY,
6235 SPOOL_REG_PRINTSHARENAME,
6240 if (!force_update) {
6241 notify_printer_sharename(server_event_context(),
6243 snum, printer->sharename ?
6244 printer->sharename : "");
6248 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6251 p = strrchr(printer->printername, '\\' );
6255 p = printer->printername;
6258 push_reg_sz(mem_ctx, &buffer, p);
6259 winreg_set_printer_dataex(mem_ctx,
6263 SPOOL_DSSPOOLER_KEY,
6264 SPOOL_REG_PRINTERNAME,
6269 if (!force_update) {
6270 notify_printer_printername(server_event_context(),
6271 msg_ctx, snum, p ? p : "");
6275 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6276 push_reg_sz(mem_ctx, &buffer, printer->portname);
6277 winreg_set_printer_dataex(mem_ctx,
6281 SPOOL_DSSPOOLER_KEY,
6287 if (!force_update) {
6288 notify_printer_port(server_event_context(),
6289 msg_ctx, snum, printer->portname ?
6290 printer->portname : "");
6294 if (force_update || !strequal(printer->location, old_printer->location)) {
6295 push_reg_sz(mem_ctx, &buffer, printer->location);
6296 winreg_set_printer_dataex(mem_ctx,
6300 SPOOL_DSSPOOLER_KEY,
6306 if (!force_update) {
6307 notify_printer_location(server_event_context(),
6310 printer->location : "");
6314 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6315 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6316 winreg_set_printer_dataex(mem_ctx,
6320 SPOOL_DSSPOOLER_KEY,
6321 SPOOL_REG_PRINTSEPARATORFILE,
6326 if (!force_update) {
6327 notify_printer_sepfile(server_event_context(),
6330 printer->sepfile : "");
6334 if (force_update || printer->starttime != old_printer->starttime) {
6335 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6336 SIVAL(buffer.data, 0, printer->starttime);
6337 winreg_set_printer_dataex(mem_ctx,
6341 SPOOL_DSSPOOLER_KEY,
6342 SPOOL_REG_PRINTSTARTTIME,
6348 if (force_update || printer->untiltime != old_printer->untiltime) {
6349 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6350 SIVAL(buffer.data, 0, printer->untiltime);
6351 winreg_set_printer_dataex(mem_ctx,
6355 SPOOL_DSSPOOLER_KEY,
6356 SPOOL_REG_PRINTENDTIME,
6362 if (force_update || printer->priority != old_printer->priority) {
6363 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6364 SIVAL(buffer.data, 0, printer->priority);
6365 winreg_set_printer_dataex(mem_ctx,
6369 SPOOL_DSSPOOLER_KEY,
6376 if (force_update || printer->attributes != old_printer->attributes) {
6377 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6378 SIVAL(buffer.data, 0, (printer->attributes &
6379 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6380 winreg_set_printer_dataex(mem_ctx,
6384 SPOOL_DSSPOOLER_KEY,
6385 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6390 switch (printer->attributes & 0x3) {
6392 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6395 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6398 spooling = SPOOL_REGVAL_PRINTDIRECT;
6401 spooling = "unknown";
6403 push_reg_sz(mem_ctx, &buffer, spooling);
6404 winreg_set_printer_dataex(mem_ctx,
6408 SPOOL_DSSPOOLER_KEY,
6409 SPOOL_REG_PRINTSPOOLING,
6415 push_reg_sz(mem_ctx, &buffer, global_myname());
6416 winreg_set_printer_dataex(mem_ctx,
6420 SPOOL_DSSPOOLER_KEY,
6421 SPOOL_REG_SHORTSERVERNAME,
6426 dnsdomname = get_mydnsfullname();
6427 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6428 longname = talloc_strdup(mem_ctx, dnsdomname);
6430 longname = talloc_strdup(mem_ctx, global_myname());
6432 if (longname == NULL) {
6433 result = WERR_NOMEM;
6437 push_reg_sz(mem_ctx, &buffer, longname);
6438 winreg_set_printer_dataex(mem_ctx,
6442 SPOOL_DSSPOOLER_KEY,
6443 SPOOL_REG_SERVERNAME,
6448 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6449 global_myname(), printer->sharename);
6450 push_reg_sz(mem_ctx, &buffer, uncname);
6451 winreg_set_printer_dataex(mem_ctx,
6455 SPOOL_DSSPOOLER_KEY,
6465 /********************************************************************
6466 * Called by spoolss_api_setprinter
6467 * when updating a printer description.
6468 ********************************************************************/
6470 static WERROR update_printer(struct pipes_struct *p,
6471 struct policy_handle *handle,
6472 struct spoolss_SetPrinterInfoCtr *info_ctr,
6473 struct spoolss_DeviceMode *devmode)
6475 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6476 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6477 struct spoolss_PrinterInfo2 *old_printer;
6478 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6480 WERROR result = WERR_OK;
6481 TALLOC_CTX *tmp_ctx;
6483 DEBUG(8,("update_printer\n"));
6485 tmp_ctx = talloc_new(p->mem_ctx);
6486 if (tmp_ctx == NULL) {
6491 result = WERR_BADFID;
6495 if (!get_printer_snum(p, handle, &snum, NULL)) {
6496 result = WERR_BADFID;
6500 result = winreg_get_printer(tmp_ctx,
6501 get_session_info_system(),
6503 lp_const_servicename(snum),
6505 if (!W_ERROR_IS_OK(result)) {
6506 result = WERR_BADFID;
6510 /* Do sanity check on the requested changes for Samba */
6511 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6512 result = WERR_INVALID_PARAM;
6516 /* FIXME!!! If the driver has changed we really should verify that
6517 it is installed before doing much else --jerry */
6519 /* Check calling user has permission to update printer description */
6520 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6521 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6522 result = WERR_ACCESS_DENIED;
6526 /* Call addprinter hook */
6527 /* Check changes to see if this is really needed */
6529 if (*lp_addprinter_cmd() &&
6530 (!strequal(printer->drivername, old_printer->drivername) ||
6531 !strequal(printer->comment, old_printer->comment) ||
6532 !strequal(printer->portname, old_printer->portname) ||
6533 !strequal(printer->location, old_printer->location)) )
6535 /* add_printer_hook() will call reload_services() */
6536 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6537 printer, p->client_id->addr,
6539 result = WERR_ACCESS_DENIED;
6544 update_dsspooler(tmp_ctx,
6545 get_session_info_system(),
6551 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6553 if (devmode == NULL) {
6554 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6556 result = winreg_update_printer(tmp_ctx,
6557 get_session_info_system(),
6566 talloc_free(tmp_ctx);
6571 /****************************************************************************
6572 ****************************************************************************/
6573 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6574 struct policy_handle *handle,
6575 struct spoolss_SetPrinterInfo7 *info7)
6578 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6581 struct printer_handle *Printer;
6583 if ( lp_security() != SEC_ADS ) {
6584 return WERR_UNKNOWN_LEVEL;
6587 Printer = find_printer_index_by_hnd(p, handle);
6589 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6594 if (!get_printer_snum(p, handle, &snum, NULL))
6597 result = winreg_get_printer(p->mem_ctx,
6598 get_session_info_system(),
6600 lp_servicename(snum),
6602 if (!W_ERROR_IS_OK(result)) {
6606 nt_printer_publish(pinfo2,
6607 get_session_info_system(),
6612 TALLOC_FREE(pinfo2);
6615 return WERR_UNKNOWN_LEVEL;
6619 /********************************************************************
6620 ********************************************************************/
6622 static WERROR update_printer_devmode(struct pipes_struct *p,
6623 struct policy_handle *handle,
6624 struct spoolss_DeviceMode *devmode)
6627 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6628 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6630 DEBUG(8,("update_printer_devmode\n"));
6636 if (!get_printer_snum(p, handle, &snum, NULL)) {
6640 /* Check calling user has permission to update printer description */
6641 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6642 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6643 return WERR_ACCESS_DENIED;
6646 return winreg_update_printer(p->mem_ctx,
6647 get_session_info_system(),
6649 lp_const_servicename(snum),
6657 /****************************************************************
6659 ****************************************************************/
6661 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6662 struct spoolss_SetPrinter *r)
6666 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6669 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6670 OUR_HANDLE(r->in.handle)));
6674 /* check the level */
6675 switch (r->in.info_ctr->level) {
6677 return control_printer(r->in.handle, r->in.command, p);
6679 result = update_printer(p, r->in.handle,
6681 r->in.devmode_ctr->devmode);
6682 if (!W_ERROR_IS_OK(result))
6684 if (r->in.secdesc_ctr->sd)
6685 result = update_printer_sec(r->in.handle, p,
6689 return update_printer_sec(r->in.handle, p,
6692 return publish_or_unpublish_printer(p, r->in.handle,
6693 r->in.info_ctr->info.info7);
6695 return update_printer_devmode(p, r->in.handle,
6696 r->in.devmode_ctr->devmode);
6698 return WERR_UNKNOWN_LEVEL;
6702 /****************************************************************
6703 _spoolss_FindClosePrinterNotify
6704 ****************************************************************/
6706 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6707 struct spoolss_FindClosePrinterNotify *r)
6709 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6712 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6713 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6717 if (Printer->notify.cli_chan != NULL &&
6718 Printer->notify.cli_chan->active_connections > 0) {
6721 if (Printer->printer_type == SPLHND_PRINTER) {
6722 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6727 srv_spoolss_replycloseprinter(snum, Printer);
6730 Printer->notify.flags=0;
6731 Printer->notify.options=0;
6732 Printer->notify.localmachine[0]='\0';
6733 Printer->notify.printerlocal=0;
6734 TALLOC_FREE(Printer->notify.option);
6739 /****************************************************************
6741 ****************************************************************/
6743 WERROR _spoolss_AddJob(struct pipes_struct *p,
6744 struct spoolss_AddJob *r)
6746 if (!r->in.buffer && (r->in.offered != 0)) {
6747 return WERR_INVALID_PARAM;
6750 /* this is what a NT server returns for AddJob. AddJob must fail on
6751 * non-local printers */
6753 if (r->in.level != 1) {
6754 return WERR_UNKNOWN_LEVEL;
6757 return WERR_INVALID_PARAM;
6760 /****************************************************************************
6762 ****************************************************************************/
6764 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6765 struct spoolss_JobInfo1 *r,
6766 const print_queue_struct *queue,
6767 int position, int snum,
6768 struct spoolss_PrinterInfo2 *pinfo2)
6772 t = gmtime(&queue->time);
6774 r->job_id = queue->job;
6776 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6777 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6778 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6779 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6780 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6781 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6782 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6783 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6784 r->data_type = talloc_strdup(mem_ctx, "RAW");
6785 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6786 r->text_status = talloc_strdup(mem_ctx, "");
6787 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6789 r->status = nt_printj_status(queue->status);
6790 r->priority = queue->priority;
6791 r->position = position;
6792 r->total_pages = queue->page_count;
6793 r->pages_printed = 0; /* ??? */
6795 init_systemtime(&r->submitted, t);
6800 /****************************************************************************
6802 ****************************************************************************/
6804 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6805 struct spoolss_JobInfo2 *r,
6806 const print_queue_struct *queue,
6807 int position, int snum,
6808 struct spoolss_PrinterInfo2 *pinfo2,
6809 struct spoolss_DeviceMode *devmode)
6813 t = gmtime(&queue->time);
6815 r->job_id = queue->job;
6817 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6818 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6819 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6820 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6821 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6822 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6823 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6824 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6825 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6826 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6827 r->data_type = talloc_strdup(mem_ctx, "RAW");
6828 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6829 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6830 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6831 r->parameters = talloc_strdup(mem_ctx, "");
6832 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6833 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6834 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6836 r->devmode = devmode;
6838 r->text_status = talloc_strdup(mem_ctx, "");
6839 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6843 r->status = nt_printj_status(queue->status);
6844 r->priority = queue->priority;
6845 r->position = position;
6848 r->total_pages = queue->page_count;
6849 r->size = queue->size;
6850 init_systemtime(&r->submitted, t);
6852 r->pages_printed = 0; /* ??? */
6857 /****************************************************************************
6859 ****************************************************************************/
6861 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6862 struct spoolss_JobInfo3 *r,
6863 const print_queue_struct *queue,
6864 const print_queue_struct *next_queue,
6865 int position, int snum,
6866 struct spoolss_PrinterInfo2 *pinfo2)
6868 r->job_id = queue->job;
6871 r->next_job_id = next_queue->job;
6878 /****************************************************************************
6879 Enumjobs at level 1.
6880 ****************************************************************************/
6882 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6883 const print_queue_struct *queue,
6884 uint32_t num_queues, int snum,
6885 struct spoolss_PrinterInfo2 *pinfo2,
6886 union spoolss_JobInfo **info_p,
6889 union spoolss_JobInfo *info;
6891 WERROR result = WERR_OK;
6893 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6894 W_ERROR_HAVE_NO_MEMORY(info);
6896 *count = num_queues;
6898 for (i=0; i<*count; i++) {
6899 result = fill_job_info1(info,
6905 if (!W_ERROR_IS_OK(result)) {
6911 if (!W_ERROR_IS_OK(result)) {
6922 /****************************************************************************
6923 Enumjobs at level 2.
6924 ****************************************************************************/
6926 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6927 const print_queue_struct *queue,
6928 uint32_t num_queues, int snum,
6929 struct spoolss_PrinterInfo2 *pinfo2,
6930 union spoolss_JobInfo **info_p,
6933 union spoolss_JobInfo *info;
6935 WERROR result = WERR_OK;
6937 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6938 W_ERROR_HAVE_NO_MEMORY(info);
6940 *count = num_queues;
6942 for (i=0; i<*count; i++) {
6943 struct spoolss_DeviceMode *devmode;
6945 result = spoolss_create_default_devmode(info,
6946 pinfo2->printername,
6948 if (!W_ERROR_IS_OK(result)) {
6949 DEBUG(3, ("Can't proceed w/o a devmode!"));
6953 result = fill_job_info2(info,
6960 if (!W_ERROR_IS_OK(result)) {
6966 if (!W_ERROR_IS_OK(result)) {
6977 /****************************************************************************
6978 Enumjobs at level 3.
6979 ****************************************************************************/
6981 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6982 const print_queue_struct *queue,
6983 uint32_t num_queues, int snum,
6984 struct spoolss_PrinterInfo2 *pinfo2,
6985 union spoolss_JobInfo **info_p,
6988 union spoolss_JobInfo *info;
6990 WERROR result = WERR_OK;
6992 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6993 W_ERROR_HAVE_NO_MEMORY(info);
6995 *count = num_queues;
6997 for (i=0; i<*count; i++) {
6998 const print_queue_struct *next_queue = NULL;
7001 next_queue = &queue[i+1];
7004 result = fill_job_info3(info,
7011 if (!W_ERROR_IS_OK(result)) {
7017 if (!W_ERROR_IS_OK(result)) {
7028 /****************************************************************
7030 ****************************************************************/
7032 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7033 struct spoolss_EnumJobs *r)
7036 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7038 print_status_struct prt_status;
7039 print_queue_struct *queue = NULL;
7042 /* that's an [in out] buffer */
7044 if (!r->in.buffer && (r->in.offered != 0)) {
7045 return WERR_INVALID_PARAM;
7048 DEBUG(4,("_spoolss_EnumJobs\n"));
7052 *r->out.info = NULL;
7054 /* lookup the printer snum and tdb entry */
7056 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7060 result = winreg_get_printer(p->mem_ctx,
7061 get_session_info_system(),
7063 lp_const_servicename(snum),
7065 if (!W_ERROR_IS_OK(result)) {
7069 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7070 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7071 count, prt_status.status, prt_status.message));
7075 TALLOC_FREE(pinfo2);
7079 switch (r->in.level) {
7081 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7082 pinfo2, r->out.info, r->out.count);
7085 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7086 pinfo2, r->out.info, r->out.count);
7089 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7090 pinfo2, r->out.info, r->out.count);
7093 result = WERR_UNKNOWN_LEVEL;
7098 TALLOC_FREE(pinfo2);
7100 if (!W_ERROR_IS_OK(result)) {
7104 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7106 *r->out.info, r->in.level,
7108 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7109 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7111 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7114 /****************************************************************
7115 _spoolss_ScheduleJob
7116 ****************************************************************/
7118 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7119 struct spoolss_ScheduleJob *r)
7124 /****************************************************************
7125 ****************************************************************/
7127 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7128 struct messaging_context *msg_ctx,
7129 const char *printer_name,
7131 struct spoolss_SetJobInfo1 *r)
7135 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7139 if (strequal(old_doc_name, r->document_name)) {
7143 if (!print_job_set_name(server_event_context(), msg_ctx,
7144 printer_name, job_id, r->document_name)) {
7151 /****************************************************************
7153 ****************************************************************/
7155 WERROR _spoolss_SetJob(struct pipes_struct *p,
7156 struct spoolss_SetJob *r)
7158 const struct auth_serversupplied_info *session_info = p->session_info;
7160 WERROR errcode = WERR_BADFUNC;
7162 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7166 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7167 return WERR_INVALID_PRINTER_NAME;
7170 switch (r->in.command) {
7171 case SPOOLSS_JOB_CONTROL_CANCEL:
7172 case SPOOLSS_JOB_CONTROL_DELETE:
7173 errcode = print_job_delete(session_info, p->msg_ctx,
7174 snum, r->in.job_id);
7175 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7179 case SPOOLSS_JOB_CONTROL_PAUSE:
7180 if (print_job_pause(session_info, p->msg_ctx,
7181 snum, r->in.job_id, &errcode)) {
7185 case SPOOLSS_JOB_CONTROL_RESTART:
7186 case SPOOLSS_JOB_CONTROL_RESUME:
7187 if (print_job_resume(session_info, p->msg_ctx,
7188 snum, r->in.job_id, &errcode)) {
7196 return WERR_UNKNOWN_LEVEL;
7199 if (!W_ERROR_IS_OK(errcode)) {
7203 if (r->in.ctr == NULL) {
7207 switch (r->in.ctr->level) {
7209 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7210 lp_const_servicename(snum),
7212 r->in.ctr->info.info1);
7218 return WERR_UNKNOWN_LEVEL;
7224 /****************************************************************************
7225 Enumerates all printer drivers by level and architecture.
7226 ****************************************************************************/
7228 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7229 const struct auth_serversupplied_info *session_info,
7230 struct messaging_context *msg_ctx,
7231 const char *servername,
7232 const char *architecture,
7234 union spoolss_DriverInfo **info_p,
7239 struct spoolss_DriverInfo8 *driver;
7240 union spoolss_DriverInfo *info = NULL;
7242 WERROR result = WERR_OK;
7243 uint32_t num_drivers;
7244 const char **drivers;
7249 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7250 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7251 architecture, version,
7252 &num_drivers, &drivers);
7253 if (!W_ERROR_IS_OK(result)) {
7256 DEBUG(4, ("we have:[%d] drivers in environment"
7257 " [%s] and version [%d]\n",
7258 num_drivers, architecture, version));
7260 if (num_drivers != 0) {
7261 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7262 union spoolss_DriverInfo,
7263 count + num_drivers);
7265 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7266 "failed to enlarge driver info buffer!\n"));
7267 result = WERR_NOMEM;
7272 for (i = 0; i < num_drivers; i++) {
7273 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7275 result = winreg_get_driver(mem_ctx, session_info,
7277 architecture, drivers[i],
7279 if (!W_ERROR_IS_OK(result)) {
7285 result = fill_printer_driver_info1(info, &info[count+i].info1,
7286 driver, servername);
7289 result = fill_printer_driver_info2(info, &info[count+i].info2,
7290 driver, servername);
7293 result = fill_printer_driver_info3(info, &info[count+i].info3,
7294 driver, servername);
7297 result = fill_printer_driver_info4(info, &info[count+i].info4,
7298 driver, servername);
7301 result = fill_printer_driver_info5(info, &info[count+i].info5,
7302 driver, servername);
7305 result = fill_printer_driver_info6(info, &info[count+i].info6,
7306 driver, servername);
7309 result = fill_printer_driver_info8(info, &info[count+i].info8,
7310 driver, servername);
7313 result = WERR_UNKNOWN_LEVEL;
7317 TALLOC_FREE(driver);
7319 if (!W_ERROR_IS_OK(result)) {
7324 count += num_drivers;
7325 TALLOC_FREE(drivers);
7329 TALLOC_FREE(drivers);
7331 if (!W_ERROR_IS_OK(result)) {
7342 /****************************************************************************
7343 Enumerates all printer drivers by level.
7344 ****************************************************************************/
7346 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7347 const struct auth_serversupplied_info *session_info,
7348 struct messaging_context *msg_ctx,
7349 const char *servername,
7350 const char *architecture,
7352 union spoolss_DriverInfo **info_p,
7356 WERROR result = WERR_OK;
7358 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7360 for (a=0; archi_table[a].long_archi != NULL; a++) {
7362 union spoolss_DriverInfo *info = NULL;
7365 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7369 archi_table[a].long_archi,
7373 if (!W_ERROR_IS_OK(result)) {
7377 for (i=0; i < count; i++) {
7378 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7379 info[i], info_p, count_p);
7386 return enumprinterdrivers_level_by_architecture(mem_ctx,
7396 /****************************************************************
7397 _spoolss_EnumPrinterDrivers
7398 ****************************************************************/
7400 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7401 struct spoolss_EnumPrinterDrivers *r)
7403 const char *cservername;
7406 /* that's an [in out] buffer */
7408 if (!r->in.buffer && (r->in.offered != 0)) {
7409 return WERR_INVALID_PARAM;
7412 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7416 *r->out.info = NULL;
7418 cservername = canon_servername(r->in.server);
7420 if (!is_myname_or_ipaddr(cservername)) {
7421 return WERR_UNKNOWN_PRINTER_DRIVER;
7424 result = enumprinterdrivers_level(p->mem_ctx,
7425 get_session_info_system(),
7432 if (!W_ERROR_IS_OK(result)) {
7436 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7437 spoolss_EnumPrinterDrivers,
7438 *r->out.info, r->in.level,
7440 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7441 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7443 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7446 /****************************************************************
7448 ****************************************************************/
7450 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7451 struct spoolss_EnumForms *r)
7457 *r->out.info = NULL;
7459 /* that's an [in out] buffer */
7461 if (!r->in.buffer && (r->in.offered != 0) ) {
7462 return WERR_INVALID_PARAM;
7465 DEBUG(4,("_spoolss_EnumForms\n"));
7466 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7467 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7469 switch (r->in.level) {
7471 result = winreg_printer_enumforms1(p->mem_ctx,
7472 get_session_info_system(),
7478 result = WERR_UNKNOWN_LEVEL;
7482 if (!W_ERROR_IS_OK(result)) {
7486 if (*r->out.count == 0) {
7487 return WERR_NO_MORE_ITEMS;
7490 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7492 *r->out.info, r->in.level,
7494 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7495 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7497 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7500 /****************************************************************
7502 ****************************************************************/
7504 WERROR _spoolss_GetForm(struct pipes_struct *p,
7505 struct spoolss_GetForm *r)
7509 /* that's an [in out] buffer */
7511 if (!r->in.buffer && (r->in.offered != 0)) {
7512 return WERR_INVALID_PARAM;
7515 DEBUG(4,("_spoolss_GetForm\n"));
7516 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7517 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7519 switch (r->in.level) {
7521 result = winreg_printer_getform1(p->mem_ctx,
7522 get_session_info_system(),
7525 &r->out.info->info1);
7528 result = WERR_UNKNOWN_LEVEL;
7532 if (!W_ERROR_IS_OK(result)) {
7533 TALLOC_FREE(r->out.info);
7537 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7538 r->out.info, r->in.level);
7539 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7541 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7544 /****************************************************************************
7545 ****************************************************************************/
7547 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7548 struct spoolss_PortInfo1 *r,
7551 r->port_name = talloc_strdup(mem_ctx, name);
7552 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7557 /****************************************************************************
7558 TODO: This probably needs distinguish between TCP/IP and Local ports
7560 ****************************************************************************/
7562 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7563 struct spoolss_PortInfo2 *r,
7566 r->port_name = talloc_strdup(mem_ctx, name);
7567 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7569 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7570 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7572 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7573 W_ERROR_HAVE_NO_MEMORY(r->description);
7575 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7582 /****************************************************************************
7583 wrapper around the enumer ports command
7584 ****************************************************************************/
7586 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7588 char *cmd = lp_enumports_cmd();
7589 char **qlines = NULL;
7590 char *command = NULL;
7598 /* if no hook then just fill in the default port */
7601 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7604 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7605 TALLOC_FREE(qlines);
7612 /* we have a valid enumport command */
7614 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7619 DEBUG(10,("Running [%s]\n", command));
7620 ret = smbrun(command, &fd);
7621 DEBUG(10,("Returned [%d]\n", ret));
7622 TALLOC_FREE(command);
7627 return WERR_ACCESS_DENIED;
7631 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7632 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7642 /****************************************************************************
7644 ****************************************************************************/
7646 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7647 union spoolss_PortInfo **info_p,
7650 union spoolss_PortInfo *info = NULL;
7652 WERROR result = WERR_OK;
7653 char **qlines = NULL;
7656 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7657 if (!W_ERROR_IS_OK(result)) {
7662 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7664 DEBUG(10,("Returning WERR_NOMEM\n"));
7665 result = WERR_NOMEM;
7669 for (i=0; i<numlines; i++) {
7670 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7671 result = fill_port_1(info, &info[i].info1, qlines[i]);
7672 if (!W_ERROR_IS_OK(result)) {
7677 TALLOC_FREE(qlines);
7680 if (!W_ERROR_IS_OK(result)) {
7682 TALLOC_FREE(qlines);
7694 /****************************************************************************
7696 ****************************************************************************/
7698 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7699 union spoolss_PortInfo **info_p,
7702 union spoolss_PortInfo *info = NULL;
7704 WERROR result = WERR_OK;
7705 char **qlines = NULL;
7708 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7709 if (!W_ERROR_IS_OK(result)) {
7714 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7716 DEBUG(10,("Returning WERR_NOMEM\n"));
7717 result = WERR_NOMEM;
7721 for (i=0; i<numlines; i++) {
7722 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7723 result = fill_port_2(info, &info[i].info2, qlines[i]);
7724 if (!W_ERROR_IS_OK(result)) {
7729 TALLOC_FREE(qlines);
7732 if (!W_ERROR_IS_OK(result)) {
7734 TALLOC_FREE(qlines);
7746 /****************************************************************
7748 ****************************************************************/
7750 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7751 struct spoolss_EnumPorts *r)
7755 /* that's an [in out] buffer */
7757 if (!r->in.buffer && (r->in.offered != 0)) {
7758 return WERR_INVALID_PARAM;
7761 DEBUG(4,("_spoolss_EnumPorts\n"));
7765 *r->out.info = NULL;
7767 switch (r->in.level) {
7769 result = enumports_level_1(p->mem_ctx, r->out.info,
7773 result = enumports_level_2(p->mem_ctx, r->out.info,
7777 return WERR_UNKNOWN_LEVEL;
7780 if (!W_ERROR_IS_OK(result)) {
7784 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7786 *r->out.info, r->in.level,
7788 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7789 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7791 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7794 /****************************************************************************
7795 ****************************************************************************/
7797 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7799 struct spoolss_SetPrinterInfoCtr *info_ctr,
7800 struct spoolss_DeviceMode *devmode,
7801 struct security_descriptor *secdesc,
7802 struct spoolss_UserLevelCtr *user_ctr,
7803 struct policy_handle *handle)
7805 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7806 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7808 WERROR err = WERR_OK;
7810 /* samba does not have a concept of local, non-shared printers yet, so
7811 * make sure we always setup sharename - gd */
7812 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7813 (info2->printername != NULL && info2->printername[0] != '\0')) {
7814 DEBUG(5, ("spoolss_addprinterex_level_2: "
7815 "no sharename has been set, setting printername %s as sharename\n",
7816 info2->printername));
7817 info2->sharename = info2->printername;
7820 /* check to see if the printer already exists */
7821 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7822 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7824 return WERR_PRINTER_ALREADY_EXISTS;
7827 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7828 if ((snum = print_queue_snum(info2->printername)) != -1) {
7829 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7830 info2->printername));
7831 return WERR_PRINTER_ALREADY_EXISTS;
7835 /* validate printer info struct */
7836 if (!info2->printername || strlen(info2->printername) == 0) {
7837 return WERR_INVALID_PRINTER_NAME;
7839 if (!info2->portname || strlen(info2->portname) == 0) {
7840 return WERR_UNKNOWN_PORT;
7842 if (!info2->drivername || strlen(info2->drivername) == 0) {
7843 return WERR_UNKNOWN_PRINTER_DRIVER;
7845 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7846 return WERR_UNKNOWN_PRINTPROCESSOR;
7849 /* FIXME!!! smbd should check to see if the driver is installed before
7850 trying to add a printer like this --jerry */
7852 if (*lp_addprinter_cmd() ) {
7853 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7854 info2, p->client_id->addr,
7856 return WERR_ACCESS_DENIED;
7859 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7860 "smb.conf parameter \"addprinter command\" is defined. This"
7861 "parameter must exist for this call to succeed\n",
7862 info2->sharename ));
7865 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7866 return WERR_ACCESS_DENIED;
7869 /* you must be a printer admin to add a new printer */
7870 if (!print_access_check(p->session_info,
7873 PRINTER_ACCESS_ADMINISTER)) {
7874 return WERR_ACCESS_DENIED;
7878 * Do sanity check on the requested changes for Samba.
7881 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7882 return WERR_INVALID_PARAM;
7885 if (devmode == NULL) {
7886 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7889 update_dsspooler(p->mem_ctx,
7890 get_session_info_system(),
7896 err = winreg_update_printer(p->mem_ctx,
7897 get_session_info_system(),
7904 if (!W_ERROR_IS_OK(err)) {
7908 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7909 if (!W_ERROR_IS_OK(err)) {
7910 /* Handle open failed - remove addition. */
7911 ZERO_STRUCTP(handle);
7918 /****************************************************************
7919 _spoolss_AddPrinterEx
7920 ****************************************************************/
7922 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7923 struct spoolss_AddPrinterEx *r)
7925 switch (r->in.info_ctr->level) {
7927 /* we don't handle yet */
7928 /* but I know what to do ... */
7929 return WERR_UNKNOWN_LEVEL;
7931 return spoolss_addprinterex_level_2(p, r->in.server,
7933 r->in.devmode_ctr->devmode,
7934 r->in.secdesc_ctr->sd,
7935 r->in.userlevel_ctr,
7938 return WERR_UNKNOWN_LEVEL;
7942 /****************************************************************
7944 ****************************************************************/
7946 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7947 struct spoolss_AddPrinter *r)
7949 struct spoolss_AddPrinterEx a;
7950 struct spoolss_UserLevelCtr userlevel_ctr;
7952 ZERO_STRUCT(userlevel_ctr);
7954 userlevel_ctr.level = 1;
7956 a.in.server = r->in.server;
7957 a.in.info_ctr = r->in.info_ctr;
7958 a.in.devmode_ctr = r->in.devmode_ctr;
7959 a.in.secdesc_ctr = r->in.secdesc_ctr;
7960 a.in.userlevel_ctr = &userlevel_ctr;
7961 a.out.handle = r->out.handle;
7963 return _spoolss_AddPrinterEx(p, &a);
7966 /****************************************************************
7967 _spoolss_AddPrinterDriverEx
7968 ****************************************************************/
7970 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7971 struct spoolss_AddPrinterDriverEx *r)
7973 WERROR err = WERR_OK;
7974 const char *driver_name = NULL;
7979 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7980 fn = "_spoolss_AddPrinterDriver";
7982 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7983 fn = "_spoolss_AddPrinterDriverEx";
7986 return WERR_INVALID_PARAM;
7990 * we only support the semantics of AddPrinterDriver()
7991 * i.e. only copy files that are newer than existing ones
7994 if (r->in.flags == 0) {
7995 return WERR_INVALID_PARAM;
7998 if (r->in.flags != APD_COPY_NEW_FILES) {
7999 return WERR_ACCESS_DENIED;
8003 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8004 /* Clever hack from Martin Zielinski <mz@seh.de>
8005 * to allow downgrade from level 8 (Vista).
8007 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8008 r->in.info_ctr->level));
8009 return WERR_UNKNOWN_LEVEL;
8012 DEBUG(5,("Cleaning driver's information\n"));
8013 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8014 if (!W_ERROR_IS_OK(err))
8017 DEBUG(5,("Moving driver to final destination\n"));
8018 err = move_driver_to_download_area(p, r->in.info_ctr);
8019 if (!W_ERROR_IS_OK(err)) {
8023 err = winreg_add_driver(p->mem_ctx,
8024 get_session_info_system(),
8029 if (!W_ERROR_IS_OK(err)) {
8034 * I think this is where he DrvUpgradePrinter() hook would be
8035 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8036 * server. Right now, we just need to send ourselves a message
8037 * to update each printer bound to this driver. --jerry
8040 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8041 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8049 /****************************************************************
8050 _spoolss_AddPrinterDriver
8051 ****************************************************************/
8053 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8054 struct spoolss_AddPrinterDriver *r)
8056 struct spoolss_AddPrinterDriverEx a;
8058 switch (r->in.info_ctr->level) {
8065 return WERR_UNKNOWN_LEVEL;
8068 a.in.servername = r->in.servername;
8069 a.in.info_ctr = r->in.info_ctr;
8070 a.in.flags = APD_COPY_NEW_FILES;
8072 return _spoolss_AddPrinterDriverEx(p, &a);
8075 /****************************************************************************
8076 ****************************************************************************/
8078 struct _spoolss_paths {
8084 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8086 static const struct _spoolss_paths spoolss_paths[]= {
8087 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8088 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8091 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8092 const char *servername,
8093 const char *environment,
8097 const char *pservername = NULL;
8098 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8099 const char *short_archi;
8103 /* environment may be empty */
8104 if (environment && strlen(environment)) {
8105 long_archi = environment;
8108 /* servername may be empty */
8109 if (servername && strlen(servername)) {
8110 pservername = canon_servername(servername);
8112 if (!is_myname_or_ipaddr(pservername)) {
8113 return WERR_INVALID_PARAM;
8117 if (!(short_archi = get_short_archi(long_archi))) {
8118 return WERR_INVALID_ENVIRONMENT;
8121 switch (component) {
8122 case SPOOLSS_PRTPROCS_PATH:
8123 case SPOOLSS_DRIVER_PATH:
8125 *path = talloc_asprintf(mem_ctx,
8128 spoolss_paths[component].share,
8131 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8132 SPOOLSS_DEFAULT_SERVER_PATH,
8133 spoolss_paths[component].dir,
8138 return WERR_INVALID_PARAM;
8148 /****************************************************************************
8149 ****************************************************************************/
8151 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8152 const char *servername,
8153 const char *environment,
8154 struct spoolss_DriverDirectoryInfo1 *r)
8159 werr = compose_spoolss_server_path(mem_ctx,
8162 SPOOLSS_DRIVER_PATH,
8164 if (!W_ERROR_IS_OK(werr)) {
8168 DEBUG(4,("printer driver directory: [%s]\n", path));
8170 r->directory_name = path;
8175 /****************************************************************
8176 _spoolss_GetPrinterDriverDirectory
8177 ****************************************************************/
8179 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8180 struct spoolss_GetPrinterDriverDirectory *r)
8184 /* that's an [in out] buffer */
8186 if (!r->in.buffer && (r->in.offered != 0)) {
8187 return WERR_INVALID_PARAM;
8190 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8195 /* r->in.level is ignored */
8197 werror = getprinterdriverdir_level_1(p->mem_ctx,
8200 &r->out.info->info1);
8201 if (!W_ERROR_IS_OK(werror)) {
8202 TALLOC_FREE(r->out.info);
8206 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8207 r->out.info, r->in.level);
8208 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8210 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8213 /****************************************************************
8214 _spoolss_EnumPrinterData
8215 ****************************************************************/
8217 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8218 struct spoolss_EnumPrinterData *r)
8221 struct spoolss_EnumPrinterDataEx r2;
8223 struct spoolss_PrinterEnumValues *info, *val = NULL;
8226 r2.in.handle = r->in.handle;
8227 r2.in.key_name = "PrinterDriverData";
8229 r2.out.count = &count;
8230 r2.out.info = &info;
8231 r2.out.needed = &needed;
8233 result = _spoolss_EnumPrinterDataEx(p, &r2);
8234 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8235 r2.in.offered = needed;
8236 result = _spoolss_EnumPrinterDataEx(p, &r2);
8238 if (!W_ERROR_IS_OK(result)) {
8243 * The NT machine wants to know the biggest size of value and data
8245 * cf: MSDN EnumPrinterData remark section
8248 if (!r->in.value_offered && !r->in.data_offered) {
8249 uint32_t biggest_valuesize = 0;
8250 uint32_t biggest_datasize = 0;
8253 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8255 for (i=0; i<count; i++) {
8257 name_length = strlen(info[i].value_name);
8258 if (strlen(info[i].value_name) > biggest_valuesize) {
8259 biggest_valuesize = name_length;
8262 if (info[i].data_length > biggest_datasize) {
8263 biggest_datasize = info[i].data_length;
8266 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8270 /* the value is an UNICODE string but real_value_size is the length
8271 in bytes including the trailing 0 */
8273 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8274 *r->out.data_needed = biggest_datasize;
8276 DEBUG(6,("final values: [%d], [%d]\n",
8277 *r->out.value_needed, *r->out.data_needed));
8282 if (r->in.enum_index < count) {
8283 val = &info[r->in.enum_index];
8287 /* out_value should default to "" or else NT4 has
8288 problems unmarshalling the response */
8290 if (r->in.value_offered) {
8291 *r->out.value_needed = 1;
8292 r->out.value_name = talloc_strdup(r, "");
8293 if (!r->out.value_name) {
8297 r->out.value_name = NULL;
8298 *r->out.value_needed = 0;
8301 /* the data is counted in bytes */
8303 *r->out.data_needed = r->in.data_offered;
8305 result = WERR_NO_MORE_ITEMS;
8309 * - counted in bytes in the request
8310 * - counted in UNICODE chars in the max reply
8311 * - counted in bytes in the real size
8313 * take a pause *before* coding not *during* coding
8317 if (r->in.value_offered) {
8318 r->out.value_name = talloc_strdup(r, val->value_name);
8319 if (!r->out.value_name) {
8322 *r->out.value_needed = val->value_name_len;
8324 r->out.value_name = NULL;
8325 *r->out.value_needed = 0;
8330 *r->out.type = val->type;
8332 /* data - counted in bytes */
8335 * See the section "Dynamically Typed Query Parameters"
8339 if (r->out.data && val->data && val->data->data &&
8340 val->data_length && r->in.data_offered) {
8341 memcpy(r->out.data, val->data->data,
8342 MIN(val->data_length,r->in.data_offered));
8345 *r->out.data_needed = val->data_length;
8353 /****************************************************************
8354 _spoolss_SetPrinterData
8355 ****************************************************************/
8357 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8358 struct spoolss_SetPrinterData *r)
8360 struct spoolss_SetPrinterDataEx r2;
8362 r2.in.handle = r->in.handle;
8363 r2.in.key_name = "PrinterDriverData";
8364 r2.in.value_name = r->in.value_name;
8365 r2.in.type = r->in.type;
8366 r2.in.data = r->in.data;
8367 r2.in.offered = r->in.offered;
8369 return _spoolss_SetPrinterDataEx(p, &r2);
8372 /****************************************************************
8373 _spoolss_ResetPrinter
8374 ****************************************************************/
8376 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8377 struct spoolss_ResetPrinter *r)
8379 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8382 DEBUG(5,("_spoolss_ResetPrinter\n"));
8385 * All we do is to check to see if the handle and queue is valid.
8386 * This call really doesn't mean anything to us because we only
8387 * support RAW printing. --jerry
8391 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8392 OUR_HANDLE(r->in.handle)));
8396 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8400 /* blindly return success */
8404 /****************************************************************
8405 _spoolss_DeletePrinterData
8406 ****************************************************************/
8408 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8409 struct spoolss_DeletePrinterData *r)
8411 struct spoolss_DeletePrinterDataEx r2;
8413 r2.in.handle = r->in.handle;
8414 r2.in.key_name = "PrinterDriverData";
8415 r2.in.value_name = r->in.value_name;
8417 return _spoolss_DeletePrinterDataEx(p, &r2);
8420 /****************************************************************
8422 ****************************************************************/
8424 WERROR _spoolss_AddForm(struct pipes_struct *p,
8425 struct spoolss_AddForm *r)
8427 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8429 WERROR status = WERR_OK;
8431 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8433 DEBUG(5,("_spoolss_AddForm\n"));
8436 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8437 OUR_HANDLE(r->in.handle)));
8441 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8442 and not a printer admin, then fail */
8444 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8445 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8446 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8447 p->session_info->info3->base.domain.string,
8449 p->session_info->security_token,
8450 lp_printer_admin(snum))) {
8451 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8452 return WERR_ACCESS_DENIED;
8455 switch (form->flags) {
8456 case SPOOLSS_FORM_USER:
8457 case SPOOLSS_FORM_BUILTIN:
8458 case SPOOLSS_FORM_PRINTER:
8461 return WERR_INVALID_PARAM;
8464 status = winreg_printer_addform1(p->mem_ctx,
8465 get_session_info_system(),
8468 if (!W_ERROR_IS_OK(status)) {
8473 * ChangeID must always be set if this is a printer
8475 if (Printer->printer_type == SPLHND_PRINTER) {
8476 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8480 status = winreg_printer_update_changeid(p->mem_ctx,
8481 get_session_info_system(),
8483 lp_const_servicename(snum));
8484 if (!W_ERROR_IS_OK(status)) {
8492 /****************************************************************
8494 ****************************************************************/
8496 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8497 struct spoolss_DeleteForm *r)
8499 const char *form_name = r->in.form_name;
8500 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8502 WERROR status = WERR_OK;
8504 DEBUG(5,("_spoolss_DeleteForm\n"));
8507 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8508 OUR_HANDLE(r->in.handle)));
8512 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8513 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8514 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8515 p->session_info->info3->base.domain.string,
8517 p->session_info->security_token,
8518 lp_printer_admin(snum))) {
8519 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8520 return WERR_ACCESS_DENIED;
8523 status = winreg_printer_deleteform1(p->mem_ctx,
8524 get_session_info_system(),
8527 if (!W_ERROR_IS_OK(status)) {
8532 * ChangeID must always be set if this is a printer
8534 if (Printer->printer_type == SPLHND_PRINTER) {
8535 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8539 status = winreg_printer_update_changeid(p->mem_ctx,
8540 get_session_info_system(),
8542 lp_const_servicename(snum));
8543 if (!W_ERROR_IS_OK(status)) {
8551 /****************************************************************
8553 ****************************************************************/
8555 WERROR _spoolss_SetForm(struct pipes_struct *p,
8556 struct spoolss_SetForm *r)
8558 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8559 const char *form_name = r->in.form_name;
8561 WERROR status = WERR_OK;
8563 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8565 DEBUG(5,("_spoolss_SetForm\n"));
8568 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8569 OUR_HANDLE(r->in.handle)));
8573 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8574 and not a printer admin, then fail */
8576 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8577 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8578 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8579 p->session_info->info3->base.domain.string,
8581 p->session_info->security_token,
8582 lp_printer_admin(snum))) {
8583 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8584 return WERR_ACCESS_DENIED;
8587 status = winreg_printer_setform1(p->mem_ctx,
8588 get_session_info_system(),
8592 if (!W_ERROR_IS_OK(status)) {
8597 * ChangeID must always be set if this is a printer
8599 if (Printer->printer_type == SPLHND_PRINTER) {
8600 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8604 status = winreg_printer_update_changeid(p->mem_ctx,
8605 get_session_info_system(),
8607 lp_const_servicename(snum));
8608 if (!W_ERROR_IS_OK(status)) {
8616 /****************************************************************************
8617 fill_print_processor1
8618 ****************************************************************************/
8620 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8621 struct spoolss_PrintProcessorInfo1 *r,
8622 const char *print_processor_name)
8624 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8625 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8630 /****************************************************************************
8631 enumprintprocessors level 1.
8632 ****************************************************************************/
8634 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8635 union spoolss_PrintProcessorInfo **info_p,
8638 union spoolss_PrintProcessorInfo *info;
8641 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8642 W_ERROR_HAVE_NO_MEMORY(info);
8646 result = fill_print_processor1(info, &info[0].info1, "winprint");
8647 if (!W_ERROR_IS_OK(result)) {
8652 if (!W_ERROR_IS_OK(result)) {
8663 /****************************************************************
8664 _spoolss_EnumPrintProcessors
8665 ****************************************************************/
8667 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8668 struct spoolss_EnumPrintProcessors *r)
8672 /* that's an [in out] buffer */
8674 if (!r->in.buffer && (r->in.offered != 0)) {
8675 return WERR_INVALID_PARAM;
8678 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8681 * Enumerate the print processors ...
8683 * Just reply with "winprint", to keep NT happy
8684 * and I can use my nice printer checker.
8689 *r->out.info = NULL;
8691 if (!get_short_archi(r->in.environment)) {
8692 return WERR_INVALID_ENVIRONMENT;
8695 switch (r->in.level) {
8697 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8701 return WERR_UNKNOWN_LEVEL;
8704 if (!W_ERROR_IS_OK(result)) {
8708 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8709 spoolss_EnumPrintProcessors,
8710 *r->out.info, r->in.level,
8712 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8713 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8715 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8718 /****************************************************************************
8719 fill_printprocdatatype1
8720 ****************************************************************************/
8722 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8723 struct spoolss_PrintProcDataTypesInfo1 *r,
8724 const char *name_array)
8726 r->name_array = talloc_strdup(mem_ctx, name_array);
8727 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8732 /****************************************************************************
8733 enumprintprocdatatypes level 1.
8734 ****************************************************************************/
8736 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8737 union spoolss_PrintProcDataTypesInfo **info_p,
8741 union spoolss_PrintProcDataTypesInfo *info;
8743 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8744 W_ERROR_HAVE_NO_MEMORY(info);
8748 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8749 if (!W_ERROR_IS_OK(result)) {
8754 if (!W_ERROR_IS_OK(result)) {
8765 /****************************************************************
8766 _spoolss_EnumPrintProcDataTypes
8767 ****************************************************************/
8769 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8770 struct spoolss_EnumPrintProcDataTypes *r)
8774 /* that's an [in out] buffer */
8776 if (!r->in.buffer && (r->in.offered != 0)) {
8777 return WERR_INVALID_PARAM;
8780 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8784 *r->out.info = NULL;
8786 if (r->in.print_processor_name == NULL ||
8787 !strequal(r->in.print_processor_name, "winprint")) {
8788 return WERR_UNKNOWN_PRINTPROCESSOR;
8791 switch (r->in.level) {
8793 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8797 return WERR_UNKNOWN_LEVEL;
8800 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8801 spoolss_EnumPrintProcDataTypes,
8802 *r->out.info, r->in.level,
8804 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8805 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8807 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8810 /****************************************************************************
8812 ****************************************************************************/
8814 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8815 struct spoolss_MonitorInfo1 *r,
8816 const char *monitor_name)
8818 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8819 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8824 /****************************************************************************
8826 ****************************************************************************/
8828 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8829 struct spoolss_MonitorInfo2 *r,
8830 const char *monitor_name,
8831 const char *environment,
8832 const char *dll_name)
8834 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8835 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8836 r->environment = talloc_strdup(mem_ctx, environment);
8837 W_ERROR_HAVE_NO_MEMORY(r->environment);
8838 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8839 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8844 /****************************************************************************
8845 enumprintmonitors level 1.
8846 ****************************************************************************/
8848 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8849 union spoolss_MonitorInfo **info_p,
8852 union spoolss_MonitorInfo *info;
8853 WERROR result = WERR_OK;
8855 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8856 W_ERROR_HAVE_NO_MEMORY(info);
8860 result = fill_monitor_1(info, &info[0].info1,
8862 if (!W_ERROR_IS_OK(result)) {
8866 result = fill_monitor_1(info, &info[1].info1,
8868 if (!W_ERROR_IS_OK(result)) {
8873 if (!W_ERROR_IS_OK(result)) {
8884 /****************************************************************************
8885 enumprintmonitors level 2.
8886 ****************************************************************************/
8888 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8889 union spoolss_MonitorInfo **info_p,
8892 union spoolss_MonitorInfo *info;
8893 WERROR result = WERR_OK;
8895 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8896 W_ERROR_HAVE_NO_MEMORY(info);
8900 result = fill_monitor_2(info, &info[0].info2,
8902 "Windows NT X86", /* FIXME */
8904 if (!W_ERROR_IS_OK(result)) {
8908 result = fill_monitor_2(info, &info[1].info2,
8910 "Windows NT X86", /* FIXME */
8912 if (!W_ERROR_IS_OK(result)) {
8917 if (!W_ERROR_IS_OK(result)) {
8928 /****************************************************************
8929 _spoolss_EnumMonitors
8930 ****************************************************************/
8932 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8933 struct spoolss_EnumMonitors *r)
8937 /* that's an [in out] buffer */
8939 if (!r->in.buffer && (r->in.offered != 0)) {
8940 return WERR_INVALID_PARAM;
8943 DEBUG(5,("_spoolss_EnumMonitors\n"));
8946 * Enumerate the print monitors ...
8948 * Just reply with "Local Port", to keep NT happy
8949 * and I can use my nice printer checker.
8954 *r->out.info = NULL;
8956 switch (r->in.level) {
8958 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8962 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8966 return WERR_UNKNOWN_LEVEL;
8969 if (!W_ERROR_IS_OK(result)) {
8973 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8974 spoolss_EnumMonitors,
8975 *r->out.info, r->in.level,
8977 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8978 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8980 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8983 /****************************************************************************
8984 ****************************************************************************/
8986 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8987 const print_queue_struct *queue,
8988 int count, int snum,
8989 struct spoolss_PrinterInfo2 *pinfo2,
8991 struct spoolss_JobInfo1 *r)
8996 for (i=0; i<count; i++) {
8997 if (queue[i].job == (int)jobid) {
9003 if (found == false) {
9004 /* NT treats not found as bad param... yet another bad choice */
9005 return WERR_INVALID_PARAM;
9008 return fill_job_info1(mem_ctx,
9016 /****************************************************************************
9017 ****************************************************************************/
9019 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9020 const print_queue_struct *queue,
9021 int count, int snum,
9022 struct spoolss_PrinterInfo2 *pinfo2,
9024 struct spoolss_JobInfo2 *r)
9028 struct spoolss_DeviceMode *devmode;
9031 for (i=0; i<count; i++) {
9032 if (queue[i].job == (int)jobid) {
9038 if (found == false) {
9039 /* NT treats not found as bad param... yet another bad
9041 return WERR_INVALID_PARAM;
9045 * if the print job does not have a DEVMODE associated with it,
9046 * just use the one for the printer. A NULL devicemode is not
9047 * a failure condition
9050 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9052 result = spoolss_create_default_devmode(mem_ctx,
9053 pinfo2->printername,
9055 if (!W_ERROR_IS_OK(result)) {
9056 DEBUG(3, ("Can't proceed w/o a devmode!"));
9061 return fill_job_info2(mem_ctx,
9070 /****************************************************************
9072 ****************************************************************/
9074 WERROR _spoolss_GetJob(struct pipes_struct *p,
9075 struct spoolss_GetJob *r)
9077 WERROR result = WERR_OK;
9078 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9081 print_queue_struct *queue = NULL;
9082 print_status_struct prt_status;
9084 /* that's an [in out] buffer */
9086 if (!r->in.buffer && (r->in.offered != 0)) {
9087 return WERR_INVALID_PARAM;
9090 DEBUG(5,("_spoolss_GetJob\n"));
9094 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9098 result = winreg_get_printer(p->mem_ctx,
9099 get_session_info_system(),
9101 lp_const_servicename(snum),
9103 if (!W_ERROR_IS_OK(result)) {
9107 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9109 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9110 count, prt_status.status, prt_status.message));
9112 switch (r->in.level) {
9114 result = getjob_level_1(p->mem_ctx,
9115 queue, count, snum, pinfo2,
9116 r->in.job_id, &r->out.info->info1);
9119 result = getjob_level_2(p->mem_ctx,
9120 queue, count, snum, pinfo2,
9121 r->in.job_id, &r->out.info->info2);
9124 result = WERR_UNKNOWN_LEVEL;
9129 TALLOC_FREE(pinfo2);
9131 if (!W_ERROR_IS_OK(result)) {
9132 TALLOC_FREE(r->out.info);
9136 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9138 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9140 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9143 /****************************************************************
9144 _spoolss_GetPrinterDataEx
9145 ****************************************************************/
9147 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9148 struct spoolss_GetPrinterDataEx *r)
9151 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9152 const char *printer;
9154 WERROR result = WERR_OK;
9156 enum winreg_Type val_type;
9161 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9163 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9164 r->in.key_name, r->in.value_name));
9166 /* in case of problem, return some default values */
9169 *r->out.type = REG_NONE;
9172 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9173 OUR_HANDLE(r->in.handle)));
9174 result = WERR_BADFID;
9178 /* Is the handle to a printer or to the server? */
9180 if (Printer->printer_type == SPLHND_SERVER) {
9182 union spoolss_PrinterData data;
9184 result = getprinterdata_printer_server(p->mem_ctx,
9188 if (!W_ERROR_IS_OK(result)) {
9192 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9193 *r->out.type, &data);
9194 if (!W_ERROR_IS_OK(result)) {
9198 *r->out.needed = blob.length;
9200 if (r->in.offered >= *r->out.needed) {
9201 memcpy(r->out.data, blob.data, blob.length);
9204 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9207 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9210 printer = lp_const_servicename(snum);
9212 /* check to see if the keyname is valid */
9213 if (!strlen(r->in.key_name)) {
9214 return WERR_INVALID_PARAM;
9217 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9218 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9219 strequal(r->in.value_name, "ChangeId")) {
9220 *r->out.type = REG_DWORD;
9222 if (r->in.offered >= *r->out.needed) {
9223 uint32_t changeid = 0;
9225 result = winreg_printer_get_changeid(p->mem_ctx,
9226 get_session_info_system(),
9230 if (!W_ERROR_IS_OK(result)) {
9234 SIVAL(r->out.data, 0, changeid);
9240 result = winreg_get_printer_dataex(p->mem_ctx,
9241 get_session_info_system(),
9249 if (!W_ERROR_IS_OK(result)) {
9253 *r->out.needed = val_size;
9254 *r->out.type = val_type;
9256 if (r->in.offered >= *r->out.needed) {
9257 memcpy(r->out.data, val_data, val_size);
9261 /* retain type when returning WERR_MORE_DATA */
9262 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9264 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9267 /****************************************************************
9268 _spoolss_SetPrinterDataEx
9269 ****************************************************************/
9271 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9272 struct spoolss_SetPrinterDataEx *r)
9274 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9276 WERROR result = WERR_OK;
9277 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9280 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9282 /* From MSDN documentation of SetPrinterDataEx: pass request to
9283 SetPrinterData if key is "PrinterDriverData" */
9286 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9287 OUR_HANDLE(r->in.handle)));
9291 if (Printer->printer_type == SPLHND_SERVER) {
9292 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9293 "Not implemented for server handles yet\n"));
9294 return WERR_INVALID_PARAM;
9297 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9302 * Access check : NT returns "access denied" if you make a
9303 * SetPrinterData call without the necessary privildge.
9304 * we were originally returning OK if nothing changed
9305 * which made Win2k issue **a lot** of SetPrinterData
9306 * when connecting to a printer --jerry
9309 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9310 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9311 "change denied by handle access permissions\n"));
9312 return WERR_ACCESS_DENIED;
9315 result = winreg_get_printer(Printer,
9316 get_session_info_system(),
9318 lp_servicename(snum),
9320 if (!W_ERROR_IS_OK(result)) {
9324 /* check for OID in valuename */
9326 oid_string = strchr(r->in.value_name, ',');
9332 /* save the registry data */
9334 result = winreg_set_printer_dataex(p->mem_ctx,
9335 get_session_info_system(),
9344 if (W_ERROR_IS_OK(result)) {
9345 /* save the OID if one was specified */
9347 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9348 r->in.key_name, SPOOL_OID_KEY);
9350 result = WERR_NOMEM;
9355 * I'm not checking the status here on purpose. Don't know
9356 * if this is right, but I'm returning the status from the
9357 * previous set_printer_dataex() call. I have no idea if
9358 * this is right. --jerry
9360 winreg_set_printer_dataex(p->mem_ctx,
9361 get_session_info_system(),
9367 (uint8_t *) oid_string,
9368 strlen(oid_string) + 1);
9371 result = winreg_printer_update_changeid(p->mem_ctx,
9372 get_session_info_system(),
9374 lp_const_servicename(snum));
9379 talloc_free(pinfo2);
9383 /****************************************************************
9384 _spoolss_DeletePrinterDataEx
9385 ****************************************************************/
9387 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9388 struct spoolss_DeletePrinterDataEx *r)
9390 const char *printer;
9392 WERROR status = WERR_OK;
9393 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9395 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9398 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9399 "Invalid handle (%s:%u:%u).\n",
9400 OUR_HANDLE(r->in.handle)));
9404 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9405 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9406 "printer properties change denied by handle\n"));
9407 return WERR_ACCESS_DENIED;
9410 if (!r->in.value_name || !r->in.key_name) {
9414 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9417 printer = lp_const_servicename(snum);
9419 status = winreg_delete_printer_dataex(p->mem_ctx,
9420 get_session_info_system(),
9425 if (W_ERROR_IS_OK(status)) {
9426 status = winreg_printer_update_changeid(p->mem_ctx,
9427 get_session_info_system(),
9435 /****************************************************************
9436 _spoolss_EnumPrinterKey
9437 ****************************************************************/
9439 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9440 struct spoolss_EnumPrinterKey *r)
9443 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9445 WERROR result = WERR_BADFILE;
9446 const char **array = NULL;
9449 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9452 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9453 OUR_HANDLE(r->in.handle)));
9457 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9461 result = winreg_enum_printer_key(p->mem_ctx,
9462 get_session_info_system(),
9464 lp_const_servicename(snum),
9468 if (!W_ERROR_IS_OK(result)) {
9472 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9473 result = WERR_NOMEM;
9477 *r->out._ndr_size = r->in.offered / 2;
9478 *r->out.needed = blob.length;
9480 if (r->in.offered < *r->out.needed) {
9481 result = WERR_MORE_DATA;
9484 r->out.key_buffer->string_array = array;
9488 if (!W_ERROR_IS_OK(result)) {
9490 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9498 /****************************************************************
9499 _spoolss_DeletePrinterKey
9500 ****************************************************************/
9502 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9503 struct spoolss_DeletePrinterKey *r)
9505 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9508 const char *printer;
9510 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9513 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9514 OUR_HANDLE(r->in.handle)));
9518 /* if keyname == NULL, return error */
9519 if ( !r->in.key_name )
9520 return WERR_INVALID_PARAM;
9522 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9526 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9527 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9528 "printer properties change denied by handle\n"));
9529 return WERR_ACCESS_DENIED;
9532 printer = lp_const_servicename(snum);
9534 /* delete the key and all subkeys */
9535 status = winreg_delete_printer_key(p->mem_ctx,
9536 get_session_info_system(),
9540 if (W_ERROR_IS_OK(status)) {
9541 status = winreg_printer_update_changeid(p->mem_ctx,
9542 get_session_info_system(),
9550 /****************************************************************
9551 _spoolss_EnumPrinterDataEx
9552 ****************************************************************/
9554 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9555 struct spoolss_EnumPrinterDataEx *r)
9558 struct spoolss_PrinterEnumValues *info = NULL;
9559 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9563 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9567 *r->out.info = NULL;
9570 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9571 OUR_HANDLE(r->in.handle)));
9576 * first check for a keyname of NULL or "". Win2k seems to send
9577 * this a lot and we should send back WERR_INVALID_PARAM
9578 * no need to spend time looking up the printer in this case.
9582 if (!strlen(r->in.key_name)) {
9583 result = WERR_INVALID_PARAM;
9587 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9591 /* now look for a match on the key name */
9592 result = winreg_enum_printer_dataex(p->mem_ctx,
9593 get_session_info_system(),
9595 lp_const_servicename(snum),
9599 if (!W_ERROR_IS_OK(result)) {
9603 #if 0 /* FIXME - gd */
9604 /* housekeeping information in the reply */
9606 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9607 * the hand marshalled container size is a multiple
9608 * of 4 bytes for RPC alignment.
9612 needed += 4-(needed % 4);
9615 *r->out.count = count;
9616 *r->out.info = info;
9619 if (!W_ERROR_IS_OK(result)) {
9623 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9624 spoolss_EnumPrinterDataEx,
9627 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9628 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9630 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9633 /****************************************************************************
9634 ****************************************************************************/
9636 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9637 const char *servername,
9638 const char *environment,
9639 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9644 werr = compose_spoolss_server_path(mem_ctx,
9647 SPOOLSS_PRTPROCS_PATH,
9649 if (!W_ERROR_IS_OK(werr)) {
9653 DEBUG(4,("print processor directory: [%s]\n", path));
9655 r->directory_name = path;
9660 /****************************************************************
9661 _spoolss_GetPrintProcessorDirectory
9662 ****************************************************************/
9664 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9665 struct spoolss_GetPrintProcessorDirectory *r)
9668 char *prnproc_share = NULL;
9669 bool prnproc_share_exists = false;
9672 /* that's an [in out] buffer */
9674 if (!r->in.buffer && (r->in.offered != 0)) {
9675 return WERR_INVALID_PARAM;
9678 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9683 /* r->in.level is ignored */
9685 /* We always should reply with a local print processor directory so that
9686 * users are not forced to have a [prnproc$] share on the Samba spoolss
9687 * server, if users decide to do so, lets announce it though - Guenther */
9689 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9690 if (!prnproc_share) {
9694 prnproc_share_exists = true;
9697 result = getprintprocessordirectory_level_1(p->mem_ctx,
9698 prnproc_share_exists ? r->in.server : NULL,
9700 &r->out.info->info1);
9701 if (!W_ERROR_IS_OK(result)) {
9702 TALLOC_FREE(r->out.info);
9706 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9707 r->out.info, r->in.level);
9708 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9710 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9713 /*******************************************************************
9714 ********************************************************************/
9716 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9717 const char *dllname)
9719 enum ndr_err_code ndr_err;
9720 struct spoolss_MonitorUi ui;
9722 ui.dll_name = dllname;
9724 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9725 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9726 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9727 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9729 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9732 /*******************************************************************
9733 Streams the monitor UI DLL name in UNICODE
9734 *******************************************************************/
9736 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9737 struct security_token *token, DATA_BLOB *in,
9738 DATA_BLOB *out, uint32_t *needed)
9740 const char *dllname = "tcpmonui.dll";
9742 *needed = (strlen(dllname)+1) * 2;
9744 if (out->length < *needed) {
9745 return WERR_INSUFFICIENT_BUFFER;
9748 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9755 /*******************************************************************
9756 ********************************************************************/
9758 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9759 struct spoolss_PortData1 *port1,
9760 const DATA_BLOB *buf)
9762 enum ndr_err_code ndr_err;
9763 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9764 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9765 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9766 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9768 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9771 /*******************************************************************
9772 ********************************************************************/
9774 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9775 struct spoolss_PortData2 *port2,
9776 const DATA_BLOB *buf)
9778 enum ndr_err_code ndr_err;
9779 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9780 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9781 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9782 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9784 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9787 /*******************************************************************
9788 Create a new TCP/IP port
9789 *******************************************************************/
9791 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9792 struct security_token *token, DATA_BLOB *in,
9793 DATA_BLOB *out, uint32_t *needed)
9795 struct spoolss_PortData1 port1;
9796 struct spoolss_PortData2 port2;
9797 char *device_uri = NULL;
9800 const char *portname;
9801 const char *hostaddress;
9803 uint32_t port_number;
9806 /* peek for spoolss_PortData version */
9808 if (!in || (in->length < (128 + 4))) {
9809 return WERR_GENERAL_FAILURE;
9812 version = IVAL(in->data, 128);
9818 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9822 portname = port1.portname;
9823 hostaddress = port1.hostaddress;
9824 queue = port1.queue;
9825 protocol = port1.protocol;
9826 port_number = port1.port_number;
9832 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9836 portname = port2.portname;
9837 hostaddress = port2.hostaddress;
9838 queue = port2.queue;
9839 protocol = port2.protocol;
9840 port_number = port2.port_number;
9844 DEBUG(1,("xcvtcp_addport: "
9845 "unknown version of port_data: %d\n", version));
9846 return WERR_UNKNOWN_PORT;
9849 /* create the device URI and call the add_port_hook() */
9852 case PROTOCOL_RAWTCP_TYPE:
9853 device_uri = talloc_asprintf(mem_ctx,
9854 "socket://%s:%d/", hostaddress,
9858 case PROTOCOL_LPR_TYPE:
9859 device_uri = talloc_asprintf(mem_ctx,
9860 "lpr://%s/%s", hostaddress, queue );
9864 return WERR_UNKNOWN_PORT;
9871 return add_port_hook(mem_ctx, token, portname, device_uri);
9874 /*******************************************************************
9875 *******************************************************************/
9877 struct xcv_api_table xcvtcp_cmds[] = {
9878 { "MonitorUI", xcvtcp_monitorui },
9879 { "AddPort", xcvtcp_addport},
9883 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9884 struct security_token *token, const char *command,
9891 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9893 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9894 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9895 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9898 return WERR_BADFUNC;
9901 /*******************************************************************
9902 *******************************************************************/
9903 #if 0 /* don't support management using the "Local Port" monitor */
9905 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9906 struct security_token *token, DATA_BLOB *in,
9907 DATA_BLOB *out, uint32_t *needed)
9909 const char *dllname = "localui.dll";
9911 *needed = (strlen(dllname)+1) * 2;
9913 if (out->length < *needed) {
9914 return WERR_INSUFFICIENT_BUFFER;
9917 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9924 /*******************************************************************
9925 *******************************************************************/
9927 struct xcv_api_table xcvlocal_cmds[] = {
9928 { "MonitorUI", xcvlocal_monitorui },
9932 struct xcv_api_table xcvlocal_cmds[] = {
9939 /*******************************************************************
9940 *******************************************************************/
9942 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9943 struct security_token *token, const char *command,
9944 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9949 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9951 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9952 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9953 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9955 return WERR_BADFUNC;
9958 /****************************************************************
9960 ****************************************************************/
9962 WERROR _spoolss_XcvData(struct pipes_struct *p,
9963 struct spoolss_XcvData *r)
9965 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9966 DATA_BLOB out_data = data_blob_null;
9970 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9971 OUR_HANDLE(r->in.handle)));
9975 /* Has to be a handle to the TCP/IP port monitor */
9977 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9978 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9982 /* requires administrative access to the server */
9984 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9985 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9986 return WERR_ACCESS_DENIED;
9989 /* Allocate the outgoing buffer */
9991 if (r->in.out_data_size) {
9992 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9993 if (out_data.data == NULL) {
9998 switch ( Printer->printer_type ) {
9999 case SPLHND_PORTMON_TCP:
10000 werror = process_xcvtcp_command(p->mem_ctx,
10001 p->session_info->security_token,
10002 r->in.function_name,
10003 &r->in.in_data, &out_data,
10006 case SPLHND_PORTMON_LOCAL:
10007 werror = process_xcvlocal_command(p->mem_ctx,
10008 p->session_info->security_token,
10009 r->in.function_name,
10010 &r->in.in_data, &out_data,
10014 werror = WERR_INVALID_PRINT_MONITOR;
10017 if (!W_ERROR_IS_OK(werror)) {
10021 *r->out.status_code = 0;
10023 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10024 memcpy(r->out.out_data, out_data.data,
10025 MIN(r->in.out_data_size, out_data.length));
10031 /****************************************************************
10032 _spoolss_AddPrintProcessor
10033 ****************************************************************/
10035 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10036 struct spoolss_AddPrintProcessor *r)
10038 /* for now, just indicate success and ignore the add. We'll
10039 automatically set the winprint processor for printer
10040 entries later. Used to debug the LexMark Optra S 1855 PCL
10046 /****************************************************************
10048 ****************************************************************/
10050 WERROR _spoolss_AddPort(struct pipes_struct *p,
10051 struct spoolss_AddPort *r)
10053 /* do what w2k3 does */
10055 return WERR_NOT_SUPPORTED;
10058 /****************************************************************
10059 _spoolss_GetPrinterDriver
10060 ****************************************************************/
10062 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10063 struct spoolss_GetPrinterDriver *r)
10065 p->rng_fault_state = true;
10066 return WERR_NOT_SUPPORTED;
10069 /****************************************************************
10070 _spoolss_ReadPrinter
10071 ****************************************************************/
10073 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10074 struct spoolss_ReadPrinter *r)
10076 p->rng_fault_state = true;
10077 return WERR_NOT_SUPPORTED;
10080 /****************************************************************
10081 _spoolss_WaitForPrinterChange
10082 ****************************************************************/
10084 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10085 struct spoolss_WaitForPrinterChange *r)
10087 p->rng_fault_state = true;
10088 return WERR_NOT_SUPPORTED;
10091 /****************************************************************
10092 _spoolss_ConfigurePort
10093 ****************************************************************/
10095 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10096 struct spoolss_ConfigurePort *r)
10098 p->rng_fault_state = true;
10099 return WERR_NOT_SUPPORTED;
10102 /****************************************************************
10103 _spoolss_DeletePort
10104 ****************************************************************/
10106 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10107 struct spoolss_DeletePort *r)
10109 p->rng_fault_state = true;
10110 return WERR_NOT_SUPPORTED;
10113 /****************************************************************
10114 _spoolss_CreatePrinterIC
10115 ****************************************************************/
10117 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10118 struct spoolss_CreatePrinterIC *r)
10120 p->rng_fault_state = true;
10121 return WERR_NOT_SUPPORTED;
10124 /****************************************************************
10125 _spoolss_PlayGDIScriptOnPrinterIC
10126 ****************************************************************/
10128 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10129 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10131 p->rng_fault_state = true;
10132 return WERR_NOT_SUPPORTED;
10135 /****************************************************************
10136 _spoolss_DeletePrinterIC
10137 ****************************************************************/
10139 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10140 struct spoolss_DeletePrinterIC *r)
10142 p->rng_fault_state = true;
10143 return WERR_NOT_SUPPORTED;
10146 /****************************************************************
10147 _spoolss_AddPrinterConnection
10148 ****************************************************************/
10150 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10151 struct spoolss_AddPrinterConnection *r)
10153 p->rng_fault_state = true;
10154 return WERR_NOT_SUPPORTED;
10157 /****************************************************************
10158 _spoolss_DeletePrinterConnection
10159 ****************************************************************/
10161 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10162 struct spoolss_DeletePrinterConnection *r)
10164 p->rng_fault_state = true;
10165 return WERR_NOT_SUPPORTED;
10168 /****************************************************************
10169 _spoolss_PrinterMessageBox
10170 ****************************************************************/
10172 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10173 struct spoolss_PrinterMessageBox *r)
10175 p->rng_fault_state = true;
10176 return WERR_NOT_SUPPORTED;
10179 /****************************************************************
10180 _spoolss_AddMonitor
10181 ****************************************************************/
10183 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10184 struct spoolss_AddMonitor *r)
10186 p->rng_fault_state = true;
10187 return WERR_NOT_SUPPORTED;
10190 /****************************************************************
10191 _spoolss_DeleteMonitor
10192 ****************************************************************/
10194 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10195 struct spoolss_DeleteMonitor *r)
10197 p->rng_fault_state = true;
10198 return WERR_NOT_SUPPORTED;
10201 /****************************************************************
10202 _spoolss_DeletePrintProcessor
10203 ****************************************************************/
10205 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10206 struct spoolss_DeletePrintProcessor *r)
10208 p->rng_fault_state = true;
10209 return WERR_NOT_SUPPORTED;
10212 /****************************************************************
10213 _spoolss_AddPrintProvidor
10214 ****************************************************************/
10216 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10217 struct spoolss_AddPrintProvidor *r)
10219 p->rng_fault_state = true;
10220 return WERR_NOT_SUPPORTED;
10223 /****************************************************************
10224 _spoolss_DeletePrintProvidor
10225 ****************************************************************/
10227 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10228 struct spoolss_DeletePrintProvidor *r)
10230 p->rng_fault_state = true;
10231 return WERR_NOT_SUPPORTED;
10234 /****************************************************************
10235 _spoolss_FindFirstPrinterChangeNotification
10236 ****************************************************************/
10238 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10239 struct spoolss_FindFirstPrinterChangeNotification *r)
10241 p->rng_fault_state = true;
10242 return WERR_NOT_SUPPORTED;
10245 /****************************************************************
10246 _spoolss_FindNextPrinterChangeNotification
10247 ****************************************************************/
10249 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10250 struct spoolss_FindNextPrinterChangeNotification *r)
10252 p->rng_fault_state = true;
10253 return WERR_NOT_SUPPORTED;
10256 /****************************************************************
10257 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10258 ****************************************************************/
10260 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10261 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10263 p->rng_fault_state = true;
10264 return WERR_NOT_SUPPORTED;
10267 /****************************************************************
10268 _spoolss_ReplyOpenPrinter
10269 ****************************************************************/
10271 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10272 struct spoolss_ReplyOpenPrinter *r)
10274 p->rng_fault_state = true;
10275 return WERR_NOT_SUPPORTED;
10278 /****************************************************************
10279 _spoolss_RouterReplyPrinter
10280 ****************************************************************/
10282 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10283 struct spoolss_RouterReplyPrinter *r)
10285 p->rng_fault_state = true;
10286 return WERR_NOT_SUPPORTED;
10289 /****************************************************************
10290 _spoolss_ReplyClosePrinter
10291 ****************************************************************/
10293 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10294 struct spoolss_ReplyClosePrinter *r)
10296 p->rng_fault_state = true;
10297 return WERR_NOT_SUPPORTED;
10300 /****************************************************************
10302 ****************************************************************/
10304 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10305 struct spoolss_AddPortEx *r)
10307 p->rng_fault_state = true;
10308 return WERR_NOT_SUPPORTED;
10311 /****************************************************************
10312 _spoolss_RouterFindFirstPrinterChangeNotification
10313 ****************************************************************/
10315 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10316 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10318 p->rng_fault_state = true;
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_SpoolerInit
10324 ****************************************************************/
10326 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10327 struct spoolss_SpoolerInit *r)
10329 p->rng_fault_state = true;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_ResetPrinterEx
10335 ****************************************************************/
10337 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10338 struct spoolss_ResetPrinterEx *r)
10340 p->rng_fault_state = true;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10345 _spoolss_RouterReplyPrinterEx
10346 ****************************************************************/
10348 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10349 struct spoolss_RouterReplyPrinterEx *r)
10351 p->rng_fault_state = true;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10357 ****************************************************************/
10359 WERROR _spoolss_44(struct pipes_struct *p,
10360 struct spoolss_44 *r)
10362 p->rng_fault_state = true;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10368 ****************************************************************/
10370 WERROR _spoolss_SetPort(struct pipes_struct *p,
10371 struct spoolss_SetPort *r)
10373 p->rng_fault_state = true;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10379 ****************************************************************/
10381 WERROR _spoolss_4a(struct pipes_struct *p,
10382 struct spoolss_4a *r)
10384 p->rng_fault_state = true;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10390 ****************************************************************/
10392 WERROR _spoolss_4b(struct pipes_struct *p,
10393 struct spoolss_4b *r)
10395 p->rng_fault_state = true;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10401 ****************************************************************/
10403 WERROR _spoolss_4c(struct pipes_struct *p,
10404 struct spoolss_4c *r)
10406 p->rng_fault_state = true;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10412 ****************************************************************/
10414 WERROR _spoolss_53(struct pipes_struct *p,
10415 struct spoolss_53 *r)
10417 p->rng_fault_state = true;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_AddPerMachineConnection
10423 ****************************************************************/
10425 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10426 struct spoolss_AddPerMachineConnection *r)
10428 p->rng_fault_state = true;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_DeletePerMachineConnection
10434 ****************************************************************/
10436 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10437 struct spoolss_DeletePerMachineConnection *r)
10439 p->rng_fault_state = true;
10440 return WERR_NOT_SUPPORTED;
10443 /****************************************************************
10444 _spoolss_EnumPerMachineConnections
10445 ****************************************************************/
10447 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10448 struct spoolss_EnumPerMachineConnections *r)
10450 p->rng_fault_state = true;
10451 return WERR_NOT_SUPPORTED;
10454 /****************************************************************
10456 ****************************************************************/
10458 WERROR _spoolss_5a(struct pipes_struct *p,
10459 struct spoolss_5a *r)
10461 p->rng_fault_state = true;
10462 return WERR_NOT_SUPPORTED;
10465 /****************************************************************
10467 ****************************************************************/
10469 WERROR _spoolss_5b(struct pipes_struct *p,
10470 struct spoolss_5b *r)
10472 p->rng_fault_state = true;
10473 return WERR_NOT_SUPPORTED;
10476 /****************************************************************
10478 ****************************************************************/
10480 WERROR _spoolss_5c(struct pipes_struct *p,
10481 struct spoolss_5c *r)
10483 p->rng_fault_state = true;
10484 return WERR_NOT_SUPPORTED;
10487 /****************************************************************
10489 ****************************************************************/
10491 WERROR _spoolss_5d(struct pipes_struct *p,
10492 struct spoolss_5d *r)
10494 p->rng_fault_state = true;
10495 return WERR_NOT_SUPPORTED;
10498 /****************************************************************
10500 ****************************************************************/
10502 WERROR _spoolss_5e(struct pipes_struct *p,
10503 struct spoolss_5e *r)
10505 p->rng_fault_state = true;
10506 return WERR_NOT_SUPPORTED;
10509 /****************************************************************
10511 ****************************************************************/
10513 WERROR _spoolss_5f(struct pipes_struct *p,
10514 struct spoolss_5f *r)
10516 p->rng_fault_state = true;
10517 return WERR_NOT_SUPPORTED;
10520 /****************************************************************
10522 ****************************************************************/
10524 WERROR _spoolss_60(struct pipes_struct *p,
10525 struct spoolss_60 *r)
10527 p->rng_fault_state = true;
10528 return WERR_NOT_SUPPORTED;
10531 /****************************************************************
10533 ****************************************************************/
10535 WERROR _spoolss_61(struct pipes_struct *p,
10536 struct spoolss_61 *r)
10538 p->rng_fault_state = true;
10539 return WERR_NOT_SUPPORTED;
10542 /****************************************************************
10544 ****************************************************************/
10546 WERROR _spoolss_62(struct pipes_struct *p,
10547 struct spoolss_62 *r)
10549 p->rng_fault_state = true;
10550 return WERR_NOT_SUPPORTED;
10553 /****************************************************************
10555 ****************************************************************/
10557 WERROR _spoolss_63(struct pipes_struct *p,
10558 struct spoolss_63 *r)
10560 p->rng_fault_state = true;
10561 return WERR_NOT_SUPPORTED;
10564 /****************************************************************
10566 ****************************************************************/
10568 WERROR _spoolss_64(struct pipes_struct *p,
10569 struct spoolss_64 *r)
10571 p->rng_fault_state = true;
10572 return WERR_NOT_SUPPORTED;
10575 /****************************************************************
10577 ****************************************************************/
10579 WERROR _spoolss_65(struct pipes_struct *p,
10580 struct spoolss_65 *r)
10582 p->rng_fault_state = true;
10583 return WERR_NOT_SUPPORTED;
10586 /****************************************************************
10587 _spoolss_GetCorePrinterDrivers
10588 ****************************************************************/
10590 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10591 struct spoolss_GetCorePrinterDrivers *r)
10593 p->rng_fault_state = true;
10594 return WERR_NOT_SUPPORTED;
10597 /****************************************************************
10599 ****************************************************************/
10601 WERROR _spoolss_67(struct pipes_struct *p,
10602 struct spoolss_67 *r)
10604 p->rng_fault_state = true;
10605 return WERR_NOT_SUPPORTED;
10608 /****************************************************************
10609 _spoolss_GetPrinterDriverPackagePath
10610 ****************************************************************/
10612 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10613 struct spoolss_GetPrinterDriverPackagePath *r)
10615 p->rng_fault_state = true;
10616 return WERR_NOT_SUPPORTED;
10619 /****************************************************************
10621 ****************************************************************/
10623 WERROR _spoolss_69(struct pipes_struct *p,
10624 struct spoolss_69 *r)
10626 p->rng_fault_state = true;
10627 return WERR_NOT_SUPPORTED;
10630 /****************************************************************
10632 ****************************************************************/
10634 WERROR _spoolss_6a(struct pipes_struct *p,
10635 struct spoolss_6a *r)
10637 p->rng_fault_state = true;
10638 return WERR_NOT_SUPPORTED;
10641 /****************************************************************
10643 ****************************************************************/
10645 WERROR _spoolss_6b(struct pipes_struct *p,
10646 struct spoolss_6b *r)
10648 p->rng_fault_state = true;
10649 return WERR_NOT_SUPPORTED;
10652 /****************************************************************
10654 ****************************************************************/
10656 WERROR _spoolss_6c(struct pipes_struct *p,
10657 struct spoolss_6c *r)
10659 p->rng_fault_state = true;
10660 return WERR_NOT_SUPPORTED;
10663 /****************************************************************
10665 ****************************************************************/
10667 WERROR _spoolss_6d(struct pipes_struct *p,
10668 struct spoolss_6d *r)
10670 p->rng_fault_state = true;
10671 return WERR_NOT_SUPPORTED;