2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "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"
49 #include "smbd/globals.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59 #include "rpc_server/spoolss/srv_spoolss_handle.h"
61 /* macros stolen from s4 spoolss server */
62 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
63 ((info)?ndr_size_##fn(info, level, 0):0)
65 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
66 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
68 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
69 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
71 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
74 #define DBGC_CLASS DBGC_RPC_SRV
76 #ifndef MAX_OPEN_PRINTER_EXS
77 #define MAX_OPEN_PRINTER_EXS 50
80 #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
81 #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
82 #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
83 #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
85 static struct printer_handle *printers_list;
87 struct printer_session_counter {
88 struct printer_session_counter *next;
89 struct printer_session_counter *prev;
95 static struct printer_session_counter *counter_list;
97 struct notify_back_channel {
98 struct notify_back_channel *prev, *next;
100 /* associated client */
101 struct sockaddr_storage client_address;
103 /* print notify back-channel pipe handle*/
104 struct rpc_pipe_client *cli_pipe;
105 struct cli_state *cli;
106 uint32_t active_connections;
109 static struct notify_back_channel *back_channels;
111 /* Map generic permissions to printer object specific permissions */
113 const struct standard_mapping printer_std_mapping = {
120 /* Map generic permissions to print server object specific permissions */
122 const struct standard_mapping printserver_std_mapping = {
129 /* API table for Xcv Monitor functions */
131 struct xcv_api_table {
133 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
136 static void prune_printername_cache(void);
138 /********************************************************************
139 * Canonicalize servername.
140 ********************************************************************/
142 static const char *canon_servername(const char *servername)
144 const char *pservername = servername;
146 if (servername == NULL) {
150 while (*pservername == '\\') {
156 /* translate between internal status numbers and NT status numbers */
157 static int nt_printj_status(int v)
163 return JOB_STATUS_PAUSED;
165 return JOB_STATUS_SPOOLING;
167 return JOB_STATUS_PRINTING;
169 return JOB_STATUS_ERROR;
171 return JOB_STATUS_DELETING;
173 return JOB_STATUS_OFFLINE;
175 return JOB_STATUS_PAPEROUT;
177 return JOB_STATUS_PRINTED;
179 return JOB_STATUS_DELETED;
181 return JOB_STATUS_BLOCKED_DEVQ;
182 case LPQ_USER_INTERVENTION:
183 return JOB_STATUS_USER_INTERVENTION;
188 static int nt_printq_status(int v)
192 return PRINTER_STATUS_PAUSED;
201 /***************************************************************************
202 Disconnect from the client
203 ****************************************************************************/
205 static void srv_spoolss_replycloseprinter(int snum,
206 struct printer_handle *prn_hnd)
212 * Tell the specific printing tdb we no longer want messages for this printer
213 * by deregistering our PID.
216 if (!print_notify_deregister_pid(snum)) {
217 DEBUG(0, ("Failed to register our pid for printer %s\n",
218 lp_const_servicename(snum)));
221 /* weird if the test succeeds !!! */
222 if (prn_hnd->notify.cli_chan == NULL ||
223 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
224 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
225 prn_hnd->notify.cli_chan->active_connections == 0) {
226 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
227 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
228 TALLOC_FREE(prn_hnd->notify.cli_chan);
232 status = dcerpc_spoolss_ReplyClosePrinter(
233 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
235 &prn_hnd->notify.cli_hnd,
237 if (!NT_STATUS_IS_OK(status)) {
238 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
240 result = ntstatus_to_werror(status);
241 } else if (!W_ERROR_IS_OK(result)) {
242 DEBUG(0, ("reply_close_printer failed [%s].\n",
243 win_errstr(result)));
246 /* if it's the last connection, deconnect the IPC$ share */
247 if (prn_hnd->notify.cli_chan->active_connections == 1) {
249 cli_shutdown(prn_hnd->notify.cli_chan->cli);
250 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
251 TALLOC_FREE(prn_hnd->notify.cli_chan);
253 if (prn_hnd->notify.msg_ctx != NULL) {
254 messaging_deregister(prn_hnd->notify.msg_ctx,
255 MSG_PRINTER_NOTIFY2, NULL);
259 if (prn_hnd->notify.cli_chan) {
260 prn_hnd->notify.cli_chan->active_connections--;
261 prn_hnd->notify.cli_chan = NULL;
265 /****************************************************************************
266 Functions to free a printer entry datastruct.
267 ****************************************************************************/
269 static int printer_entry_destructor(struct printer_handle *Printer)
271 if (Printer->notify.cli_chan != NULL &&
272 Printer->notify.cli_chan->active_connections > 0) {
275 switch(Printer->printer_type) {
277 srv_spoolss_replycloseprinter(snum, Printer);
281 snum = print_queue_snum(Printer->sharename);
283 srv_spoolss_replycloseprinter(snum, Printer);
291 Printer->notify.flags=0;
292 Printer->notify.options=0;
293 Printer->notify.localmachine[0]='\0';
294 Printer->notify.printerlocal=0;
295 TALLOC_FREE(Printer->notify.option);
296 TALLOC_FREE(Printer->devmode);
298 /* Remove from the internal list. */
299 DLIST_REMOVE(printers_list, Printer);
303 /****************************************************************************
304 find printer index by handle
305 ****************************************************************************/
307 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
308 struct policy_handle *hnd)
310 struct printer_handle *find_printer = NULL;
312 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
313 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
320 /****************************************************************************
321 Close printer index by handle.
322 ****************************************************************************/
324 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
326 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
329 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
334 close_policy_hnd(p, hnd);
339 /****************************************************************************
340 Delete a printer given a handle.
341 ****************************************************************************/
343 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
344 const char *sharename,
345 struct messaging_context *msg_ctx)
347 char *cmd = lp_deleteprinter_command(talloc_tos());
348 char *command = NULL;
350 bool is_print_op = false;
352 /* can't fail if we don't try */
357 command = talloc_asprintf(ctx,
361 return WERR_NOT_ENOUGH_MEMORY;
364 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
366 DEBUG(10,("Running [%s]\n", command));
368 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
373 ret = smbrun(command, NULL, NULL);
375 /* Tell everyone we updated smb.conf. */
376 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
382 /********** END SePrintOperatorPrivlege BLOCK **********/
384 DEBUGADD(10,("returned [%d]\n", ret));
386 TALLOC_FREE(command);
389 return WERR_INVALID_HANDLE; /* What to return here? */
394 /****************************************************************************
395 Delete a printer given a handle.
396 ****************************************************************************/
398 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
400 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
404 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
406 return WERR_INVALID_HANDLE;
410 * It turns out that Windows allows delete printer on a handle
411 * opened by an admin user, then used on a pipe handle created
412 * by an anonymous user..... but they're working on security.... riiight !
416 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
417 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
418 return WERR_ACCESS_DENIED;
421 /* this does not need a become root since the access check has been
422 done on the handle already */
424 result = winreg_delete_printer_key_internal(p->mem_ctx,
425 get_session_info_system(),
429 if (!W_ERROR_IS_OK(result)) {
430 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
431 return WERR_INVALID_HANDLE;
434 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
435 Printer->sharename, p->msg_ctx);
436 if (!W_ERROR_IS_OK(result)) {
439 prune_printername_cache();
443 /****************************************************************************
444 Return the snum of a printer corresponding to an handle.
445 ****************************************************************************/
447 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
448 int *number, struct share_params **params)
450 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
453 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
458 switch (Printer->printer_type) {
460 DEBUG(4,("short name:%s\n", Printer->sharename));
461 *number = print_queue_snum(Printer->sharename);
462 return (*number != -1);
470 /****************************************************************************
471 Set printer handle type.
472 Check if it's \\server or \\server\printer
473 ****************************************************************************/
475 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
477 DEBUG(3,("Setting printer type=%s\n", handlename));
479 /* it's a print server */
480 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
481 DEBUGADD(4,("Printer is a print server\n"));
482 Printer->printer_type = SPLHND_SERVER;
484 /* it's a printer (set_printer_hnd_name() will handle port monitors */
486 DEBUGADD(4,("Printer is a printer\n"));
487 Printer->printer_type = SPLHND_PRINTER;
493 static void prune_printername_cache_fn(const char *key, const char *value,
494 time_t timeout, void *private_data)
499 static void prune_printername_cache(void)
501 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
504 /****************************************************************************
505 Set printer handle name.. Accept names like \\server, \\server\printer,
506 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
507 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
508 XcvDataPort() interface.
509 ****************************************************************************/
511 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
512 const struct auth_session_info *session_info,
513 struct messaging_context *msg_ctx,
514 struct printer_handle *Printer,
515 const char *handlename)
518 int n_services=lp_numservices();
520 const char *printername;
521 const char *servername = NULL;
524 struct spoolss_PrinterInfo2 *info2 = NULL;
529 * Hopefully nobody names his printers like this. Maybe \ or ,
530 * are illegal in printer names even?
532 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
536 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
537 (unsigned long)strlen(handlename)));
539 aprinter = discard_const_p(char, handlename);
540 if ( *handlename == '\\' ) {
541 servername = canon_servername(handlename);
542 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
546 if (!is_myname_or_ipaddr(servername)) {
547 return WERR_INVALID_PRINTER_NAME;
549 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
550 if (Printer->servername == NULL) {
551 return WERR_NOT_ENOUGH_MEMORY;
555 if (Printer->printer_type == SPLHND_SERVER) {
559 if (Printer->printer_type != SPLHND_PRINTER) {
560 return WERR_INVALID_HANDLE;
563 DEBUGADD(5, ("searching for [%s]\n", aprinter));
565 p = strchr(aprinter, ',');
572 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
574 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
580 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
583 /* check for the Port Monitor Interface */
584 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
585 Printer->printer_type = SPLHND_PORTMON_TCP;
586 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
589 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
590 Printer->printer_type = SPLHND_PORTMON_LOCAL;
591 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
595 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
596 if (cache_key == NULL) {
597 return WERR_NOT_ENOUGH_MEMORY;
601 * With hundreds of printers, the "for" loop iterating all
602 * shares can be quite expensive, as it is done on every
603 * OpenPrinter. The loop maps "aprinter" to "sname", the
604 * result of which we cache in gencache.
606 if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
607 found = (strcmp(tmp, printer_not_found) != 0);
609 DEBUG(4, ("Printer %s not found\n", aprinter));
611 return WERR_INVALID_PRINTER_NAME;
617 /* Search all sharenames first as this is easier than pulling
618 the printer_info_2 off of disk. Don't use find_service() since
619 that calls out to map_username() */
621 /* do another loop to look for printernames */
622 for (snum = 0; !found && snum < n_services; snum++) {
623 const char *printer = lp_const_servicename(snum);
625 /* no point going on if this is not a printer */
626 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
630 /* ignore [printers] share */
631 if (strequal(printer, "printers")) {
635 fstrcpy(sname, printer);
636 if (strequal(aprinter, printer)) {
641 /* no point looking up the printer object if
642 we aren't allowing printername != sharename */
643 if (lp_force_printername(snum)) {
647 result = winreg_get_printer_internal(mem_ctx,
652 if ( !W_ERROR_IS_OK(result) ) {
653 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
654 sname, win_errstr(result)));
658 printername = strrchr(info2->printername, '\\');
659 if (printername == NULL) {
660 printername = info2->printername;
665 if (strequal(printername, aprinter)) {
670 DEBUGADD(10, ("printername: %s\n", printername));
676 gencache_set(cache_key, printer_not_found,
678 TALLOC_FREE(cache_key);
679 DEBUGADD(4,("Printer not found\n"));
680 return WERR_INVALID_PRINTER_NAME;
683 gencache_set(cache_key, sname, time(NULL) + 300);
684 TALLOC_FREE(cache_key);
686 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
688 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
693 /****************************************************************************
694 Find first available printer slot. creates a printer handle for you.
695 ****************************************************************************/
697 static WERROR open_printer_hnd(struct pipes_struct *p,
698 struct policy_handle *hnd,
700 uint32_t access_granted)
702 struct printer_handle *new_printer;
705 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
707 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
708 if (new_printer == NULL) {
709 return WERR_NOT_ENOUGH_MEMORY;
711 talloc_set_destructor(new_printer, printer_entry_destructor);
713 /* This also steals the printer_handle on the policy_handle */
714 if (!create_policy_hnd(p, hnd, new_printer)) {
715 TALLOC_FREE(new_printer);
716 return WERR_INVALID_HANDLE;
719 /* Add to the internal list. */
720 DLIST_ADD(printers_list, new_printer);
722 new_printer->notify.option=NULL;
724 if (!set_printer_hnd_printertype(new_printer, name)) {
725 close_printer_handle(p, hnd);
726 return WERR_INVALID_HANDLE;
729 result = set_printer_hnd_name(p->mem_ctx,
730 get_session_info_system(),
733 if (!W_ERROR_IS_OK(result)) {
734 close_printer_handle(p, hnd);
738 new_printer->access_granted = access_granted;
740 DEBUG(5, ("%d printer handles active\n",
741 (int)num_pipe_handles(p)));
746 /***************************************************************************
747 check to see if the client motify handle is monitoring the notification
748 given by (notify_type, notify_field).
749 **************************************************************************/
751 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
752 uint16_t notify_field)
757 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
758 uint16_t notify_field)
760 struct spoolss_NotifyOption *option = p->notify.option;
764 * Flags should always be zero when the change notify
765 * is registered by the client's spooler. A user Win32 app
766 * might use the flags though instead of the NOTIFY_OPTION_INFO
775 return is_monitoring_event_flags(
776 p->notify.flags, notify_type, notify_field);
778 for (i = 0; i < option->count; i++) {
780 /* Check match for notify_type */
782 if (option->types[i].type != notify_type)
785 /* Check match for field */
787 for (j = 0; j < option->types[i].count; j++) {
788 if (option->types[i].fields[j].field == notify_field) {
794 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
795 p->servername, p->sharename, notify_type, notify_field));
800 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
801 _data->data.integer[0] = _integer; \
802 _data->data.integer[1] = 0;
805 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
806 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
807 if (!_data->data.string.string) {\
808 _data->data.string.size = 0; \
810 _data->data.string.size = strlen_m_term(_p) * 2;
812 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
813 _data->data.devmode.devmode = _devmode;
815 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
820 struct spoolss_Time st;
824 if (!init_systemtime(&st, t)) {
828 p = talloc_array(mem_ctx, char, len);
834 * Systemtime must be linearized as a set of UINT16's.
835 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
838 SSVAL(p, 0, st.year);
839 SSVAL(p, 2, st.month);
840 SSVAL(p, 4, st.day_of_week);
842 SSVAL(p, 8, st.hour);
843 SSVAL(p, 10, st.minute);
844 SSVAL(p, 12, st.second);
845 SSVAL(p, 14, st.millisecond);
851 /* Convert a notification message to a struct spoolss_Notify */
853 static void notify_one_value(struct spoolss_notify_msg *msg,
854 struct spoolss_Notify *data,
857 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
860 static void notify_string(struct spoolss_notify_msg *msg,
861 struct spoolss_Notify *data,
864 /* The length of the message includes the trailing \0 */
866 data->data.string.size = msg->len * 2;
867 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
868 if (!data->data.string.string) {
869 data->data.string.size = 0;
874 static void notify_system_time(struct spoolss_notify_msg *msg,
875 struct spoolss_Notify *data,
878 data->data.string.string = NULL;
879 data->data.string.size = 0;
881 if (msg->len != sizeof(time_t)) {
882 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
887 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
888 &data->data.string.string,
889 &data->data.string.size);
892 struct notify2_message_table {
894 void (*fn)(struct spoolss_notify_msg *msg,
895 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
898 static struct notify2_message_table printer_notify_table[] = {
899 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
900 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
901 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
902 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
903 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
904 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
905 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
906 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
907 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
908 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
909 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
910 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
911 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
912 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
913 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
914 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
915 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
916 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
917 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
920 static struct notify2_message_table job_notify_table[] = {
921 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
922 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
923 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
924 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
925 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
926 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
927 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
928 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
929 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
930 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
931 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
932 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
933 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
934 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
935 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
936 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
937 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
938 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
939 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
940 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
941 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
942 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
943 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
944 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
948 /***********************************************************************
949 Allocate talloc context for container object
950 **********************************************************************/
952 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
957 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
962 /***********************************************************************
963 release all allocated memory and zero out structure
964 **********************************************************************/
966 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
972 talloc_destroy(ctr->ctx);
979 /***********************************************************************
980 **********************************************************************/
982 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
990 /***********************************************************************
991 **********************************************************************/
993 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
995 if ( !ctr || !ctr->msg_groups )
998 if ( idx >= ctr->num_groups )
1001 return &ctr->msg_groups[idx];
1005 /***********************************************************************
1006 How many groups of change messages do we have ?
1007 **********************************************************************/
1009 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1014 return ctr->num_groups;
1017 /***********************************************************************
1018 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1019 **********************************************************************/
1021 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1023 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1024 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1025 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1031 /* loop over all groups looking for a matching printer name */
1033 for ( i=0; i<ctr->num_groups; i++ ) {
1034 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1038 /* add a new group? */
1040 if ( i == ctr->num_groups ) {
1043 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1044 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1047 ctr->msg_groups = groups;
1049 /* clear the new entry and set the printer name */
1051 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1052 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1055 /* add the change messages; 'i' is the correct index now regardless */
1057 msg_grp = &ctr->msg_groups[i];
1059 msg_grp->num_msgs++;
1061 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1062 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1065 msg_grp->msgs = msg_list;
1067 new_slot = msg_grp->num_msgs-1;
1068 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1070 /* need to allocate own copy of data */
1072 if ( msg->len != 0 )
1073 msg_grp->msgs[new_slot].notify.data = (char *)
1074 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1076 return ctr->num_groups;
1079 static void construct_info_data(struct spoolss_Notify *info_data,
1080 enum spoolss_NotifyType type,
1081 uint16_t field, int id);
1083 /***********************************************************************
1084 Send a change notication message on all handles which have a call
1086 **********************************************************************/
1088 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1089 struct printer_handle *prn_hnd,
1090 SPOOLSS_NOTIFY_MSG *messages,
1092 struct spoolss_Notify **_notifies,
1095 struct spoolss_Notify *notifies;
1096 SPOOLSS_NOTIFY_MSG *msg;
1101 notifies = talloc_zero_array(mem_ctx,
1102 struct spoolss_Notify, num_msgs);
1107 for (i = 0; i < num_msgs; i++) {
1111 /* Are we monitoring this event? */
1113 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1117 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1118 "for printer [%s]\n",
1119 msg->type, msg->field, prn_hnd->sharename));
1122 * if the is a printer notification handle and not a job
1123 * notification type, then set the id to 0.
1124 * Otherwise just use what was specified in the message.
1126 * When registering change notification on a print server
1127 * handle we always need to send back the id (snum) matching
1128 * the printer for which the change took place.
1129 * For change notify registered on a printer handle,
1130 * this does not matter and the id should be 0.
1135 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1136 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1142 /* Convert unix jobid to smb jobid */
1144 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1145 id = sysjob_to_jobid(msg->id);
1148 DEBUG(3, ("no such unix jobid %d\n",
1154 construct_info_data(¬ifies[count],
1155 msg->type, msg->field, id);
1158 case PRINTER_NOTIFY_TYPE:
1159 if (printer_notify_table[msg->field].fn) {
1160 printer_notify_table[msg->field].fn(msg,
1161 ¬ifies[count], mem_ctx);
1165 case JOB_NOTIFY_TYPE:
1166 if (job_notify_table[msg->field].fn) {
1167 job_notify_table[msg->field].fn(msg,
1168 ¬ifies[count], mem_ctx);
1173 DEBUG(5, ("Unknown notification type %d\n",
1181 *_notifies = notifies;
1187 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1188 struct printer_handle *prn_hnd,
1189 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1191 struct spoolss_Notify *notifies;
1193 union spoolss_ReplyPrinterInfo info;
1194 struct spoolss_NotifyInfo info0;
1195 uint32_t reply_result;
1200 /* Is there notification on this handle? */
1201 if (prn_hnd->notify.cli_chan == NULL ||
1202 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1203 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1204 prn_hnd->notify.cli_chan->active_connections == 0) {
1208 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1209 prn_hnd->servername, prn_hnd->sharename));
1211 /* For this printer? Print servers always receive notifications. */
1212 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1213 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1217 DEBUG(10,("Our printer\n"));
1219 /* build the array of change notifications */
1220 ret = build_notify2_messages(mem_ctx, prn_hnd,
1222 msg_group->num_msgs,
1228 info0.version = 0x2;
1229 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1230 info0.count = count;
1231 info0.notifies = notifies;
1233 info.info0 = &info0;
1235 status = dcerpc_spoolss_RouterReplyPrinterEx(
1236 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1238 &prn_hnd->notify.cli_hnd,
1239 prn_hnd->notify.change, /* color */
1240 prn_hnd->notify.flags,
1242 0, /* reply_type, must be 0 */
1244 if (!NT_STATUS_IS_OK(status)) {
1245 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1247 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1248 nt_errstr(status)));
1249 werr = ntstatus_to_werror(status);
1250 } else if (!W_ERROR_IS_OK(werr)) {
1251 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1253 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1256 switch (reply_result) {
1259 case PRINTER_NOTIFY_INFO_DISCARDED:
1260 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1261 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1270 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1272 struct printer_handle *p;
1273 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1274 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1278 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1282 if (!msg_group->msgs) {
1283 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1287 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1289 /* loop over all printers */
1291 for (p = printers_list; p; p = p->next) {
1292 ret = send_notify2_printer(mem_ctx, p, msg_group);
1299 DEBUG(8,("send_notify2_changes: Exit...\n"));
1303 /***********************************************************************
1304 **********************************************************************/
1306 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1309 uint32_t tv_sec, tv_usec;
1312 /* Unpack message */
1314 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1317 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1319 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1322 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1323 &msg->notify.value[0], &msg->notify.value[1]);
1325 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1326 &msg->len, &msg->notify.data);
1328 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1329 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1331 tv->tv_sec = tv_sec;
1332 tv->tv_usec = tv_usec;
1335 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1336 msg->notify.value[1]));
1338 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1343 /********************************************************************
1344 Receive a notify2 message list
1345 ********************************************************************/
1347 static void receive_notify2_message_list(struct messaging_context *msg,
1350 struct server_id server_id,
1353 size_t msg_count, i;
1354 char *buf = (char *)data->data;
1357 SPOOLSS_NOTIFY_MSG notify;
1358 SPOOLSS_NOTIFY_MSG_CTR messages;
1361 if (data->length < 4) {
1362 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1366 msg_count = IVAL(buf, 0);
1369 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1371 if (msg_count == 0) {
1372 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1376 /* initialize the container */
1378 ZERO_STRUCT( messages );
1379 notify_msg_ctr_init( &messages );
1382 * build message groups for each printer identified
1383 * in a change_notify msg. Remember that a PCN message
1384 * includes the handle returned for the srv_spoolss_replyopenprinter()
1385 * call. Therefore messages are grouped according to printer handle.
1388 for ( i=0; i<msg_count; i++ ) {
1389 struct timeval msg_tv;
1391 if (msg_ptr + 4 - buf > data->length) {
1392 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1396 msg_len = IVAL(msg_ptr,0);
1399 if (msg_ptr + msg_len - buf > data->length) {
1400 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1404 /* unpack messages */
1406 ZERO_STRUCT( notify );
1407 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1410 /* add to correct list in container */
1412 notify_msg_ctr_addmsg( &messages, ¬ify );
1414 /* free memory that might have been allocated by notify2_unpack_msg() */
1416 if ( notify.len != 0 )
1417 SAFE_FREE( notify.notify.data );
1420 /* process each group of messages */
1422 num_groups = notify_msg_ctr_numgroups( &messages );
1423 for ( i=0; i<num_groups; i++ )
1424 send_notify2_changes( &messages, i );
1429 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1430 (uint32_t)msg_count ));
1432 notify_msg_ctr_destroy( &messages );
1437 /********************************************************************
1438 Send a message to ourself about new driver being installed
1439 so we can upgrade the information for each printer bound to this
1441 ********************************************************************/
1443 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1444 struct messaging_context *msg_ctx)
1446 int len = strlen(drivername);
1451 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1454 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1455 MSG_PRINTER_DRVUPGRADE,
1456 (const uint8_t *)drivername, len+1);
1461 void srv_spoolss_cleanup(void)
1463 struct printer_session_counter *session_counter;
1465 for (session_counter = counter_list;
1466 session_counter != NULL;
1467 session_counter = counter_list) {
1468 DLIST_REMOVE(counter_list, session_counter);
1469 TALLOC_FREE(session_counter);
1473 /**********************************************************************
1474 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1475 over all printers, upgrading ones as necessary
1476 This is now *ONLY* called inside the background lpq updater. JRA.
1477 **********************************************************************/
1479 void do_drv_upgrade_printer(struct messaging_context *msg,
1482 struct server_id server_id,
1485 TALLOC_CTX *tmp_ctx;
1486 const struct auth_session_info *session_info = get_session_info_system();
1487 struct spoolss_PrinterInfo2 *pinfo2;
1489 const char *drivername;
1491 int n_services = lp_numservices();
1492 struct dcerpc_binding_handle *b = NULL;
1494 tmp_ctx = talloc_new(NULL);
1495 if (!tmp_ctx) return;
1497 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1499 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1503 DEBUG(10, ("do_drv_upgrade_printer: "
1504 "Got message for new driver [%s]\n", drivername));
1506 /* Iterate the printer list */
1508 for (snum = 0; snum < n_services; snum++) {
1509 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1513 /* ignore [printers] share */
1514 if (strequal(lp_const_servicename(snum), "printers")) {
1519 result = winreg_printer_binding_handle(tmp_ctx,
1523 if (!W_ERROR_IS_OK(result)) {
1528 result = winreg_get_printer(tmp_ctx, b,
1529 lp_const_servicename(snum),
1532 if (!W_ERROR_IS_OK(result)) {
1536 if (!pinfo2->drivername) {
1540 if (strcmp(drivername, pinfo2->drivername) != 0) {
1544 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1546 /* all we care about currently is the change_id */
1547 result = winreg_printer_update_changeid(tmp_ctx, b,
1548 pinfo2->printername);
1550 if (!W_ERROR_IS_OK(result)) {
1551 DEBUG(3, ("do_drv_upgrade_printer: "
1552 "Failed to update changeid [%s]\n",
1553 win_errstr(result)));
1559 talloc_free(tmp_ctx);
1562 /********************************************************************
1563 Update the cache for all printq's with a registered client
1565 ********************************************************************/
1567 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1569 struct printer_handle *printer = printers_list;
1572 /* loop through all printers and update the cache where
1573 a client is connected */
1575 if ((printer->printer_type == SPLHND_PRINTER) &&
1576 ((printer->notify.cli_chan != NULL) &&
1577 (printer->notify.cli_chan->active_connections > 0))) {
1578 snum = print_queue_snum(printer->sharename);
1579 print_queue_status(msg_ctx, snum, NULL, NULL);
1582 printer = printer->next;
1588 /****************************************************************
1589 _spoolss_OpenPrinter
1590 ****************************************************************/
1592 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1593 struct spoolss_OpenPrinter *r)
1595 struct spoolss_OpenPrinterEx e;
1596 struct spoolss_UserLevel1 level1;
1599 ZERO_STRUCT(level1);
1601 e.in.printername = r->in.printername;
1602 e.in.datatype = r->in.datatype;
1603 e.in.devmode_ctr = r->in.devmode_ctr;
1604 e.in.access_mask = r->in.access_mask;
1605 e.in.userlevel_ctr.level = 1;
1606 e.in.userlevel_ctr.user_info.level1 = &level1;
1608 e.out.handle = r->out.handle;
1610 werr = _spoolss_OpenPrinterEx(p, &e);
1612 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1613 /* OpenPrinterEx returns this for a bad
1614 * printer name. We must return WERR_INVALID_PRINTER_NAME
1617 werr = WERR_INVALID_PRINTER_NAME;
1623 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1624 struct spoolss_DeviceMode *orig,
1625 struct spoolss_DeviceMode **dest)
1627 struct spoolss_DeviceMode *dm;
1629 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1631 return WERR_NOT_ENOUGH_MEMORY;
1634 /* copy all values, then duplicate strings and structs */
1637 dm->devicename = talloc_strdup(dm, orig->devicename);
1638 if (!dm->devicename) {
1639 return WERR_NOT_ENOUGH_MEMORY;
1641 dm->formname = talloc_strdup(dm, orig->formname);
1642 if (!dm->formname) {
1643 return WERR_NOT_ENOUGH_MEMORY;
1645 if (orig->driverextra_data.data) {
1646 dm->driverextra_data.data =
1647 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1648 orig->driverextra_data.length);
1649 if (!dm->driverextra_data.data) {
1650 return WERR_NOT_ENOUGH_MEMORY;
1658 /****************************************************************
1659 _spoolss_OpenPrinterEx
1660 ****************************************************************/
1662 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1663 struct spoolss_OpenPrinterEx *r)
1668 struct printer_handle *Printer=NULL;
1672 if (!r->in.printername) {
1673 return WERR_INVALID_PARAMETER;
1676 if (!*r->in.printername) {
1677 return WERR_INVALID_PARAMETER;
1680 if (r->in.userlevel_ctr.level > 3) {
1681 return WERR_INVALID_PARAMETER;
1683 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1684 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1685 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1686 return WERR_INVALID_PARAMETER;
1690 * The printcap printer share inventory is updated on client
1691 * enumeration. For clients that do not perform enumeration prior to
1692 * access, such as cupssmbadd, we reinitialise the printer share
1693 * inventory on open as well.
1696 delete_and_reload_printers(server_event_context(), p->msg_ctx);
1699 /* some sanity check because you can open a printer or a print server */
1700 /* aka: \\server\printer or \\server */
1702 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1704 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1705 if (!W_ERROR_IS_OK(result)) {
1706 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1707 "for printer %s\n", r->in.printername));
1708 ZERO_STRUCTP(r->out.handle);
1712 Printer = find_printer_index_by_hnd(p, r->out.handle);
1714 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1715 "handle we created for printer %s\n", r->in.printername));
1716 close_printer_handle(p, r->out.handle);
1717 ZERO_STRUCTP(r->out.handle);
1718 return WERR_INVALID_PARAMETER;
1722 * First case: the user is opening the print server:
1724 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1725 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1727 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1728 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1729 * or if the user is listed in the smb.conf printer admin parameter.
1731 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1732 * client view printer folder, but does not show the MSAPW.
1734 * Note: this test needs code to check access rights here too. Jeremy
1735 * could you look at this?
1737 * Second case: the user is opening a printer:
1738 * NT doesn't let us connect to a printer if the connecting user
1739 * doesn't have print permission.
1741 * Third case: user is opening a Port Monitor
1742 * access checks same as opening a handle to the print server.
1745 switch (Printer->printer_type )
1748 case SPLHND_PORTMON_TCP:
1749 case SPLHND_PORTMON_LOCAL:
1750 /* Printserver handles use global struct... */
1754 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1755 r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1756 r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1759 /* Map standard access rights to object specific access rights */
1761 se_map_standard(&r->in.access_mask,
1762 &printserver_std_mapping);
1764 /* Deny any object specific bits that don't apply to print
1765 servers (i.e printer and job specific bits) */
1767 r->in.access_mask &= SEC_MASK_SPECIFIC;
1769 if (r->in.access_mask &
1770 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1771 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1772 close_printer_handle(p, r->out.handle);
1773 ZERO_STRUCTP(r->out.handle);
1774 return WERR_ACCESS_DENIED;
1777 /* Allow admin access */
1779 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1781 if (!lp_show_add_printer_wizard()) {
1782 close_printer_handle(p, r->out.handle);
1783 ZERO_STRUCTP(r->out.handle);
1784 return WERR_ACCESS_DENIED;
1787 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1788 and not a printer admin, then fail */
1790 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1791 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1792 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1793 p->session_info->security_token)) {
1794 close_printer_handle(p, r->out.handle);
1795 ZERO_STRUCTP(r->out.handle);
1796 DEBUG(3,("access DENIED as user is not root, "
1797 "has no printoperator privilege and is "
1798 "not a member of the printoperator builtin group\n"));
1799 return WERR_ACCESS_DENIED;
1802 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1806 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1809 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1810 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1814 case SPLHND_PRINTER:
1815 /* NT doesn't let us connect to a printer if the connecting user
1816 doesn't have print permission. */
1818 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1819 close_printer_handle(p, r->out.handle);
1820 ZERO_STRUCTP(r->out.handle);
1821 return WERR_INVALID_HANDLE;
1824 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1825 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1828 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1830 /* map an empty access mask to the minimum access mask */
1831 if (r->in.access_mask == 0x0)
1832 r->in.access_mask = PRINTER_ACCESS_USE;
1835 * If we are not serving the printer driver for this printer,
1836 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1837 * will keep NT clients happy --jerry
1840 if (lp_use_client_driver(snum)
1841 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1843 r->in.access_mask = PRINTER_ACCESS_USE;
1846 /* check smb.conf parameters and the the sec_desc */
1847 raddr = tsocket_address_inet_addr_string(p->remote_address,
1849 if (raddr == NULL) {
1850 return WERR_NOT_ENOUGH_MEMORY;
1853 rc = get_remote_hostname(p->remote_address,
1857 return WERR_NOT_ENOUGH_MEMORY;
1859 if (strequal(rhost, "UNKNOWN")) {
1863 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1865 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1866 ZERO_STRUCTP(r->out.handle);
1867 return WERR_ACCESS_DENIED;
1870 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1871 p->session_info->security_token, snum) ||
1872 !W_ERROR_IS_OK(print_access_check(p->session_info,
1875 r->in.access_mask))) {
1876 DEBUG(3, ("access DENIED for printer open\n"));
1877 close_printer_handle(p, r->out.handle);
1878 ZERO_STRUCTP(r->out.handle);
1879 return WERR_ACCESS_DENIED;
1882 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1883 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1884 close_printer_handle(p, r->out.handle);
1885 ZERO_STRUCTP(r->out.handle);
1886 return WERR_ACCESS_DENIED;
1889 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1890 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1892 r->in.access_mask = PRINTER_ACCESS_USE;
1894 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1895 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1897 winreg_create_printer_internal(p->mem_ctx,
1898 get_session_info_system(),
1900 lp_const_servicename(snum));
1905 /* sanity check to prevent programmer error */
1906 ZERO_STRUCTP(r->out.handle);
1907 return WERR_INVALID_HANDLE;
1910 Printer->access_granted = r->in.access_mask;
1913 * If the client sent a devmode in the OpenPrinter() call, then
1914 * save it here in case we get a job submission on this handle
1917 if ((Printer->printer_type != SPLHND_SERVER)
1918 && (r->in.devmode_ctr.devmode != NULL)) {
1919 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1926 /****************************************************************
1927 _spoolss_ClosePrinter
1928 ****************************************************************/
1930 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1931 struct spoolss_ClosePrinter *r)
1933 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1935 if (Printer && Printer->document_started) {
1936 struct spoolss_EndDocPrinter e;
1938 e.in.handle = r->in.handle;
1940 _spoolss_EndDocPrinter(p, &e);
1943 if (!close_printer_handle(p, r->in.handle))
1944 return WERR_INVALID_HANDLE;
1946 /* clear the returned printer handle. Observed behavior
1947 from Win2k server. Don't think this really matters.
1948 Previous code just copied the value of the closed
1951 ZERO_STRUCTP(r->out.handle);
1956 /****************************************************************
1957 _spoolss_DeletePrinter
1958 ****************************************************************/
1960 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1961 struct spoolss_DeletePrinter *r)
1963 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1967 if (Printer && Printer->document_started) {
1968 struct spoolss_EndDocPrinter e;
1970 e.in.handle = r->in.handle;
1972 _spoolss_EndDocPrinter(p, &e);
1975 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1976 winreg_delete_printer_key_internal(p->mem_ctx,
1977 get_session_info_system(),
1979 lp_const_servicename(snum),
1983 result = delete_printer_handle(p, r->in.handle);
1988 /*******************************************************************
1989 * static function to lookup the version id corresponding to an
1990 * long architecture string
1991 ******************************************************************/
1993 static const struct print_architecture_table_node archi_table[]= {
1995 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1996 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1997 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1998 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1999 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2000 {"Windows IA64", SPL_ARCH_IA64, 3 },
2001 {"Windows x64", SPL_ARCH_X64, 3 },
2005 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2006 SPOOLSS_DRIVER_VERSION_NT35,
2007 SPOOLSS_DRIVER_VERSION_NT4,
2008 SPOOLSS_DRIVER_VERSION_200X,
2011 static int get_version_id(const char *arch)
2015 for (i=0; archi_table[i].long_archi != NULL; i++)
2017 if (strcmp(arch, archi_table[i].long_archi) == 0)
2018 return (archi_table[i].version);
2024 /****************************************************************
2025 _spoolss_DeletePrinterDriver
2026 ****************************************************************/
2028 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2029 struct spoolss_DeletePrinterDriver *r)
2032 struct spoolss_DriverInfo8 *info = NULL;
2035 struct dcerpc_binding_handle *b;
2036 TALLOC_CTX *tmp_ctx = NULL;
2040 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2041 and not a printer admin, then fail */
2043 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2044 !security_token_has_privilege(p->session_info->security_token,
2045 SEC_PRIV_PRINT_OPERATOR)) {
2046 return WERR_ACCESS_DENIED;
2049 if (r->in.architecture == NULL || r->in.driver == NULL) {
2050 return WERR_INVALID_ENVIRONMENT;
2053 /* check that we have a valid driver name first */
2055 if ((version = get_version_id(r->in.architecture)) == -1) {
2056 return WERR_INVALID_ENVIRONMENT;
2059 tmp_ctx = talloc_new(p->mem_ctx);
2061 return WERR_NOT_ENOUGH_MEMORY;
2064 status = winreg_printer_binding_handle(tmp_ctx,
2065 get_session_info_system(),
2068 if (!W_ERROR_IS_OK(status)) {
2072 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2073 status = winreg_get_driver(tmp_ctx, b,
2074 r->in.architecture, r->in.driver,
2075 drv_cversion[i], &info);
2076 if (!W_ERROR_IS_OK(status)) {
2077 DEBUG(5, ("skipping del of driver with version %d\n",
2083 if (printer_driver_in_use(tmp_ctx, b, info)) {
2084 status = WERR_PRINTER_DRIVER_IN_USE;
2088 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2089 if (!W_ERROR_IS_OK(status)) {
2090 DEBUG(0, ("failed del of driver with version %d\n",
2095 if (found == false) {
2096 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2097 status = WERR_UNKNOWN_PRINTER_DRIVER;
2103 talloc_free(tmp_ctx);
2108 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2109 struct pipes_struct *p,
2110 struct spoolss_DeletePrinterDriverEx *r,
2111 struct dcerpc_binding_handle *b,
2112 struct spoolss_DriverInfo8 *info)
2117 if (printer_driver_in_use(mem_ctx, b, info)) {
2118 status = WERR_PRINTER_DRIVER_IN_USE;
2123 * we have a couple of cases to consider.
2124 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2125 * then the delete should fail if **any** files overlap with
2127 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2128 * non-overlapping files
2129 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2130 * are set, then do not delete any files
2131 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2134 delete_files = r->in.delete_flags
2135 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2139 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2140 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2141 status = WERR_PRINTER_DRIVER_IN_USE;
2145 * printer_driver_files_in_use() has trimmed overlapping files
2146 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2151 status = winreg_del_driver(mem_ctx, b, info, info->version);
2152 if (!W_ERROR_IS_OK(status)) {
2157 * now delete any associated files if delete_files is
2158 * true. Even if this part failes, we return succes
2159 * because the driver doesn not exist any more
2162 delete_driver_files(p->session_info, info);
2169 /****************************************************************
2170 _spoolss_DeletePrinterDriverEx
2171 ****************************************************************/
2173 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2174 struct spoolss_DeletePrinterDriverEx *r)
2176 struct spoolss_DriverInfo8 *info = NULL;
2178 struct dcerpc_binding_handle *b;
2179 TALLOC_CTX *tmp_ctx = NULL;
2183 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2184 and not a printer admin, then fail */
2186 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2187 !security_token_has_privilege(p->session_info->security_token,
2188 SEC_PRIV_PRINT_OPERATOR)) {
2189 return WERR_ACCESS_DENIED;
2192 if (r->in.architecture == NULL || r->in.driver == NULL) {
2193 return WERR_INVALID_ENVIRONMENT;
2196 /* check that we have a valid driver name first */
2197 if (get_version_id(r->in.architecture) == -1) {
2198 /* this is what NT returns */
2199 return WERR_INVALID_ENVIRONMENT;
2202 tmp_ctx = talloc_new(p->mem_ctx);
2204 return WERR_NOT_ENOUGH_MEMORY;
2207 status = winreg_printer_binding_handle(tmp_ctx,
2208 get_session_info_system(),
2211 if (!W_ERROR_IS_OK(status)) {
2215 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2216 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2217 && (drv_cversion[i] != r->in.version)) {
2221 /* check if a driver with this version exists before delete */
2222 status = winreg_get_driver(tmp_ctx, b,
2223 r->in.architecture, r->in.driver,
2224 drv_cversion[i], &info);
2225 if (!W_ERROR_IS_OK(status)) {
2226 DEBUG(5, ("skipping del of driver with version %d\n",
2232 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2233 if (!W_ERROR_IS_OK(status)) {
2234 DEBUG(0, ("failed to delete driver with version %d\n",
2239 if (found == false) {
2240 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2241 status = WERR_UNKNOWN_PRINTER_DRIVER;
2247 talloc_free(tmp_ctx);
2252 /********************************************************************
2253 GetPrinterData on a printer server Handle.
2254 ********************************************************************/
2256 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2258 enum winreg_Type *type,
2259 union spoolss_PrinterData *data)
2261 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2263 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2265 SIVAL(&data->value, 0, 0x00);
2269 if (!strcasecmp_m(value, "BeepEnabled")) {
2271 SIVAL(&data->value, 0, 0x00);
2275 if (!strcasecmp_m(value, "EventLog")) {
2277 /* formally was 0x1b */
2278 SIVAL(&data->value, 0, 0x00);
2282 if (!strcasecmp_m(value, "NetPopup")) {
2284 SIVAL(&data->value, 0, 0x00);
2288 if (!strcasecmp_m(value, "MajorVersion")) {
2291 /* Windows NT 4.0 seems to not allow uploading of drivers
2292 to a server that reports 0x3 as the MajorVersion.
2293 need to investigate more how Win2k gets around this .
2296 if (RA_WINNT == get_remote_arch()) {
2297 SIVAL(&data->value, 0, 0x02);
2299 SIVAL(&data->value, 0, 0x03);
2305 if (!strcasecmp_m(value, "MinorVersion")) {
2307 SIVAL(&data->value, 0, 0x00);
2312 * uint32_t size = 0x114
2313 * uint32_t major = 5
2314 * uint32_t minor = [0|1]
2315 * uint32_t build = [2195|2600]
2316 * extra unicode string = e.g. "Service Pack 3"
2318 if (!strcasecmp_m(value, "OSVersion")) {
2320 enum ndr_err_code ndr_err;
2321 struct spoolss_OSVersion os;
2324 * Set the default OSVersion to:
2326 * Windows Server 2003R2 SP2 (5.2.3790)
2328 * used to be Windows 2000 (5.0.2195)
2330 os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2331 "spoolss", "os_major",
2332 GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2333 os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2334 "spoolss", "os_minor",
2335 GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2336 os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2337 "spoolss", "os_build",
2338 GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2339 os.extra_string = ""; /* leave extra string empty */
2341 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2342 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2343 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2344 return WERR_GEN_FAILURE;
2347 if (DEBUGLEVEL >= 10) {
2348 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2352 data->binary = blob;
2358 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2361 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2362 W_ERROR_HAVE_NO_MEMORY(data->string);
2367 if (!strcasecmp_m(value, "Architecture")) {
2369 data->string = talloc_strdup(mem_ctx,
2370 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2371 W_ERROR_HAVE_NO_MEMORY(data->string);
2376 if (!strcasecmp_m(value, "DsPresent")) {
2379 /* only show the publish check box if we are a
2380 member of a AD domain */
2382 if (lp_security() == SEC_ADS) {
2383 SIVAL(&data->value, 0, 0x01);
2385 SIVAL(&data->value, 0, 0x00);
2390 if (!strcasecmp_m(value, "DNSMachineName")) {
2391 const char *hostname = get_mydnsfullname();
2394 return WERR_FILE_NOT_FOUND;
2398 data->string = talloc_strdup(mem_ctx, hostname);
2399 W_ERROR_HAVE_NO_MEMORY(data->string);
2406 return WERR_INVALID_PARAMETER;
2409 /****************************************************************
2410 _spoolss_GetPrinterData
2411 ****************************************************************/
2413 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2414 struct spoolss_GetPrinterData *r)
2416 struct spoolss_GetPrinterDataEx r2;
2418 r2.in.handle = r->in.handle;
2419 r2.in.key_name = "PrinterDriverData";
2420 r2.in.value_name = r->in.value_name;
2421 r2.in.offered = r->in.offered;
2422 r2.out.type = r->out.type;
2423 r2.out.data = r->out.data;
2424 r2.out.needed = r->out.needed;
2426 return _spoolss_GetPrinterDataEx(p, &r2);
2429 /*********************************************************
2430 Connect to the client machine.
2431 **********************************************************/
2433 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2434 struct sockaddr_storage *client_ss, const char *remote_machine)
2437 struct sockaddr_storage rm_addr;
2438 char addr[INET6_ADDRSTRLEN];
2440 if ( is_zero_addr(client_ss) ) {
2441 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2443 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2444 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2447 print_sockaddr(addr, sizeof(addr), &rm_addr);
2449 rm_addr = *client_ss;
2450 print_sockaddr(addr, sizeof(addr), &rm_addr);
2451 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2455 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2456 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2461 /* setup the connection */
2462 ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2463 &rm_addr, 0, "IPC$", "IPC",
2467 0, lp_client_signing());
2469 if ( !NT_STATUS_IS_OK( ret ) ) {
2470 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2475 if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2476 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2477 cli_shutdown(*pp_cli);
2482 * Ok - we have an anonymous connection to the IPC$ share.
2483 * Now start the NT Domain stuff :-).
2486 ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2487 if (!NT_STATUS_IS_OK(ret)) {
2488 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2489 remote_machine, nt_errstr(ret)));
2490 cli_shutdown(*pp_cli);
2497 /***************************************************************************
2498 Connect to the client.
2499 ****************************************************************************/
2501 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2502 uint32_t localprinter,
2503 enum winreg_Type type,
2504 struct policy_handle *handle,
2505 struct notify_back_channel **_chan,
2506 struct sockaddr_storage *client_ss,
2507 struct messaging_context *msg_ctx)
2511 struct notify_back_channel *chan;
2513 for (chan = back_channels; chan; chan = chan->next) {
2514 if (memcmp(&chan->client_address, client_ss,
2515 sizeof(struct sockaddr_storage)) == 0) {
2521 * If it's the first connection, contact the client
2522 * and connect to the IPC$ share anonymously
2525 fstring unix_printer;
2527 /* the +2 is to strip the leading 2 backslashs */
2528 fstrcpy(unix_printer, printer + 2);
2530 chan = talloc_zero(NULL, struct notify_back_channel);
2534 chan->client_address = *client_ss;
2536 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2541 DLIST_ADD(back_channels, chan);
2543 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2544 receive_notify2_message_list);
2547 if (chan->cli_pipe == NULL ||
2548 chan->cli_pipe->binding_handle == NULL) {
2549 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2550 "NULL %s for printer %s\n",
2551 chan->cli_pipe == NULL ?
2552 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2558 * Tell the specific printing tdb we want messages for this printer
2559 * by registering our PID.
2562 if (!print_notify_register_pid(snum)) {
2563 DEBUG(0, ("Failed to register our pid for printer %s\n",
2567 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2576 if (!NT_STATUS_IS_OK(status)) {
2577 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2578 result = ntstatus_to_werror(status);
2579 } else if (!W_ERROR_IS_OK(result)) {
2580 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2583 chan->active_connections++;
2586 return (W_ERROR_IS_OK(result));
2589 /****************************************************************
2590 ****************************************************************/
2592 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2593 const struct spoolss_NotifyOption *r)
2595 struct spoolss_NotifyOption *option;
2602 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2609 if (!option->count) {
2613 option->types = talloc_zero_array(option,
2614 struct spoolss_NotifyOptionType, option->count);
2615 if (!option->types) {
2616 talloc_free(option);
2620 for (i=0; i < option->count; i++) {
2621 option->types[i] = r->types[i];
2623 if (option->types[i].count) {
2624 option->types[i].fields = talloc_zero_array(option,
2625 union spoolss_Field, option->types[i].count);
2626 if (!option->types[i].fields) {
2627 talloc_free(option);
2630 for (k=0; k<option->types[i].count; k++) {
2631 option->types[i].fields[k] =
2632 r->types[i].fields[k];
2640 /****************************************************************
2641 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2643 * before replying OK: status=0 a rpc call is made to the workstation
2644 * asking ReplyOpenPrinter
2646 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2647 * called from api_spoolss_rffpcnex
2648 ****************************************************************/
2650 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2651 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2654 struct spoolss_NotifyOption *option = r->in.notify_options;
2655 struct sockaddr_storage client_ss;
2658 /* store the notify value in the printer struct */
2660 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2663 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2664 "Invalid handle (%s:%u:%u).\n",
2665 OUR_HANDLE(r->in.handle)));
2666 return WERR_INVALID_HANDLE;
2669 Printer->notify.flags = r->in.flags;
2670 Printer->notify.options = r->in.options;
2671 Printer->notify.printerlocal = r->in.printer_local;
2672 Printer->notify.msg_ctx = p->msg_ctx;
2674 TALLOC_FREE(Printer->notify.option);
2675 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2677 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2679 /* Connect to the client machine and send a ReplyOpenPrinter */
2681 if ( Printer->printer_type == SPLHND_SERVER)
2683 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2684 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2685 return WERR_INVALID_HANDLE;
2687 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2688 "remote_address is %s\n",
2689 tsocket_address_string(p->remote_address, p->mem_ctx)));
2691 if (!lp_print_notify_backchannel(snum)) {
2692 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2693 "backchannel disabled\n"));
2694 return WERR_RPC_S_SERVER_UNAVAILABLE;
2697 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2698 (struct sockaddr *) &client_ss,
2699 sizeof(struct sockaddr_storage));
2700 if (client_len < 0) {
2701 return WERR_NOT_ENOUGH_MEMORY;
2704 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2705 Printer->notify.printerlocal, REG_SZ,
2706 &Printer->notify.cli_hnd,
2707 &Printer->notify.cli_chan,
2708 &client_ss, p->msg_ctx)) {
2709 return WERR_RPC_S_SERVER_UNAVAILABLE;
2715 /*******************************************************************
2716 * fill a notify_info_data with the servername
2717 ********************************************************************/
2719 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2721 struct spoolss_Notify *data,
2722 print_queue_struct *queue,
2723 struct spoolss_PrinterInfo2 *pinfo2,
2724 TALLOC_CTX *mem_ctx)
2726 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2729 /*******************************************************************
2730 * fill a notify_info_data with the printername (not including the servername).
2731 ********************************************************************/
2733 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2735 struct spoolss_Notify *data,
2736 print_queue_struct *queue,
2737 struct spoolss_PrinterInfo2 *pinfo2,
2738 TALLOC_CTX *mem_ctx)
2740 /* the notify name should not contain the \\server\ part */
2741 const char *p = strrchr(pinfo2->printername, '\\');
2744 p = pinfo2->printername;
2749 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2752 /*******************************************************************
2753 * fill a notify_info_data with the servicename
2754 ********************************************************************/
2756 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2758 struct spoolss_Notify *data,
2759 print_queue_struct *queue,
2760 struct spoolss_PrinterInfo2 *pinfo2,
2761 TALLOC_CTX *mem_ctx)
2763 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2766 /*******************************************************************
2767 * fill a notify_info_data with the port name
2768 ********************************************************************/
2770 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2772 struct spoolss_Notify *data,
2773 print_queue_struct *queue,
2774 struct spoolss_PrinterInfo2 *pinfo2,
2775 TALLOC_CTX *mem_ctx)
2777 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2780 /*******************************************************************
2781 * fill a notify_info_data with the printername
2782 * but it doesn't exist, have to see what to do
2783 ********************************************************************/
2785 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2787 struct spoolss_Notify *data,
2788 print_queue_struct *queue,
2789 struct spoolss_PrinterInfo2 *pinfo2,
2790 TALLOC_CTX *mem_ctx)
2792 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2795 /*******************************************************************
2796 * fill a notify_info_data with the comment
2797 ********************************************************************/
2799 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2801 struct spoolss_Notify *data,
2802 print_queue_struct *queue,
2803 struct spoolss_PrinterInfo2 *pinfo2,
2804 TALLOC_CTX *mem_ctx)
2808 if (*pinfo2->comment == '\0') {
2809 p = lp_comment(talloc_tos(), snum);
2811 p = pinfo2->comment;
2814 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2817 /*******************************************************************
2818 * fill a notify_info_data with the comment
2819 * location = "Room 1, floor 2, building 3"
2820 ********************************************************************/
2822 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2824 struct spoolss_Notify *data,
2825 print_queue_struct *queue,
2826 struct spoolss_PrinterInfo2 *pinfo2,
2827 TALLOC_CTX *mem_ctx)
2829 const char *loc = pinfo2->location;
2832 status = printer_list_get_printer(mem_ctx,
2837 if (NT_STATUS_IS_OK(status)) {
2839 loc = pinfo2->location;
2843 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2846 /*******************************************************************
2847 * fill a notify_info_data with the device mode
2848 * jfm:xxxx don't to it for know but that's a real problem !!!
2849 ********************************************************************/
2851 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2853 struct spoolss_Notify *data,
2854 print_queue_struct *queue,
2855 struct spoolss_PrinterInfo2 *pinfo2,
2856 TALLOC_CTX *mem_ctx)
2858 /* for a dummy implementation we have to zero the fields */
2859 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2862 /*******************************************************************
2863 * fill a notify_info_data with the separator file name
2864 ********************************************************************/
2866 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2868 struct spoolss_Notify *data,
2869 print_queue_struct *queue,
2870 struct spoolss_PrinterInfo2 *pinfo2,
2871 TALLOC_CTX *mem_ctx)
2873 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2876 /*******************************************************************
2877 * fill a notify_info_data with the print processor
2878 * jfm:xxxx return always winprint to indicate we don't do anything to it
2879 ********************************************************************/
2881 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2883 struct spoolss_Notify *data,
2884 print_queue_struct *queue,
2885 struct spoolss_PrinterInfo2 *pinfo2,
2886 TALLOC_CTX *mem_ctx)
2888 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2891 /*******************************************************************
2892 * fill a notify_info_data with the print processor options
2893 * jfm:xxxx send an empty string
2894 ********************************************************************/
2896 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2898 struct spoolss_Notify *data,
2899 print_queue_struct *queue,
2900 struct spoolss_PrinterInfo2 *pinfo2,
2901 TALLOC_CTX *mem_ctx)
2903 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2906 /*******************************************************************
2907 * fill a notify_info_data with the data type
2908 * jfm:xxxx always send RAW as data type
2909 ********************************************************************/
2911 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2913 struct spoolss_Notify *data,
2914 print_queue_struct *queue,
2915 struct spoolss_PrinterInfo2 *pinfo2,
2916 TALLOC_CTX *mem_ctx)
2918 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2921 /*******************************************************************
2922 * fill a notify_info_data with the security descriptor
2923 * jfm:xxxx send an null pointer to say no security desc
2924 * have to implement security before !
2925 ********************************************************************/
2927 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2929 struct spoolss_Notify *data,
2930 print_queue_struct *queue,
2931 struct spoolss_PrinterInfo2 *pinfo2,
2932 TALLOC_CTX *mem_ctx)
2934 if (pinfo2->secdesc == NULL) {
2935 data->data.sd.sd = NULL;
2937 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2940 data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2944 /*******************************************************************
2945 * fill a notify_info_data with the attributes
2946 * jfm:xxxx a samba printer is always shared
2947 ********************************************************************/
2949 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2951 struct spoolss_Notify *data,
2952 print_queue_struct *queue,
2953 struct spoolss_PrinterInfo2 *pinfo2,
2954 TALLOC_CTX *mem_ctx)
2956 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2959 /*******************************************************************
2960 * fill a notify_info_data with the priority
2961 ********************************************************************/
2963 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2965 struct spoolss_Notify *data,
2966 print_queue_struct *queue,
2967 struct spoolss_PrinterInfo2 *pinfo2,
2968 TALLOC_CTX *mem_ctx)
2970 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2973 /*******************************************************************
2974 * fill a notify_info_data with the default priority
2975 ********************************************************************/
2977 static void spoolss_notify_default_priority(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->defaultpriority);
2987 /*******************************************************************
2988 * fill a notify_info_data with the start time
2989 ********************************************************************/
2991 static void spoolss_notify_start_time(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->starttime);
3001 /*******************************************************************
3002 * fill a notify_info_data with the until time
3003 ********************************************************************/
3005 static void spoolss_notify_until_time(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->untiltime);
3015 /*******************************************************************
3016 * fill a notify_info_data with the status
3017 ********************************************************************/
3019 static void spoolss_notify_status(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 print_status_struct status;
3028 print_queue_length(msg_ctx, snum, &status);
3029 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3032 /*******************************************************************
3033 * fill a notify_info_data with the number of jobs queued
3034 ********************************************************************/
3036 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3038 struct spoolss_Notify *data,
3039 print_queue_struct *queue,
3040 struct spoolss_PrinterInfo2 *pinfo2,
3041 TALLOC_CTX *mem_ctx)
3043 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3044 data, print_queue_length(msg_ctx, snum, NULL));
3047 /*******************************************************************
3048 * fill a notify_info_data with the average ppm
3049 ********************************************************************/
3051 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3053 struct spoolss_Notify *data,
3054 print_queue_struct *queue,
3055 struct spoolss_PrinterInfo2 *pinfo2,
3056 TALLOC_CTX *mem_ctx)
3058 /* always respond 8 pages per minutes */
3059 /* a little hard ! */
3060 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3063 /*******************************************************************
3064 * fill a notify_info_data with username
3065 ********************************************************************/
3067 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3069 struct spoolss_Notify *data,
3070 print_queue_struct *queue,
3071 struct spoolss_PrinterInfo2 *pinfo2,
3072 TALLOC_CTX *mem_ctx)
3074 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3083 struct spoolss_Notify *data,
3084 print_queue_struct *queue,
3085 struct spoolss_PrinterInfo2 *pinfo2,
3086 TALLOC_CTX *mem_ctx)
3088 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3091 /*******************************************************************
3092 * fill a notify_info_data with job name
3093 ********************************************************************/
3095 static void spoolss_notify_job_name(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_file);
3105 /*******************************************************************
3106 * fill a notify_info_data with job status
3107 ********************************************************************/
3109 static void spoolss_notify_job_status_string(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)
3117 * Now we're returning job status codes we just return a "" here. JRA.
3122 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3125 switch (queue->status) {
3130 p = ""; /* NT provides the paused string */
3139 #endif /* NO LONGER NEEDED. */
3141 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3144 /*******************************************************************
3145 * fill a notify_info_data with job time
3146 ********************************************************************/
3148 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3150 struct spoolss_Notify *data,
3151 print_queue_struct *queue,
3152 struct spoolss_PrinterInfo2 *pinfo2,
3153 TALLOC_CTX *mem_ctx)
3155 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3158 /*******************************************************************
3159 * fill a notify_info_data with job size
3160 ********************************************************************/
3162 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3164 struct spoolss_Notify *data,
3165 print_queue_struct *queue,
3166 struct spoolss_PrinterInfo2 *pinfo2,
3167 TALLOC_CTX *mem_ctx)
3169 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3172 /*******************************************************************
3173 * fill a notify_info_data with page info
3174 ********************************************************************/
3175 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3177 struct spoolss_Notify *data,
3178 print_queue_struct *queue,
3179 struct spoolss_PrinterInfo2 *pinfo2,
3180 TALLOC_CTX *mem_ctx)
3182 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3185 /*******************************************************************
3186 * fill a notify_info_data with pages printed info.
3187 ********************************************************************/
3188 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3190 struct spoolss_Notify *data,
3191 print_queue_struct *queue,
3192 struct spoolss_PrinterInfo2 *pinfo2,
3193 TALLOC_CTX *mem_ctx)
3195 /* Add code when back-end tracks this */
3196 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3199 /*******************************************************************
3200 Fill a notify_info_data with job position.
3201 ********************************************************************/
3203 static void spoolss_notify_job_position(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->sysjob);
3213 /*******************************************************************
3214 Fill a notify_info_data with submitted time.
3215 ********************************************************************/
3217 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 struct spoolss_PrinterInfo2 *pinfo2,
3222 TALLOC_CTX *mem_ctx)
3224 data->data.string.string = NULL;
3225 data->data.string.size = 0;
3227 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3228 &data->data.string.string,
3229 &data->data.string.size);
3233 struct s_notify_info_data_table
3235 enum spoolss_NotifyType type;
3238 enum spoolss_NotifyTable variable_type;
3239 void (*fn) (struct messaging_context *msg_ctx,
3240 int snum, struct spoolss_Notify *data,
3241 print_queue_struct *queue,
3242 struct spoolss_PrinterInfo2 *pinfo2,
3243 TALLOC_CTX *mem_ctx);
3246 /* A table describing the various print notification constants and
3247 whether the notification data is a pointer to a variable sized
3248 buffer, a one value uint32_t or a two value uint32_t. */
3250 static const struct s_notify_info_data_table notify_info_data_table[] =
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3303 /*******************************************************************
3304 Return the variable_type of info_data structure.
3305 ********************************************************************/
3307 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3312 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3313 if ( (notify_info_data_table[i].type == type) &&
3314 (notify_info_data_table[i].field == field) ) {
3315 return notify_info_data_table[i].variable_type;
3319 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3321 return (enum spoolss_NotifyTable) 0;
3324 /****************************************************************************
3325 ****************************************************************************/
3327 static bool search_notify(enum spoolss_NotifyType type,
3333 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3334 if (notify_info_data_table[i].type == type &&
3335 notify_info_data_table[i].field == field &&
3336 notify_info_data_table[i].fn != NULL) {
3345 /****************************************************************************
3346 ****************************************************************************/
3348 static void construct_info_data(struct spoolss_Notify *info_data,
3349 enum spoolss_NotifyType type,
3350 uint16_t field, int id)
3352 info_data->type = type;
3353 info_data->field.field = field;
3354 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3355 info_data->job_id = id;
3358 /*******************************************************************
3360 * fill a notify_info struct with info asked
3362 ********************************************************************/
3364 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3365 struct printer_handle *print_hnd,
3366 struct spoolss_NotifyInfo *info,
3367 struct spoolss_PrinterInfo2 *pinfo2,
3369 const struct spoolss_NotifyOptionType *option_type,
3371 TALLOC_CTX *mem_ctx)
3374 enum spoolss_NotifyType type;
3377 struct spoolss_Notify *current_data;
3379 type = option_type->type;
3381 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3382 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3383 option_type->count, lp_servicename(talloc_tos(), snum)));
3385 for(field_num=0; field_num < option_type->count; field_num++) {
3386 field = option_type->fields[field_num].field;
3388 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3390 if (!search_notify(type, field, &j) )
3393 info->notifies = talloc_realloc(info, info->notifies,
3394 struct spoolss_Notify,
3396 if (info->notifies == NULL) {
3397 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3401 current_data = &info->notifies[info->count];
3403 construct_info_data(current_data, type, field, id);
3405 DEBUG(10, ("construct_notify_printer_info: "
3406 "calling [%s] snum=%d printername=[%s])\n",
3407 notify_info_data_table[j].name, snum,
3408 pinfo2->printername));
3410 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3411 NULL, pinfo2, mem_ctx);
3419 /*******************************************************************
3421 * fill a notify_info struct with info asked
3423 ********************************************************************/
3425 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3426 print_queue_struct *queue,
3427 struct spoolss_NotifyInfo *info,
3428 struct spoolss_PrinterInfo2 *pinfo2,
3430 const struct spoolss_NotifyOptionType *option_type,
3432 TALLOC_CTX *mem_ctx)
3435 enum spoolss_NotifyType type;
3437 struct spoolss_Notify *current_data;
3439 DEBUG(4,("construct_notify_jobs_info\n"));
3441 type = option_type->type;
3443 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3444 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3445 option_type->count));
3447 for(field_num=0; field_num<option_type->count; field_num++) {
3448 field = option_type->fields[field_num].field;
3450 if (!search_notify(type, field, &j) )
3453 info->notifies = talloc_realloc(info, info->notifies,
3454 struct spoolss_Notify,
3456 if (info->notifies == NULL) {
3457 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3461 current_data=&(info->notifies[info->count]);
3463 construct_info_data(current_data, type, field, id);
3464 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3465 queue, pinfo2, mem_ctx);
3473 * JFM: The enumeration is not that simple, it's even non obvious.
3475 * let's take an example: I want to monitor the PRINTER SERVER for
3476 * the printer's name and the number of jobs currently queued.
3477 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3478 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3480 * I have 3 printers on the back of my server.
3482 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3485 * 1 printer 1 name 1
3486 * 2 printer 1 cjob 1
3487 * 3 printer 2 name 2
3488 * 4 printer 2 cjob 2
3489 * 5 printer 3 name 3
3490 * 6 printer 3 name 3
3492 * that's the print server case, the printer case is even worse.
3495 /*******************************************************************
3497 * enumerate all printers on the printserver
3498 * fill a notify_info struct with info asked
3500 ********************************************************************/
3502 static WERROR printserver_notify_info(struct pipes_struct *p,
3503 struct policy_handle *hnd,
3504 struct spoolss_NotifyInfo *info,
3505 TALLOC_CTX *mem_ctx)
3508 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3509 int n_services=lp_numservices();
3511 struct spoolss_NotifyOption *option;
3512 struct spoolss_NotifyOptionType option_type;
3513 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3516 DEBUG(4,("printserver_notify_info\n"));
3519 return WERR_INVALID_HANDLE;
3521 option = Printer->notify.option;
3524 info->notifies = NULL;
3527 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3528 sending a ffpcn() request first */
3531 return WERR_INVALID_HANDLE;
3533 for (i=0; i<option->count; i++) {
3534 option_type = option->types[i];
3536 if (option_type.type != PRINTER_NOTIFY_TYPE)
3539 for (snum = 0; snum < n_services; snum++) {
3540 if (!lp_browseable(snum) ||
3541 !lp_snum_ok(snum) ||
3542 !lp_printable(snum)) {
3543 continue; /* skip */
3546 /* Maybe we should use the SYSTEM session_info here... */
3547 result = winreg_get_printer_internal(mem_ctx,
3548 get_session_info_system(),
3550 lp_servicename(talloc_tos(), snum),
3552 if (!W_ERROR_IS_OK(result)) {
3553 DEBUG(4, ("printserver_notify_info: "
3554 "Failed to get printer [%s]\n",
3555 lp_servicename(talloc_tos(), snum)));
3560 construct_notify_printer_info(p->msg_ctx,
3566 TALLOC_FREE(pinfo2);
3572 * Debugging information, don't delete.
3575 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3576 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3577 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3579 for (i=0; i<info->count; i++) {
3580 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3581 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3582 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3589 /*******************************************************************
3591 * fill a notify_info struct with info asked
3593 ********************************************************************/
3595 static WERROR printer_notify_info(struct pipes_struct *p,
3596 struct policy_handle *hnd,
3597 struct spoolss_NotifyInfo *info,
3598 TALLOC_CTX *mem_ctx)
3601 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3604 struct spoolss_NotifyOption *option;
3605 struct spoolss_NotifyOptionType option_type;
3607 print_queue_struct *queue=NULL;
3608 print_status_struct status;
3609 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3611 struct tdb_print_db *pdb;
3613 DEBUG(4,("printer_notify_info\n"));
3616 return WERR_INVALID_HANDLE;
3618 option = Printer->notify.option;
3622 info->notifies = NULL;
3625 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3626 sending a ffpcn() request first */
3629 return WERR_INVALID_HANDLE;
3631 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3632 return WERR_INVALID_HANDLE;
3635 pdb = get_print_db_byname(Printer->sharename);
3637 return WERR_INVALID_HANDLE;
3640 /* Maybe we should use the SYSTEM session_info here... */
3641 result = winreg_get_printer_internal(mem_ctx,
3642 get_session_info_system(),
3644 lp_servicename(talloc_tos(), snum), &pinfo2);
3645 if (!W_ERROR_IS_OK(result)) {
3646 result = WERR_INVALID_HANDLE;
3651 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3652 * correct servername.
3654 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3655 if (pinfo2->servername == NULL) {
3656 result = WERR_NOT_ENOUGH_MEMORY;
3660 for (i = 0; i < option->count; i++) {
3661 option_type = option->types[i];
3663 switch (option_type.type) {
3664 case PRINTER_NOTIFY_TYPE:
3665 if (construct_notify_printer_info(p->msg_ctx,
3674 case JOB_NOTIFY_TYPE:
3676 count = print_queue_status(p->msg_ctx, snum, &queue,
3679 for (j = 0; j < count; j++) {
3681 jobid = sysjob_to_jobid_pdb(pdb,
3683 if (jobid == (uint32_t)-1) {
3684 DEBUG(2, ("ignoring untracked job %d\n",
3688 /* FIXME check return value */
3689 construct_notify_jobs_info(p->msg_ctx,
3703 * Debugging information, don't delete.
3706 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3707 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3708 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3710 for (i=0; i<info->count; i++) {
3711 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3712 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3713 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3717 talloc_free(pinfo2);
3720 release_print_db(pdb);
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_INVALID_HANDLE;
3736 /* we always have a spoolss_NotifyInfo struct */
3737 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3739 result = WERR_NOT_ENOUGH_MEMORY;
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_session_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;
3852 int os_major, os_minor, os_build;
3853 const char *architecture;
3854 uint32_t processor_architecture, processor_type;
3856 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3857 if (!W_ERROR_IS_OK(result)) {
3862 r->servername = talloc_strdup(mem_ctx, servername);
3863 W_ERROR_HAVE_NO_MEMORY(r->servername);
3865 r->servername = NULL;
3868 count = print_queue_length(msg_ctx, snum, &status);
3870 /* check if we already have a counter for this printer */
3871 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3872 if (session_counter->snum == snum)
3876 /* it's the first time, add it to the list */
3877 if (session_counter == NULL) {
3878 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3879 W_ERROR_HAVE_NO_MEMORY(session_counter);
3880 session_counter->snum = snum;
3881 session_counter->counter = 0;
3882 DLIST_ADD(counter_list, session_counter);
3886 session_counter->counter++;
3892 get_startup_time(&setuptime);
3893 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3896 * the global_counter should be stored in a TDB as it's common to all the clients
3897 * and should be zeroed on samba startup
3899 r->global_counter = session_counter->counter;
3902 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3903 os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3904 "spoolss", "os_major",
3905 GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3906 os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3907 "spoolss", "os_minor",
3908 GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3909 os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3910 "spoolss", "os_build",
3911 GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3913 SCVAL(&r->version, 0, os_major);
3914 SCVAL(&r->version, 1, os_minor);
3915 SSVAL(&r->version, 2, os_build);
3917 architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3920 GLOBAL_SPOOLSS_ARCHITECTURE);
3922 if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3923 processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3924 processor_type = PROCESSOR_AMD_X8664;
3926 processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3927 processor_type = PROCESSOR_INTEL_PENTIUM;
3930 r->free_build = SPOOLSS_RELEASE_BUILD;
3932 r->max_spooling = 0;
3933 r->session_counter = session_counter->counter;
3934 r->num_error_out_of_paper = 0x0;
3935 r->num_error_not_ready = 0x0; /* number of print failure */
3937 r->number_of_processors = 0x1;
3938 r->processor_type = processor_type;
3939 r->high_part_total_bytes = 0x0;
3941 /* ChangeID in milliseconds*/
3942 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3943 info2->sharename, &r->change_id);
3945 r->last_error = WERR_OK;
3946 r->status = nt_printq_status(status.status);
3947 r->enumerate_network_printers = 0x0;
3948 r->c_setprinter = 0x0;
3949 r->processor_architecture = processor_architecture;
3950 r->processor_level = 0x6; /* 6 ???*/
3959 /********************************************************************
3960 * construct_printer_info1
3961 * fill a spoolss_PrinterInfo1 struct
3962 ********************************************************************/
3964 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3965 const struct spoolss_PrinterInfo2 *info2,
3967 const char *servername,
3968 struct spoolss_PrinterInfo1 *r,
3975 if (info2->comment == NULL || info2->comment[0] == '\0') {
3976 r->comment = lp_comment(mem_ctx, snum);
3978 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3980 W_ERROR_HAVE_NO_MEMORY(r->comment);
3982 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3983 if (!W_ERROR_IS_OK(result)) {
3987 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3991 W_ERROR_HAVE_NO_MEMORY(r->description);
3996 /********************************************************************
3997 * construct_printer_info2
3998 * fill a spoolss_PrinterInfo2 struct
3999 ********************************************************************/
4001 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4002 struct messaging_context *msg_ctx,
4003 const struct spoolss_PrinterInfo2 *info2,
4004 const char *servername,
4005 struct spoolss_PrinterInfo2 *r,
4009 print_status_struct status;
4012 count = print_queue_length(msg_ctx, snum, &status);
4015 r->servername = talloc_strdup(mem_ctx, servername);
4016 W_ERROR_HAVE_NO_MEMORY(r->servername);
4018 r->servername = NULL;
4021 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4022 if (!W_ERROR_IS_OK(result)) {
4026 r->sharename = lp_servicename(mem_ctx, snum);
4027 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4028 r->portname = talloc_strdup(mem_ctx, info2->portname);
4029 W_ERROR_HAVE_NO_MEMORY(r->portname);
4030 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4031 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4033 if (info2->comment[0] == '\0') {
4034 r->comment = lp_comment(mem_ctx, snum);
4036 r->comment = talloc_strdup(mem_ctx, info2->comment);
4038 W_ERROR_HAVE_NO_MEMORY(r->comment);
4040 r->location = talloc_strdup(mem_ctx, info2->location);
4041 if (info2->location[0] == '\0') {
4042 const char *loc = NULL;
4045 nt_status = printer_list_get_printer(mem_ctx,
4050 if (NT_STATUS_IS_OK(nt_status)) {
4052 r->location = talloc_strdup(mem_ctx, loc);
4056 W_ERROR_HAVE_NO_MEMORY(r->location);
4058 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4059 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4060 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4061 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4062 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4063 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4064 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4065 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4067 r->attributes = info2->attributes;
4069 r->priority = info2->priority;
4070 r->defaultpriority = info2->defaultpriority;
4071 r->starttime = info2->starttime;
4072 r->untiltime = info2->untiltime;
4073 r->status = nt_printq_status(status.status);
4075 r->averageppm = info2->averageppm;
4077 if (info2->devmode != NULL) {
4078 result = copy_devicemode(mem_ctx,
4081 if (!W_ERROR_IS_OK(result)) {
4084 } else if (lp_default_devmode(snum)) {
4085 result = spoolss_create_default_devmode(mem_ctx,
4088 if (!W_ERROR_IS_OK(result)) {
4093 DEBUG(8,("Returning NULL Devicemode!\n"));
4096 compose_devicemode_devicename(r->devmode, r->printername);
4100 if (info2->secdesc != NULL) {
4101 /* don't use talloc_steal() here unless you do a deep steal of all
4102 the SEC_DESC members */
4104 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4105 if (r->secdesc == NULL) {
4106 return WERR_NOT_ENOUGH_MEMORY;
4113 /********************************************************************
4114 * construct_printer_info3
4115 * fill a spoolss_PrinterInfo3 struct
4116 ********************************************************************/
4118 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4119 const struct spoolss_PrinterInfo2 *info2,
4120 const char *servername,
4121 struct spoolss_PrinterInfo3 *r,
4124 /* These are the components of the SD we are returning. */
4126 if (info2->secdesc != NULL) {
4127 /* don't use talloc_steal() here unless you do a deep steal of all
4128 the SEC_DESC members */
4130 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4131 if (r->secdesc == NULL) {
4132 return WERR_NOT_ENOUGH_MEMORY;
4139 /********************************************************************
4140 * construct_printer_info4
4141 * fill a spoolss_PrinterInfo4 struct
4142 ********************************************************************/
4144 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4145 const struct spoolss_PrinterInfo2 *info2,
4146 const char *servername,
4147 struct spoolss_PrinterInfo4 *r,
4152 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4153 if (!W_ERROR_IS_OK(result)) {
4158 r->servername = talloc_strdup(mem_ctx, servername);
4159 W_ERROR_HAVE_NO_MEMORY(r->servername);
4161 r->servername = NULL;
4164 r->attributes = info2->attributes;
4169 /********************************************************************
4170 * construct_printer_info5
4171 * fill a spoolss_PrinterInfo5 struct
4172 ********************************************************************/
4174 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4175 const struct spoolss_PrinterInfo2 *info2,
4176 const char *servername,
4177 struct spoolss_PrinterInfo5 *r,
4182 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4183 if (!W_ERROR_IS_OK(result)) {
4187 r->portname = talloc_strdup(mem_ctx, info2->portname);
4188 W_ERROR_HAVE_NO_MEMORY(r->portname);
4190 r->attributes = info2->attributes;
4193 * These two are not used by NT+ according to MSDN. However the values
4194 * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4196 r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4197 r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4202 /********************************************************************
4203 * construct_printer_info_6
4204 * fill a spoolss_PrinterInfo6 struct
4205 ********************************************************************/
4207 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4208 struct messaging_context *msg_ctx,
4209 const struct spoolss_PrinterInfo2 *info2,
4210 const char *servername,
4211 struct spoolss_PrinterInfo6 *r,
4214 print_status_struct status;
4216 print_queue_length(msg_ctx, snum, &status);
4218 r->status = nt_printq_status(status.status);
4223 /********************************************************************
4224 * construct_printer_info7
4225 * fill a spoolss_PrinterInfo7 struct
4226 ********************************************************************/
4228 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4229 struct messaging_context *msg_ctx,
4230 const char *servername,
4231 struct spoolss_PrinterInfo7 *r,
4234 const struct auth_session_info *session_info;
4235 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4238 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4239 if (tmp_ctx == NULL) {
4240 return WERR_NOT_ENOUGH_MEMORY;
4243 session_info = get_session_info_system();
4244 SMB_ASSERT(session_info != NULL);
4246 printer = lp_servicename(tmp_ctx, snum);
4247 if (printer == NULL) {
4248 DEBUG(0, ("invalid printer snum %d\n", snum));
4249 werr = WERR_INVALID_PARAMETER;
4253 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4254 servername, printer, &pinfo2)) {
4257 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4259 if (!W_ERROR_IS_OK(werr)) {
4261 * If we do not have a GUID entry in the registry, then
4262 * try to retrieve it from AD and store it now.
4264 werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4266 if (!W_ERROR_IS_OK(werr)) {
4267 DBG_NOTICE("Failed to retrieve GUID for "
4268 "printer [%s] from AD - %s\n",
4271 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4273 * If we did not find it in AD, then it
4274 * is unpublished and we should reflect
4275 * this in the registry and return
4278 DBG_WARNING("Unpublish printer [%s]\n",
4280 nt_printer_publish(tmp_ctx,
4285 r->guid = talloc_strdup(mem_ctx, "");
4286 r->action = DSPRINT_UNPUBLISH;
4288 if (r->guid == NULL) {
4289 werr = WERR_NOT_ENOUGH_MEMORY;
4297 werr = nt_printer_guid_store(msg_ctx, printer, guid);
4298 if (!W_ERROR_IS_OK(werr)) {
4299 DEBUG(3, ("failed to store printer %s guid\n",
4304 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4305 guidstr = GUID_string2(mem_ctx, &guid);
4306 if (guidstr == NULL) {
4307 werr = WERR_NOT_ENOUGH_MEMORY;
4310 /* Convert GUID string to uppercase otherwise printers
4312 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4313 r->action = DSPRINT_PUBLISH;
4315 TALLOC_FREE(guidstr);
4317 r->guid = talloc_strdup(mem_ctx, "");
4318 r->action = DSPRINT_UNPUBLISH;
4320 if (r->guid == NULL) {
4321 werr = WERR_NOT_ENOUGH_MEMORY;
4327 talloc_free(tmp_ctx);
4331 /********************************************************************
4332 * construct_printer_info8
4333 * fill a spoolss_PrinterInfo8 struct
4334 ********************************************************************/
4336 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4337 const struct spoolss_PrinterInfo2 *info2,
4338 const char *servername,
4339 struct spoolss_DeviceModeInfo *r,
4343 const char *printername;
4345 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4346 if (!W_ERROR_IS_OK(result)) {
4350 if (info2->devmode != NULL) {
4351 result = copy_devicemode(mem_ctx,
4354 if (!W_ERROR_IS_OK(result)) {
4357 } else if (lp_default_devmode(snum)) {
4358 result = spoolss_create_default_devmode(mem_ctx,
4361 if (!W_ERROR_IS_OK(result)) {
4366 DEBUG(8,("Returning NULL Devicemode!\n"));
4369 compose_devicemode_devicename(r->devmode, printername);
4374 /********************************************************************
4375 Spoolss_enumprinters.
4376 ********************************************************************/
4378 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4379 const struct auth_session_info *session_info,
4380 struct messaging_context *msg_ctx,
4381 const char *servername,
4384 union spoolss_PrinterInfo **info_p,
4389 union spoolss_PrinterInfo *info = NULL;
4391 WERROR result = WERR_OK;
4392 struct dcerpc_binding_handle *b = NULL;
4393 TALLOC_CTX *tmp_ctx = NULL;
4395 tmp_ctx = talloc_new(mem_ctx);
4397 return WERR_NOT_ENOUGH_MEMORY;
4401 * printer shares are updated on client enumeration. The background
4402 * printer process updates printer_list.tdb at regular intervals.
4405 delete_and_reload_printers(server_event_context(), msg_ctx);
4408 n_services = lp_numservices();
4412 for (snum = 0; snum < n_services; snum++) {
4414 const char *printer;
4415 struct spoolss_PrinterInfo2 *info2;
4417 if (!snum_is_shared_printer(snum)) {
4421 printer = lp_const_servicename(snum);
4423 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4427 result = winreg_printer_binding_handle(tmp_ctx,
4431 if (!W_ERROR_IS_OK(result)) {
4436 result = winreg_create_printer(tmp_ctx, b,
4438 if (!W_ERROR_IS_OK(result)) {
4442 info = talloc_realloc(tmp_ctx, info,
4443 union spoolss_PrinterInfo,
4446 result = WERR_NOT_ENOUGH_MEMORY;
4450 result = winreg_get_printer(tmp_ctx, b,
4452 if (!W_ERROR_IS_OK(result)) {
4458 result = construct_printer_info0(info, session_info,
4461 &info[count].info0, snum);
4464 result = construct_printer_info1(info, info2, flags,
4466 &info[count].info1, snum);
4469 result = construct_printer_info2(info, msg_ctx, info2,
4471 &info[count].info2, snum);
4474 result = construct_printer_info4(info, info2,
4476 &info[count].info4, snum);
4479 result = construct_printer_info5(info, info2,
4481 &info[count].info5, snum);
4485 result = WERR_INVALID_LEVEL;
4489 if (!W_ERROR_IS_OK(result)) {
4497 if (W_ERROR_IS_OK(result)) {
4498 *info_p = talloc_move(mem_ctx, &info);
4502 talloc_free(tmp_ctx);
4507 /********************************************************************
4508 * handle enumeration of printers at level 0
4509 ********************************************************************/
4511 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4512 const struct auth_session_info *session_info,
4513 struct messaging_context *msg_ctx,
4515 const char *servername,
4516 union spoolss_PrinterInfo **info,
4519 DEBUG(4,("enum_all_printers_info_0\n"));
4521 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4522 servername, 0, flags, info, count);
4526 /********************************************************************
4527 ********************************************************************/
4529 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4530 const struct auth_session_info *session_info,
4531 struct messaging_context *msg_ctx,
4532 const char *servername,
4534 union spoolss_PrinterInfo **info,
4537 DEBUG(4,("enum_all_printers_info_1\n"));
4539 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4540 servername, 1, flags, info, count);
4543 /********************************************************************
4544 enum_all_printers_info_1_local.
4545 *********************************************************************/
4547 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4548 const struct auth_session_info *session_info,
4549 struct messaging_context *msg_ctx,
4550 const char *servername,
4551 union spoolss_PrinterInfo **info,
4554 DEBUG(4,("enum_all_printers_info_1_local\n"));
4556 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4557 servername, PRINTER_ENUM_ICON8, info, count);
4560 /********************************************************************
4561 enum_all_printers_info_1_name.
4562 *********************************************************************/
4564 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4565 const struct auth_session_info *session_info,
4566 struct messaging_context *msg_ctx,
4567 const char *servername,
4568 union spoolss_PrinterInfo **info,
4571 const char *s = servername;
4573 DEBUG(4,("enum_all_printers_info_1_name\n"));
4575 if (servername != NULL &&
4576 (servername[0] == '\\') && (servername[1] == '\\')) {
4580 if (!is_myname_or_ipaddr(s)) {
4581 return WERR_INVALID_NAME;
4584 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4585 servername, PRINTER_ENUM_ICON8, info, count);
4588 /********************************************************************
4589 enum_all_printers_info_1_network.
4590 *********************************************************************/
4592 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4593 const struct auth_session_info *session_info,
4594 struct messaging_context *msg_ctx,
4595 const char *servername,
4596 union spoolss_PrinterInfo **info,
4599 const char *s = servername;
4601 DEBUG(4,("enum_all_printers_info_1_network\n"));
4603 /* If we respond to a enum_printers level 1 on our name with flags
4604 set to PRINTER_ENUM_REMOTE with a list of printers then these
4605 printers incorrectly appear in the APW browse list.
4606 Specifically the printers for the server appear at the workgroup
4607 level where all the other servers in the domain are
4608 listed. Windows responds to this call with a
4609 WERR_CAN_NOT_COMPLETE so we should do the same. */
4611 if (servername != NULL &&
4612 (servername[0] == '\\') && (servername[1] == '\\')) {
4616 if (is_myname_or_ipaddr(s)) {
4617 return WERR_CAN_NOT_COMPLETE;
4620 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4621 servername, PRINTER_ENUM_NAME, info, count);
4624 /********************************************************************
4625 * api_spoolss_enumprinters
4627 * called from api_spoolss_enumprinters (see this to understand)
4628 ********************************************************************/
4630 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4631 const struct auth_session_info *session_info,
4632 struct messaging_context *msg_ctx,
4633 const char *servername,
4634 union spoolss_PrinterInfo **info,
4637 DEBUG(4,("enum_all_printers_info_2\n"));
4639 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4640 servername, 2, 0, info, count);
4643 /********************************************************************
4644 * handle enumeration of printers at level 1
4645 ********************************************************************/
4647 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4648 const struct auth_session_info *session_info,
4649 struct messaging_context *msg_ctx,
4651 const char *servername,
4652 union spoolss_PrinterInfo **info,
4655 /* Not all the flags are equals */
4657 if (flags & PRINTER_ENUM_LOCAL) {
4658 return enum_all_printers_info_1_local(mem_ctx, session_info,
4659 msg_ctx, servername, info, count);
4662 if (flags & PRINTER_ENUM_NAME) {
4663 return enum_all_printers_info_1_name(mem_ctx, session_info,
4664 msg_ctx, servername, info,
4668 if (flags & PRINTER_ENUM_NETWORK) {
4669 return enum_all_printers_info_1_network(mem_ctx, session_info,
4670 msg_ctx, servername, info,
4674 return WERR_OK; /* NT4sp5 does that */
4677 /********************************************************************
4678 * handle enumeration of printers at level 2
4679 ********************************************************************/
4681 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4682 const struct auth_session_info *session_info,
4683 struct messaging_context *msg_ctx,
4685 const char *servername,
4686 union spoolss_PrinterInfo **info,
4689 if (flags & PRINTER_ENUM_LOCAL) {
4691 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4696 if (flags & PRINTER_ENUM_NAME) {
4697 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4698 return WERR_INVALID_NAME;
4701 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4706 if (flags & PRINTER_ENUM_REMOTE) {
4707 return WERR_INVALID_LEVEL;
4713 /********************************************************************
4714 * handle enumeration of printers at level 4
4715 ********************************************************************/
4717 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4718 const struct auth_session_info *session_info,
4719 struct messaging_context *msg_ctx,
4721 const char *servername,
4722 union spoolss_PrinterInfo **info,
4725 DEBUG(4,("enum_all_printers_info_4\n"));
4727 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4728 servername, 4, flags, info, count);
4732 /********************************************************************
4733 * handle enumeration of printers at level 5
4734 ********************************************************************/
4736 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4737 const struct auth_session_info *session_info,
4738 struct messaging_context *msg_ctx,
4740 const char *servername,
4741 union spoolss_PrinterInfo **info,
4744 DEBUG(4,("enum_all_printers_info_5\n"));
4746 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4747 servername, 5, flags, info, count);
4750 /****************************************************************
4751 _spoolss_EnumPrinters
4752 ****************************************************************/
4754 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4755 struct spoolss_EnumPrinters *r)
4757 const struct auth_session_info *session_info = get_session_info_system();
4760 /* that's an [in out] buffer */
4762 if (!r->in.buffer && (r->in.offered != 0)) {
4763 return WERR_INVALID_PARAMETER;
4766 DEBUG(4,("_spoolss_EnumPrinters\n"));
4770 *r->out.info = NULL;
4774 * flags==PRINTER_ENUM_NAME
4775 * if name=="" then enumerates all printers
4776 * if name!="" then enumerate the printer
4777 * flags==PRINTER_ENUM_REMOTE
4778 * name is NULL, enumerate printers
4779 * Level 2: name!="" enumerates printers, name can't be NULL
4780 * Level 3: doesn't exist
4781 * Level 4: does a local registry lookup
4782 * Level 5: same as Level 2
4785 if (r->in.server && r->in.server[0] == '\0') {
4786 r->in.server = NULL;
4789 switch (r->in.level) {
4791 result = enumprinters_level0(p->mem_ctx, session_info,
4792 p->msg_ctx, r->in.flags,
4794 r->out.info, r->out.count);
4797 result = enumprinters_level1(p->mem_ctx, session_info,
4798 p->msg_ctx, r->in.flags,
4800 r->out.info, r->out.count);
4803 result = enumprinters_level2(p->mem_ctx, session_info,
4804 p->msg_ctx, r->in.flags,
4806 r->out.info, r->out.count);
4809 result = enumprinters_level4(p->mem_ctx, session_info,
4810 p->msg_ctx, r->in.flags,
4812 r->out.info, r->out.count);
4815 result = enumprinters_level5(p->mem_ctx, session_info,
4816 p->msg_ctx, r->in.flags,
4818 r->out.info, r->out.count);
4821 return WERR_INVALID_LEVEL;
4824 if (!W_ERROR_IS_OK(result)) {
4828 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4829 spoolss_EnumPrinters,
4830 *r->out.info, r->in.level,
4832 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4833 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4835 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4838 /****************************************************************
4840 ****************************************************************/
4842 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4843 struct spoolss_GetPrinter *r)
4845 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4846 struct spoolss_PrinterInfo2 *info2 = NULL;
4847 WERROR result = WERR_OK;
4850 /* that's an [in out] buffer */
4852 if (!r->in.buffer && (r->in.offered != 0)) {
4853 result = WERR_INVALID_PARAMETER;
4859 if (Printer == NULL) {
4860 result = WERR_INVALID_HANDLE;
4864 if (Printer->printer_type == SPLHND_SERVER) {
4866 struct dcerpc_binding_handle *b;
4868 if (r->in.level != 3) {
4869 result = WERR_INVALID_LEVEL;
4873 result = winreg_printer_binding_handle(p->mem_ctx,
4874 get_session_info_system(),
4877 if (!W_ERROR_IS_OK(result)) {
4881 result = winreg_get_printserver_secdesc(p->mem_ctx,
4883 &r->out.info->info3.secdesc);
4884 if (!W_ERROR_IS_OK(result)) {
4891 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4892 result = WERR_INVALID_HANDLE;
4896 result = winreg_get_printer_internal(p->mem_ctx,
4897 get_session_info_system(),
4899 lp_const_servicename(snum),
4901 if (!W_ERROR_IS_OK(result)) {
4905 switch (r->in.level) {
4907 result = construct_printer_info0(p->mem_ctx,
4908 get_session_info_system(),
4911 Printer->servername,
4912 &r->out.info->info0,
4916 result = construct_printer_info1(p->mem_ctx, info2,
4918 Printer->servername,
4919 &r->out.info->info1, snum);
4922 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4923 Printer->servername,
4924 &r->out.info->info2, snum);
4927 result = construct_printer_info3(p->mem_ctx, info2,
4928 Printer->servername,
4929 &r->out.info->info3, snum);
4932 result = construct_printer_info4(p->mem_ctx, info2,
4933 Printer->servername,
4934 &r->out.info->info4, snum);
4937 result = construct_printer_info5(p->mem_ctx, info2,
4938 Printer->servername,
4939 &r->out.info->info5, snum);
4942 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4943 Printer->servername,
4944 &r->out.info->info6, snum);
4947 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4948 Printer->servername,
4949 &r->out.info->info7, snum);
4952 result = construct_printer_info8(p->mem_ctx, info2,
4953 Printer->servername,
4954 &r->out.info->info8, snum);
4957 result = WERR_INVALID_LEVEL;
4962 if (!W_ERROR_IS_OK(result)) {
4963 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4964 r->in.level, win_errstr(result)));
4968 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4969 r->out.info, r->in.level);
4970 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4972 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4975 TALLOC_FREE(r->out.info);
4979 /********************************************************************
4980 ********************************************************************/
4982 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4984 if (in && strlen(in)) { \
4985 out = talloc_strdup(mem_ctx, in); \
4987 out = talloc_strdup(mem_ctx, ""); \
4989 W_ERROR_HAVE_NO_MEMORY(out); \
4992 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4994 if (in && strlen(in)) { \
4995 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4997 out = talloc_strdup(mem_ctx, ""); \
4999 W_ERROR_HAVE_NO_MEMORY(out); \
5002 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5003 const char **string_array,
5004 const char ***presult,
5005 const char *cservername,
5010 size_t num_strings = 0;
5011 const char **array = NULL;
5013 if (string_array == NULL) {
5014 return WERR_INVALID_PARAMETER;
5017 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5018 const char *str = NULL;
5020 if (cservername == NULL || arch == NULL) {
5021 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5023 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5026 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5028 return WERR_NOT_ENOUGH_MEMORY;
5033 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5034 &array, &num_strings);
5037 if (presult != NULL) {
5046 /********************************************************************
5047 * fill a spoolss_DriverInfo1 struct
5048 ********************************************************************/
5050 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5051 struct spoolss_DriverInfo1 *r,
5052 const struct spoolss_DriverInfo8 *driver,
5053 const char *servername)
5055 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5056 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5061 /********************************************************************
5062 * fill a spoolss_DriverInfo2 struct
5063 ********************************************************************/
5065 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5066 struct spoolss_DriverInfo2 *r,
5067 const struct spoolss_DriverInfo8 *driver,
5068 const char *servername)
5071 const char *cservername = canon_servername(servername);
5073 r->version = driver->version;
5075 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5076 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5077 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5078 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5080 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5081 driver->architecture,
5083 driver->driver_path,
5086 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5087 driver->architecture,
5092 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093 driver->architecture,
5095 driver->config_file,
5101 /********************************************************************
5102 * fill a spoolss_DriverInfo3 struct
5103 ********************************************************************/
5105 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5106 struct spoolss_DriverInfo3 *r,
5107 const struct spoolss_DriverInfo8 *driver,
5108 const char *servername)
5110 const char *cservername = canon_servername(servername);
5112 r->version = driver->version;
5114 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5115 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5116 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5117 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5119 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120 driver->architecture,
5122 driver->driver_path,
5125 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126 driver->architecture,
5131 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5132 driver->architecture,
5134 driver->config_file,
5137 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5138 driver->architecture,
5143 FILL_DRIVER_STRING(mem_ctx,
5144 driver->monitor_name,
5147 FILL_DRIVER_STRING(mem_ctx,
5148 driver->default_datatype,
5149 r->default_datatype);
5151 return string_array_from_driver_info(mem_ctx,
5152 driver->dependent_files,
5153 &r->dependent_files,
5155 driver->architecture,
5159 /********************************************************************
5160 * fill a spoolss_DriverInfo4 struct
5161 ********************************************************************/
5163 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5164 struct spoolss_DriverInfo4 *r,
5165 const struct spoolss_DriverInfo8 *driver,
5166 const char *servername)
5168 const char *cservername = canon_servername(servername);
5171 r->version = driver->version;
5173 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5174 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5175 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5176 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5178 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179 driver->architecture,
5181 driver->driver_path,
5184 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185 driver->architecture,
5190 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5191 driver->architecture,
5193 driver->config_file,
5196 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197 driver->architecture,
5202 result = string_array_from_driver_info(mem_ctx,
5203 driver->dependent_files,
5204 &r->dependent_files,
5206 driver->architecture,
5208 if (!W_ERROR_IS_OK(result)) {
5212 FILL_DRIVER_STRING(mem_ctx,
5213 driver->monitor_name,
5216 FILL_DRIVER_STRING(mem_ctx,
5217 driver->default_datatype,
5218 r->default_datatype);
5221 result = string_array_from_driver_info(mem_ctx,
5222 driver->previous_names,
5229 /********************************************************************
5230 * fill a spoolss_DriverInfo5 struct
5231 ********************************************************************/
5233 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5234 struct spoolss_DriverInfo5 *r,
5235 const struct spoolss_DriverInfo8 *driver,
5236 const char *servername)
5238 const char *cservername = canon_servername(servername);
5240 r->version = driver->version;
5242 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5243 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5244 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5245 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5247 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5248 driver->architecture,
5250 driver->driver_path,
5253 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5254 driver->architecture,
5259 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5260 driver->architecture,
5262 driver->config_file,
5265 r->driver_attributes = 0;
5266 r->config_version = 0;
5267 r->driver_version = 0;
5271 /********************************************************************
5272 * fill a spoolss_DriverInfo6 struct
5273 ********************************************************************/
5275 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5276 struct spoolss_DriverInfo6 *r,
5277 const struct spoolss_DriverInfo8 *driver,
5278 const char *servername)
5280 const char *cservername = canon_servername(servername);
5283 r->version = driver->version;
5285 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5286 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5287 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5288 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5290 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5291 driver->architecture,
5293 driver->driver_path,
5296 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5297 driver->architecture,
5302 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5303 driver->architecture,
5305 driver->config_file,
5308 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5309 driver->architecture,
5314 FILL_DRIVER_STRING(mem_ctx,
5315 driver->monitor_name,
5318 FILL_DRIVER_STRING(mem_ctx,
5319 driver->default_datatype,
5320 r->default_datatype);
5322 result = string_array_from_driver_info(mem_ctx,
5323 driver->dependent_files,
5324 &r->dependent_files,
5326 driver->architecture,
5328 if (!W_ERROR_IS_OK(result)) {
5332 result = string_array_from_driver_info(mem_ctx,
5333 driver->previous_names,
5336 if (!W_ERROR_IS_OK(result)) {
5340 r->driver_date = driver->driver_date;
5341 r->driver_version = driver->driver_version;
5343 FILL_DRIVER_STRING(mem_ctx,
5344 driver->manufacturer_name,
5345 r->manufacturer_name);
5346 FILL_DRIVER_STRING(mem_ctx,
5347 driver->manufacturer_url,
5348 r->manufacturer_url);
5349 FILL_DRIVER_STRING(mem_ctx,
5350 driver->hardware_id,
5352 FILL_DRIVER_STRING(mem_ctx,
5359 /********************************************************************
5360 * fill a spoolss_DriverInfo8 struct
5361 ********************************************************************/
5363 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5364 struct spoolss_DriverInfo8 *r,
5365 const struct spoolss_DriverInfo8 *driver,
5366 const char *servername)
5368 const char *cservername = canon_servername(servername);
5371 r->version = driver->version;
5373 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5374 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5375 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5376 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5378 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5379 driver->architecture,
5381 driver->driver_path,
5384 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5385 driver->architecture,
5390 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5391 driver->architecture,
5393 driver->config_file,
5396 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5397 driver->architecture,
5402 FILL_DRIVER_STRING(mem_ctx,
5403 driver->monitor_name,
5406 FILL_DRIVER_STRING(mem_ctx,
5407 driver->default_datatype,
5408 r->default_datatype);
5410 result = string_array_from_driver_info(mem_ctx,
5411 driver->dependent_files,
5412 &r->dependent_files,
5414 driver->architecture,
5416 if (!W_ERROR_IS_OK(result)) {
5420 result = string_array_from_driver_info(mem_ctx,
5421 driver->previous_names,
5424 if (!W_ERROR_IS_OK(result)) {
5428 r->driver_date = driver->driver_date;
5429 r->driver_version = driver->driver_version;
5431 FILL_DRIVER_STRING(mem_ctx,
5432 driver->manufacturer_name,
5433 r->manufacturer_name);
5434 FILL_DRIVER_STRING(mem_ctx,
5435 driver->manufacturer_url,
5436 r->manufacturer_url);
5437 FILL_DRIVER_STRING(mem_ctx,
5438 driver->hardware_id,
5440 FILL_DRIVER_STRING(mem_ctx,
5444 FILL_DRIVER_STRING(mem_ctx,
5445 driver->print_processor,
5446 r->print_processor);
5447 FILL_DRIVER_STRING(mem_ctx,
5448 driver->vendor_setup,
5451 result = string_array_from_driver_info(mem_ctx,
5452 driver->color_profiles,
5455 if (!W_ERROR_IS_OK(result)) {
5459 FILL_DRIVER_STRING(mem_ctx,
5463 r->printer_driver_attributes = driver->printer_driver_attributes;
5465 result = string_array_from_driver_info(mem_ctx,
5466 driver->core_driver_dependencies,
5467 &r->core_driver_dependencies,
5469 if (!W_ERROR_IS_OK(result)) {
5473 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5474 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5479 #if 0 /* disabled until marshalling issues are resolved - gd */
5480 /********************************************************************
5481 ********************************************************************/
5483 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5484 struct spoolss_DriverFileInfo *r,
5485 const char *cservername,
5486 const char *file_name,
5487 enum spoolss_DriverFileType file_type,
5488 uint32_t file_version)
5490 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5491 cservername, file_name);
5492 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5493 r->file_type = file_type;
5494 r->file_version = file_version;
5499 /********************************************************************
5500 ********************************************************************/
5502 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5503 const struct spoolss_DriverInfo8 *driver,
5504 const char *cservername,
5505 struct spoolss_DriverFileInfo **info_p,
5508 struct spoolss_DriverFileInfo *info = NULL;
5516 if (strlen(driver->driver_path)) {
5517 info = talloc_realloc(mem_ctx, info,
5518 struct spoolss_DriverFileInfo,
5520 W_ERROR_HAVE_NO_MEMORY(info);
5521 result = fill_spoolss_DriverFileInfo(info,
5524 driver->driver_path,
5525 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5527 W_ERROR_NOT_OK_RETURN(result);
5531 if (strlen(driver->config_file)) {
5532 info = talloc_realloc(mem_ctx, info,
5533 struct spoolss_DriverFileInfo,
5535 W_ERROR_HAVE_NO_MEMORY(info);
5536 result = fill_spoolss_DriverFileInfo(info,
5539 driver->config_file,
5540 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5542 W_ERROR_NOT_OK_RETURN(result);
5546 if (strlen(driver->data_file)) {
5547 info = talloc_realloc(mem_ctx, info,
5548 struct spoolss_DriverFileInfo,
5550 W_ERROR_HAVE_NO_MEMORY(info);
5551 result = fill_spoolss_DriverFileInfo(info,
5555 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5557 W_ERROR_NOT_OK_RETURN(result);
5561 if (strlen(driver->help_file)) {
5562 info = talloc_realloc(mem_ctx, info,
5563 struct spoolss_DriverFileInfo,
5565 W_ERROR_HAVE_NO_MEMORY(info);
5566 result = fill_spoolss_DriverFileInfo(info,
5570 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5572 W_ERROR_NOT_OK_RETURN(result);
5576 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5577 info = talloc_realloc(mem_ctx, info,
5578 struct spoolss_DriverFileInfo,
5580 W_ERROR_HAVE_NO_MEMORY(info);
5581 result = fill_spoolss_DriverFileInfo(info,
5584 driver->dependent_files[i],
5585 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5587 W_ERROR_NOT_OK_RETURN(result);
5597 /********************************************************************
5598 * fill a spoolss_DriverInfo101 struct
5599 ********************************************************************/
5601 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5602 struct spoolss_DriverInfo101 *r,
5603 const struct spoolss_DriverInfo8 *driver,
5604 const char *servername)
5606 const char *cservername = canon_servername(servername);
5609 r->version = driver->version;
5611 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5612 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5613 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5614 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5616 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5620 if (!W_ERROR_IS_OK(result)) {
5624 FILL_DRIVER_STRING(mem_ctx,
5625 driver->monitor_name,
5628 FILL_DRIVER_STRING(mem_ctx,
5629 driver->default_datatype,
5630 r->default_datatype);
5632 result = string_array_from_driver_info(mem_ctx,
5633 driver->previous_names,
5636 if (!W_ERROR_IS_OK(result)) {
5640 r->driver_date = driver->driver_date;
5641 r->driver_version = driver->driver_version;
5643 FILL_DRIVER_STRING(mem_ctx,
5644 driver->manufacturer_name,
5645 r->manufacturer_name);
5646 FILL_DRIVER_STRING(mem_ctx,
5647 driver->manufacturer_url,
5648 r->manufacturer_url);
5649 FILL_DRIVER_STRING(mem_ctx,
5650 driver->hardware_id,
5652 FILL_DRIVER_STRING(mem_ctx,
5659 /********************************************************************
5660 ********************************************************************/
5662 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5663 const struct auth_session_info *session_info,
5664 struct messaging_context *msg_ctx,
5666 union spoolss_DriverInfo *r,
5668 const char *servername,
5669 const char *architecture,
5672 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5673 struct spoolss_DriverInfo8 *driver;
5675 struct dcerpc_binding_handle *b;
5676 TALLOC_CTX *tmp_ctx = NULL;
5679 return WERR_INVALID_LEVEL;
5682 tmp_ctx = talloc_new(mem_ctx);
5684 return WERR_NOT_ENOUGH_MEMORY;
5687 result = winreg_printer_binding_handle(tmp_ctx,
5691 if (!W_ERROR_IS_OK(result)) {
5695 result = winreg_get_printer(tmp_ctx, b,
5696 lp_const_servicename(snum),
5698 if (!W_ERROR_IS_OK(result)) {
5699 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5700 lp_const_servicename(snum), win_errstr(result));
5701 result = WERR_INVALID_PRINTER_NAME;
5705 if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5706 return WERR_UNKNOWN_PRINTER_DRIVER;
5709 DBG_INFO("Construct printer driver [%s] for [%s]\n",
5713 result = winreg_get_driver(tmp_ctx, b,
5715 pinfo2->drivername, version, &driver);
5717 DBG_INFO("winreg_get_driver() status: %s\n",
5718 win_errstr(result));
5720 if (!W_ERROR_IS_OK(result)) {
5722 * Is this a W2k client ?
5726 result = WERR_UNKNOWN_PRINTER_DRIVER;
5730 /* Yes - try again with a WinNT driver. */
5732 result = winreg_get_driver(tmp_ctx, b,
5736 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5737 win_errstr(result)));
5738 if (!W_ERROR_IS_OK(result)) {
5739 result = WERR_UNKNOWN_PRINTER_DRIVER;
5744 /* these are allocated on mem_ctx and not tmp_ctx because they are
5745 * the 'return value' and need to utlive this call */
5748 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5751 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5754 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5757 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5760 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5763 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5766 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5768 #if 0 /* disabled until marshalling issues are resolved - gd */
5770 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5774 result = WERR_INVALID_LEVEL;
5779 talloc_free(tmp_ctx);
5783 /****************************************************************
5784 _spoolss_GetPrinterDriver2
5785 ****************************************************************/
5787 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5788 struct spoolss_GetPrinterDriver2 *r)
5790 struct printer_handle *printer;
5792 uint32_t version = r->in.client_major_version;
5796 /* that's an [in out] buffer */
5798 if (!r->in.buffer && (r->in.offered != 0)) {
5799 result = WERR_INVALID_PARAMETER;
5803 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5805 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5806 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5807 result = WERR_INVALID_PRINTER_NAME;
5812 *r->out.server_major_version = 0;
5813 *r->out.server_minor_version = 0;
5815 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5816 result = WERR_INVALID_HANDLE;
5820 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5821 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5822 "downgrading to v3\n"));
5823 version = SPOOLSS_DRIVER_VERSION_200X;
5826 result = construct_printer_driver_info_level(p->mem_ctx,
5827 get_session_info_system(),
5829 r->in.level, r->out.info,
5830 snum, printer->servername,
5833 if (!W_ERROR_IS_OK(result)) {
5837 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5838 r->out.info, r->in.level);
5839 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5841 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5844 TALLOC_FREE(r->out.info);
5849 /****************************************************************
5850 _spoolss_StartPagePrinter
5851 ****************************************************************/
5853 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5854 struct spoolss_StartPagePrinter *r)
5856 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5859 DEBUG(3,("_spoolss_StartPagePrinter: "
5860 "Error in startpageprinter printer handle\n"));
5861 return WERR_INVALID_HANDLE;
5864 Printer->page_started = true;
5868 /****************************************************************
5869 _spoolss_EndPagePrinter
5870 ****************************************************************/
5872 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5873 struct spoolss_EndPagePrinter *r)
5877 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5880 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5881 OUR_HANDLE(r->in.handle)));
5882 return WERR_INVALID_HANDLE;
5885 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5886 return WERR_INVALID_HANDLE;
5888 Printer->page_started = false;
5889 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5894 /****************************************************************
5895 _spoolss_StartDocPrinter
5896 ****************************************************************/
5898 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5899 struct spoolss_StartDocPrinter *r)
5901 struct spoolss_DocumentInfo1 *info_1;
5903 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5909 DEBUG(2,("_spoolss_StartDocPrinter: "
5910 "Invalid handle (%s:%u:%u)\n",
5911 OUR_HANDLE(r->in.handle)));
5912 return WERR_INVALID_HANDLE;
5915 if (Printer->jobid) {
5916 DEBUG(2, ("_spoolss_StartDocPrinter: "
5917 "StartDocPrinter called twice! "
5918 "(existing jobid = %d)\n", Printer->jobid));
5919 return WERR_INVALID_HANDLE;
5922 if (r->in.info_ctr->level != 1) {
5923 return WERR_INVALID_LEVEL;
5926 info_1 = r->in.info_ctr->info.info1;
5929 * a nice thing with NT is it doesn't listen to what you tell it.
5930 * when asked to send _only_ RAW datas, it tries to send datas
5933 * So I add checks like in NT Server ...
5936 if (info_1->datatype) {
5938 * The v4 driver model used in Windows 8 declares print jobs
5939 * intended to bypass the XPS processing layer by setting
5940 * datatype to "XPS_PASS" instead of "RAW".
5942 if ((strcmp(info_1->datatype, "RAW") != 0)
5943 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5945 return WERR_INVALID_DATATYPE;
5949 /* get the share number of the printer */
5950 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5951 return WERR_INVALID_HANDLE;
5954 rc = get_remote_hostname(p->remote_address,
5958 return WERR_NOT_ENOUGH_MEMORY;
5960 if (strequal(rhost,"UNKNOWN")) {
5961 rhost = tsocket_address_inet_addr_string(p->remote_address,
5963 if (rhost == NULL) {
5964 return WERR_NOT_ENOUGH_MEMORY;
5968 werr = print_job_start(p->session_info,
5972 info_1->document_name,
5973 info_1->output_file,
5977 /* An error occurred in print_job_start() so return an appropriate
5980 if (!W_ERROR_IS_OK(werr)) {
5984 Printer->document_started = true;
5985 *r->out.job_id = Printer->jobid;
5990 /****************************************************************
5991 _spoolss_EndDocPrinter
5992 ****************************************************************/
5994 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5995 struct spoolss_EndDocPrinter *r)
5997 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6002 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6003 OUR_HANDLE(r->in.handle)));
6004 return WERR_INVALID_HANDLE;
6007 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6008 return WERR_INVALID_HANDLE;
6011 Printer->document_started = false;
6012 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6013 if (!NT_STATUS_IS_OK(status)) {
6014 DEBUG(2, ("_spoolss_EndDocPrinter: "
6015 "print_job_end failed [%s]\n",
6016 nt_errstr(status)));
6020 return ntstatus_to_werror(status);
6023 /****************************************************************
6024 _spoolss_WritePrinter
6025 ****************************************************************/
6027 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6028 struct spoolss_WritePrinter *r)
6030 ssize_t buffer_written;
6032 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6035 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6036 OUR_HANDLE(r->in.handle)));
6037 *r->out.num_written = r->in._data_size;
6038 return WERR_INVALID_HANDLE;
6041 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6042 return WERR_INVALID_HANDLE;
6044 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6045 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
6046 snum, Printer->jobid,
6047 (const char *)r->in.data.data,
6048 (size_t)r->in._data_size);
6049 if (buffer_written == (ssize_t)-1) {
6050 *r->out.num_written = 0;
6051 if (errno == ENOSPC)
6052 return WERR_NO_SPOOL_SPACE;
6054 return WERR_ACCESS_DENIED;
6057 *r->out.num_written = r->in._data_size;
6062 /********************************************************************
6063 * api_spoolss_getprinter
6064 * called from the spoolss dispatcher
6066 ********************************************************************/
6068 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6069 struct pipes_struct *p)
6071 const struct auth_session_info *session_info = p->session_info;
6073 WERROR errcode = WERR_INVALID_FUNCTION;
6074 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6077 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6078 OUR_HANDLE(handle)));
6079 return WERR_INVALID_HANDLE;
6082 if (!get_printer_snum(p, handle, &snum, NULL))
6083 return WERR_INVALID_HANDLE;
6086 case SPOOLSS_PRINTER_CONTROL_PAUSE:
6087 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6089 case SPOOLSS_PRINTER_CONTROL_RESUME:
6090 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6091 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6093 case SPOOLSS_PRINTER_CONTROL_PURGE:
6094 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6097 return WERR_INVALID_LEVEL;
6104 /****************************************************************
6105 _spoolss_AbortPrinter
6106 * From MSDN: "Deletes printer's spool file if printer is configured
6108 ****************************************************************/
6110 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6111 struct spoolss_AbortPrinter *r)
6113 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6115 WERROR errcode = WERR_OK;
6118 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6119 OUR_HANDLE(r->in.handle)));
6120 return WERR_INVALID_HANDLE;
6123 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6124 return WERR_INVALID_HANDLE;
6126 if (!Printer->document_started) {
6127 return WERR_SPL_NO_STARTDOC;
6130 errcode = print_job_delete(p->session_info,
6138 /********************************************************************
6139 * called by spoolss_api_setprinter
6140 * when updating a printer description
6141 ********************************************************************/
6143 static WERROR update_printer_sec(struct policy_handle *handle,
6144 struct pipes_struct *p,
6145 struct sec_desc_buf *secdesc_ctr)
6147 struct spoolss_security_descriptor *new_secdesc = NULL;
6148 struct spoolss_security_descriptor *old_secdesc = NULL;
6149 const char *printer = NULL;
6152 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6153 struct dcerpc_binding_handle *b;
6154 TALLOC_CTX *tmp_ctx = NULL;
6158 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6159 OUR_HANDLE(handle)));
6161 result = WERR_INVALID_HANDLE;
6165 if (secdesc_ctr == NULL) {
6166 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6167 result = WERR_INVALID_PARAMETER;
6171 switch (Printer->printer_type) {
6174 case SPLHND_PRINTER:
6175 if (!get_printer_snum(p, handle, &snum, NULL)) {
6176 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6177 OUR_HANDLE(handle)));
6178 result = WERR_INVALID_HANDLE;
6181 printer = lp_const_servicename(snum);
6187 /* Check the user has permissions to change the security
6188 descriptor. By experimentation with two NT machines, the user
6189 requires Full Access to the printer to change security
6192 switch (Printer->printer_type) {
6194 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6196 case SPLHND_PRINTER:
6197 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6204 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6205 "(access_granted: 0x%08x)\n", Printer->access_granted));
6206 result = WERR_ACCESS_DENIED;
6210 tmp_ctx = talloc_new(p->mem_ctx);
6212 return WERR_NOT_ENOUGH_MEMORY;
6215 result = winreg_printer_binding_handle(tmp_ctx,
6216 get_session_info_system(),
6219 if (!W_ERROR_IS_OK(result)) {
6223 /* NT seems to like setting the security descriptor even though
6224 nothing may have actually changed. */
6226 if (printer != NULL) {
6227 result = winreg_get_printer_secdesc(tmp_ctx, b,
6231 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6234 if (!W_ERROR_IS_OK(result)) {
6235 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6236 result = WERR_INVALID_HANDLE;
6240 if (DEBUGLEVEL >= 10) {
6241 struct security_acl *the_acl;
6244 the_acl = old_secdesc->dacl;
6245 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6246 printer, the_acl->num_aces));
6248 for (i = 0; i < the_acl->num_aces; i++) {
6249 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6250 &the_acl->aces[i].trustee),
6251 the_acl->aces[i].access_mask));
6254 the_acl = secdesc_ctr->sd->dacl;
6257 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6258 printer, the_acl->num_aces));
6260 for (i = 0; i < the_acl->num_aces; i++) {
6261 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6262 &the_acl->aces[i].trustee),
6263 the_acl->aces[i].access_mask));
6266 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6270 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6271 if (new_secdesc == NULL) {
6272 result = WERR_NOT_ENOUGH_MEMORY;
6276 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6281 if (printer != NULL) {
6282 result = winreg_set_printer_secdesc(tmp_ctx, b,
6286 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6291 talloc_free(tmp_ctx);
6295 /********************************************************************
6296 Canonicalize printer info from a client
6297 ********************************************************************/
6299 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6300 struct spoolss_SetPrinterInfo2 *info2,
6303 fstring printername;
6306 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6307 "portname=%s drivername=%s comment=%s location=%s\n",
6308 info2->servername, info2->printername, info2->sharename,
6309 info2->portname, info2->drivername, info2->comment,
6312 /* we force some elements to "correct" values */
6313 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6314 if (info2->servername == NULL) {
6317 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6318 if (info2->sharename == NULL) {
6322 /* check to see if we allow printername != sharename */
6323 if (lp_force_printername(snum)) {
6324 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6325 lp_netbios_name(), info2->sharename);
6327 /* make sure printername is in \\server\printername format */
6328 fstrcpy(printername, info2->printername);
6330 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6331 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6335 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6336 lp_netbios_name(), p);
6338 if (info2->printername == NULL) {
6342 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6343 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6348 /****************************************************************************
6349 ****************************************************************************/
6351 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6353 char *cmd = lp_addport_command(talloc_tos());
6354 char *command = NULL;
6356 bool is_print_op = false;
6359 return WERR_ACCESS_DENIED;
6362 command = talloc_asprintf(ctx,
6363 "%s \"%s\" \"%s\"", cmd, portname, uri );
6365 return WERR_NOT_ENOUGH_MEMORY;
6369 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6371 DEBUG(10,("Running [%s]\n", command));
6373 /********* BEGIN SePrintOperatorPrivilege **********/
6378 ret = smbrun(command, NULL, NULL);
6383 /********* END SePrintOperatorPrivilege **********/
6385 DEBUGADD(10,("returned [%d]\n", ret));
6387 TALLOC_FREE(command);
6390 return WERR_ACCESS_DENIED;
6396 /****************************************************************************
6397 ****************************************************************************/
6399 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6403 * As we do not know if we are embedded in the file server process
6404 * or not, we have to pretend that all shares are in use.
6409 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6410 struct spoolss_SetPrinterInfo2 *info2,
6411 const char *remote_machine,
6412 struct messaging_context *msg_ctx)
6414 char *cmd = lp_addprinter_command(talloc_tos());
6416 char *command = NULL;
6420 bool is_print_op = false;
6422 if (!remote_machine) {
6426 command = talloc_asprintf(ctx,
6427 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6428 cmd, info2->printername, info2->sharename,
6429 info2->portname, info2->drivername,
6430 info2->location, info2->comment, remote_machine);
6436 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6438 DEBUG(10,("Running [%s]\n", command));
6440 /********* BEGIN SePrintOperatorPrivilege **********/
6445 ret = smbrun(command, &fd, NULL);
6447 /* Tell everyone we updated smb.conf. */
6448 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6454 /********* END SePrintOperatorPrivilege **********/
6456 DEBUGADD(10,("returned [%d]\n", ret));
6458 TALLOC_FREE(command);
6466 /* reload our services immediately */
6468 reload_services(NULL, spoolss_conn_snum_used, false);
6472 /* Get lines and convert them back to dos-codepage */
6473 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6474 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6477 /* Set the portname to what the script says the portname should be. */
6478 /* but don't require anything to be return from the script exit a good error code */
6481 /* Set the portname to what the script says the portname should be. */
6482 info2->portname = talloc_strdup(ctx, qlines[0]);
6483 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6486 TALLOC_FREE(qlines);
6490 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6491 const struct auth_session_info *session_info,
6492 struct messaging_context *msg_ctx,
6494 struct spoolss_SetPrinterInfo2 *printer,
6495 struct spoolss_PrinterInfo2 *old_printer)
6497 bool force_update = (old_printer == NULL);
6498 const char *dnsdomname;
6499 const char *longname;
6500 const char *uncname;
6501 const char *spooling;
6503 WERROR result = WERR_OK;
6504 struct dcerpc_binding_handle *b;
6505 TALLOC_CTX *tmp_ctx;
6508 tmp_ctx = talloc_new(mem_ctx);
6510 return WERR_NOT_ENOUGH_MEMORY;
6513 result = winreg_printer_binding_handle(tmp_ctx,
6517 if (!W_ERROR_IS_OK(result)) {
6521 if (printer->drivername != NULL &&
6523 !strequal(printer->drivername, old_printer->drivername))) {
6524 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6526 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6527 result = WERR_INVALID_DATA;
6530 result = winreg_set_printer_dataex(tmp_ctx, b,
6532 SPOOL_DSSPOOLER_KEY,
6533 SPOOL_REG_DRIVERNAME,
6537 if (!W_ERROR_IS_OK(result)) {
6538 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6542 if (!force_update) {
6543 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6544 printer->drivername));
6546 notify_printer_driver(server_event_context(), msg_ctx,
6547 snum, printer->drivername ?
6548 printer->drivername : "");
6552 if (printer->comment != NULL &&
6554 !strequal(printer->comment, old_printer->comment))) {
6555 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6557 DEBUG(0, ("comment data corrupted\n"));
6558 result = WERR_INVALID_DATA;
6561 result = winreg_set_printer_dataex(tmp_ctx, b,
6563 SPOOL_DSSPOOLER_KEY,
6564 SPOOL_REG_DESCRIPTION,
6568 if (!W_ERROR_IS_OK(result)) {
6569 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6573 if (!force_update) {
6574 notify_printer_comment(server_event_context(), msg_ctx,
6575 snum, printer->comment ?
6576 printer->comment : "");
6580 if (printer->sharename != NULL &&
6582 !strequal(printer->sharename, old_printer->sharename))) {
6583 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6585 DEBUG(0, ("sharename data corrupted\n"));
6586 result = WERR_INVALID_DATA;
6589 result = winreg_set_printer_dataex(tmp_ctx, b,
6591 SPOOL_DSSPOOLER_KEY,
6592 SPOOL_REG_PRINTSHARENAME,
6596 if (!W_ERROR_IS_OK(result)) {
6597 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6601 if (!force_update) {
6602 notify_printer_sharename(server_event_context(),
6604 snum, printer->sharename ?
6605 printer->sharename : "");
6608 /* name change, purge any cache entries for the old */
6609 prune_printername_cache();
6612 if (printer->printername != NULL &&
6614 !strequal(printer->printername, old_printer->printername))) {
6617 p = strrchr(printer->printername, '\\' );
6621 p = printer->printername;
6624 ok = push_reg_sz(tmp_ctx, &buffer, p);
6626 DEBUG(0, ("printername data corrupted\n"));
6627 result = WERR_INVALID_DATA;
6630 result = winreg_set_printer_dataex(tmp_ctx, b,
6632 SPOOL_DSSPOOLER_KEY,
6633 SPOOL_REG_PRINTERNAME,
6637 if (!W_ERROR_IS_OK(result)) {
6638 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6642 if (!force_update) {
6643 notify_printer_printername(server_event_context(),
6644 msg_ctx, snum, p ? p : "");
6647 /* name change, purge any cache entries for the old */
6648 prune_printername_cache();
6651 if (printer->portname != NULL &&
6653 !strequal(printer->portname, old_printer->portname))) {
6654 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6656 DEBUG(0, ("portname data corrupted\n"));
6657 result = WERR_INVALID_DATA;
6660 result = winreg_set_printer_dataex(tmp_ctx, b,
6662 SPOOL_DSSPOOLER_KEY,
6667 if (!W_ERROR_IS_OK(result)) {
6668 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6672 if (!force_update) {
6673 notify_printer_port(server_event_context(),
6674 msg_ctx, snum, printer->portname ?
6675 printer->portname : "");
6679 if (printer->location != NULL &&
6681 !strequal(printer->location, old_printer->location))) {
6682 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6684 DEBUG(0, ("location data corrupted\n"));
6685 result = WERR_INVALID_DATA;
6688 result = winreg_set_printer_dataex(tmp_ctx, b,
6690 SPOOL_DSSPOOLER_KEY,
6695 if (!W_ERROR_IS_OK(result)) {
6696 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6700 if (!force_update) {
6701 notify_printer_location(server_event_context(),
6704 printer->location : "");
6708 if (printer->sepfile != NULL &&
6710 !strequal(printer->sepfile, old_printer->sepfile))) {
6711 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6713 DEBUG(0, ("sepfile data corrupted\n"));
6714 result = WERR_INVALID_DATA;
6717 result = winreg_set_printer_dataex(tmp_ctx, b,
6719 SPOOL_DSSPOOLER_KEY,
6720 SPOOL_REG_PRINTSEPARATORFILE,
6724 if (!W_ERROR_IS_OK(result)) {
6725 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6729 if (!force_update) {
6730 notify_printer_sepfile(server_event_context(),
6733 printer->sepfile : "");
6737 if (printer->starttime != 0 &&
6739 printer->starttime != old_printer->starttime)) {
6740 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6741 SIVAL(buffer.data, 0, printer->starttime);
6742 result = winreg_set_printer_dataex(tmp_ctx, b,
6744 SPOOL_DSSPOOLER_KEY,
6745 SPOOL_REG_PRINTSTARTTIME,
6749 if (!W_ERROR_IS_OK(result)) {
6750 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6755 if (printer->untiltime != 0 &&
6757 printer->untiltime != old_printer->untiltime)) {
6758 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6759 SIVAL(buffer.data, 0, printer->untiltime);
6760 result = winreg_set_printer_dataex(tmp_ctx, b,
6762 SPOOL_DSSPOOLER_KEY,
6763 SPOOL_REG_PRINTENDTIME,
6767 if (!W_ERROR_IS_OK(result)) {
6768 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6773 if (force_update || printer->priority != old_printer->priority) {
6774 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6775 SIVAL(buffer.data, 0, printer->priority);
6776 result = winreg_set_printer_dataex(tmp_ctx, b,
6778 SPOOL_DSSPOOLER_KEY,
6783 if (!W_ERROR_IS_OK(result)) {
6784 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6789 if (force_update || printer->attributes != old_printer->attributes) {
6790 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6791 SIVAL(buffer.data, 0, (printer->attributes &
6792 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6793 result = winreg_set_printer_dataex(tmp_ctx, b,
6795 SPOOL_DSSPOOLER_KEY,
6796 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6800 if (!W_ERROR_IS_OK(result)) {
6801 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6805 switch (printer->attributes & 0x3) {
6807 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6810 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6813 spooling = SPOOL_REGVAL_PRINTDIRECT;
6816 spooling = "unknown";
6818 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6820 DEBUG(0, ("printSpooling data corrupted\n"));
6821 result = WERR_INVALID_DATA;
6824 winreg_set_printer_dataex(tmp_ctx, b,
6826 SPOOL_DSSPOOLER_KEY,
6827 SPOOL_REG_PRINTSPOOLING,
6833 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6835 DEBUG(0, ("shortServerName data corrupted\n"));
6836 result = WERR_INVALID_DATA;
6839 result = winreg_set_printer_dataex(tmp_ctx, b,
6841 SPOOL_DSSPOOLER_KEY,
6842 SPOOL_REG_SHORTSERVERNAME,
6846 if (!W_ERROR_IS_OK(result)) {
6847 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6851 dnsdomname = get_mydnsfullname();
6852 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6853 longname = talloc_strdup(tmp_ctx, dnsdomname);
6855 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6857 if (longname == NULL) {
6858 result = WERR_NOT_ENOUGH_MEMORY;
6862 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6864 DEBUG(0, ("longname data corrupted\n"));
6865 result = WERR_INVALID_DATA;
6868 result = winreg_set_printer_dataex(tmp_ctx, b,
6870 SPOOL_DSSPOOLER_KEY,
6871 SPOOL_REG_SERVERNAME,
6875 if (!W_ERROR_IS_OK(result)) {
6876 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6880 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6881 lp_netbios_name(), printer->sharename);
6882 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6884 DEBUG(0, ("uncName data corrupted\n"));
6885 result = WERR_INVALID_DATA;
6888 result = winreg_set_printer_dataex(tmp_ctx, b,
6890 SPOOL_DSSPOOLER_KEY,
6895 if (!W_ERROR_IS_OK(result)) {
6896 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6901 talloc_free(tmp_ctx);
6905 /********************************************************************
6906 * Called by spoolss_api_setprinter
6907 * when updating a printer description.
6908 ********************************************************************/
6910 static WERROR update_printer(struct pipes_struct *p,
6911 struct policy_handle *handle,
6912 struct spoolss_SetPrinterInfoCtr *info_ctr,
6913 struct spoolss_DeviceMode *devmode)
6915 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6916 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6917 struct spoolss_PrinterInfo2 *old_printer;
6918 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6920 WERROR result = WERR_OK;
6921 TALLOC_CTX *tmp_ctx;
6922 struct dcerpc_binding_handle *b;
6924 DEBUG(8,("update_printer\n"));
6926 tmp_ctx = talloc_new(p->mem_ctx);
6927 if (tmp_ctx == NULL) {
6928 return WERR_NOT_ENOUGH_MEMORY;
6932 result = WERR_INVALID_HANDLE;
6936 if (!get_printer_snum(p, handle, &snum, NULL)) {
6937 result = WERR_INVALID_HANDLE;
6941 result = winreg_printer_binding_handle(tmp_ctx,
6942 get_session_info_system(),
6945 if (!W_ERROR_IS_OK(result)) {
6949 result = winreg_get_printer(tmp_ctx, b,
6950 lp_const_servicename(snum),
6952 if (!W_ERROR_IS_OK(result)) {
6953 result = WERR_INVALID_HANDLE;
6957 /* Do sanity check on the requested changes for Samba */
6958 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6959 result = WERR_INVALID_PARAMETER;
6963 /* FIXME!!! If the driver has changed we really should verify that
6964 it is installed before doing much else --jerry */
6966 /* Check calling user has permission to update printer description */
6967 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6968 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6969 result = WERR_ACCESS_DENIED;
6973 /* Call addprinter hook */
6974 /* Check changes to see if this is really needed */
6976 if (*lp_addprinter_command(talloc_tos()) &&
6977 (!strequal(printer->drivername, old_printer->drivername) ||
6978 !strequal(printer->comment, old_printer->comment) ||
6979 !strequal(printer->portname, old_printer->portname) ||
6980 !strequal(printer->location, old_printer->location)) )
6984 raddr = tsocket_address_inet_addr_string(p->remote_address,
6986 if (raddr == NULL) {
6987 return WERR_NOT_ENOUGH_MEMORY;
6990 /* add_printer_hook() will call reload_services() */
6991 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6994 result = WERR_ACCESS_DENIED;
6999 result = update_dsspooler(tmp_ctx,
7000 get_session_info_system(),
7005 if (!W_ERROR_IS_OK(result)) {
7009 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7011 if (devmode == NULL) {
7012 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7014 result = winreg_update_printer(tmp_ctx, b,
7022 talloc_free(tmp_ctx);
7027 /****************************************************************************
7028 ****************************************************************************/
7029 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7030 struct policy_handle *handle,
7031 struct spoolss_SetPrinterInfo7 *info7)
7034 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7037 struct printer_handle *Printer;
7039 if ( lp_security() != SEC_ADS ) {
7040 return WERR_INVALID_LEVEL;
7043 Printer = find_printer_index_by_hnd(p, handle);
7045 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7048 return WERR_INVALID_HANDLE;
7050 if (!get_printer_snum(p, handle, &snum, NULL))
7051 return WERR_INVALID_HANDLE;
7053 result = winreg_get_printer_internal(p->mem_ctx,
7054 get_session_info_system(),
7056 lp_servicename(talloc_tos(), snum),
7058 if (!W_ERROR_IS_OK(result)) {
7059 return WERR_INVALID_HANDLE;
7062 nt_printer_publish(pinfo2,
7063 get_session_info_system(),
7068 TALLOC_FREE(pinfo2);
7071 return WERR_INVALID_LEVEL;
7075 /********************************************************************
7076 ********************************************************************/
7078 static WERROR update_printer_devmode(struct pipes_struct *p,
7079 struct policy_handle *handle,
7080 struct spoolss_DeviceMode *devmode)
7083 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7084 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7086 DEBUG(8,("update_printer_devmode\n"));
7089 return WERR_INVALID_HANDLE;
7092 if (!get_printer_snum(p, handle, &snum, NULL)) {
7093 return WERR_INVALID_HANDLE;
7096 /* Check calling user has permission to update printer description */
7097 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7098 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7099 return WERR_ACCESS_DENIED;
7102 return winreg_update_printer_internal(p->mem_ctx,
7103 get_session_info_system(),
7105 lp_const_servicename(snum),
7113 /****************************************************************
7115 ****************************************************************/
7117 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7118 struct spoolss_SetPrinter *r)
7122 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7125 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7126 OUR_HANDLE(r->in.handle)));
7127 return WERR_INVALID_HANDLE;
7130 /* check the level */
7131 switch (r->in.info_ctr->level) {
7133 return control_printer(r->in.handle, r->in.command, p);
7135 result = update_printer(p, r->in.handle,
7137 r->in.devmode_ctr->devmode);
7138 if (!W_ERROR_IS_OK(result))
7140 if (r->in.secdesc_ctr->sd)
7141 result = update_printer_sec(r->in.handle, p,
7145 return update_printer_sec(r->in.handle, p,
7148 struct spoolss_PrinterInfo2 *old_printer;
7149 struct spoolss_SetPrinterInfo2 *set_old_printer;
7150 struct spoolss_SetPrinterInfoCtr *info_ctr;
7151 struct dcerpc_binding_handle *b;
7153 TALLOC_CTX *tmp_ctx;
7155 tmp_ctx = talloc_new(p->mem_ctx);
7156 if (tmp_ctx == NULL) {
7157 return WERR_NOT_ENOUGH_MEMORY;
7160 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7161 TALLOC_FREE(tmp_ctx);
7162 return WERR_INVALID_HANDLE;
7165 result = winreg_printer_binding_handle(tmp_ctx,
7166 get_session_info_system(),
7169 if (!W_ERROR_IS_OK(result)) {
7170 TALLOC_FREE(tmp_ctx);
7174 result = winreg_get_printer(tmp_ctx, b,
7175 lp_const_servicename(snum),
7177 if (!W_ERROR_IS_OK(result)) {
7178 TALLOC_FREE(tmp_ctx);
7179 return WERR_INVALID_HANDLE;
7182 old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7183 if (old_printer->servername == NULL) {
7184 TALLOC_FREE(tmp_ctx);
7185 return WERR_NOT_ENOUGH_MEMORY;
7188 old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7189 if (old_printer->printername == NULL) {
7190 TALLOC_FREE(tmp_ctx);
7191 return WERR_NOT_ENOUGH_MEMORY;
7194 old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7196 set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7197 if (set_old_printer == NULL) {
7198 TALLOC_FREE(tmp_ctx);
7199 return WERR_NOT_ENOUGH_MEMORY;
7202 spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7204 info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7205 if (info_ctr == NULL) {
7206 TALLOC_FREE(tmp_ctx);
7207 return WERR_NOT_ENOUGH_MEMORY;
7210 info_ctr->level = 2;
7211 info_ctr->info.info2 = set_old_printer;
7213 result = update_printer(p, r->in.handle,
7215 r->in.devmode_ctr->devmode);
7217 if (!W_ERROR_IS_OK(result)) {
7218 TALLOC_FREE(tmp_ctx);
7222 if (r->in.secdesc_ctr->sd) {
7223 result = update_printer_sec(r->in.handle, p,
7227 TALLOC_FREE(tmp_ctx);
7231 return publish_or_unpublish_printer(p, r->in.handle,
7232 r->in.info_ctr->info.info7);
7234 return update_printer_devmode(p, r->in.handle,
7235 r->in.devmode_ctr->devmode);
7237 return WERR_INVALID_LEVEL;
7241 /****************************************************************
7242 _spoolss_FindClosePrinterNotify
7243 ****************************************************************/
7245 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7246 struct spoolss_FindClosePrinterNotify *r)
7248 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7251 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7252 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7253 return WERR_INVALID_HANDLE;
7256 if (Printer->notify.cli_chan != NULL &&
7257 Printer->notify.cli_chan->active_connections > 0) {
7260 if (Printer->printer_type == SPLHND_PRINTER) {
7261 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7262 return WERR_INVALID_HANDLE;
7266 srv_spoolss_replycloseprinter(snum, Printer);
7269 Printer->notify.flags=0;
7270 Printer->notify.options=0;
7271 Printer->notify.localmachine[0]='\0';
7272 Printer->notify.printerlocal=0;
7273 TALLOC_FREE(Printer->notify.option);
7278 /****************************************************************
7280 ****************************************************************/
7282 WERROR _spoolss_AddJob(struct pipes_struct *p,
7283 struct spoolss_AddJob *r)
7285 if (!r->in.buffer && (r->in.offered != 0)) {
7286 return WERR_INVALID_PARAMETER;
7289 /* this is what a NT server returns for AddJob. AddJob must fail on
7290 * non-local printers */
7292 if (r->in.level != 1) {
7293 return WERR_INVALID_LEVEL;
7296 return WERR_INVALID_PARAMETER;
7299 /****************************************************************************
7301 ****************************************************************************/
7303 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7304 struct spoolss_JobInfo1 *r,
7305 const print_queue_struct *queue,
7307 int position, int snum,
7308 struct spoolss_PrinterInfo2 *pinfo2)
7312 t = gmtime(&queue->time);
7316 r->printer_name = lp_servicename(mem_ctx, snum);
7317 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7318 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7319 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7320 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7321 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7322 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7323 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7324 r->data_type = talloc_strdup(mem_ctx, "RAW");
7325 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7326 r->text_status = talloc_strdup(mem_ctx, "");
7327 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7329 r->status = nt_printj_status(queue->status);
7330 r->priority = queue->priority;
7331 r->position = position;
7332 r->total_pages = queue->page_count;
7333 r->pages_printed = 0; /* ??? */
7335 init_systemtime(&r->submitted, t);
7340 /****************************************************************************
7342 ****************************************************************************/
7344 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7345 struct spoolss_JobInfo2 *r,
7346 const print_queue_struct *queue,
7348 int position, int snum,
7349 struct spoolss_PrinterInfo2 *pinfo2,
7350 struct spoolss_DeviceMode *devmode)
7354 t = gmtime(&queue->time);
7358 r->printer_name = lp_servicename(mem_ctx, snum);
7359 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7360 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7361 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7362 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7363 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7364 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7365 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7366 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7367 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7368 r->data_type = talloc_strdup(mem_ctx, "RAW");
7369 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7370 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7371 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7372 r->parameters = talloc_strdup(mem_ctx, "");
7373 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7374 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7375 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7377 r->devmode = devmode;
7379 r->text_status = talloc_strdup(mem_ctx, "");
7380 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7384 r->status = nt_printj_status(queue->status);
7385 r->priority = queue->priority;
7386 r->position = position;
7389 r->total_pages = queue->page_count;
7390 r->size = queue->size;
7391 init_systemtime(&r->submitted, t);
7393 r->pages_printed = 0; /* ??? */
7398 /****************************************************************************
7399 Enumjobs at level 1.
7400 ****************************************************************************/
7402 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7403 const print_queue_struct *queue,
7404 uint32_t num_queues, int snum,
7405 struct spoolss_PrinterInfo2 *pinfo2,
7406 union spoolss_JobInfo **info_p,
7409 union spoolss_JobInfo *info;
7411 WERROR result = WERR_OK;
7412 uint32_t num_filled;
7413 struct tdb_print_db *pdb;
7415 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7417 result = WERR_NOT_ENOUGH_MEMORY;
7421 pdb = get_print_db_byname(pinfo2->sharename);
7423 result = WERR_INVALID_PARAMETER;
7428 for (i = 0; i < num_queues; i++) {
7429 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7430 if (jobid == (uint32_t)-1) {
7431 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7435 result = fill_job_info1(info,
7436 &info[num_filled].info1,
7442 if (!W_ERROR_IS_OK(result)) {
7449 release_print_db(pdb);
7451 *count = num_filled;
7456 release_print_db(pdb);
7464 /****************************************************************************
7465 Enumjobs at level 2.
7466 ****************************************************************************/
7468 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7469 const print_queue_struct *queue,
7470 uint32_t num_queues, int snum,
7471 struct spoolss_PrinterInfo2 *pinfo2,
7472 union spoolss_JobInfo **info_p,
7475 union spoolss_JobInfo *info;
7477 WERROR result = WERR_OK;
7478 uint32_t num_filled;
7479 struct tdb_print_db *pdb;
7481 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7483 result = WERR_NOT_ENOUGH_MEMORY;
7487 pdb = get_print_db_byname(pinfo2->sharename);
7489 result = WERR_INVALID_PARAMETER;
7494 for (i = 0; i< num_queues; i++) {
7495 struct spoolss_DeviceMode *devmode;
7496 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7497 if (jobid == (uint32_t)-1) {
7498 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7502 result = spoolss_create_default_devmode(info,
7503 pinfo2->printername,
7505 if (!W_ERROR_IS_OK(result)) {
7506 DEBUG(3, ("Can't proceed w/o a devmode!"));
7510 result = fill_job_info2(info,
7511 &info[num_filled].info2,
7518 if (!W_ERROR_IS_OK(result)) {
7524 release_print_db(pdb);
7526 *count = num_filled;
7531 release_print_db(pdb);
7539 /****************************************************************************
7540 Enumjobs at level 3.
7541 ****************************************************************************/
7543 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7544 const print_queue_struct *queue,
7545 uint32_t num_queues, int snum,
7546 struct spoolss_PrinterInfo2 *pinfo2,
7547 union spoolss_JobInfo **info_p,
7550 union spoolss_JobInfo *info;
7552 WERROR result = WERR_OK;
7553 uint32_t num_filled;
7554 struct tdb_print_db *pdb;
7556 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7558 result = WERR_NOT_ENOUGH_MEMORY;
7562 pdb = get_print_db_byname(pinfo2->sharename);
7564 result = WERR_INVALID_PARAMETER;
7569 for (i = 0; i < num_queues; i++) {
7570 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7571 if (jobid == (uint32_t)-1) {
7572 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7576 info[num_filled].info3.job_id = jobid;
7577 /* next_job_id is overwritten on next iteration */
7578 info[num_filled].info3.next_job_id = 0;
7579 info[num_filled].info3.reserved = 0;
7581 if (num_filled > 0) {
7582 info[num_filled - 1].info3.next_job_id = jobid;
7587 release_print_db(pdb);
7589 *count = num_filled;
7600 /****************************************************************
7602 ****************************************************************/
7604 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7605 struct spoolss_EnumJobs *r)
7608 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7610 print_status_struct prt_status;
7611 print_queue_struct *queue = NULL;
7614 /* that's an [in out] buffer */
7616 if (!r->in.buffer && (r->in.offered != 0)) {
7617 return WERR_INVALID_PARAMETER;
7620 if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7621 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7622 return WERR_INVALID_LEVEL;
7625 DEBUG(4,("_spoolss_EnumJobs\n"));
7629 *r->out.info = NULL;
7631 /* lookup the printer snum and tdb entry */
7633 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7634 return WERR_INVALID_HANDLE;
7637 result = winreg_get_printer_internal(p->mem_ctx,
7638 get_session_info_system(),
7640 lp_const_servicename(snum),
7642 if (!W_ERROR_IS_OK(result)) {
7646 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7647 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7648 count, prt_status.status, prt_status.message));
7652 TALLOC_FREE(pinfo2);
7656 switch (r->in.level) {
7658 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7659 pinfo2, r->out.info, r->out.count);
7662 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7663 pinfo2, r->out.info, r->out.count);
7666 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7667 pinfo2, r->out.info, r->out.count);
7670 SMB_ASSERT(false); /* level checked on entry */
7675 TALLOC_FREE(pinfo2);
7677 if (!W_ERROR_IS_OK(result)) {
7681 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7683 *r->out.info, r->in.level,
7685 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7686 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7688 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7691 /****************************************************************
7692 _spoolss_ScheduleJob
7693 ****************************************************************/
7695 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7696 struct spoolss_ScheduleJob *r)
7701 /****************************************************************
7702 ****************************************************************/
7704 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7705 struct messaging_context *msg_ctx,
7706 const char *printer_name,
7708 struct spoolss_SetJobInfo1 *r)
7712 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7713 return WERR_INVALID_HANDLE;
7716 if (strequal(old_doc_name, r->document_name)) {
7720 if (!print_job_set_name(server_event_context(), msg_ctx,
7721 printer_name, job_id, r->document_name)) {
7722 return WERR_INVALID_HANDLE;
7728 /****************************************************************
7730 ****************************************************************/
7732 WERROR _spoolss_SetJob(struct pipes_struct *p,
7733 struct spoolss_SetJob *r)
7735 const struct auth_session_info *session_info = p->session_info;
7737 WERROR errcode = WERR_INVALID_FUNCTION;
7739 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7740 return WERR_INVALID_HANDLE;
7743 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7744 return WERR_INVALID_PRINTER_NAME;
7747 switch (r->in.command) {
7748 case SPOOLSS_JOB_CONTROL_CANCEL:
7749 case SPOOLSS_JOB_CONTROL_DELETE:
7750 errcode = print_job_delete(session_info, p->msg_ctx,
7751 snum, r->in.job_id);
7752 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7756 case SPOOLSS_JOB_CONTROL_PAUSE:
7757 errcode = print_job_pause(session_info, p->msg_ctx,
7758 snum, r->in.job_id);
7760 case SPOOLSS_JOB_CONTROL_RESTART:
7761 case SPOOLSS_JOB_CONTROL_RESUME:
7762 errcode = print_job_resume(session_info, p->msg_ctx,
7763 snum, r->in.job_id);
7765 case SPOOLSS_JOB_CONTROL_NOOP:
7769 return WERR_INVALID_LEVEL;
7772 if (!W_ERROR_IS_OK(errcode)) {
7776 if (r->in.ctr == NULL) {
7780 switch (r->in.ctr->level) {
7782 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7783 lp_const_servicename(snum),
7785 r->in.ctr->info.info1);
7791 return WERR_INVALID_LEVEL;
7797 /****************************************************************************
7798 Enumerates all printer drivers by level and architecture.
7799 ****************************************************************************/
7801 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7802 const struct auth_session_info *session_info,
7803 struct messaging_context *msg_ctx,
7804 const char *servername,
7805 const char *architecture,
7807 union spoolss_DriverInfo **info_p,
7812 struct spoolss_DriverInfo8 *driver;
7813 union spoolss_DriverInfo *info = NULL;
7815 WERROR result = WERR_OK;
7816 uint32_t num_drivers;
7817 const char **drivers;
7818 struct dcerpc_binding_handle *b;
7819 TALLOC_CTX *tmp_ctx = NULL;
7824 tmp_ctx = talloc_new(mem_ctx);
7826 return WERR_NOT_ENOUGH_MEMORY;
7829 result = winreg_printer_binding_handle(tmp_ctx,
7833 if (!W_ERROR_IS_OK(result)) {
7837 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7838 result = winreg_get_driver_list(tmp_ctx, b,
7839 architecture, version,
7840 &num_drivers, &drivers);
7841 if (!W_ERROR_IS_OK(result)) {
7844 DEBUG(4, ("we have:[%d] drivers in environment"
7845 " [%s] and version [%d]\n",
7846 num_drivers, architecture, version));
7848 if (num_drivers != 0) {
7849 info = talloc_realloc(tmp_ctx, info,
7850 union spoolss_DriverInfo,
7851 count + num_drivers);
7853 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7854 "failed to enlarge driver info buffer!\n"));
7855 result = WERR_NOT_ENOUGH_MEMORY;
7860 for (i = 0; i < num_drivers; i++) {
7861 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7863 result = winreg_get_driver(tmp_ctx, b,
7864 architecture, drivers[i],
7866 if (!W_ERROR_IS_OK(result)) {
7872 result = fill_printer_driver_info1(info, &info[count+i].info1,
7873 driver, servername);
7876 result = fill_printer_driver_info2(info, &info[count+i].info2,
7877 driver, servername);
7880 result = fill_printer_driver_info3(info, &info[count+i].info3,
7881 driver, servername);
7884 result = fill_printer_driver_info4(info, &info[count+i].info4,
7885 driver, servername);
7888 result = fill_printer_driver_info5(info, &info[count+i].info5,
7889 driver, servername);
7892 result = fill_printer_driver_info6(info, &info[count+i].info6,
7893 driver, servername);
7896 result = fill_printer_driver_info8(info, &info[count+i].info8,
7897 driver, servername);
7900 result = WERR_INVALID_LEVEL;
7904 TALLOC_FREE(driver);
7906 if (!W_ERROR_IS_OK(result)) {
7911 count += num_drivers;
7912 TALLOC_FREE(drivers);
7916 if (W_ERROR_IS_OK(result)) {
7917 *info_p = talloc_move(mem_ctx, &info);
7921 talloc_free(tmp_ctx);
7925 /****************************************************************************
7926 Enumerates all printer drivers by level.
7927 ****************************************************************************/
7929 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7930 const struct auth_session_info *session_info,
7931 struct messaging_context *msg_ctx,
7932 const char *servername,
7933 const char *architecture,
7935 union spoolss_DriverInfo **info_p,
7939 WERROR result = WERR_OK;
7941 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7943 for (a=0; archi_table[a].long_archi != NULL; a++) {
7945 union spoolss_DriverInfo *info = NULL;
7948 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7952 archi_table[a].long_archi,
7956 if (!W_ERROR_IS_OK(result)) {
7960 for (i=0; i < count; i++) {
7961 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7962 info[i], info_p, count_p);
7969 return enumprinterdrivers_level_by_architecture(mem_ctx,
7979 /****************************************************************
7980 _spoolss_EnumPrinterDrivers
7981 ****************************************************************/
7983 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7984 struct spoolss_EnumPrinterDrivers *r)
7986 const char *cservername;
7989 /* that's an [in out] buffer */
7991 if (!r->in.buffer && (r->in.offered != 0)) {
7992 return WERR_INVALID_PARAMETER;
7995 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7999 *r->out.info = NULL;
8001 cservername = canon_servername(r->in.server);
8003 if (!is_myname_or_ipaddr(cservername)) {
8004 return WERR_UNKNOWN_PRINTER_DRIVER;
8007 result = enumprinterdrivers_level(p->mem_ctx,
8008 get_session_info_system(),
8015 if (!W_ERROR_IS_OK(result)) {
8019 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8020 spoolss_EnumPrinterDrivers,
8021 *r->out.info, r->in.level,
8023 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8024 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8026 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8029 /****************************************************************
8031 ****************************************************************/
8033 WERROR _spoolss_EnumForms(struct pipes_struct *p,
8034 struct spoolss_EnumForms *r)
8040 *r->out.info = NULL;
8042 /* that's an [in out] buffer */
8044 if (!r->in.buffer && (r->in.offered != 0) ) {
8045 return WERR_INVALID_PARAMETER;
8048 DEBUG(4,("_spoolss_EnumForms\n"));
8049 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8050 DEBUGADD(5,("Info level [%d]\n", r->in.level));
8052 switch (r->in.level) {
8054 result = winreg_printer_enumforms1_internal(p->mem_ctx,
8055 get_session_info_system(),
8061 result = WERR_INVALID_LEVEL;
8065 if (!W_ERROR_IS_OK(result)) {
8069 if (*r->out.count == 0) {
8070 return WERR_NO_MORE_ITEMS;
8073 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8075 *r->out.info, r->in.level,
8077 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8078 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8080 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8083 /****************************************************************
8085 ****************************************************************/
8087 WERROR _spoolss_GetForm(struct pipes_struct *p,
8088 struct spoolss_GetForm *r)
8092 /* that's an [in out] buffer */
8094 if (!r->in.buffer && (r->in.offered != 0)) {
8095 TALLOC_FREE(r->out.info);
8096 return WERR_INVALID_PARAMETER;
8099 DEBUG(4,("_spoolss_GetForm\n"));
8100 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8101 DEBUGADD(5,("Info level [%d]\n", r->in.level));
8103 switch (r->in.level) {
8105 result = winreg_printer_getform1_internal(p->mem_ctx,
8106 get_session_info_system(),
8109 &r->out.info->info1);
8112 result = WERR_INVALID_LEVEL;
8116 if (!W_ERROR_IS_OK(result)) {
8117 TALLOC_FREE(r->out.info);
8121 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8122 r->out.info, r->in.level);
8123 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8125 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8128 /****************************************************************************
8129 ****************************************************************************/
8131 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8132 struct spoolss_PortInfo1 *r,
8135 r->port_name = talloc_strdup(mem_ctx, name);
8136 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8141 /****************************************************************************
8142 TODO: This probably needs distinguish between TCP/IP and Local ports
8144 ****************************************************************************/
8146 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8147 struct spoolss_PortInfo2 *r,
8150 r->port_name = talloc_strdup(mem_ctx, name);
8151 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8153 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8154 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8156 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8157 W_ERROR_HAVE_NO_MEMORY(r->description);
8159 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8166 /****************************************************************************
8167 wrapper around the enumer ports command
8168 ****************************************************************************/
8170 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8172 char *cmd = lp_enumports_command(talloc_tos());
8173 char **qlines = NULL;
8174 char *command = NULL;
8182 /* if no hook then just fill in the default port */
8185 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8186 return WERR_NOT_ENOUGH_MEMORY;
8188 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8189 TALLOC_FREE(qlines);
8190 return WERR_NOT_ENOUGH_MEMORY;
8196 /* we have a valid enumport command */
8198 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8200 return WERR_NOT_ENOUGH_MEMORY;
8203 DEBUG(10,("Running [%s]\n", command));
8204 ret = smbrun(command, &fd, NULL);
8205 DEBUG(10,("Returned [%d]\n", ret));
8206 TALLOC_FREE(command);
8211 return WERR_ACCESS_DENIED;
8215 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8216 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8226 /****************************************************************************
8228 ****************************************************************************/
8230 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8231 union spoolss_PortInfo **info_p,
8234 union spoolss_PortInfo *info = NULL;
8236 WERROR result = WERR_OK;
8237 char **qlines = NULL;
8240 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8241 if (!W_ERROR_IS_OK(result)) {
8246 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8248 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8249 result = WERR_NOT_ENOUGH_MEMORY;
8253 for (i=0; i<numlines; i++) {
8254 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8255 result = fill_port_1(info, &info[i].info1, qlines[i]);
8256 if (!W_ERROR_IS_OK(result)) {
8261 TALLOC_FREE(qlines);
8264 if (!W_ERROR_IS_OK(result)) {
8266 TALLOC_FREE(qlines);
8278 /****************************************************************************
8280 ****************************************************************************/
8282 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8283 union spoolss_PortInfo **info_p,
8286 union spoolss_PortInfo *info = NULL;
8288 WERROR result = WERR_OK;
8289 char **qlines = NULL;
8292 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8293 if (!W_ERROR_IS_OK(result)) {
8298 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8300 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8301 result = WERR_NOT_ENOUGH_MEMORY;
8305 for (i=0; i<numlines; i++) {
8306 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8307 result = fill_port_2(info, &info[i].info2, qlines[i]);
8308 if (!W_ERROR_IS_OK(result)) {
8313 TALLOC_FREE(qlines);
8316 if (!W_ERROR_IS_OK(result)) {
8318 TALLOC_FREE(qlines);
8330 /****************************************************************
8332 ****************************************************************/
8334 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8335 struct spoolss_EnumPorts *r)
8339 /* that's an [in out] buffer */
8341 if (!r->in.buffer && (r->in.offered != 0)) {
8342 return WERR_INVALID_PARAMETER;
8345 DEBUG(4,("_spoolss_EnumPorts\n"));
8349 *r->out.info = NULL;
8351 switch (r->in.level) {
8353 result = enumports_level_1(p->mem_ctx, r->out.info,
8357 result = enumports_level_2(p->mem_ctx, r->out.info,
8361 return WERR_INVALID_LEVEL;
8364 if (!W_ERROR_IS_OK(result)) {
8368 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8370 *r->out.info, r->in.level,
8372 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8373 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8375 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8378 /****************************************************************************
8379 ****************************************************************************/
8381 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8383 struct spoolss_SetPrinterInfoCtr *info_ctr,
8384 struct spoolss_DeviceMode *devmode,
8385 struct security_descriptor *secdesc,
8386 struct spoolss_UserLevelCtr *user_ctr,
8387 struct policy_handle *handle)
8389 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8390 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8392 WERROR err = WERR_OK;
8394 /* samba does not have a concept of local, non-shared printers yet, so
8395 * make sure we always setup sharename - gd */
8396 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8397 (info2->printername != NULL && info2->printername[0] != '\0')) {
8398 DEBUG(5, ("spoolss_addprinterex_level_2: "
8399 "no sharename has been set, setting printername %s as sharename\n",
8400 info2->printername));
8401 info2->sharename = info2->printername;
8404 /* check to see if the printer already exists */
8405 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8406 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8408 return WERR_PRINTER_ALREADY_EXISTS;
8411 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8412 if ((snum = print_queue_snum(info2->printername)) != -1) {
8413 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8414 info2->printername));
8415 return WERR_PRINTER_ALREADY_EXISTS;
8419 /* validate printer info struct */
8420 if (!info2->printername || strlen(info2->printername) == 0) {
8421 return WERR_INVALID_PRINTER_NAME;
8423 if (!info2->portname || strlen(info2->portname) == 0) {
8424 return WERR_UNKNOWN_PORT;
8426 if (!info2->drivername || strlen(info2->drivername) == 0) {
8427 return WERR_UNKNOWN_PRINTER_DRIVER;
8429 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8430 return WERR_UNKNOWN_PRINTPROCESSOR;
8433 /* FIXME!!! smbd should check to see if the driver is installed before
8434 trying to add a printer like this --jerry */
8436 if (*lp_addprinter_command(talloc_tos()) ) {
8439 raddr = tsocket_address_inet_addr_string(p->remote_address,
8441 if (raddr == NULL) {
8442 return WERR_NOT_ENOUGH_MEMORY;
8445 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8448 return WERR_ACCESS_DENIED;
8451 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8452 "smb.conf parameter \"addprinter command\" is defined. This "
8453 "parameter must exist for this call to succeed\n",
8454 info2->sharename ));
8457 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8458 return WERR_ACCESS_DENIED;
8461 /* you must be a printer admin to add a new printer */
8462 if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8465 PRINTER_ACCESS_ADMINISTER))) {
8466 return WERR_ACCESS_DENIED;
8470 * Do sanity check on the requested changes for Samba.
8473 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8474 return WERR_INVALID_PARAMETER;
8477 if (devmode == NULL) {
8478 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8481 err = update_dsspooler(p->mem_ctx,
8482 get_session_info_system(),
8487 if (!W_ERROR_IS_OK(err)) {
8491 err = winreg_update_printer_internal(p->mem_ctx,
8492 get_session_info_system(),
8499 if (!W_ERROR_IS_OK(err)) {
8503 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8504 if (!W_ERROR_IS_OK(err)) {
8505 /* Handle open failed - remove addition. */
8506 ZERO_STRUCTP(handle);
8513 /****************************************************************
8514 _spoolss_AddPrinterEx
8515 ****************************************************************/
8517 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8518 struct spoolss_AddPrinterEx *r)
8520 switch (r->in.info_ctr->level) {
8522 /* we don't handle yet */
8523 /* but I know what to do ... */
8524 return WERR_INVALID_LEVEL;
8526 return spoolss_addprinterex_level_2(p, r->in.server,
8528 r->in.devmode_ctr->devmode,
8529 r->in.secdesc_ctr->sd,
8530 r->in.userlevel_ctr,
8533 return WERR_INVALID_LEVEL;
8537 /****************************************************************
8539 ****************************************************************/
8541 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8542 struct spoolss_AddPrinter *r)
8544 struct spoolss_AddPrinterEx a;
8545 struct spoolss_UserLevelCtr userlevel_ctr;
8547 ZERO_STRUCT(userlevel_ctr);
8549 userlevel_ctr.level = 1;
8551 a.in.server = r->in.server;
8552 a.in.info_ctr = r->in.info_ctr;
8553 a.in.devmode_ctr = r->in.devmode_ctr;
8554 a.in.secdesc_ctr = r->in.secdesc_ctr;
8555 a.in.userlevel_ctr = &userlevel_ctr;
8556 a.out.handle = r->out.handle;
8558 return _spoolss_AddPrinterEx(p, &a);
8561 /****************************************************************
8562 _spoolss_AddPrinterDriverEx
8563 ****************************************************************/
8565 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8566 struct spoolss_AddPrinterDriverEx *r)
8568 WERROR err = WERR_OK;
8569 const char *driver_name = NULL;
8570 const char *driver_directory = NULL;
8574 * we only support the semantics of AddPrinterDriver()
8575 * i.e. only copy files that are newer than existing ones
8578 if (r->in.flags == 0) {
8579 return WERR_INVALID_PARAMETER;
8582 if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8583 !(r->in.flags & APD_COPY_NEW_FILES)) {
8584 return WERR_ACCESS_DENIED;
8588 if (r->in.info_ctr->level != 3 &&
8589 r->in.info_ctr->level != 6 &&
8590 r->in.info_ctr->level != 8) {
8591 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8592 r->in.info_ctr->level));
8593 return WERR_INVALID_LEVEL;
8596 DEBUG(5,("Cleaning driver's information\n"));
8597 err = clean_up_driver_struct(p->mem_ctx,
8602 if (!W_ERROR_IS_OK(err)) {
8603 DBG_ERR("clean_up_driver_struct failed - %s\n",
8608 DEBUG(5,("Moving driver to final destination\n"));
8609 err = move_driver_to_download_area(p->session_info,
8612 if (!W_ERROR_IS_OK(err)) {
8613 DBG_ERR("move_driver_to_download_area failed - %s\n",
8618 err = winreg_add_driver_internal(p->mem_ctx,
8619 get_session_info_system(),
8624 if (!W_ERROR_IS_OK(err)) {
8625 DBG_ERR("winreg_add_driver_internal failed - %s\n",
8631 * I think this is where he DrvUpgradePrinter() hook would be
8632 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8633 * server. Right now, we just need to send ourselves a message
8634 * to update each printer bound to this driver. --jerry
8637 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8638 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8639 __func__, driver_name));
8646 /****************************************************************
8647 _spoolss_AddPrinterDriver
8648 ****************************************************************/
8650 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8651 struct spoolss_AddPrinterDriver *r)
8653 struct spoolss_AddPrinterDriverEx a;
8655 switch (r->in.info_ctr->level) {
8662 return WERR_INVALID_LEVEL;
8665 a.in.servername = r->in.servername;
8666 a.in.info_ctr = r->in.info_ctr;
8667 a.in.flags = APD_COPY_NEW_FILES;
8669 return _spoolss_AddPrinterDriverEx(p, &a);
8672 /****************************************************************************
8673 ****************************************************************************/
8675 struct _spoolss_paths {
8681 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8683 static const struct _spoolss_paths spoolss_paths[]= {
8684 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8685 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8688 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8689 const char *servername,
8690 const char *environment,
8694 const char *pservername = NULL;
8695 const char *long_archi;
8696 const char *short_archi;
8700 /* environment may be empty */
8701 if (environment && strlen(environment)) {
8702 long_archi = environment;
8704 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8705 "spoolss", "architecture",
8706 GLOBAL_SPOOLSS_ARCHITECTURE);
8709 /* servername may be empty */
8710 if (servername && strlen(servername)) {
8711 pservername = canon_servername(servername);
8713 if (!is_myname_or_ipaddr(pservername)) {
8714 return WERR_INVALID_PARAMETER;
8718 if (!(short_archi = get_short_archi(long_archi))) {
8719 return WERR_INVALID_ENVIRONMENT;
8722 switch (component) {
8723 case SPOOLSS_PRTPROCS_PATH:
8724 case SPOOLSS_DRIVER_PATH:
8726 *path = talloc_asprintf(mem_ctx,
8729 spoolss_paths[component].share,
8732 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8733 SPOOLSS_DEFAULT_SERVER_PATH,
8734 spoolss_paths[component].dir,
8739 return WERR_INVALID_PARAMETER;
8743 return WERR_NOT_ENOUGH_MEMORY;
8749 /****************************************************************************
8750 ****************************************************************************/
8752 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8753 const char *servername,
8754 const char *environment,
8755 struct spoolss_DriverDirectoryInfo1 *r)
8760 werr = compose_spoolss_server_path(mem_ctx,
8763 SPOOLSS_DRIVER_PATH,
8765 if (!W_ERROR_IS_OK(werr)) {
8769 DEBUG(4,("printer driver directory: [%s]\n", path));
8771 r->directory_name = path;
8776 /****************************************************************
8777 _spoolss_GetPrinterDriverDirectory
8778 ****************************************************************/
8780 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8781 struct spoolss_GetPrinterDriverDirectory *r)
8785 /* that's an [in out] buffer */
8787 if (!r->in.buffer && (r->in.offered != 0)) {
8788 TALLOC_FREE(r->out.info);
8789 return WERR_INVALID_PARAMETER;
8792 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8797 /* r->in.level is ignored */
8799 werror = getprinterdriverdir_level_1(p->mem_ctx,
8802 &r->out.info->info1);
8803 if (!W_ERROR_IS_OK(werror)) {
8804 TALLOC_FREE(r->out.info);
8808 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8809 r->out.info, r->in.level);
8810 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8812 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8815 /****************************************************************
8816 _spoolss_EnumPrinterData
8817 ****************************************************************/
8819 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8820 struct spoolss_EnumPrinterData *r)
8823 struct spoolss_EnumPrinterDataEx r2;
8825 struct spoolss_PrinterEnumValues *info, *val = NULL;
8828 r2.in.handle = r->in.handle;
8829 r2.in.key_name = "PrinterDriverData";
8831 r2.out.count = &count;
8832 r2.out.info = &info;
8833 r2.out.needed = &needed;
8835 result = _spoolss_EnumPrinterDataEx(p, &r2);
8836 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8837 r2.in.offered = needed;
8838 result = _spoolss_EnumPrinterDataEx(p, &r2);
8840 if (!W_ERROR_IS_OK(result)) {
8845 * The NT machine wants to know the biggest size of value and data
8847 * cf: MSDN EnumPrinterData remark section
8850 if (!r->in.value_offered && !r->in.data_offered) {
8851 uint32_t biggest_valuesize = 0;
8852 uint32_t biggest_datasize = 0;
8855 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8857 for (i=0; i<count; i++) {
8859 name_length = strlen(info[i].value_name);
8860 if (strlen(info[i].value_name) > biggest_valuesize) {
8861 biggest_valuesize = name_length;
8864 if (info[i].data_length > biggest_datasize) {
8865 biggest_datasize = info[i].data_length;
8868 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8872 /* the value is an UNICODE string but real_value_size is the length
8873 in bytes including the trailing 0 */
8875 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8876 *r->out.data_needed = biggest_datasize;
8878 DEBUG(6,("final values: [%d], [%d]\n",
8879 *r->out.value_needed, *r->out.data_needed));
8884 if (r->in.enum_index < count) {
8885 val = &info[r->in.enum_index];
8889 /* out_value should default to "" or else NT4 has
8890 problems unmarshalling the response */
8892 if (r->in.value_offered) {
8893 *r->out.value_needed = 1;
8894 r->out.value_name = talloc_strdup(r, "");
8895 if (!r->out.value_name) {
8896 return WERR_NOT_ENOUGH_MEMORY;
8899 r->out.value_name = NULL;
8900 *r->out.value_needed = 0;
8903 /* the data is counted in bytes */
8905 *r->out.data_needed = r->in.data_offered;
8907 result = WERR_NO_MORE_ITEMS;
8911 * - counted in bytes in the request
8912 * - counted in UNICODE chars in the max reply
8913 * - counted in bytes in the real size
8915 * take a pause *before* coding not *during* coding
8919 if (r->in.value_offered) {
8920 r->out.value_name = talloc_strdup(r, val->value_name);
8921 if (!r->out.value_name) {
8922 return WERR_NOT_ENOUGH_MEMORY;
8924 *r->out.value_needed = val->value_name_len;
8926 r->out.value_name = NULL;
8927 *r->out.value_needed = 0;
8932 *r->out.type = val->type;
8934 /* data - counted in bytes */
8937 * See the section "Dynamically Typed Query Parameters"
8941 if (r->out.data && val->data && val->data->data &&
8942 val->data_length && r->in.data_offered) {
8943 memcpy(r->out.data, val->data->data,
8944 MIN(val->data_length,r->in.data_offered));
8947 *r->out.data_needed = val->data_length;
8955 /****************************************************************
8956 _spoolss_SetPrinterData
8957 ****************************************************************/
8959 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8960 struct spoolss_SetPrinterData *r)
8962 struct spoolss_SetPrinterDataEx r2;
8964 r2.in.handle = r->in.handle;
8965 r2.in.key_name = "PrinterDriverData";
8966 r2.in.value_name = r->in.value_name;
8967 r2.in.type = r->in.type;
8968 r2.in.data = r->in.data;
8969 r2.in.offered = r->in.offered;
8971 return _spoolss_SetPrinterDataEx(p, &r2);
8974 /****************************************************************
8975 _spoolss_ResetPrinter
8976 ****************************************************************/
8978 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8979 struct spoolss_ResetPrinter *r)
8981 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8984 DEBUG(5,("_spoolss_ResetPrinter\n"));
8987 * All we do is to check to see if the handle and queue is valid.
8988 * This call really doesn't mean anything to us because we only
8989 * support RAW printing. --jerry
8993 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8994 OUR_HANDLE(r->in.handle)));
8995 return WERR_INVALID_HANDLE;
8998 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8999 return WERR_INVALID_HANDLE;
9002 /* blindly return success */
9006 /****************************************************************
9007 _spoolss_DeletePrinterData
9008 ****************************************************************/
9010 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9011 struct spoolss_DeletePrinterData *r)
9013 struct spoolss_DeletePrinterDataEx r2;
9015 r2.in.handle = r->in.handle;
9016 r2.in.key_name = "PrinterDriverData";
9017 r2.in.value_name = r->in.value_name;
9019 return _spoolss_DeletePrinterDataEx(p, &r2);
9022 /****************************************************************
9024 ****************************************************************/
9026 WERROR _spoolss_AddForm(struct pipes_struct *p,
9027 struct spoolss_AddForm *r)
9029 struct spoolss_AddFormInfo1 *form;
9031 WERROR status = WERR_OK;
9032 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9033 struct dcerpc_binding_handle *b;
9034 TALLOC_CTX *tmp_ctx = NULL;
9036 DEBUG(5,("_spoolss_AddForm\n"));
9039 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9040 OUR_HANDLE(r->in.handle)));
9041 return WERR_INVALID_HANDLE;
9044 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9045 and not a printer admin, then fail */
9047 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9048 !security_token_has_privilege(p->session_info->security_token,
9049 SEC_PRIV_PRINT_OPERATOR)) {
9050 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9051 return WERR_ACCESS_DENIED;
9054 if (r->in.info_ctr->level != 1) {
9055 return WERR_INVALID_LEVEL;
9058 form = r->in.info_ctr->info.info1;
9060 return WERR_INVALID_PARAMETER;
9063 switch (form->flags) {
9064 case SPOOLSS_FORM_USER:
9065 case SPOOLSS_FORM_BUILTIN:
9066 case SPOOLSS_FORM_PRINTER:
9069 return WERR_INVALID_PARAMETER;
9072 tmp_ctx = talloc_new(p->mem_ctx);
9074 return WERR_NOT_ENOUGH_MEMORY;
9077 status = winreg_printer_binding_handle(tmp_ctx,
9078 get_session_info_system(),
9081 if (!W_ERROR_IS_OK(status)) {
9085 status = winreg_printer_addform1(tmp_ctx, b, form);
9086 if (!W_ERROR_IS_OK(status)) {
9091 * ChangeID must always be set if this is a printer
9093 if (Printer->printer_type == SPLHND_PRINTER) {
9094 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9095 status = WERR_INVALID_HANDLE;
9099 status = winreg_printer_update_changeid(tmp_ctx, b,
9100 lp_const_servicename(snum));
9104 talloc_free(tmp_ctx);
9108 /****************************************************************
9110 ****************************************************************/
9112 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9113 struct spoolss_DeleteForm *r)
9115 const char *form_name = r->in.form_name;
9116 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9118 WERROR status = WERR_OK;
9119 struct dcerpc_binding_handle *b;
9120 TALLOC_CTX *tmp_ctx = NULL;
9122 DEBUG(5,("_spoolss_DeleteForm\n"));
9125 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9126 OUR_HANDLE(r->in.handle)));
9127 return WERR_INVALID_HANDLE;
9130 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9131 !security_token_has_privilege(p->session_info->security_token,
9132 SEC_PRIV_PRINT_OPERATOR)) {
9133 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9134 return WERR_ACCESS_DENIED;
9137 tmp_ctx = talloc_new(p->mem_ctx);
9139 return WERR_NOT_ENOUGH_MEMORY;
9142 status = winreg_printer_binding_handle(tmp_ctx,
9143 get_session_info_system(),
9146 if (!W_ERROR_IS_OK(status)) {
9150 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9151 if (!W_ERROR_IS_OK(status)) {
9156 * ChangeID must always be set if this is a printer
9158 if (Printer->printer_type == SPLHND_PRINTER) {
9159 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9160 status = WERR_INVALID_HANDLE;
9164 status = winreg_printer_update_changeid(tmp_ctx, b,
9165 lp_const_servicename(snum));
9169 talloc_free(tmp_ctx);
9173 /****************************************************************
9175 ****************************************************************/
9177 WERROR _spoolss_SetForm(struct pipes_struct *p,
9178 struct spoolss_SetForm *r)
9180 struct spoolss_AddFormInfo1 *form;
9181 const char *form_name = r->in.form_name;
9183 WERROR status = WERR_OK;
9184 struct dcerpc_binding_handle *b;
9185 TALLOC_CTX *tmp_ctx = NULL;
9187 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9189 DEBUG(5,("_spoolss_SetForm\n"));
9192 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9193 OUR_HANDLE(r->in.handle)));
9194 return WERR_INVALID_HANDLE;
9197 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9198 and not a printer admin, then fail */
9200 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9201 !security_token_has_privilege(p->session_info->security_token,
9202 SEC_PRIV_PRINT_OPERATOR)) {
9203 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9204 return WERR_ACCESS_DENIED;
9207 if (r->in.info_ctr->level != 1) {
9208 return WERR_INVALID_LEVEL;
9211 form = r->in.info_ctr->info.info1;
9213 return WERR_INVALID_PARAMETER;
9216 tmp_ctx = talloc_new(p->mem_ctx);
9218 return WERR_NOT_ENOUGH_MEMORY;
9221 status = winreg_printer_binding_handle(tmp_ctx,
9222 get_session_info_system(),
9225 if (!W_ERROR_IS_OK(status)) {
9229 status = winreg_printer_setform1(tmp_ctx, b,
9232 if (!W_ERROR_IS_OK(status)) {
9237 * ChangeID must always be set if this is a printer
9239 if (Printer->printer_type == SPLHND_PRINTER) {
9240 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9241 status = WERR_INVALID_HANDLE;
9245 status = winreg_printer_update_changeid(tmp_ctx, b,
9246 lp_const_servicename(snum));
9250 talloc_free(tmp_ctx);
9254 /****************************************************************************
9255 fill_print_processor1
9256 ****************************************************************************/
9258 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9259 struct spoolss_PrintProcessorInfo1 *r,
9260 const char *print_processor_name)
9262 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9263 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9268 /****************************************************************************
9269 enumprintprocessors level 1.
9270 ****************************************************************************/
9272 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9273 union spoolss_PrintProcessorInfo **info_p,
9276 union spoolss_PrintProcessorInfo *info;
9279 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9280 W_ERROR_HAVE_NO_MEMORY(info);
9284 result = fill_print_processor1(info, &info[0].info1, "winprint");
9285 if (!W_ERROR_IS_OK(result)) {
9290 if (!W_ERROR_IS_OK(result)) {
9301 /****************************************************************
9302 _spoolss_EnumPrintProcessors
9303 ****************************************************************/
9305 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9306 struct spoolss_EnumPrintProcessors *r)
9310 /* that's an [in out] buffer */
9312 if (!r->in.buffer && (r->in.offered != 0)) {
9313 return WERR_INVALID_PARAMETER;
9316 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9319 * Enumerate the print processors ...
9321 * Just reply with "winprint", to keep NT happy
9322 * and I can use my nice printer checker.
9327 *r->out.info = NULL;
9329 if (!get_short_archi(r->in.environment)) {
9330 return WERR_INVALID_ENVIRONMENT;
9333 switch (r->in.level) {
9335 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9339 return WERR_INVALID_LEVEL;
9342 if (!W_ERROR_IS_OK(result)) {
9346 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9347 spoolss_EnumPrintProcessors,
9348 *r->out.info, r->in.level,
9350 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9351 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9353 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9356 /****************************************************************************
9357 fill_printprocdatatype1
9358 ****************************************************************************/
9360 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9361 struct spoolss_PrintProcDataTypesInfo1 *r,
9362 const char *name_array)
9364 r->name_array = talloc_strdup(mem_ctx, name_array);
9365 W_ERROR_HAVE_NO_MEMORY(r->name_array);
9370 /****************************************************************************
9371 enumprintprocdatatypes level 1.
9372 ****************************************************************************/
9374 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9375 union spoolss_PrintProcDataTypesInfo **info_p,
9379 union spoolss_PrintProcDataTypesInfo *info;
9381 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9382 W_ERROR_HAVE_NO_MEMORY(info);
9386 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9387 if (!W_ERROR_IS_OK(result)) {
9392 if (!W_ERROR_IS_OK(result)) {
9403 /****************************************************************
9404 _spoolss_EnumPrintProcessorDataTypes
9405 ****************************************************************/
9407 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9408 struct spoolss_EnumPrintProcessorDataTypes *r)
9412 /* that's an [in out] buffer */
9414 if (!r->in.buffer && (r->in.offered != 0)) {
9415 return WERR_INVALID_PARAMETER;
9418 DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9422 *r->out.info = NULL;
9424 if (r->in.print_processor_name == NULL ||
9425 !strequal(r->in.print_processor_name, "winprint")) {
9426 return WERR_UNKNOWN_PRINTPROCESSOR;
9429 switch (r->in.level) {
9431 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9435 return WERR_INVALID_LEVEL;
9438 if (!W_ERROR_IS_OK(result)) {
9442 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9443 spoolss_EnumPrintProcessorDataTypes,
9444 *r->out.info, r->in.level,
9446 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9447 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9449 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9452 /****************************************************************************
9454 ****************************************************************************/
9456 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9457 struct spoolss_MonitorInfo1 *r,
9458 const char *monitor_name)
9460 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9461 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9466 /****************************************************************************
9468 ****************************************************************************/
9470 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9471 struct spoolss_MonitorInfo2 *r,
9472 const char *monitor_name,
9473 const char *environment,
9474 const char *dll_name)
9476 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9477 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9478 r->environment = talloc_strdup(mem_ctx, environment);
9479 W_ERROR_HAVE_NO_MEMORY(r->environment);
9480 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9481 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9486 /****************************************************************************
9487 enumprintmonitors level 1.
9488 ****************************************************************************/
9490 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9491 union spoolss_MonitorInfo **info_p,
9494 union spoolss_MonitorInfo *info;
9495 WERROR result = WERR_OK;
9497 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9498 W_ERROR_HAVE_NO_MEMORY(info);
9502 result = fill_monitor_1(info, &info[0].info1,
9504 if (!W_ERROR_IS_OK(result)) {
9508 result = fill_monitor_1(info, &info[1].info1,
9510 if (!W_ERROR_IS_OK(result)) {
9515 if (!W_ERROR_IS_OK(result)) {
9526 /****************************************************************************
9527 enumprintmonitors level 2.
9528 ****************************************************************************/
9530 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9531 union spoolss_MonitorInfo **info_p,
9534 union spoolss_MonitorInfo *info;
9535 WERROR result = WERR_OK;
9536 const char *architecture;
9538 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9539 W_ERROR_HAVE_NO_MEMORY(info);
9543 architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9546 GLOBAL_SPOOLSS_ARCHITECTURE);
9548 result = fill_monitor_2(info, &info[0].info2,
9552 if (!W_ERROR_IS_OK(result)) {
9556 result = fill_monitor_2(info, &info[1].info2,
9560 if (!W_ERROR_IS_OK(result)) {
9565 if (!W_ERROR_IS_OK(result)) {
9576 /****************************************************************
9577 _spoolss_EnumMonitors
9578 ****************************************************************/
9580 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9581 struct spoolss_EnumMonitors *r)
9585 /* that's an [in out] buffer */
9587 if (!r->in.buffer && (r->in.offered != 0)) {
9588 return WERR_INVALID_PARAMETER;
9591 DEBUG(5,("_spoolss_EnumMonitors\n"));
9594 * Enumerate the print monitors ...
9596 * Just reply with "Local Port", to keep NT happy
9597 * and I can use my nice printer checker.
9602 *r->out.info = NULL;
9604 switch (r->in.level) {
9606 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9610 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9614 return WERR_INVALID_LEVEL;
9617 if (!W_ERROR_IS_OK(result)) {
9621 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9622 spoolss_EnumMonitors,
9623 *r->out.info, r->in.level,
9625 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9626 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9628 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9631 /****************************************************************************
9632 ****************************************************************************/
9634 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9635 const print_queue_struct *queue,
9636 int count, int snum,
9637 struct spoolss_PrinterInfo2 *pinfo2,
9640 struct spoolss_JobInfo1 *r)
9645 for (i=0; i<count; i++) {
9646 if (queue[i].sysjob == sysjob) {
9652 if (found == false) {
9653 /* NT treats not found as bad param... yet another bad choice */
9654 return WERR_INVALID_PARAMETER;
9657 return fill_job_info1(mem_ctx,
9666 /****************************************************************************
9667 ****************************************************************************/
9669 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9670 const print_queue_struct *queue,
9671 int count, int snum,
9672 struct spoolss_PrinterInfo2 *pinfo2,
9675 struct spoolss_JobInfo2 *r)
9679 struct spoolss_DeviceMode *devmode;
9682 for (i=0; i<count; i++) {
9683 if (queue[i].sysjob == sysjob) {
9689 if (found == false) {
9690 /* NT treats not found as bad param... yet another bad
9692 return WERR_INVALID_PARAMETER;
9696 * if the print job does not have a DEVMODE associated with it,
9697 * just use the one for the printer. A NULL devicemode is not
9698 * a failure condition
9701 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9703 result = spoolss_create_default_devmode(mem_ctx,
9704 pinfo2->printername,
9706 if (!W_ERROR_IS_OK(result)) {
9707 DEBUG(3, ("Can't proceed w/o a devmode!"));
9712 return fill_job_info2(mem_ctx,
9722 /****************************************************************
9724 ****************************************************************/
9726 WERROR _spoolss_GetJob(struct pipes_struct *p,
9727 struct spoolss_GetJob *r)
9729 WERROR result = WERR_OK;
9730 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9731 const char *svc_name;
9735 struct tdb_print_db *pdb;
9736 print_queue_struct *queue = NULL;
9737 print_status_struct prt_status;
9739 /* that's an [in out] buffer */
9741 if (!r->in.buffer && (r->in.offered != 0)) {
9742 result = WERR_INVALID_PARAMETER;
9743 goto err_jinfo_free;
9746 DEBUG(5,("_spoolss_GetJob\n"));
9750 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9751 result = WERR_INVALID_HANDLE;
9752 goto err_jinfo_free;
9755 svc_name = lp_const_servicename(snum);
9756 if (svc_name == NULL) {
9757 result = WERR_INVALID_PARAMETER;
9758 goto err_jinfo_free;
9761 result = winreg_get_printer_internal(p->mem_ctx,
9762 get_session_info_system(),
9766 if (!W_ERROR_IS_OK(result)) {
9767 goto err_jinfo_free;
9770 pdb = get_print_db_byname(svc_name);
9772 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9773 result = WERR_INVALID_PARAMETER;
9774 goto err_pinfo_free;
9777 sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9778 release_print_db(pdb);
9780 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9781 result = WERR_INVALID_PARAMETER;
9782 goto err_pinfo_free;
9785 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9787 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9788 count, prt_status.status, prt_status.message));
9790 switch (r->in.level) {
9792 result = getjob_level_1(p->mem_ctx,
9793 queue, count, snum, pinfo2,
9794 r->in.job_id, sysjob,
9795 &r->out.info->info1);
9798 result = getjob_level_2(p->mem_ctx,
9799 queue, count, snum, pinfo2,
9800 r->in.job_id, sysjob,
9801 &r->out.info->info2);
9804 result = WERR_INVALID_LEVEL;
9809 TALLOC_FREE(pinfo2);
9811 if (!W_ERROR_IS_OK(result)) {
9812 goto err_jinfo_free;
9815 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9817 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9819 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9822 TALLOC_FREE(pinfo2);
9824 TALLOC_FREE(r->out.info);
9828 /****************************************************************
9829 _spoolss_GetPrinterDataEx
9830 ****************************************************************/
9832 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9833 struct spoolss_GetPrinterDataEx *r)
9836 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9837 const char *printer;
9839 WERROR result = WERR_OK;
9841 enum winreg_Type val_type = REG_NONE;
9842 uint8_t *val_data = NULL;
9843 uint32_t val_size = 0;
9844 struct dcerpc_binding_handle *b;
9845 TALLOC_CTX *tmp_ctx;
9847 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9849 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9850 r->in.key_name, r->in.value_name));
9852 /* in case of problem, return some default values */
9855 *r->out.type = REG_NONE;
9857 tmp_ctx = talloc_new(p->mem_ctx);
9859 return WERR_NOT_ENOUGH_MEMORY;
9863 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9864 OUR_HANDLE(r->in.handle)));
9865 result = WERR_INVALID_HANDLE;
9869 /* Is the handle to a printer or to the server? */
9871 if (Printer->printer_type == SPLHND_SERVER) {
9873 union spoolss_PrinterData data;
9875 result = getprinterdata_printer_server(tmp_ctx,
9879 if (!W_ERROR_IS_OK(result)) {
9883 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9884 *r->out.type, &data);
9885 if (!W_ERROR_IS_OK(result)) {
9889 *r->out.needed = blob.length;
9891 if (r->in.offered >= *r->out.needed) {
9892 memcpy(r->out.data, blob.data, blob.length);
9899 /* check to see if the keyname is valid */
9900 if (!strlen(r->in.key_name)) {
9901 result = WERR_INVALID_PARAMETER;
9905 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9906 result = WERR_INVALID_HANDLE;
9909 printer = lp_const_servicename(snum);
9911 result = winreg_printer_binding_handle(tmp_ctx,
9912 get_session_info_system(),
9915 if (!W_ERROR_IS_OK(result)) {
9919 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9920 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9921 strequal(r->in.value_name, "ChangeId")) {
9922 *r->out.type = REG_DWORD;
9924 if (r->in.offered >= *r->out.needed) {
9925 uint32_t changeid = 0;
9927 result = winreg_printer_get_changeid(tmp_ctx, b,
9930 if (!W_ERROR_IS_OK(result)) {
9934 SIVAL(r->out.data, 0, changeid);
9940 result = winreg_get_printer_dataex(tmp_ctx, b,
9947 if (!W_ERROR_IS_OK(result)) {
9951 *r->out.needed = val_size;
9952 *r->out.type = val_type;
9954 if (r->in.offered >= *r->out.needed) {
9955 memcpy(r->out.data, val_data, val_size);
9959 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9961 if (W_ERROR_IS_OK(result)) {
9962 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9965 talloc_free(tmp_ctx);
9969 /****************************************************************
9970 _spoolss_SetPrinterDataEx
9971 ****************************************************************/
9973 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9974 struct spoolss_SetPrinterDataEx *r)
9976 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9978 WERROR result = WERR_OK;
9979 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9981 struct dcerpc_binding_handle *b;
9982 TALLOC_CTX *tmp_ctx;
9984 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9986 /* From MSDN documentation of SetPrinterDataEx: pass request to
9987 SetPrinterData if key is "PrinterDriverData" */
9990 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9991 OUR_HANDLE(r->in.handle)));
9992 return WERR_INVALID_HANDLE;
9995 if (Printer->printer_type == SPLHND_SERVER) {
9996 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9997 "Not implemented for server handles yet\n"));
9998 return WERR_INVALID_PARAMETER;
10001 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10002 return WERR_INVALID_HANDLE;
10006 * Access check : NT returns "access denied" if you make a
10007 * SetPrinterData call without the necessary privildge.
10008 * we were originally returning OK if nothing changed
10009 * which made Win2k issue **a lot** of SetPrinterData
10010 * when connecting to a printer --jerry
10013 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10014 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10015 "change denied by handle access permissions\n"));
10016 return WERR_ACCESS_DENIED;
10019 tmp_ctx = talloc_new(p->mem_ctx);
10021 return WERR_NOT_ENOUGH_MEMORY;
10024 result = winreg_printer_binding_handle(tmp_ctx,
10025 get_session_info_system(),
10028 if (!W_ERROR_IS_OK(result)) {
10032 result = winreg_get_printer(tmp_ctx, b,
10033 lp_servicename(talloc_tos(), snum),
10035 if (!W_ERROR_IS_OK(result)) {
10039 /* check for OID in valuename */
10041 oid_string = strchr(r->in.value_name, ',');
10043 *oid_string = '\0';
10047 /* save the registry data */
10049 result = winreg_set_printer_dataex(tmp_ctx, b,
10057 if (W_ERROR_IS_OK(result)) {
10058 /* save the OID if one was specified */
10060 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10061 r->in.key_name, SPOOL_OID_KEY);
10063 result = WERR_NOT_ENOUGH_MEMORY;
10068 * I'm not checking the status here on purpose. Don't know
10069 * if this is right, but I'm returning the status from the
10070 * previous set_printer_dataex() call. I have no idea if
10071 * this is right. --jerry
10073 winreg_set_printer_dataex(tmp_ctx, b,
10078 (uint8_t *) oid_string,
10079 strlen(oid_string) + 1);
10082 result = winreg_printer_update_changeid(tmp_ctx, b,
10083 lp_const_servicename(snum));
10088 talloc_free(tmp_ctx);
10092 /****************************************************************
10093 _spoolss_DeletePrinterDataEx
10094 ****************************************************************/
10096 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10097 struct spoolss_DeletePrinterDataEx *r)
10099 const char *printer;
10101 WERROR status = WERR_OK;
10102 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10104 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10107 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10108 "Invalid handle (%s:%u:%u).\n",
10109 OUR_HANDLE(r->in.handle)));
10110 return WERR_INVALID_HANDLE;
10113 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10114 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10115 "printer properties change denied by handle\n"));
10116 return WERR_ACCESS_DENIED;
10119 if (!r->in.value_name || !r->in.key_name) {
10120 return WERR_NOT_ENOUGH_MEMORY;
10123 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10124 return WERR_INVALID_HANDLE;
10126 printer = lp_const_servicename(snum);
10128 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10129 get_session_info_system(),
10134 if (W_ERROR_IS_OK(status)) {
10135 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10136 get_session_info_system(),
10144 /****************************************************************
10145 _spoolss_EnumPrinterKey
10146 ****************************************************************/
10148 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10149 struct spoolss_EnumPrinterKey *r)
10152 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10154 WERROR result = WERR_FILE_NOT_FOUND;
10155 const char **array = NULL;
10158 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10161 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10162 OUR_HANDLE(r->in.handle)));
10163 return WERR_INVALID_HANDLE;
10166 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10167 return WERR_INVALID_HANDLE;
10170 result = winreg_enum_printer_key_internal(p->mem_ctx,
10171 get_session_info_system(),
10173 lp_const_servicename(snum),
10177 if (!W_ERROR_IS_OK(result)) {
10181 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10182 result = WERR_NOT_ENOUGH_MEMORY;
10186 *r->out._ndr_size = r->in.offered / 2;
10187 *r->out.needed = blob.length;
10189 if (r->in.offered < *r->out.needed) {
10190 result = WERR_MORE_DATA;
10193 r->out.key_buffer->string_array = array;
10197 if (!W_ERROR_IS_OK(result)) {
10198 TALLOC_FREE(array);
10199 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10200 *r->out.needed = 0;
10207 /****************************************************************
10208 _spoolss_DeletePrinterKey
10209 ****************************************************************/
10211 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10212 struct spoolss_DeletePrinterKey *r)
10214 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10217 const char *printer;
10218 struct dcerpc_binding_handle *b;
10219 TALLOC_CTX *tmp_ctx;
10221 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10224 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10225 OUR_HANDLE(r->in.handle)));
10226 return WERR_INVALID_HANDLE;
10229 /* if keyname == NULL, return error */
10230 if ( !r->in.key_name )
10231 return WERR_INVALID_PARAMETER;
10233 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10234 return WERR_INVALID_HANDLE;
10237 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10238 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10239 "printer properties change denied by handle\n"));
10240 return WERR_ACCESS_DENIED;
10243 printer = lp_const_servicename(snum);
10245 tmp_ctx = talloc_new(p->mem_ctx);
10247 return WERR_NOT_ENOUGH_MEMORY;
10250 status = winreg_printer_binding_handle(tmp_ctx,
10251 get_session_info_system(),
10254 if (!W_ERROR_IS_OK(status)) {
10258 /* delete the key and all subkeys */
10259 status = winreg_delete_printer_key(tmp_ctx, b,
10262 if (W_ERROR_IS_OK(status)) {
10263 status = winreg_printer_update_changeid(tmp_ctx, b,
10268 talloc_free(tmp_ctx);
10272 /****************************************************************
10273 _spoolss_EnumPrinterDataEx
10274 ****************************************************************/
10276 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10277 struct spoolss_EnumPrinterDataEx *r)
10279 uint32_t count = 0;
10280 struct spoolss_PrinterEnumValues *info = NULL;
10281 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10285 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10288 *r->out.needed = 0;
10289 *r->out.info = NULL;
10292 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10293 OUR_HANDLE(r->in.handle)));
10294 return WERR_INVALID_HANDLE;
10298 * first check for a keyname of NULL or "". Win2k seems to send
10299 * this a lot and we should send back WERR_INVALID_PARAMETER
10300 * no need to spend time looking up the printer in this case.
10304 if (!strlen(r->in.key_name)) {
10305 result = WERR_INVALID_PARAMETER;
10309 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10310 return WERR_INVALID_HANDLE;
10313 /* now look for a match on the key name */
10314 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10315 get_session_info_system(),
10317 lp_const_servicename(snum),
10321 if (!W_ERROR_IS_OK(result)) {
10325 #if 0 /* FIXME - gd */
10326 /* housekeeping information in the reply */
10328 /* Fix from Martin Zielinski <mz@seh.de> - ensure
10329 * the hand marshalled container size is a multiple
10330 * of 4 bytes for RPC alignment.
10334 needed += 4-(needed % 4);
10337 *r->out.count = count;
10338 *r->out.info = info;
10341 if (!W_ERROR_IS_OK(result)) {
10345 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10346 spoolss_EnumPrinterDataEx,
10349 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10350 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10352 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10355 /****************************************************************************
10356 ****************************************************************************/
10358 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10359 const char *servername,
10360 const char *environment,
10361 struct spoolss_PrintProcessorDirectoryInfo1 *r)
10366 werr = compose_spoolss_server_path(mem_ctx,
10369 SPOOLSS_PRTPROCS_PATH,
10371 if (!W_ERROR_IS_OK(werr)) {
10375 DEBUG(4,("print processor directory: [%s]\n", path));
10377 r->directory_name = path;
10382 /****************************************************************
10383 _spoolss_GetPrintProcessorDirectory
10384 ****************************************************************/
10386 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10387 struct spoolss_GetPrintProcessorDirectory *r)
10390 char *prnproc_share = NULL;
10391 bool prnproc_share_exists = false;
10394 /* that's an [in out] buffer */
10396 if (!r->in.buffer && (r->in.offered != 0)) {
10397 result = WERR_INVALID_PARAMETER;
10398 goto err_info_free;
10401 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10404 *r->out.needed = 0;
10406 /* r->in.level is ignored */
10408 /* We always should reply with a local print processor directory so that
10409 * users are not forced to have a [prnproc$] share on the Samba spoolss
10410 * server, if users decide to do so, lets announce it though - Guenther */
10412 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10413 if (!prnproc_share) {
10414 result = WERR_NOT_ENOUGH_MEMORY;
10415 goto err_info_free;
10418 prnproc_share_exists = true;
10421 result = getprintprocessordirectory_level_1(p->mem_ctx,
10422 prnproc_share_exists ? r->in.server : NULL,
10424 &r->out.info->info1);
10425 if (!W_ERROR_IS_OK(result)) {
10426 goto err_info_free;
10429 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10430 r->out.info, r->in.level);
10431 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10433 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10436 TALLOC_FREE(r->out.info);
10440 /*******************************************************************
10441 ********************************************************************/
10443 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10444 const char *dllname)
10446 enum ndr_err_code ndr_err;
10447 struct spoolss_MonitorUi ui;
10449 ui.dll_name = dllname;
10451 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10452 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10453 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10454 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10456 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10459 /*******************************************************************
10460 Streams the monitor UI DLL name in UNICODE
10461 *******************************************************************/
10463 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10464 struct security_token *token, DATA_BLOB *in,
10465 DATA_BLOB *out, uint32_t *needed)
10467 const char *dllname = "tcpmonui.dll";
10469 *needed = (strlen(dllname)+1) * 2;
10471 if (out->length < *needed) {
10472 return WERR_INSUFFICIENT_BUFFER;
10475 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10476 return WERR_NOT_ENOUGH_MEMORY;
10482 /*******************************************************************
10483 ********************************************************************/
10485 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10486 struct spoolss_PortData1 *port1,
10487 const DATA_BLOB *buf)
10489 enum ndr_err_code ndr_err;
10490 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10491 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10492 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10493 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10495 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10498 /*******************************************************************
10499 ********************************************************************/
10501 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10502 struct spoolss_PortData2 *port2,
10503 const DATA_BLOB *buf)
10505 enum ndr_err_code ndr_err;
10506 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10507 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10508 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10509 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10511 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10514 /*******************************************************************
10515 Create a new TCP/IP port
10516 *******************************************************************/
10518 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10519 struct security_token *token, DATA_BLOB *in,
10520 DATA_BLOB *out, uint32_t *needed)
10522 struct spoolss_PortData1 port1;
10523 struct spoolss_PortData2 port2;
10524 char *device_uri = NULL;
10527 const char *portname;
10528 const char *hostaddress;
10530 uint32_t port_number;
10533 /* peek for spoolss_PortData version */
10535 if (!in || (in->length < (128 + 4))) {
10536 return WERR_GEN_FAILURE;
10539 version = IVAL(in->data, 128);
10543 ZERO_STRUCT(port1);
10545 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10546 return WERR_NOT_ENOUGH_MEMORY;
10549 portname = port1.portname;
10550 hostaddress = port1.hostaddress;
10551 queue = port1.queue;
10552 protocol = port1.protocol;
10553 port_number = port1.port_number;
10557 ZERO_STRUCT(port2);
10559 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10560 return WERR_NOT_ENOUGH_MEMORY;
10563 portname = port2.portname;
10564 hostaddress = port2.hostaddress;
10565 queue = port2.queue;
10566 protocol = port2.protocol;
10567 port_number = port2.port_number;
10571 DEBUG(1,("xcvtcp_addport: "
10572 "unknown version of port_data: %d\n", version));
10573 return WERR_UNKNOWN_PORT;
10576 /* create the device URI and call the add_port_hook() */
10578 switch (protocol) {
10579 case PROTOCOL_RAWTCP_TYPE:
10580 device_uri = talloc_asprintf(mem_ctx,
10581 "socket://%s:%d/", hostaddress,
10585 case PROTOCOL_LPR_TYPE:
10586 device_uri = talloc_asprintf(mem_ctx,
10587 "lpr://%s/%s", hostaddress, queue );
10591 return WERR_UNKNOWN_PORT;
10595 return WERR_NOT_ENOUGH_MEMORY;
10598 return add_port_hook(mem_ctx, token, portname, device_uri);
10601 /*******************************************************************
10602 *******************************************************************/
10604 struct xcv_api_table xcvtcp_cmds[] = {
10605 { "MonitorUI", xcvtcp_monitorui },
10606 { "AddPort", xcvtcp_addport},
10610 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10611 struct security_token *token, const char *command,
10618 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10620 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10621 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10622 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10625 return WERR_INVALID_FUNCTION;
10628 /*******************************************************************
10629 *******************************************************************/
10630 #if 0 /* don't support management using the "Local Port" monitor */
10632 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10633 struct security_token *token, DATA_BLOB *in,
10634 DATA_BLOB *out, uint32_t *needed)
10636 const char *dllname = "localui.dll";
10638 *needed = (strlen(dllname)+1) * 2;
10640 if (out->length < *needed) {
10641 return WERR_INSUFFICIENT_BUFFER;
10644 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10645 return WERR_NOT_ENOUGH_MEMORY;
10651 /*******************************************************************
10652 *******************************************************************/
10654 struct xcv_api_table xcvlocal_cmds[] = {
10655 { "MonitorUI", xcvlocal_monitorui },
10659 struct xcv_api_table xcvlocal_cmds[] = {
10666 /*******************************************************************
10667 *******************************************************************/
10669 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10670 struct security_token *token, const char *command,
10671 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10676 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10678 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10679 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10680 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10682 return WERR_INVALID_FUNCTION;
10685 /****************************************************************
10687 ****************************************************************/
10689 WERROR _spoolss_XcvData(struct pipes_struct *p,
10690 struct spoolss_XcvData *r)
10692 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10693 DATA_BLOB out_data = data_blob_null;
10697 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10698 OUR_HANDLE(r->in.handle)));
10699 return WERR_INVALID_HANDLE;
10702 /* Has to be a handle to the TCP/IP port monitor */
10704 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10705 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10706 return WERR_INVALID_HANDLE;
10709 /* requires administrative access to the server */
10711 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10712 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10713 return WERR_ACCESS_DENIED;
10716 /* Allocate the outgoing buffer */
10718 if (r->in.out_data_size) {
10719 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10720 if (out_data.data == NULL) {
10721 return WERR_NOT_ENOUGH_MEMORY;
10725 switch ( Printer->printer_type ) {
10726 case SPLHND_PORTMON_TCP:
10727 werror = process_xcvtcp_command(p->mem_ctx,
10728 p->session_info->security_token,
10729 r->in.function_name,
10730 &r->in.in_data, &out_data,
10733 case SPLHND_PORTMON_LOCAL:
10734 werror = process_xcvlocal_command(p->mem_ctx,
10735 p->session_info->security_token,
10736 r->in.function_name,
10737 &r->in.in_data, &out_data,
10741 werror = WERR_INVALID_PRINT_MONITOR;
10744 if (!W_ERROR_IS_OK(werror)) {
10748 *r->out.status_code = 0;
10750 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10751 memcpy(r->out.out_data, out_data.data,
10752 MIN(r->in.out_data_size, out_data.length));
10758 /****************************************************************
10759 _spoolss_AddPrintProcessor
10760 ****************************************************************/
10762 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10763 struct spoolss_AddPrintProcessor *r)
10765 /* for now, just indicate success and ignore the add. We'll
10766 automatically set the winprint processor for printer
10767 entries later. Used to debug the LexMark Optra S 1855 PCL
10773 /****************************************************************
10775 ****************************************************************/
10777 WERROR _spoolss_AddPort(struct pipes_struct *p,
10778 struct spoolss_AddPort *r)
10780 /* do what w2k3 does */
10782 return WERR_NOT_SUPPORTED;
10785 /****************************************************************
10786 _spoolss_GetPrinterDriver
10787 ****************************************************************/
10789 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10790 struct spoolss_GetPrinterDriver *r)
10792 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10793 return WERR_NOT_SUPPORTED;
10796 /****************************************************************
10797 _spoolss_ReadPrinter
10798 ****************************************************************/
10800 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10801 struct spoolss_ReadPrinter *r)
10803 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10804 return WERR_NOT_SUPPORTED;
10807 /****************************************************************
10808 _spoolss_WaitForPrinterChange
10809 ****************************************************************/
10811 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10812 struct spoolss_WaitForPrinterChange *r)
10814 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10815 return WERR_NOT_SUPPORTED;
10818 /****************************************************************
10819 _spoolss_ConfigurePort
10820 ****************************************************************/
10822 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10823 struct spoolss_ConfigurePort *r)
10825 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10826 return WERR_NOT_SUPPORTED;
10829 /****************************************************************
10830 _spoolss_DeletePort
10831 ****************************************************************/
10833 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10834 struct spoolss_DeletePort *r)
10836 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10837 return WERR_NOT_SUPPORTED;
10840 /****************************************************************
10841 _spoolss_CreatePrinterIC
10842 ****************************************************************/
10844 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10845 struct spoolss_CreatePrinterIC *r)
10847 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10848 return WERR_NOT_SUPPORTED;
10851 /****************************************************************
10852 _spoolss_PlayGDIScriptOnPrinterIC
10853 ****************************************************************/
10855 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10856 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10858 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10859 return WERR_NOT_SUPPORTED;
10862 /****************************************************************
10863 _spoolss_DeletePrinterIC
10864 ****************************************************************/
10866 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10867 struct spoolss_DeletePrinterIC *r)
10869 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10870 return WERR_NOT_SUPPORTED;
10873 /****************************************************************
10874 _spoolss_AddPrinterConnection
10875 ****************************************************************/
10877 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10878 struct spoolss_AddPrinterConnection *r)
10880 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10881 return WERR_NOT_SUPPORTED;
10884 /****************************************************************
10885 _spoolss_DeletePrinterConnection
10886 ****************************************************************/
10888 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10889 struct spoolss_DeletePrinterConnection *r)
10891 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10892 return WERR_NOT_SUPPORTED;
10895 /****************************************************************
10896 _spoolss_PrinterMessageBox
10897 ****************************************************************/
10899 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10900 struct spoolss_PrinterMessageBox *r)
10902 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10903 return WERR_NOT_SUPPORTED;
10906 /****************************************************************
10907 _spoolss_AddMonitor
10908 ****************************************************************/
10910 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10911 struct spoolss_AddMonitor *r)
10913 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10914 return WERR_NOT_SUPPORTED;
10917 /****************************************************************
10918 _spoolss_DeleteMonitor
10919 ****************************************************************/
10921 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10922 struct spoolss_DeleteMonitor *r)
10924 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10925 return WERR_NOT_SUPPORTED;
10928 /****************************************************************
10929 _spoolss_DeletePrintProcessor
10930 ****************************************************************/
10932 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10933 struct spoolss_DeletePrintProcessor *r)
10935 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10936 return WERR_NOT_SUPPORTED;
10939 /****************************************************************
10940 _spoolss_AddPrintProvidor
10941 ****************************************************************/
10943 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10944 struct spoolss_AddPrintProvidor *r)
10946 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10947 return WERR_NOT_SUPPORTED;
10950 /****************************************************************
10951 _spoolss_DeletePrintProvidor
10952 ****************************************************************/
10954 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10955 struct spoolss_DeletePrintProvidor *r)
10957 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10958 return WERR_NOT_SUPPORTED;
10961 /****************************************************************
10962 _spoolss_FindFirstPrinterChangeNotification
10963 ****************************************************************/
10965 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10966 struct spoolss_FindFirstPrinterChangeNotification *r)
10968 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10969 return WERR_NOT_SUPPORTED;
10972 /****************************************************************
10973 _spoolss_FindNextPrinterChangeNotification
10974 ****************************************************************/
10976 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10977 struct spoolss_FindNextPrinterChangeNotification *r)
10979 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10980 return WERR_NOT_SUPPORTED;
10983 /****************************************************************
10984 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10985 ****************************************************************/
10987 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10988 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10990 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10991 return WERR_NOT_SUPPORTED;
10994 /****************************************************************
10995 _spoolss_ReplyOpenPrinter
10996 ****************************************************************/
10998 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10999 struct spoolss_ReplyOpenPrinter *r)
11001 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11002 return WERR_NOT_SUPPORTED;
11005 /****************************************************************
11006 _spoolss_RouterReplyPrinter
11007 ****************************************************************/
11009 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11010 struct spoolss_RouterReplyPrinter *r)
11012 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11013 return WERR_NOT_SUPPORTED;
11016 /****************************************************************
11017 _spoolss_ReplyClosePrinter
11018 ****************************************************************/
11020 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11021 struct spoolss_ReplyClosePrinter *r)
11023 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11024 return WERR_NOT_SUPPORTED;
11027 /****************************************************************
11029 ****************************************************************/
11031 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11032 struct spoolss_AddPortEx *r)
11034 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11035 return WERR_NOT_SUPPORTED;
11038 /****************************************************************
11039 _spoolss_RouterFindFirstPrinterChangeNotification
11040 ****************************************************************/
11042 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11043 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11045 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11046 return WERR_NOT_SUPPORTED;
11049 /****************************************************************
11050 _spoolss_SpoolerInit
11051 ****************************************************************/
11053 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11054 struct spoolss_SpoolerInit *r)
11056 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11057 return WERR_NOT_SUPPORTED;
11060 /****************************************************************
11061 _spoolss_ResetPrinterEx
11062 ****************************************************************/
11064 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11065 struct spoolss_ResetPrinterEx *r)
11067 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11068 return WERR_NOT_SUPPORTED;
11071 /****************************************************************
11072 _spoolss_RouterReplyPrinterEx
11073 ****************************************************************/
11075 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11076 struct spoolss_RouterReplyPrinterEx *r)
11078 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11079 return WERR_NOT_SUPPORTED;
11082 /****************************************************************
11084 ****************************************************************/
11086 WERROR _spoolss_44(struct pipes_struct *p,
11087 struct spoolss_44 *r)
11089 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11090 return WERR_NOT_SUPPORTED;
11093 /****************************************************************
11095 ****************************************************************/
11097 WERROR _spoolss_SetPort(struct pipes_struct *p,
11098 struct spoolss_SetPort *r)
11100 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11101 return WERR_NOT_SUPPORTED;
11104 /****************************************************************
11106 ****************************************************************/
11108 WERROR _spoolss_4a(struct pipes_struct *p,
11109 struct spoolss_4a *r)
11111 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11112 return WERR_NOT_SUPPORTED;
11115 /****************************************************************
11117 ****************************************************************/
11119 WERROR _spoolss_4b(struct pipes_struct *p,
11120 struct spoolss_4b *r)
11122 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11123 return WERR_NOT_SUPPORTED;
11126 /****************************************************************
11128 ****************************************************************/
11130 WERROR _spoolss_4c(struct pipes_struct *p,
11131 struct spoolss_4c *r)
11133 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11134 return WERR_NOT_SUPPORTED;
11137 /****************************************************************
11139 ****************************************************************/
11141 WERROR _spoolss_53(struct pipes_struct *p,
11142 struct spoolss_53 *r)
11144 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11145 return WERR_NOT_SUPPORTED;
11148 /****************************************************************
11149 _spoolss_AddPerMachineConnection
11150 ****************************************************************/
11152 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11153 struct spoolss_AddPerMachineConnection *r)
11155 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11156 return WERR_NOT_SUPPORTED;
11159 /****************************************************************
11160 _spoolss_DeletePerMachineConnection
11161 ****************************************************************/
11163 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11164 struct spoolss_DeletePerMachineConnection *r)
11166 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11167 return WERR_NOT_SUPPORTED;
11170 /****************************************************************
11171 _spoolss_EnumPerMachineConnections
11172 ****************************************************************/
11174 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11175 struct spoolss_EnumPerMachineConnections *r)
11177 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11178 return WERR_NOT_SUPPORTED;
11181 /****************************************************************
11183 ****************************************************************/
11185 WERROR _spoolss_5a(struct pipes_struct *p,
11186 struct spoolss_5a *r)
11188 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11189 return WERR_NOT_SUPPORTED;
11192 /****************************************************************
11194 ****************************************************************/
11196 WERROR _spoolss_5b(struct pipes_struct *p,
11197 struct spoolss_5b *r)
11199 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11200 return WERR_NOT_SUPPORTED;
11203 /****************************************************************
11205 ****************************************************************/
11207 WERROR _spoolss_5c(struct pipes_struct *p,
11208 struct spoolss_5c *r)
11210 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11211 return WERR_NOT_SUPPORTED;
11214 /****************************************************************
11216 ****************************************************************/
11218 WERROR _spoolss_5d(struct pipes_struct *p,
11219 struct spoolss_5d *r)
11221 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11222 return WERR_NOT_SUPPORTED;
11225 /****************************************************************
11227 ****************************************************************/
11229 WERROR _spoolss_5e(struct pipes_struct *p,
11230 struct spoolss_5e *r)
11232 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11233 return WERR_NOT_SUPPORTED;
11236 /****************************************************************
11238 ****************************************************************/
11240 WERROR _spoolss_5f(struct pipes_struct *p,
11241 struct spoolss_5f *r)
11243 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11244 return WERR_NOT_SUPPORTED;
11247 /****************************************************************
11249 ****************************************************************/
11251 WERROR _spoolss_60(struct pipes_struct *p,
11252 struct spoolss_60 *r)
11254 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11255 return WERR_NOT_SUPPORTED;
11258 /****************************************************************
11259 _spoolss_SendRecvBidiData
11260 ****************************************************************/
11262 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11263 struct spoolss_SendRecvBidiData *r)
11265 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11266 return WERR_NOT_SUPPORTED;
11269 /****************************************************************
11271 ****************************************************************/
11273 WERROR _spoolss_62(struct pipes_struct *p,
11274 struct spoolss_62 *r)
11276 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11277 return WERR_NOT_SUPPORTED;
11280 /****************************************************************
11282 ****************************************************************/
11284 WERROR _spoolss_63(struct pipes_struct *p,
11285 struct spoolss_63 *r)
11287 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11288 return WERR_NOT_SUPPORTED;
11291 /****************************************************************
11293 ****************************************************************/
11295 WERROR _spoolss_64(struct pipes_struct *p,
11296 struct spoolss_64 *r)
11298 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11299 return WERR_NOT_SUPPORTED;
11302 /****************************************************************
11304 ****************************************************************/
11306 WERROR _spoolss_65(struct pipes_struct *p,
11307 struct spoolss_65 *r)
11309 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11310 return WERR_NOT_SUPPORTED;
11313 /****************************************************************
11314 _spoolss_GetCorePrinterDrivers
11315 ****************************************************************/
11317 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11318 struct spoolss_GetCorePrinterDrivers *r)
11320 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11321 return HRES_ERROR_NOT_SUPPORTED;
11324 /****************************************************************
11326 ****************************************************************/
11328 WERROR _spoolss_67(struct pipes_struct *p,
11329 struct spoolss_67 *r)
11331 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11332 return WERR_NOT_SUPPORTED;
11335 /****************************************************************
11336 _spoolss_GetPrinterDriverPackagePath
11337 ****************************************************************/
11339 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11340 struct spoolss_GetPrinterDriverPackagePath *r)
11342 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11343 return HRES_ERROR_NOT_SUPPORTED;
11346 /****************************************************************
11348 ****************************************************************/
11350 WERROR _spoolss_69(struct pipes_struct *p,
11351 struct spoolss_69 *r)
11353 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11354 return WERR_NOT_SUPPORTED;
11357 /****************************************************************
11359 ****************************************************************/
11361 WERROR _spoolss_6a(struct pipes_struct *p,
11362 struct spoolss_6a *r)
11364 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11365 return WERR_NOT_SUPPORTED;
11368 /****************************************************************
11370 ****************************************************************/
11372 WERROR _spoolss_6b(struct pipes_struct *p,
11373 struct spoolss_6b *r)
11375 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11376 return WERR_NOT_SUPPORTED;
11379 /****************************************************************
11381 ****************************************************************/
11383 WERROR _spoolss_6c(struct pipes_struct *p,
11384 struct spoolss_6c *r)
11386 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11387 return WERR_NOT_SUPPORTED;
11390 /****************************************************************
11392 ****************************************************************/
11394 WERROR _spoolss_6d(struct pipes_struct *p,
11395 struct spoolss_6d *r)
11397 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11398 return WERR_NOT_SUPPORTED;
11401 /****************************************************************
11402 _spoolss_GetJobNamedPropertyValue
11403 ****************************************************************/
11405 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11406 struct spoolss_GetJobNamedPropertyValue *r)
11408 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11409 return WERR_NOT_SUPPORTED;
11412 /****************************************************************
11413 _spoolss_SetJobNamedProperty
11414 ****************************************************************/
11416 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11417 struct spoolss_SetJobNamedProperty *r)
11419 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11420 return WERR_NOT_SUPPORTED;
11423 /****************************************************************
11424 _spoolss_DeleteJobNamedProperty
11425 ****************************************************************/
11427 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11428 struct spoolss_DeleteJobNamedProperty *r)
11430 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11431 return WERR_NOT_SUPPORTED;
11434 /****************************************************************
11435 _spoolss_EnumJobNamedProperties
11436 ****************************************************************/
11438 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11439 struct spoolss_EnumJobNamedProperties *r)
11441 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11442 return WERR_NOT_SUPPORTED;
11445 /****************************************************************
11447 ****************************************************************/
11449 WERROR _spoolss_72(struct pipes_struct *p,
11450 struct spoolss_72 *r)
11452 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11453 return WERR_NOT_SUPPORTED;
11456 /****************************************************************
11458 ****************************************************************/
11460 WERROR _spoolss_73(struct pipes_struct *p,
11461 struct spoolss_73 *r)
11463 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11464 return WERR_NOT_SUPPORTED;
11467 /****************************************************************
11468 _spoolss_RpcLogJobInfoForBranchOffice
11469 ****************************************************************/
11471 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11472 struct spoolss_LogJobInfoForBranchOffice *r)
11474 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11475 return WERR_NOT_SUPPORTED;