2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
44 #include "../librpc/gen_ndr/netlogon.h"
46 #include "printing/notify.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
55 /* macros stolen from s4 spoolss server */
56 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
57 ((info)?ndr_size_##fn(info, level, 0):0)
59 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
60 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
62 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
63 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
65 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
68 #define DBGC_CLASS DBGC_RPC_SRV
70 #ifndef MAX_OPEN_PRINTER_EXS
71 #define MAX_OPEN_PRINTER_EXS 50
74 struct notify_back_channel;
76 /* structure to store the printer handles */
77 /* and a reference to what it's pointing to */
78 /* and the notify info asked about */
79 /* that's the central struct */
80 struct printer_handle {
81 struct printer_handle *prev, *next;
82 bool document_started;
84 uint32 jobid; /* jobid in printing backend */
86 const char *servername;
89 uint32 access_granted;
95 struct spoolss_NotifyOption *option;
96 struct policy_handle cli_hnd;
97 struct notify_back_channel *cli_chan;
99 /* are we in a FindNextPrinterChangeNotify() call? */
101 struct messaging_context *msg_ctx;
108 /* devmode sent in the OpenPrinter() call */
109 struct spoolss_DeviceMode *devmode;
111 /* TODO cache the printer info2 structure */
112 struct spoolss_PrinterInfo2 *info2;
116 static struct printer_handle *printers_list;
118 struct printer_session_counter {
119 struct printer_session_counter *next;
120 struct printer_session_counter *prev;
126 static struct printer_session_counter *counter_list;
128 struct notify_back_channel {
129 struct notify_back_channel *prev, *next;
131 /* associated client */
132 struct sockaddr_storage client_address;
134 /* print notify back-channel pipe handle*/
135 struct rpc_pipe_client *cli_pipe;
136 struct dcerpc_binding_handle *binding_handle;
137 uint32_t active_connections;
140 static struct notify_back_channel *back_channels;
142 /* Map generic permissions to printer object specific permissions */
144 const struct standard_mapping printer_std_mapping = {
151 /* Map generic permissions to print server object specific permissions */
153 const struct standard_mapping printserver_std_mapping = {
160 /* API table for Xcv Monitor functions */
162 struct xcv_api_table {
164 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
167 static void prune_printername_cache(void);
169 /********************************************************************
170 * Canonicalize servername.
171 ********************************************************************/
173 static const char *canon_servername(const char *servername)
175 const char *pservername = servername;
176 while (*pservername == '\\') {
182 /* translate between internal status numbers and NT status numbers */
183 static int nt_printj_status(int v)
189 return JOB_STATUS_PAUSED;
191 return JOB_STATUS_SPOOLING;
193 return JOB_STATUS_PRINTING;
195 return JOB_STATUS_ERROR;
197 return JOB_STATUS_DELETING;
199 return JOB_STATUS_OFFLINE;
201 return JOB_STATUS_PAPEROUT;
203 return JOB_STATUS_PRINTED;
205 return JOB_STATUS_DELETED;
207 return JOB_STATUS_BLOCKED_DEVQ;
208 case LPQ_USER_INTERVENTION:
209 return JOB_STATUS_USER_INTERVENTION;
214 static int nt_printq_status(int v)
218 return PRINTER_STATUS_PAUSED;
227 /***************************************************************************
228 Disconnect from the client
229 ****************************************************************************/
231 static void srv_spoolss_replycloseprinter(int snum,
232 struct printer_handle *prn_hnd)
238 * Tell the specific printing tdb we no longer want messages for this printer
239 * by deregistering our PID.
242 if (!print_notify_deregister_pid(snum)) {
243 DEBUG(0, ("Failed to register our pid for printer %s\n",
244 lp_const_servicename(snum)));
247 /* weird if the test succeeds !!! */
248 if (prn_hnd->notify.cli_chan == NULL ||
249 prn_hnd->notify.cli_chan->active_connections == 0) {
250 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
251 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
252 TALLOC_FREE(prn_hnd->notify.cli_chan);
256 status = dcerpc_spoolss_ReplyClosePrinter(
257 prn_hnd->notify.cli_chan->binding_handle,
259 &prn_hnd->notify.cli_hnd,
261 if (!NT_STATUS_IS_OK(status)) {
262 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
264 result = ntstatus_to_werror(status);
265 } else if (!W_ERROR_IS_OK(result)) {
266 DEBUG(0, ("reply_close_printer failed [%s].\n",
267 win_errstr(result)));
270 /* if it's the last connection, deconnect the IPC$ share */
271 if (prn_hnd->notify.cli_chan->active_connections == 1) {
273 prn_hnd->notify.cli_chan->binding_handle = NULL;
274 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
275 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
276 TALLOC_FREE(prn_hnd->notify.cli_chan);
278 if (prn_hnd->notify.msg_ctx != NULL) {
279 messaging_deregister(prn_hnd->notify.msg_ctx,
280 MSG_PRINTER_NOTIFY2, NULL);
283 * Tell the serverid.tdb we're no longer
284 * interested in printer notify messages.
287 serverid_register_msg_flags(
288 messaging_server_id(prn_hnd->notify.msg_ctx),
289 false, FLAG_MSG_PRINT_NOTIFY);
293 if (prn_hnd->notify.cli_chan) {
294 prn_hnd->notify.cli_chan->active_connections--;
298 /****************************************************************************
299 Functions to free a printer entry datastruct.
300 ****************************************************************************/
302 static int printer_entry_destructor(struct printer_handle *Printer)
304 if (Printer->notify.cli_chan != NULL &&
305 Printer->notify.cli_chan->active_connections > 0) {
308 switch(Printer->printer_type) {
310 srv_spoolss_replycloseprinter(snum, Printer);
314 snum = print_queue_snum(Printer->sharename);
316 srv_spoolss_replycloseprinter(snum, Printer);
324 Printer->notify.flags=0;
325 Printer->notify.options=0;
326 Printer->notify.localmachine[0]='\0';
327 Printer->notify.printerlocal=0;
328 TALLOC_FREE(Printer->notify.option);
329 TALLOC_FREE(Printer->devmode);
331 /* Remove from the internal list. */
332 DLIST_REMOVE(printers_list, Printer);
336 /****************************************************************************
337 find printer index by handle
338 ****************************************************************************/
340 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
341 struct policy_handle *hnd)
343 struct printer_handle *find_printer = NULL;
345 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
346 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
353 /****************************************************************************
354 Close printer index by handle.
355 ****************************************************************************/
357 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
359 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
362 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
367 close_policy_hnd(p, hnd);
372 /****************************************************************************
373 Delete a printer given a handle.
374 ****************************************************************************/
376 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
377 const char *sharename,
378 struct messaging_context *msg_ctx)
380 char *cmd = lp_deleteprinter_cmd();
381 char *command = NULL;
383 bool is_print_op = false;
385 /* can't fail if we don't try */
390 command = talloc_asprintf(ctx,
397 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
399 DEBUG(10,("Running [%s]\n", command));
401 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
406 if ( (ret = smbrun(command, NULL)) == 0 ) {
407 /* Tell everyone we updated smb.conf. */
408 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
414 /********** END SePrintOperatorPrivlege BLOCK **********/
416 DEBUGADD(10,("returned [%d]\n", ret));
418 TALLOC_FREE(command);
421 return WERR_BADFID; /* What to return here? */
423 /* go ahead and re-read the services immediately */
425 reload_services(msg_ctx, -1, false);
428 if ( lp_servicenumber( sharename ) >= 0 )
429 return WERR_ACCESS_DENIED;
434 /****************************************************************************
435 Delete a printer given a handle.
436 ****************************************************************************/
438 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
440 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
444 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
450 * It turns out that Windows allows delete printer on a handle
451 * opened by an admin user, then used on a pipe handle created
452 * by an anonymous user..... but they're working on security.... riiight !
456 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
457 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
458 return WERR_ACCESS_DENIED;
461 /* this does not need a become root since the access check has been
462 done on the handle already */
464 result = winreg_delete_printer_key(p->mem_ctx,
465 get_session_info_system(),
469 if (!W_ERROR_IS_OK(result)) {
470 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
474 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
475 Printer->sharename, p->msg_ctx);
476 if (!W_ERROR_IS_OK(result)) {
479 prune_printername_cache();
483 /****************************************************************************
484 Return the snum of a printer corresponding to an handle.
485 ****************************************************************************/
487 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
488 int *number, struct share_params **params)
490 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
493 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
498 switch (Printer->printer_type) {
500 DEBUG(4,("short name:%s\n", Printer->sharename));
501 *number = print_queue_snum(Printer->sharename);
502 return (*number != -1);
510 /****************************************************************************
511 Set printer handle type.
512 Check if it's \\server or \\server\printer
513 ****************************************************************************/
515 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
517 DEBUG(3,("Setting printer type=%s\n", handlename));
519 /* it's a print server */
520 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
521 DEBUGADD(4,("Printer is a print server\n"));
522 Printer->printer_type = SPLHND_SERVER;
524 /* it's a printer (set_printer_hnd_name() will handle port monitors */
526 DEBUGADD(4,("Printer is a printer\n"));
527 Printer->printer_type = SPLHND_PRINTER;
533 static void prune_printername_cache_fn(const char *key, const char *value,
534 time_t timeout, void *private_data)
539 static void prune_printername_cache(void)
541 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
544 /****************************************************************************
545 Set printer handle name.. Accept names like \\server, \\server\printer,
546 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
547 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
548 XcvDataPort() interface.
549 ****************************************************************************/
551 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
552 const struct auth_serversupplied_info *session_info,
553 struct messaging_context *msg_ctx,
554 struct printer_handle *Printer,
555 const char *handlename)
558 int n_services=lp_numservices();
560 const char *printername;
561 const char *servername = NULL;
564 struct spoolss_PrinterInfo2 *info2 = NULL;
569 * Hopefully nobody names his printers like this. Maybe \ or ,
570 * are illegal in printer names even?
572 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
576 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
577 (unsigned long)strlen(handlename)));
579 aprinter = discard_const_p(char, handlename);
580 if ( *handlename == '\\' ) {
581 servername = canon_servername(handlename);
582 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
586 if (!is_myname_or_ipaddr(servername)) {
587 return WERR_INVALID_PRINTER_NAME;
589 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
590 if (Printer->servername == NULL) {
595 if (Printer->printer_type == SPLHND_SERVER) {
599 if (Printer->printer_type != SPLHND_PRINTER) {
600 return WERR_INVALID_HANDLE;
603 DEBUGADD(5, ("searching for [%s]\n", aprinter));
605 p = strchr(aprinter, ',');
612 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
614 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
620 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
623 /* check for the Port Monitor Interface */
624 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
625 Printer->printer_type = SPLHND_PORTMON_TCP;
626 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
629 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
630 Printer->printer_type = SPLHND_PORTMON_LOCAL;
631 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
636 * With hundreds of printers, the "for" loop iterating all
637 * shares can be quite expensive, as it is done on every
638 * OpenPrinter. The loop maps "aprinter" to "sname", the
639 * result of which we cache in gencache.
642 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
644 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
646 found = (strcmp(tmp, printer_not_found) != 0);
648 DEBUG(4, ("Printer %s not found\n", aprinter));
650 return WERR_INVALID_PRINTER_NAME;
656 /* Search all sharenames first as this is easier than pulling
657 the printer_info_2 off of disk. Don't use find_service() since
658 that calls out to map_username() */
660 /* do another loop to look for printernames */
661 for (snum = 0; !found && snum < n_services; snum++) {
662 const char *printer = lp_const_servicename(snum);
664 /* no point going on if this is not a printer */
665 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
669 /* ignore [printers] share */
670 if (strequal(printer, "printers")) {
674 fstrcpy(sname, printer);
675 if (strequal(aprinter, printer)) {
680 /* no point looking up the printer object if
681 we aren't allowing printername != sharename */
682 if (lp_force_printername(snum)) {
686 result = winreg_get_printer(mem_ctx,
691 if ( !W_ERROR_IS_OK(result) ) {
692 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
693 sname, win_errstr(result)));
697 printername = strrchr(info2->printername, '\\');
698 if (printername == NULL) {
699 printername = info2->printername;
704 if (strequal(printername, aprinter)) {
709 DEBUGADD(10, ("printername: %s\n", printername));
715 if (cache_key != NULL) {
716 gencache_set(cache_key, printer_not_found,
718 TALLOC_FREE(cache_key);
720 DEBUGADD(4,("Printer not found\n"));
721 return WERR_INVALID_PRINTER_NAME;
724 if (cache_key != NULL) {
725 gencache_set(cache_key, sname, time(NULL)+300);
726 TALLOC_FREE(cache_key);
729 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
731 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
736 /****************************************************************************
737 Find first available printer slot. creates a printer handle for you.
738 ****************************************************************************/
740 static WERROR open_printer_hnd(struct pipes_struct *p,
741 struct policy_handle *hnd,
743 uint32_t access_granted)
745 struct printer_handle *new_printer;
748 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
750 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
751 if (new_printer == NULL) {
754 talloc_set_destructor(new_printer, printer_entry_destructor);
756 /* This also steals the printer_handle on the policy_handle */
757 if (!create_policy_hnd(p, hnd, new_printer)) {
758 TALLOC_FREE(new_printer);
759 return WERR_INVALID_HANDLE;
762 /* Add to the internal list. */
763 DLIST_ADD(printers_list, new_printer);
765 new_printer->notify.option=NULL;
767 if (!set_printer_hnd_printertype(new_printer, name)) {
768 close_printer_handle(p, hnd);
769 return WERR_INVALID_HANDLE;
772 result = set_printer_hnd_name(p->mem_ctx,
773 get_session_info_system(),
776 if (!W_ERROR_IS_OK(result)) {
777 close_printer_handle(p, hnd);
781 new_printer->access_granted = access_granted;
783 DEBUG(5, ("%d printer handles active\n",
784 (int)num_pipe_handles(p)));
789 /***************************************************************************
790 check to see if the client motify handle is monitoring the notification
791 given by (notify_type, notify_field).
792 **************************************************************************/
794 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
795 uint16_t notify_field)
800 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
801 uint16_t notify_field)
803 struct spoolss_NotifyOption *option = p->notify.option;
807 * Flags should always be zero when the change notify
808 * is registered by the client's spooler. A user Win32 app
809 * might use the flags though instead of the NOTIFY_OPTION_INFO
818 return is_monitoring_event_flags(
819 p->notify.flags, notify_type, notify_field);
821 for (i = 0; i < option->count; i++) {
823 /* Check match for notify_type */
825 if (option->types[i].type != notify_type)
828 /* Check match for field */
830 for (j = 0; j < option->types[i].count; j++) {
831 if (option->types[i].fields[j].field == notify_field) {
837 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
838 p->servername, p->sharename, notify_type, notify_field));
843 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
844 _data->data.integer[0] = _integer; \
845 _data->data.integer[1] = 0;
848 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
849 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
850 if (!_data->data.string.string) {\
851 _data->data.string.size = 0; \
853 _data->data.string.size = strlen_m_term(_p) * 2;
855 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
856 _data->data.devmode.devmode = _devmode;
858 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
859 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
860 if (!_data->data.sd.sd) { \
861 _data->data.sd.sd_size = 0; \
863 _data->data.sd.sd_size = \
864 ndr_size_security_descriptor(_data->data.sd.sd, 0);
866 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
871 struct spoolss_Time st;
875 if (!init_systemtime(&st, t)) {
879 p = talloc_array(mem_ctx, char, len);
885 * Systemtime must be linearized as a set of UINT16's.
886 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
889 SSVAL(p, 0, st.year);
890 SSVAL(p, 2, st.month);
891 SSVAL(p, 4, st.day_of_week);
893 SSVAL(p, 8, st.hour);
894 SSVAL(p, 10, st.minute);
895 SSVAL(p, 12, st.second);
896 SSVAL(p, 14, st.millisecond);
902 /* Convert a notification message to a struct spoolss_Notify */
904 static void notify_one_value(struct spoolss_notify_msg *msg,
905 struct spoolss_Notify *data,
908 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
911 static void notify_string(struct spoolss_notify_msg *msg,
912 struct spoolss_Notify *data,
915 /* The length of the message includes the trailing \0 */
917 data->data.string.size = msg->len * 2;
918 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
919 if (!data->data.string.string) {
920 data->data.string.size = 0;
925 static void notify_system_time(struct spoolss_notify_msg *msg,
926 struct spoolss_Notify *data,
929 data->data.string.string = NULL;
930 data->data.string.size = 0;
932 if (msg->len != sizeof(time_t)) {
933 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
938 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
939 &data->data.string.string,
940 &data->data.string.size);
943 struct notify2_message_table {
945 void (*fn)(struct spoolss_notify_msg *msg,
946 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
949 static struct notify2_message_table printer_notify_table[] = {
950 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
951 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
952 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
953 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
954 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
955 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
956 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
957 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
958 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
959 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
960 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
961 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
962 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
963 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
964 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
965 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
966 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
967 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
968 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
971 static struct notify2_message_table job_notify_table[] = {
972 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
973 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
974 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
975 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
976 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
977 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
978 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
979 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
980 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
981 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
982 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
983 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
984 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
985 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
986 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
987 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
988 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
989 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
990 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
991 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
992 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
993 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
994 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
995 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
999 /***********************************************************************
1000 Allocate talloc context for container object
1001 **********************************************************************/
1003 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1008 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1013 /***********************************************************************
1014 release all allocated memory and zero out structure
1015 **********************************************************************/
1017 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 talloc_destroy(ctr->ctx);
1030 /***********************************************************************
1031 **********************************************************************/
1033 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1041 /***********************************************************************
1042 **********************************************************************/
1044 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1046 if ( !ctr || !ctr->msg_groups )
1049 if ( idx >= ctr->num_groups )
1052 return &ctr->msg_groups[idx];
1056 /***********************************************************************
1057 How many groups of change messages do we have ?
1058 **********************************************************************/
1060 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1065 return ctr->num_groups;
1068 /***********************************************************************
1069 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1070 **********************************************************************/
1072 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1074 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1075 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1076 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1082 /* loop over all groups looking for a matching printer name */
1084 for ( i=0; i<ctr->num_groups; i++ ) {
1085 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1089 /* add a new group? */
1091 if ( i == ctr->num_groups ) {
1094 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1095 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1098 ctr->msg_groups = groups;
1100 /* clear the new entry and set the printer name */
1102 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1103 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1106 /* add the change messages; 'i' is the correct index now regardless */
1108 msg_grp = &ctr->msg_groups[i];
1110 msg_grp->num_msgs++;
1112 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1113 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1116 msg_grp->msgs = msg_list;
1118 new_slot = msg_grp->num_msgs-1;
1119 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1121 /* need to allocate own copy of data */
1123 if ( msg->len != 0 )
1124 msg_grp->msgs[new_slot].notify.data = (char *)
1125 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1127 return ctr->num_groups;
1130 static void construct_info_data(struct spoolss_Notify *info_data,
1131 enum spoolss_NotifyType type,
1132 uint16_t field, int id);
1134 /***********************************************************************
1135 Send a change notication message on all handles which have a call
1137 **********************************************************************/
1139 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1140 struct printer_handle *prn_hnd,
1141 SPOOLSS_NOTIFY_MSG *messages,
1143 struct spoolss_Notify **_notifies,
1146 struct spoolss_Notify *notifies;
1147 SPOOLSS_NOTIFY_MSG *msg;
1152 notifies = talloc_zero_array(mem_ctx,
1153 struct spoolss_Notify, num_msgs);
1158 for (i = 0; i < num_msgs; i++) {
1162 /* Are we monitoring this event? */
1164 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1168 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1169 "for printer [%s]\n",
1170 msg->type, msg->field, prn_hnd->sharename));
1173 * if the is a printer notification handle and not a job
1174 * notification type, then set the id to 0.
1175 * Otherwise just use what was specified in the message.
1177 * When registering change notification on a print server
1178 * handle we always need to send back the id (snum) matching
1179 * the printer for which the change took place.
1180 * For change notify registered on a printer handle,
1181 * this does not matter and the id should be 0.
1186 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1187 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1193 /* Convert unix jobid to smb jobid */
1195 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1196 id = sysjob_to_jobid(msg->id);
1199 DEBUG(3, ("no such unix jobid %d\n",
1205 construct_info_data(¬ifies[count],
1206 msg->type, msg->field, id);
1209 case PRINTER_NOTIFY_TYPE:
1210 if (printer_notify_table[msg->field].fn) {
1211 printer_notify_table[msg->field].fn(msg,
1212 ¬ifies[count], mem_ctx);
1216 case JOB_NOTIFY_TYPE:
1217 if (job_notify_table[msg->field].fn) {
1218 job_notify_table[msg->field].fn(msg,
1219 ¬ifies[count], mem_ctx);
1224 DEBUG(5, ("Unknown notification type %d\n",
1232 *_notifies = notifies;
1238 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1239 struct printer_handle *prn_hnd,
1240 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1242 struct spoolss_Notify *notifies;
1244 union spoolss_ReplyPrinterInfo info;
1245 struct spoolss_NotifyInfo info0;
1246 uint32_t reply_result;
1251 /* Is there notification on this handle? */
1252 if (prn_hnd->notify.cli_chan == NULL ||
1253 prn_hnd->notify.cli_chan->active_connections == 0) {
1257 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1258 prn_hnd->servername, prn_hnd->sharename));
1260 /* For this printer? Print servers always receive notifications. */
1261 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1262 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1266 DEBUG(10,("Our printer\n"));
1268 /* build the array of change notifications */
1269 ret = build_notify2_messages(mem_ctx, prn_hnd,
1271 msg_group->num_msgs,
1277 info0.version = 0x2;
1278 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1279 info0.count = count;
1280 info0.notifies = notifies;
1282 info.info0 = &info0;
1284 status = dcerpc_spoolss_RouterReplyPrinterEx(
1285 prn_hnd->notify.cli_chan->binding_handle,
1287 &prn_hnd->notify.cli_hnd,
1288 prn_hnd->notify.change, /* color */
1289 prn_hnd->notify.flags,
1291 0, /* reply_type, must be 0 */
1293 if (!NT_STATUS_IS_OK(status)) {
1294 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1296 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1297 nt_errstr(status)));
1298 werr = ntstatus_to_werror(status);
1299 } else if (!W_ERROR_IS_OK(werr)) {
1300 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1302 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1305 switch (reply_result) {
1308 case PRINTER_NOTIFY_INFO_DISCARDED:
1309 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1310 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1319 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1321 struct printer_handle *p;
1322 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1323 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1327 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1331 if (!msg_group->msgs) {
1332 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1336 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1338 /* loop over all printers */
1340 for (p = printers_list; p; p = p->next) {
1341 ret = send_notify2_printer(mem_ctx, p, msg_group);
1348 DEBUG(8,("send_notify2_changes: Exit...\n"));
1352 /***********************************************************************
1353 **********************************************************************/
1355 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1358 uint32_t tv_sec, tv_usec;
1361 /* Unpack message */
1363 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1366 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1368 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1371 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1372 &msg->notify.value[0], &msg->notify.value[1]);
1374 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1375 &msg->len, &msg->notify.data);
1377 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1378 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1380 tv->tv_sec = tv_sec;
1381 tv->tv_usec = tv_usec;
1384 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1385 msg->notify.value[1]));
1387 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1392 /********************************************************************
1393 Receive a notify2 message list
1394 ********************************************************************/
1396 static void receive_notify2_message_list(struct messaging_context *msg,
1399 struct server_id server_id,
1402 size_t msg_count, i;
1403 char *buf = (char *)data->data;
1406 SPOOLSS_NOTIFY_MSG notify;
1407 SPOOLSS_NOTIFY_MSG_CTR messages;
1410 if (data->length < 4) {
1411 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1415 msg_count = IVAL(buf, 0);
1418 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1420 if (msg_count == 0) {
1421 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1425 /* initialize the container */
1427 ZERO_STRUCT( messages );
1428 notify_msg_ctr_init( &messages );
1431 * build message groups for each printer identified
1432 * in a change_notify msg. Remember that a PCN message
1433 * includes the handle returned for the srv_spoolss_replyopenprinter()
1434 * call. Therefore messages are grouped according to printer handle.
1437 for ( i=0; i<msg_count; i++ ) {
1438 struct timeval msg_tv;
1440 if (msg_ptr + 4 - buf > data->length) {
1441 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1445 msg_len = IVAL(msg_ptr,0);
1448 if (msg_ptr + msg_len - buf > data->length) {
1449 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1453 /* unpack messages */
1455 ZERO_STRUCT( notify );
1456 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1459 /* add to correct list in container */
1461 notify_msg_ctr_addmsg( &messages, ¬ify );
1463 /* free memory that might have been allocated by notify2_unpack_msg() */
1465 if ( notify.len != 0 )
1466 SAFE_FREE( notify.notify.data );
1469 /* process each group of messages */
1471 num_groups = notify_msg_ctr_numgroups( &messages );
1472 for ( i=0; i<num_groups; i++ )
1473 send_notify2_changes( &messages, i );
1478 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1479 (uint32_t)msg_count ));
1481 notify_msg_ctr_destroy( &messages );
1486 /********************************************************************
1487 Send a message to ourself about new driver being installed
1488 so we can upgrade the information for each printer bound to this
1490 ********************************************************************/
1492 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1493 struct messaging_context *msg_ctx)
1495 int len = strlen(drivername);
1500 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1503 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1504 MSG_PRINTER_DRVUPGRADE,
1505 (const uint8_t *)drivername, len+1);
1510 void srv_spoolss_cleanup(void)
1512 struct printer_session_counter *session_counter;
1514 for (session_counter = counter_list;
1515 session_counter != NULL;
1516 session_counter = counter_list) {
1517 DLIST_REMOVE(counter_list, session_counter);
1518 TALLOC_FREE(session_counter);
1522 /**********************************************************************
1523 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1524 over all printers, upgrading ones as necessary
1525 **********************************************************************/
1527 void do_drv_upgrade_printer(struct messaging_context *msg,
1530 struct server_id server_id,
1533 TALLOC_CTX *tmp_ctx;
1534 struct auth_serversupplied_info *session_info = NULL;
1535 struct spoolss_PrinterInfo2 *pinfo2;
1538 const char *drivername;
1540 int n_services = lp_numservices();
1542 tmp_ctx = talloc_new(NULL);
1543 if (!tmp_ctx) return;
1545 status = make_session_info_system(tmp_ctx, &session_info);
1546 if (!NT_STATUS_IS_OK(status)) {
1547 DEBUG(0, ("do_drv_upgrade_printer: "
1548 "Could not create system session_info\n"));
1552 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1554 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1558 DEBUG(10, ("do_drv_upgrade_printer: "
1559 "Got message for new driver [%s]\n", drivername));
1561 /* Iterate the printer list */
1563 for (snum = 0; snum < n_services; snum++) {
1564 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1568 /* ignore [printers] share */
1569 if (strequal(lp_const_servicename(snum), "printers")) {
1573 result = winreg_get_printer(tmp_ctx, session_info, msg,
1574 lp_const_servicename(snum),
1577 if (!W_ERROR_IS_OK(result)) {
1581 if (!pinfo2->drivername) {
1585 if (strcmp(drivername, pinfo2->drivername) != 0) {
1589 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1591 /* all we care about currently is the change_id */
1592 result = winreg_printer_update_changeid(tmp_ctx,
1595 pinfo2->printername);
1597 if (!W_ERROR_IS_OK(result)) {
1598 DEBUG(3, ("do_drv_upgrade_printer: "
1599 "Failed to update changeid [%s]\n",
1600 win_errstr(result)));
1606 talloc_free(tmp_ctx);
1609 /********************************************************************
1610 Update the cache for all printq's with a registered client
1612 ********************************************************************/
1614 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1616 struct printer_handle *printer = printers_list;
1619 /* loop through all printers and update the cache where
1620 a client is connected */
1622 if ((printer->printer_type == SPLHND_PRINTER) &&
1623 ((printer->notify.cli_chan != NULL) &&
1624 (printer->notify.cli_chan->active_connections > 0))) {
1625 snum = print_queue_snum(printer->sharename);
1626 print_queue_status(msg_ctx, snum, NULL, NULL);
1629 printer = printer->next;
1635 /****************************************************************
1636 _spoolss_OpenPrinter
1637 ****************************************************************/
1639 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1640 struct spoolss_OpenPrinter *r)
1642 struct spoolss_OpenPrinterEx e;
1645 ZERO_STRUCT(e.in.userlevel);
1647 e.in.printername = r->in.printername;
1648 e.in.datatype = r->in.datatype;
1649 e.in.devmode_ctr = r->in.devmode_ctr;
1650 e.in.access_mask = r->in.access_mask;
1653 e.out.handle = r->out.handle;
1655 werr = _spoolss_OpenPrinterEx(p, &e);
1657 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1658 /* OpenPrinterEx returns this for a bad
1659 * printer name. We must return WERR_INVALID_PRINTER_NAME
1662 werr = WERR_INVALID_PRINTER_NAME;
1668 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1669 struct spoolss_DeviceMode *orig,
1670 struct spoolss_DeviceMode **dest)
1672 struct spoolss_DeviceMode *dm;
1674 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1679 /* copy all values, then duplicate strings and structs */
1682 dm->devicename = talloc_strdup(dm, orig->devicename);
1683 if (!dm->devicename) {
1686 dm->formname = talloc_strdup(dm, orig->formname);
1687 if (!dm->formname) {
1690 if (orig->driverextra_data.data) {
1691 dm->driverextra_data.data =
1692 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1693 orig->driverextra_data.length);
1694 if (!dm->driverextra_data.data) {
1703 /****************************************************************
1704 _spoolss_OpenPrinterEx
1705 ****************************************************************/
1707 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1708 struct spoolss_OpenPrinterEx *r)
1711 struct printer_handle *Printer=NULL;
1714 if (!r->in.printername) {
1715 return WERR_INVALID_PARAM;
1718 if (r->in.level > 3) {
1719 return WERR_INVALID_PARAM;
1721 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1722 (r->in.level == 2 && !r->in.userlevel.level2) ||
1723 (r->in.level == 3 && !r->in.userlevel.level3)) {
1724 return WERR_INVALID_PARAM;
1727 /* some sanity check because you can open a printer or a print server */
1728 /* aka: \\server\printer or \\server */
1730 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1732 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1733 if (!W_ERROR_IS_OK(result)) {
1734 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1735 "for printer %s\n", r->in.printername));
1736 ZERO_STRUCTP(r->out.handle);
1740 Printer = find_printer_index_by_hnd(p, r->out.handle);
1742 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1743 "handle we created for printer %s\n", r->in.printername));
1744 close_printer_handle(p, r->out.handle);
1745 ZERO_STRUCTP(r->out.handle);
1746 return WERR_INVALID_PARAM;
1750 * First case: the user is opening the print server:
1752 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1753 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1755 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1756 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1757 * or if the user is listed in the smb.conf printer admin parameter.
1759 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1760 * client view printer folder, but does not show the MSAPW.
1762 * Note: this test needs code to check access rights here too. Jeremy
1763 * could you look at this?
1765 * Second case: the user is opening a printer:
1766 * NT doesn't let us connect to a printer if the connecting user
1767 * doesn't have print permission.
1769 * Third case: user is opening a Port Monitor
1770 * access checks same as opening a handle to the print server.
1773 switch (Printer->printer_type )
1776 case SPLHND_PORTMON_TCP:
1777 case SPLHND_PORTMON_LOCAL:
1778 /* Printserver handles use global struct... */
1782 /* Map standard access rights to object specific access rights */
1784 se_map_standard(&r->in.access_mask,
1785 &printserver_std_mapping);
1787 /* Deny any object specific bits that don't apply to print
1788 servers (i.e printer and job specific bits) */
1790 r->in.access_mask &= SEC_MASK_SPECIFIC;
1792 if (r->in.access_mask &
1793 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1794 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1795 close_printer_handle(p, r->out.handle);
1796 ZERO_STRUCTP(r->out.handle);
1797 return WERR_ACCESS_DENIED;
1800 /* Allow admin access */
1802 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1804 if (!lp_ms_add_printer_wizard()) {
1805 close_printer_handle(p, r->out.handle);
1806 ZERO_STRUCTP(r->out.handle);
1807 return WERR_ACCESS_DENIED;
1810 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1811 and not a printer admin, then fail */
1813 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1814 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1815 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1816 !token_contains_name_in_list(
1817 uidtoname(p->session_info->utok.uid),
1818 p->session_info->info3->base.domain.string,
1820 p->session_info->security_token,
1821 lp_printer_admin(snum))) {
1822 close_printer_handle(p, r->out.handle);
1823 ZERO_STRUCTP(r->out.handle);
1824 DEBUG(3,("access DENIED as user is not root, "
1825 "has no printoperator privilege, "
1826 "not a member of the printoperator builtin group and "
1827 "is not in printer admin list"));
1828 return WERR_ACCESS_DENIED;
1831 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1835 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1838 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1839 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1841 /* We fall through to return WERR_OK */
1844 case SPLHND_PRINTER:
1845 /* NT doesn't let us connect to a printer if the connecting user
1846 doesn't have print permission. */
1848 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1849 close_printer_handle(p, r->out.handle);
1850 ZERO_STRUCTP(r->out.handle);
1854 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1855 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1858 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1860 /* map an empty access mask to the minimum access mask */
1861 if (r->in.access_mask == 0x0)
1862 r->in.access_mask = PRINTER_ACCESS_USE;
1865 * If we are not serving the printer driver for this printer,
1866 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1867 * will keep NT clients happy --jerry
1870 if (lp_use_client_driver(snum)
1871 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1873 r->in.access_mask = PRINTER_ACCESS_USE;
1876 /* check smb.conf parameters and the the sec_desc */
1878 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1879 p->client_id->name, p->client_id->addr)) {
1880 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1881 ZERO_STRUCTP(r->out.handle);
1882 return WERR_ACCESS_DENIED;
1885 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1886 p->session_info->security_token, snum) ||
1887 !print_access_check(p->session_info,
1890 r->in.access_mask)) {
1891 DEBUG(3, ("access DENIED for printer open\n"));
1892 close_printer_handle(p, r->out.handle);
1893 ZERO_STRUCTP(r->out.handle);
1894 return WERR_ACCESS_DENIED;
1897 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1898 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1899 close_printer_handle(p, r->out.handle);
1900 ZERO_STRUCTP(r->out.handle);
1901 return WERR_ACCESS_DENIED;
1904 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1905 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1907 r->in.access_mask = PRINTER_ACCESS_USE;
1909 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1910 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1912 winreg_create_printer(p->mem_ctx,
1913 get_session_info_system(),
1915 lp_const_servicename(snum));
1920 /* sanity check to prevent programmer error */
1921 ZERO_STRUCTP(r->out.handle);
1925 Printer->access_granted = r->in.access_mask;
1928 * If the client sent a devmode in the OpenPrinter() call, then
1929 * save it here in case we get a job submission on this handle
1932 if ((Printer->printer_type != SPLHND_SERVER) &&
1933 r->in.devmode_ctr.devmode) {
1934 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1938 #if 0 /* JERRY -- I'm doubtful this is really effective */
1939 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1940 optimization in Windows 2000 clients --jerry */
1942 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1943 && (RA_WIN2K == get_remote_arch()) )
1945 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1946 sys_usleep( 500000 );
1953 /****************************************************************
1954 _spoolss_ClosePrinter
1955 ****************************************************************/
1957 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1958 struct spoolss_ClosePrinter *r)
1960 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962 if (Printer && Printer->document_started) {
1963 struct spoolss_EndDocPrinter e;
1965 e.in.handle = r->in.handle;
1967 _spoolss_EndDocPrinter(p, &e);
1970 if (!close_printer_handle(p, r->in.handle))
1973 /* clear the returned printer handle. Observed behavior
1974 from Win2k server. Don't think this really matters.
1975 Previous code just copied the value of the closed
1978 ZERO_STRUCTP(r->out.handle);
1983 /****************************************************************
1984 _spoolss_DeletePrinter
1985 ****************************************************************/
1987 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1988 struct spoolss_DeletePrinter *r)
1990 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1994 if (Printer && Printer->document_started) {
1995 struct spoolss_EndDocPrinter e;
1997 e.in.handle = r->in.handle;
1999 _spoolss_EndDocPrinter(p, &e);
2002 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2003 winreg_delete_printer_key(p->mem_ctx,
2004 get_session_info_system(),
2006 lp_const_servicename(snum),
2010 result = delete_printer_handle(p, r->in.handle);
2015 /*******************************************************************
2016 * static function to lookup the version id corresponding to an
2017 * long architecture string
2018 ******************************************************************/
2020 static const struct print_architecture_table_node archi_table[]= {
2022 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2023 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2024 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2025 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2026 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2027 {"Windows IA64", SPL_ARCH_IA64, 3 },
2028 {"Windows x64", SPL_ARCH_X64, 3 },
2032 static int get_version_id(const char *arch)
2036 for (i=0; archi_table[i].long_archi != NULL; i++)
2038 if (strcmp(arch, archi_table[i].long_archi) == 0)
2039 return (archi_table[i].version);
2045 /****************************************************************
2046 _spoolss_DeletePrinterDriver
2047 ****************************************************************/
2049 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2050 struct spoolss_DeletePrinterDriver *r)
2053 struct spoolss_DriverInfo8 *info = NULL;
2054 struct spoolss_DriverInfo8 *info_win2k = NULL;
2058 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2059 and not a printer admin, then fail */
2061 if ( (p->session_info->utok.uid != sec_initial_uid())
2062 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2063 && !token_contains_name_in_list(
2064 uidtoname(p->session_info->utok.uid),
2065 p->session_info->info3->base.domain.string,
2067 p->session_info->security_token,
2068 lp_printer_admin(-1)) )
2070 return WERR_ACCESS_DENIED;
2073 /* check that we have a valid driver name first */
2075 if ((version = get_version_id(r->in.architecture)) == -1)
2076 return WERR_INVALID_ENVIRONMENT;
2078 status = winreg_get_driver(p->mem_ctx,
2079 get_session_info_system(),
2081 r->in.architecture, r->in.driver,
2083 if (!W_ERROR_IS_OK(status)) {
2084 /* try for Win2k driver if "Windows NT x86" */
2086 if ( version == 2 ) {
2089 status = winreg_get_driver(p->mem_ctx,
2090 get_session_info_system(),
2095 if (!W_ERROR_IS_OK(status)) {
2096 status = WERR_UNKNOWN_PRINTER_DRIVER;
2100 /* otherwise it was a failure */
2102 status = WERR_UNKNOWN_PRINTER_DRIVER;
2108 if (printer_driver_in_use(p->mem_ctx,
2109 get_session_info_system(),
2112 status = WERR_PRINTER_DRIVER_IN_USE;
2117 status = winreg_get_driver(p->mem_ctx,
2118 get_session_info_system(),
2121 r->in.driver, 3, &info_win2k);
2122 if (W_ERROR_IS_OK(status)) {
2123 /* if we get to here, we now have 2 driver info structures to remove */
2124 /* remove the Win2k driver first*/
2126 status = winreg_del_driver(p->mem_ctx,
2127 get_session_info_system(),
2130 talloc_free(info_win2k);
2132 /* this should not have failed---if it did, report to client */
2133 if (!W_ERROR_IS_OK(status)) {
2139 status = winreg_del_driver(p->mem_ctx,
2140 get_session_info_system(),
2150 /****************************************************************
2151 _spoolss_DeletePrinterDriverEx
2152 ****************************************************************/
2154 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2155 struct spoolss_DeletePrinterDriverEx *r)
2157 struct spoolss_DriverInfo8 *info = NULL;
2158 struct spoolss_DriverInfo8 *info_win2k = NULL;
2163 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2164 and not a printer admin, then fail */
2166 if ( (p->session_info->utok.uid != sec_initial_uid())
2167 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2168 && !token_contains_name_in_list(
2169 uidtoname(p->session_info->utok.uid),
2170 p->session_info->info3->base.domain.string,
2172 p->session_info->security_token, lp_printer_admin(-1)) )
2174 return WERR_ACCESS_DENIED;
2177 /* check that we have a valid driver name first */
2178 if ((version = get_version_id(r->in.architecture)) == -1) {
2179 /* this is what NT returns */
2180 return WERR_INVALID_ENVIRONMENT;
2183 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2184 version = r->in.version;
2186 status = winreg_get_driver(p->mem_ctx,
2187 get_session_info_system(),
2193 if (!W_ERROR_IS_OK(status)) {
2194 status = WERR_UNKNOWN_PRINTER_DRIVER;
2197 * if the client asked for a specific version,
2198 * or this is something other than Windows NT x86,
2202 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2205 /* try for Win2k driver if "Windows NT x86" */
2208 status = winreg_get_driver(info,
2209 get_session_info_system(),
2214 if (!W_ERROR_IS_OK(status)) {
2215 status = WERR_UNKNOWN_PRINTER_DRIVER;
2220 if (printer_driver_in_use(info,
2221 get_session_info_system(),
2224 status = WERR_PRINTER_DRIVER_IN_USE;
2229 * we have a couple of cases to consider.
2230 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2231 * then the delete should fail if **any** files overlap with
2233 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2234 * non-overlapping files
2235 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2236 * is set, the do not delete any files
2237 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2240 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2242 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2245 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2246 printer_driver_files_in_use(info,
2247 get_session_info_system(),
2250 /* no idea of the correct error here */
2251 status = WERR_ACCESS_DENIED;
2256 /* also check for W32X86/3 if necessary; maybe we already have? */
2258 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2259 status = winreg_get_driver(info,
2260 get_session_info_system(),
2263 r->in.driver, 3, &info_win2k);
2264 if (W_ERROR_IS_OK(status)) {
2267 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2268 printer_driver_files_in_use(info,
2269 get_session_info_system(),
2272 /* no idea of the correct error here */
2273 talloc_free(info_win2k);
2274 status = WERR_ACCESS_DENIED;
2278 /* if we get to here, we now have 2 driver info structures to remove */
2279 /* remove the Win2k driver first*/
2281 status = winreg_del_driver(info,
2282 get_session_info_system(),
2287 /* this should not have failed---if it did, report to client */
2289 if (!W_ERROR_IS_OK(status)) {
2294 * now delete any associated files if delete_files is
2295 * true. Even if this part failes, we return succes
2296 * because the driver doesn not exist any more
2299 delete_driver_files(get_session_info_system(),
2305 status = winreg_del_driver(info,
2306 get_session_info_system(),
2310 if (!W_ERROR_IS_OK(status)) {
2315 * now delete any associated files if delete_files is
2316 * true. Even if this part failes, we return succes
2317 * because the driver doesn not exist any more
2320 delete_driver_files(get_session_info_system(), info);
2329 /********************************************************************
2330 GetPrinterData on a printer server Handle.
2331 ********************************************************************/
2333 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2335 enum winreg_Type *type,
2336 union spoolss_PrinterData *data)
2338 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2340 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2346 if (!StrCaseCmp(value, "BeepEnabled")) {
2352 if (!StrCaseCmp(value, "EventLog")) {
2354 /* formally was 0x1b */
2359 if (!StrCaseCmp(value, "NetPopup")) {
2365 if (!StrCaseCmp(value, "MajorVersion")) {
2368 /* Windows NT 4.0 seems to not allow uploading of drivers
2369 to a server that reports 0x3 as the MajorVersion.
2370 need to investigate more how Win2k gets around this .
2373 if (RA_WINNT == get_remote_arch()) {
2382 if (!StrCaseCmp(value, "MinorVersion")) {
2389 * uint32_t size = 0x114
2390 * uint32_t major = 5
2391 * uint32_t minor = [0|1]
2392 * uint32_t build = [2195|2600]
2393 * extra unicode string = e.g. "Service Pack 3"
2395 if (!StrCaseCmp(value, "OSVersion")) {
2397 enum ndr_err_code ndr_err;
2398 struct spoolss_OSVersion os;
2400 os.major = 5; /* Windows 2000 == 5.0 */
2402 os.build = 2195; /* build */
2403 os.extra_string = ""; /* leave extra string empty */
2405 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2406 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2407 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2408 return WERR_GENERAL_FAILURE;
2412 data->binary = blob;
2418 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2421 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2422 W_ERROR_HAVE_NO_MEMORY(data->string);
2427 if (!StrCaseCmp(value, "Architecture")) {
2429 data->string = talloc_strdup(mem_ctx,
2430 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2431 W_ERROR_HAVE_NO_MEMORY(data->string);
2436 if (!StrCaseCmp(value, "DsPresent")) {
2439 /* only show the publish check box if we are a
2440 member of a AD domain */
2442 if (lp_security() == SEC_ADS) {
2450 if (!StrCaseCmp(value, "DNSMachineName")) {
2451 const char *hostname = get_mydnsfullname();
2454 return WERR_BADFILE;
2458 data->string = talloc_strdup(mem_ctx, hostname);
2459 W_ERROR_HAVE_NO_MEMORY(data->string);
2466 return WERR_INVALID_PARAM;
2469 /****************************************************************
2470 _spoolss_GetPrinterData
2471 ****************************************************************/
2473 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2474 struct spoolss_GetPrinterData *r)
2476 struct spoolss_GetPrinterDataEx r2;
2478 r2.in.handle = r->in.handle;
2479 r2.in.key_name = "PrinterDriverData";
2480 r2.in.value_name = r->in.value_name;
2481 r2.in.offered = r->in.offered;
2482 r2.out.type = r->out.type;
2483 r2.out.data = r->out.data;
2484 r2.out.needed = r->out.needed;
2486 return _spoolss_GetPrinterDataEx(p, &r2);
2489 /*********************************************************
2490 Connect to the client machine.
2491 **********************************************************/
2493 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2494 struct sockaddr_storage *client_ss, const char *remote_machine)
2497 struct cli_state *the_cli;
2498 struct sockaddr_storage rm_addr;
2499 char addr[INET6_ADDRSTRLEN];
2501 if ( is_zero_addr(client_ss) ) {
2502 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2504 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2505 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2508 print_sockaddr(addr, sizeof(addr), &rm_addr);
2510 rm_addr = *client_ss;
2511 print_sockaddr(addr, sizeof(addr), &rm_addr);
2512 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2516 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2517 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2522 /* setup the connection */
2523 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2524 &rm_addr, 0, "IPC$", "IPC",
2528 0, lp_client_signing());
2530 if ( !NT_STATUS_IS_OK( ret ) ) {
2531 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2536 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2537 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2538 cli_shutdown(the_cli);
2543 * Ok - we have an anonymous connection to the IPC$ share.
2544 * Now start the NT Domain stuff :-).
2547 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2548 if (!NT_STATUS_IS_OK(ret)) {
2549 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2550 remote_machine, nt_errstr(ret)));
2551 cli_shutdown(the_cli);
2558 /***************************************************************************
2559 Connect to the client.
2560 ****************************************************************************/
2562 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2563 uint32_t localprinter,
2564 enum winreg_Type type,
2565 struct policy_handle *handle,
2566 struct notify_back_channel **_chan,
2567 struct sockaddr_storage *client_ss,
2568 struct messaging_context *msg_ctx)
2572 struct notify_back_channel *chan;
2574 for (chan = back_channels; chan; chan = chan->next) {
2575 if (memcmp(&chan->client_address, client_ss,
2576 sizeof(struct sockaddr_storage)) == 0) {
2582 * If it's the first connection, contact the client
2583 * and connect to the IPC$ share anonymously
2586 fstring unix_printer;
2588 /* the +2 is to strip the leading 2 backslashs */
2589 fstrcpy(unix_printer, printer + 2);
2591 chan = talloc_zero(back_channels, struct notify_back_channel);
2595 chan->client_address = *client_ss;
2597 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2601 chan->binding_handle = chan->cli_pipe->binding_handle;
2603 DLIST_ADD(back_channels, chan);
2605 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2606 receive_notify2_message_list);
2607 /* Tell the connections db we're now interested in printer
2608 * notify messages. */
2609 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2610 true, FLAG_MSG_PRINT_NOTIFY);
2614 * Tell the specific printing tdb we want messages for this printer
2615 * by registering our PID.
2618 if (!print_notify_register_pid(snum)) {
2619 DEBUG(0, ("Failed to register our pid for printer %s\n",
2623 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2632 if (!NT_STATUS_IS_OK(status)) {
2633 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2634 result = ntstatus_to_werror(status);
2635 } else if (!W_ERROR_IS_OK(result)) {
2636 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2639 chan->active_connections++;
2642 return (W_ERROR_IS_OK(result));
2645 /****************************************************************
2646 ****************************************************************/
2648 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2649 const struct spoolss_NotifyOption *r)
2651 struct spoolss_NotifyOption *option;
2658 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2665 if (!option->count) {
2669 option->types = talloc_zero_array(option,
2670 struct spoolss_NotifyOptionType, option->count);
2671 if (!option->types) {
2672 talloc_free(option);
2676 for (i=0; i < option->count; i++) {
2677 option->types[i] = r->types[i];
2679 if (option->types[i].count) {
2680 option->types[i].fields = talloc_zero_array(option,
2681 union spoolss_Field, option->types[i].count);
2682 if (!option->types[i].fields) {
2683 talloc_free(option);
2686 for (k=0; k<option->types[i].count; k++) {
2687 option->types[i].fields[k] =
2688 r->types[i].fields[k];
2696 /****************************************************************
2697 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2699 * before replying OK: status=0 a rpc call is made to the workstation
2700 * asking ReplyOpenPrinter
2702 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2703 * called from api_spoolss_rffpcnex
2704 ****************************************************************/
2706 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2707 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2710 struct spoolss_NotifyOption *option = r->in.notify_options;
2711 struct sockaddr_storage client_ss;
2713 /* store the notify value in the printer struct */
2715 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2718 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2719 "Invalid handle (%s:%u:%u).\n",
2720 OUR_HANDLE(r->in.handle)));
2724 Printer->notify.flags = r->in.flags;
2725 Printer->notify.options = r->in.options;
2726 Printer->notify.printerlocal = r->in.printer_local;
2727 Printer->notify.msg_ctx = p->msg_ctx;
2729 TALLOC_FREE(Printer->notify.option);
2730 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2732 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2734 /* Connect to the client machine and send a ReplyOpenPrinter */
2736 if ( Printer->printer_type == SPLHND_SERVER)
2738 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2739 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2742 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2743 "client_address is %s\n", p->client_id->addr));
2745 if (!lp_print_notify_backchannel(snum)) {
2746 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2747 "backchannel disabled\n"));
2748 return WERR_SERVER_UNAVAILABLE;
2751 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2753 return WERR_SERVER_UNAVAILABLE;
2756 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2757 Printer->notify.printerlocal, REG_SZ,
2758 &Printer->notify.cli_hnd,
2759 &Printer->notify.cli_chan,
2760 &client_ss, p->msg_ctx)) {
2761 return WERR_SERVER_UNAVAILABLE;
2767 /*******************************************************************
2768 * fill a notify_info_data with the servername
2769 ********************************************************************/
2771 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2773 struct spoolss_Notify *data,
2774 print_queue_struct *queue,
2775 struct spoolss_PrinterInfo2 *pinfo2,
2776 TALLOC_CTX *mem_ctx)
2778 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2781 /*******************************************************************
2782 * fill a notify_info_data with the printername (not including the servername).
2783 ********************************************************************/
2785 static void spoolss_notify_printer_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 /* the notify name should not contain the \\server\ part */
2793 const char *p = strrchr(pinfo2->printername, '\\');
2796 p = pinfo2->printername;
2801 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2804 /*******************************************************************
2805 * fill a notify_info_data with the servicename
2806 ********************************************************************/
2808 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2810 struct spoolss_Notify *data,
2811 print_queue_struct *queue,
2812 struct spoolss_PrinterInfo2 *pinfo2,
2813 TALLOC_CTX *mem_ctx)
2815 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2818 /*******************************************************************
2819 * fill a notify_info_data with the port name
2820 ********************************************************************/
2822 static void spoolss_notify_port_name(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 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2832 /*******************************************************************
2833 * fill a notify_info_data with the printername
2834 * but it doesn't exist, have to see what to do
2835 ********************************************************************/
2837 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2839 struct spoolss_Notify *data,
2840 print_queue_struct *queue,
2841 struct spoolss_PrinterInfo2 *pinfo2,
2842 TALLOC_CTX *mem_ctx)
2844 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2847 /*******************************************************************
2848 * fill a notify_info_data with the comment
2849 ********************************************************************/
2851 static void spoolss_notify_comment(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)
2860 if (*pinfo2->comment == '\0') {
2861 p = lp_comment(snum);
2863 p = pinfo2->comment;
2866 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2869 /*******************************************************************
2870 * fill a notify_info_data with the comment
2871 * location = "Room 1, floor 2, building 3"
2872 ********************************************************************/
2874 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2876 struct spoolss_Notify *data,
2877 print_queue_struct *queue,
2878 struct spoolss_PrinterInfo2 *pinfo2,
2879 TALLOC_CTX *mem_ctx)
2881 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2884 /*******************************************************************
2885 * fill a notify_info_data with the device mode
2886 * jfm:xxxx don't to it for know but that's a real problem !!!
2887 ********************************************************************/
2889 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2891 struct spoolss_Notify *data,
2892 print_queue_struct *queue,
2893 struct spoolss_PrinterInfo2 *pinfo2,
2894 TALLOC_CTX *mem_ctx)
2896 /* for a dummy implementation we have to zero the fields */
2897 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2900 /*******************************************************************
2901 * fill a notify_info_data with the separator file name
2902 ********************************************************************/
2904 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2906 struct spoolss_Notify *data,
2907 print_queue_struct *queue,
2908 struct spoolss_PrinterInfo2 *pinfo2,
2909 TALLOC_CTX *mem_ctx)
2911 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2914 /*******************************************************************
2915 * fill a notify_info_data with the print processor
2916 * jfm:xxxx return always winprint to indicate we don't do anything to it
2917 ********************************************************************/
2919 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2921 struct spoolss_Notify *data,
2922 print_queue_struct *queue,
2923 struct spoolss_PrinterInfo2 *pinfo2,
2924 TALLOC_CTX *mem_ctx)
2926 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2929 /*******************************************************************
2930 * fill a notify_info_data with the print processor options
2931 * jfm:xxxx send an empty string
2932 ********************************************************************/
2934 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2936 struct spoolss_Notify *data,
2937 print_queue_struct *queue,
2938 struct spoolss_PrinterInfo2 *pinfo2,
2939 TALLOC_CTX *mem_ctx)
2941 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2944 /*******************************************************************
2945 * fill a notify_info_data with the data type
2946 * jfm:xxxx always send RAW as data type
2947 ********************************************************************/
2949 static void spoolss_notify_datatype(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_STRING(data, pinfo2->datatype);
2959 /*******************************************************************
2960 * fill a notify_info_data with the security descriptor
2961 * jfm:xxxx send an null pointer to say no security desc
2962 * have to implement security before !
2963 ********************************************************************/
2965 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2967 struct spoolss_Notify *data,
2968 print_queue_struct *queue,
2969 struct spoolss_PrinterInfo2 *pinfo2,
2970 TALLOC_CTX *mem_ctx)
2972 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2975 /*******************************************************************
2976 * fill a notify_info_data with the attributes
2977 * jfm:xxxx a samba printer is always shared
2978 ********************************************************************/
2980 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2982 struct spoolss_Notify *data,
2983 print_queue_struct *queue,
2984 struct spoolss_PrinterInfo2 *pinfo2,
2985 TALLOC_CTX *mem_ctx)
2987 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2990 /*******************************************************************
2991 * fill a notify_info_data with the priority
2992 ********************************************************************/
2994 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2996 struct spoolss_Notify *data,
2997 print_queue_struct *queue,
2998 struct spoolss_PrinterInfo2 *pinfo2,
2999 TALLOC_CTX *mem_ctx)
3001 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3004 /*******************************************************************
3005 * fill a notify_info_data with the default priority
3006 ********************************************************************/
3008 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3010 struct spoolss_Notify *data,
3011 print_queue_struct *queue,
3012 struct spoolss_PrinterInfo2 *pinfo2,
3013 TALLOC_CTX *mem_ctx)
3015 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3018 /*******************************************************************
3019 * fill a notify_info_data with the start time
3020 ********************************************************************/
3022 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3024 struct spoolss_Notify *data,
3025 print_queue_struct *queue,
3026 struct spoolss_PrinterInfo2 *pinfo2,
3027 TALLOC_CTX *mem_ctx)
3029 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3032 /*******************************************************************
3033 * fill a notify_info_data with the until time
3034 ********************************************************************/
3036 static void spoolss_notify_until_time(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(data, pinfo2->untiltime);
3046 /*******************************************************************
3047 * fill a notify_info_data with the status
3048 ********************************************************************/
3050 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3052 struct spoolss_Notify *data,
3053 print_queue_struct *queue,
3054 struct spoolss_PrinterInfo2 *pinfo2,
3055 TALLOC_CTX *mem_ctx)
3057 print_status_struct status;
3059 print_queue_length(msg_ctx, snum, &status);
3060 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3063 /*******************************************************************
3064 * fill a notify_info_data with the number of jobs queued
3065 ********************************************************************/
3067 static void spoolss_notify_cjobs(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_INTEGER(
3075 data, print_queue_length(msg_ctx, snum, NULL));
3078 /*******************************************************************
3079 * fill a notify_info_data with the average ppm
3080 ********************************************************************/
3082 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3084 struct spoolss_Notify *data,
3085 print_queue_struct *queue,
3086 struct spoolss_PrinterInfo2 *pinfo2,
3087 TALLOC_CTX *mem_ctx)
3089 /* always respond 8 pages per minutes */
3090 /* a little hard ! */
3091 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3094 /*******************************************************************
3095 * fill a notify_info_data with username
3096 ********************************************************************/
3098 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3100 struct spoolss_Notify *data,
3101 print_queue_struct *queue,
3102 struct spoolss_PrinterInfo2 *pinfo2,
3103 TALLOC_CTX *mem_ctx)
3105 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3108 /*******************************************************************
3109 * fill a notify_info_data with job status
3110 ********************************************************************/
3112 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3114 struct spoolss_Notify *data,
3115 print_queue_struct *queue,
3116 struct spoolss_PrinterInfo2 *pinfo2,
3117 TALLOC_CTX *mem_ctx)
3119 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3122 /*******************************************************************
3123 * fill a notify_info_data with job name
3124 ********************************************************************/
3126 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3128 struct spoolss_Notify *data,
3129 print_queue_struct *queue,
3130 struct spoolss_PrinterInfo2 *pinfo2,
3131 TALLOC_CTX *mem_ctx)
3133 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3136 /*******************************************************************
3137 * fill a notify_info_data with job status
3138 ********************************************************************/
3140 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3142 struct spoolss_Notify *data,
3143 print_queue_struct *queue,
3144 struct spoolss_PrinterInfo2 *pinfo2,
3145 TALLOC_CTX *mem_ctx)
3148 * Now we're returning job status codes we just return a "" here. JRA.
3153 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3156 switch (queue->status) {
3161 p = ""; /* NT provides the paused string */
3170 #endif /* NO LONGER NEEDED. */
3172 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3175 /*******************************************************************
3176 * fill a notify_info_data with job time
3177 ********************************************************************/
3179 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3181 struct spoolss_Notify *data,
3182 print_queue_struct *queue,
3183 struct spoolss_PrinterInfo2 *pinfo2,
3184 TALLOC_CTX *mem_ctx)
3186 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3189 /*******************************************************************
3190 * fill a notify_info_data with job size
3191 ********************************************************************/
3193 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3195 struct spoolss_Notify *data,
3196 print_queue_struct *queue,
3197 struct spoolss_PrinterInfo2 *pinfo2,
3198 TALLOC_CTX *mem_ctx)
3200 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3203 /*******************************************************************
3204 * fill a notify_info_data with page info
3205 ********************************************************************/
3206 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3208 struct spoolss_Notify *data,
3209 print_queue_struct *queue,
3210 struct spoolss_PrinterInfo2 *pinfo2,
3211 TALLOC_CTX *mem_ctx)
3213 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3216 /*******************************************************************
3217 * fill a notify_info_data with pages printed info.
3218 ********************************************************************/
3219 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3221 struct spoolss_Notify *data,
3222 print_queue_struct *queue,
3223 struct spoolss_PrinterInfo2 *pinfo2,
3224 TALLOC_CTX *mem_ctx)
3226 /* Add code when back-end tracks this */
3227 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3230 /*******************************************************************
3231 Fill a notify_info_data with job position.
3232 ********************************************************************/
3234 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3236 struct spoolss_Notify *data,
3237 print_queue_struct *queue,
3238 struct spoolss_PrinterInfo2 *pinfo2,
3239 TALLOC_CTX *mem_ctx)
3241 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3244 /*******************************************************************
3245 Fill a notify_info_data with submitted time.
3246 ********************************************************************/
3248 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3250 struct spoolss_Notify *data,
3251 print_queue_struct *queue,
3252 struct spoolss_PrinterInfo2 *pinfo2,
3253 TALLOC_CTX *mem_ctx)
3255 data->data.string.string = NULL;
3256 data->data.string.size = 0;
3258 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3259 &data->data.string.string,
3260 &data->data.string.size);
3264 struct s_notify_info_data_table
3266 enum spoolss_NotifyType type;
3269 enum spoolss_NotifyTable variable_type;
3270 void (*fn) (struct messaging_context *msg_ctx,
3271 int snum, struct spoolss_Notify *data,
3272 print_queue_struct *queue,
3273 struct spoolss_PrinterInfo2 *pinfo2,
3274 TALLOC_CTX *mem_ctx);
3277 /* A table describing the various print notification constants and
3278 whether the notification data is a pointer to a variable sized
3279 buffer, a one value uint32_t or a two value uint32_t. */
3281 static const struct s_notify_info_data_table notify_info_data_table[] =
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3334 /*******************************************************************
3335 Return the variable_type of info_data structure.
3336 ********************************************************************/
3338 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3343 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3344 if ( (notify_info_data_table[i].type == type) &&
3345 (notify_info_data_table[i].field == field) ) {
3346 return notify_info_data_table[i].variable_type;
3350 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3352 return (enum spoolss_NotifyTable) 0;
3355 /****************************************************************************
3356 ****************************************************************************/
3358 static bool search_notify(enum spoolss_NotifyType type,
3364 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3365 if (notify_info_data_table[i].type == type &&
3366 notify_info_data_table[i].field == field &&
3367 notify_info_data_table[i].fn != NULL) {
3376 /****************************************************************************
3377 ****************************************************************************/
3379 static void construct_info_data(struct spoolss_Notify *info_data,
3380 enum spoolss_NotifyType type,
3381 uint16_t field, int id)
3383 info_data->type = type;
3384 info_data->field.field = field;
3385 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3386 info_data->job_id = id;
3389 /*******************************************************************
3391 * fill a notify_info struct with info asked
3393 ********************************************************************/
3395 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3396 struct printer_handle *print_hnd,
3397 struct spoolss_NotifyInfo *info,
3398 struct spoolss_PrinterInfo2 *pinfo2,
3400 const struct spoolss_NotifyOptionType *option_type,
3402 TALLOC_CTX *mem_ctx)
3405 enum spoolss_NotifyType type;
3408 struct spoolss_Notify *current_data;
3409 print_queue_struct *queue=NULL;
3411 type = option_type->type;
3413 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3414 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3415 option_type->count, lp_servicename(snum)));
3417 for(field_num=0; field_num < option_type->count; field_num++) {
3418 field = option_type->fields[field_num].field;
3420 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3422 if (!search_notify(type, field, &j) )
3425 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3426 struct spoolss_Notify,
3428 if (info->notifies == NULL) {
3429 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3433 current_data = &info->notifies[info->count];
3435 construct_info_data(current_data, type, field, id);
3437 DEBUG(10, ("construct_notify_printer_info: "
3438 "calling [%s] snum=%d printername=[%s])\n",
3439 notify_info_data_table[j].name, snum,
3440 pinfo2->printername));
3442 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3443 queue, pinfo2, mem_ctx);
3451 /*******************************************************************
3453 * fill a notify_info struct with info asked
3455 ********************************************************************/
3457 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3458 print_queue_struct *queue,
3459 struct spoolss_NotifyInfo *info,
3460 struct spoolss_PrinterInfo2 *pinfo2,
3462 const struct spoolss_NotifyOptionType *option_type,
3464 TALLOC_CTX *mem_ctx)
3467 enum spoolss_NotifyType type;
3469 struct spoolss_Notify *current_data;
3471 DEBUG(4,("construct_notify_jobs_info\n"));
3473 type = option_type->type;
3475 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3476 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3477 option_type->count));
3479 for(field_num=0; field_num<option_type->count; field_num++) {
3480 field = option_type->fields[field_num].field;
3482 if (!search_notify(type, field, &j) )
3485 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3486 struct spoolss_Notify,
3488 if (info->notifies == NULL) {
3489 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3493 current_data=&(info->notifies[info->count]);
3495 construct_info_data(current_data, type, field, id);
3496 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3497 queue, pinfo2, mem_ctx);
3505 * JFM: The enumeration is not that simple, it's even non obvious.
3507 * let's take an example: I want to monitor the PRINTER SERVER for
3508 * the printer's name and the number of jobs currently queued.
3509 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3510 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3512 * I have 3 printers on the back of my server.
3514 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3517 * 1 printer 1 name 1
3518 * 2 printer 1 cjob 1
3519 * 3 printer 2 name 2
3520 * 4 printer 2 cjob 2
3521 * 5 printer 3 name 3
3522 * 6 printer 3 name 3
3524 * that's the print server case, the printer case is even worse.
3527 /*******************************************************************
3529 * enumerate all printers on the printserver
3530 * fill a notify_info struct with info asked
3532 ********************************************************************/
3534 static WERROR printserver_notify_info(struct pipes_struct *p,
3535 struct policy_handle *hnd,
3536 struct spoolss_NotifyInfo *info,
3537 TALLOC_CTX *mem_ctx)
3540 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3541 int n_services=lp_numservices();
3543 struct spoolss_NotifyOption *option;
3544 struct spoolss_NotifyOptionType option_type;
3545 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3548 DEBUG(4,("printserver_notify_info\n"));
3553 option = Printer->notify.option;
3556 info->notifies = NULL;
3559 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3560 sending a ffpcn() request first */
3565 for (i=0; i<option->count; i++) {
3566 option_type = option->types[i];
3568 if (option_type.type != PRINTER_NOTIFY_TYPE)
3571 for (snum = 0; snum < n_services; snum++) {
3572 if (!lp_browseable(snum) ||
3573 !lp_snum_ok(snum) ||
3574 !lp_print_ok(snum)) {
3575 continue; /* skip */
3578 /* Maybe we should use the SYSTEM session_info here... */
3579 result = winreg_get_printer(mem_ctx,
3580 get_session_info_system(),
3582 lp_servicename(snum),
3584 if (!W_ERROR_IS_OK(result)) {
3585 DEBUG(4, ("printserver_notify_info: "
3586 "Failed to get printer [%s]\n",
3587 lp_servicename(snum)));
3592 construct_notify_printer_info(p->msg_ctx,
3598 TALLOC_FREE(pinfo2);
3604 * Debugging information, don't delete.
3607 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3608 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3609 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3611 for (i=0; i<info->count; i++) {
3612 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3613 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3614 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3621 /*******************************************************************
3623 * fill a notify_info struct with info asked
3625 ********************************************************************/
3627 static WERROR printer_notify_info(struct pipes_struct *p,
3628 struct policy_handle *hnd,
3629 struct spoolss_NotifyInfo *info,
3630 TALLOC_CTX *mem_ctx)
3633 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3636 struct spoolss_NotifyOption *option;
3637 struct spoolss_NotifyOptionType option_type;
3639 print_queue_struct *queue=NULL;
3640 print_status_struct status;
3641 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3644 DEBUG(4,("printer_notify_info\n"));
3649 option = Printer->notify.option;
3653 info->notifies = NULL;
3656 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3657 sending a ffpcn() request first */
3662 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3666 /* Maybe we should use the SYSTEM session_info here... */
3667 result = winreg_get_printer(mem_ctx,
3668 get_session_info_system(),
3670 lp_servicename(snum), &pinfo2);
3671 if (!W_ERROR_IS_OK(result)) {
3675 for (i=0; i<option->count; i++) {
3676 option_type = option->types[i];
3678 switch (option_type.type) {
3679 case PRINTER_NOTIFY_TYPE:
3680 if (construct_notify_printer_info(p->msg_ctx,
3689 case JOB_NOTIFY_TYPE:
3691 count = print_queue_status(p->msg_ctx, snum, &queue,
3694 for (j=0; j<count; j++) {
3695 construct_notify_jobs_info(p->msg_ctx,
3709 * Debugging information, don't delete.
3712 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716 for (i=0; i<info->count; i++) {
3717 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3723 talloc_free(pinfo2);
3727 /****************************************************************
3728 _spoolss_RouterRefreshPrinterChangeNotify
3729 ****************************************************************/
3731 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3732 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3734 struct spoolss_NotifyInfo *info;
3736 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3737 WERROR result = WERR_BADFID;
3739 /* we always have a spoolss_NotifyInfo struct */
3740 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3742 result = WERR_NOMEM;
3746 *r->out.info = info;
3749 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3750 "Invalid handle (%s:%u:%u).\n",
3751 OUR_HANDLE(r->in.handle)));
3755 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3758 * We are now using the change value, and
3759 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3760 * I don't have a global notification system, I'm sending back all the
3761 * information even when _NOTHING_ has changed.
3764 /* We need to keep track of the change value to send back in
3765 RRPCN replies otherwise our updates are ignored. */
3767 Printer->notify.fnpcn = true;
3769 if (Printer->notify.cli_chan != NULL &&
3770 Printer->notify.cli_chan->active_connections > 0) {
3771 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3772 "Saving change value in request [%x]\n",
3774 Printer->notify.change = r->in.change_low;
3777 /* just ignore the spoolss_NotifyOption */
3779 switch (Printer->printer_type) {
3781 result = printserver_notify_info(p, r->in.handle,
3785 case SPLHND_PRINTER:
3786 result = printer_notify_info(p, r->in.handle,
3791 Printer->notify.fnpcn = false;
3797 /********************************************************************
3798 ********************************************************************/
3800 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3801 const char *servername,
3802 const char *printername,
3803 const char **printername_p)
3805 /* FIXME: add lp_force_printername() */
3807 if (servername == NULL) {
3808 *printername_p = talloc_strdup(mem_ctx, printername);
3809 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3813 if (servername[0] == '\\' && servername[1] == '\\') {
3817 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3818 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3823 /********************************************************************
3824 ********************************************************************/
3826 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3827 const char *printername)
3833 dm->devicename = talloc_strndup(dm, printername,
3834 MIN(strlen(printername), 31));
3837 /********************************************************************
3838 * construct_printer_info_0
3839 * fill a printer_info_0 struct
3840 ********************************************************************/
3842 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3843 const struct auth_serversupplied_info *session_info,
3844 struct messaging_context *msg_ctx,
3845 struct spoolss_PrinterInfo2 *info2,
3846 const char *servername,
3847 struct spoolss_PrinterInfo0 *r,
3851 struct printer_session_counter *session_counter;
3852 struct timeval setuptime;
3853 print_status_struct status;
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;
3901 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3902 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3903 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3904 r->free_build = SPOOLSS_RELEASE_BUILD;
3906 r->max_spooling = 0;
3907 r->session_counter = session_counter->counter;
3908 r->num_error_out_of_paper = 0x0;
3909 r->num_error_not_ready = 0x0; /* number of print failure */
3911 r->number_of_processors = 0x1;
3912 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3913 r->high_part_total_bytes = 0x0;
3915 /* ChangeID in milliseconds*/
3916 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3917 info2->sharename, &r->change_id);
3919 r->last_error = WERR_OK;
3920 r->status = nt_printq_status(status.status);
3921 r->enumerate_network_printers = 0x0;
3922 r->c_setprinter = 0x0;
3923 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3924 r->processor_level = 0x6; /* 6 ???*/
3933 /********************************************************************
3934 * construct_printer_info1
3935 * fill a spoolss_PrinterInfo1 struct
3936 ********************************************************************/
3938 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3939 const struct spoolss_PrinterInfo2 *info2,
3941 const char *servername,
3942 struct spoolss_PrinterInfo1 *r,
3949 if (info2->comment == NULL || info2->comment[0] == '\0') {
3950 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3952 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3954 W_ERROR_HAVE_NO_MEMORY(r->comment);
3956 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3957 if (!W_ERROR_IS_OK(result)) {
3961 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3965 W_ERROR_HAVE_NO_MEMORY(r->description);
3970 /********************************************************************
3971 * construct_printer_info2
3972 * fill a spoolss_PrinterInfo2 struct
3973 ********************************************************************/
3975 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3976 struct messaging_context *msg_ctx,
3977 const struct spoolss_PrinterInfo2 *info2,
3978 const char *servername,
3979 struct spoolss_PrinterInfo2 *r,
3983 print_status_struct status;
3986 count = print_queue_length(msg_ctx, snum, &status);
3989 r->servername = talloc_strdup(mem_ctx, servername);
3990 W_ERROR_HAVE_NO_MEMORY(r->servername);
3992 r->servername = NULL;
3995 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3996 if (!W_ERROR_IS_OK(result)) {
4000 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4001 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4002 r->portname = talloc_strdup(mem_ctx, info2->portname);
4003 W_ERROR_HAVE_NO_MEMORY(r->portname);
4004 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4005 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4007 if (info2->comment[0] == '\0') {
4008 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4010 r->comment = talloc_strdup(mem_ctx, info2->comment);
4012 W_ERROR_HAVE_NO_MEMORY(r->comment);
4014 r->location = talloc_strdup(mem_ctx, info2->location);
4015 W_ERROR_HAVE_NO_MEMORY(r->location);
4016 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4017 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4018 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4019 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4020 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4021 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4022 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4023 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4025 r->attributes = info2->attributes;
4027 r->priority = info2->priority;
4028 r->defaultpriority = info2->defaultpriority;
4029 r->starttime = info2->starttime;
4030 r->untiltime = info2->untiltime;
4031 r->status = nt_printq_status(status.status);
4033 r->averageppm = info2->averageppm;
4035 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4037 DEBUG(8,("Returning NULL Devicemode!\n"));
4040 compose_devicemode_devicename(r->devmode, r->printername);
4044 if (info2->secdesc != NULL) {
4045 /* don't use talloc_steal() here unless you do a deep steal of all
4046 the SEC_DESC members */
4048 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4054 /********************************************************************
4055 * construct_printer_info3
4056 * fill a spoolss_PrinterInfo3 struct
4057 ********************************************************************/
4059 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4060 const struct spoolss_PrinterInfo2 *info2,
4061 const char *servername,
4062 struct spoolss_PrinterInfo3 *r,
4065 /* These are the components of the SD we are returning. */
4067 if (info2->secdesc != NULL) {
4068 /* don't use talloc_steal() here unless you do a deep steal of all
4069 the SEC_DESC members */
4071 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4072 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4078 /********************************************************************
4079 * construct_printer_info4
4080 * fill a spoolss_PrinterInfo4 struct
4081 ********************************************************************/
4083 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4084 const struct spoolss_PrinterInfo2 *info2,
4085 const char *servername,
4086 struct spoolss_PrinterInfo4 *r,
4091 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4092 if (!W_ERROR_IS_OK(result)) {
4097 r->servername = talloc_strdup(mem_ctx, servername);
4098 W_ERROR_HAVE_NO_MEMORY(r->servername);
4100 r->servername = NULL;
4103 r->attributes = info2->attributes;
4108 /********************************************************************
4109 * construct_printer_info5
4110 * fill a spoolss_PrinterInfo5 struct
4111 ********************************************************************/
4113 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4114 const struct spoolss_PrinterInfo2 *info2,
4115 const char *servername,
4116 struct spoolss_PrinterInfo5 *r,
4121 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4122 if (!W_ERROR_IS_OK(result)) {
4126 r->portname = talloc_strdup(mem_ctx, info2->portname);
4127 W_ERROR_HAVE_NO_MEMORY(r->portname);
4129 r->attributes = info2->attributes;
4131 /* these two are not used by NT+ according to MSDN */
4132 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4133 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4138 /********************************************************************
4139 * construct_printer_info_6
4140 * fill a spoolss_PrinterInfo6 struct
4141 ********************************************************************/
4143 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4144 struct messaging_context *msg_ctx,
4145 const struct spoolss_PrinterInfo2 *info2,
4146 const char *servername,
4147 struct spoolss_PrinterInfo6 *r,
4151 print_status_struct status;
4153 count = print_queue_length(msg_ctx, snum, &status);
4155 r->status = nt_printq_status(status.status);
4160 /********************************************************************
4161 * construct_printer_info7
4162 * fill a spoolss_PrinterInfo7 struct
4163 ********************************************************************/
4165 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4166 struct messaging_context *msg_ctx,
4167 const char *servername,
4168 struct spoolss_PrinterInfo7 *r,
4171 struct auth_serversupplied_info *session_info;
4175 status = make_session_info_system(mem_ctx, &session_info);
4176 if (!NT_STATUS_IS_OK(status)) {
4177 DEBUG(0, ("construct_printer_info7: "
4178 "Could not create system session_info\n"));
4182 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4184 lp_servicename(snum), &guid, NULL)) {
4185 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4186 r->action = DSPRINT_PUBLISH;
4188 r->guid = talloc_strdup(mem_ctx, "");
4189 r->action = DSPRINT_UNPUBLISH;
4191 W_ERROR_HAVE_NO_MEMORY(r->guid);
4193 TALLOC_FREE(session_info);
4197 /********************************************************************
4198 * construct_printer_info8
4199 * fill a spoolss_PrinterInfo8 struct
4200 ********************************************************************/
4202 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4203 const struct spoolss_PrinterInfo2 *info2,
4204 const char *servername,
4205 struct spoolss_DeviceModeInfo *r,
4209 const char *printername;
4211 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4212 if (!W_ERROR_IS_OK(result)) {
4216 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4218 DEBUG(8,("Returning NULL Devicemode!\n"));
4221 compose_devicemode_devicename(r->devmode, printername);
4227 /********************************************************************
4228 ********************************************************************/
4230 static bool snum_is_shared_printer(int snum)
4232 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4235 /********************************************************************
4236 Spoolss_enumprinters.
4237 ********************************************************************/
4239 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4240 const struct auth_serversupplied_info *session_info,
4241 struct messaging_context *msg_ctx,
4242 const char *servername,
4245 union spoolss_PrinterInfo **info_p,
4249 int n_services = lp_numservices();
4250 union spoolss_PrinterInfo *info = NULL;
4252 WERROR result = WERR_OK;
4257 for (snum = 0; snum < n_services; snum++) {
4259 const char *printer;
4260 struct spoolss_PrinterInfo2 *info2;
4262 if (!snum_is_shared_printer(snum)) {
4266 printer = lp_const_servicename(snum);
4268 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4271 result = winreg_create_printer(mem_ctx,
4275 if (!W_ERROR_IS_OK(result)) {
4279 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4280 union spoolss_PrinterInfo,
4283 result = WERR_NOMEM;
4287 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4289 if (!W_ERROR_IS_OK(result)) {
4295 result = construct_printer_info0(info, session_info,
4298 &info[count].info0, snum);
4301 result = construct_printer_info1(info, info2, flags,
4303 &info[count].info1, snum);
4306 result = construct_printer_info2(info, msg_ctx, info2,
4308 &info[count].info2, snum);
4311 result = construct_printer_info4(info, info2,
4313 &info[count].info4, snum);
4316 result = construct_printer_info5(info, info2,
4318 &info[count].info5, snum);
4322 result = WERR_UNKNOWN_LEVEL;
4326 if (!W_ERROR_IS_OK(result)) {
4337 if (!W_ERROR_IS_OK(result)) {
4347 /********************************************************************
4348 * handle enumeration of printers at level 0
4349 ********************************************************************/
4351 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4352 const struct auth_serversupplied_info *session_info,
4353 struct messaging_context *msg_ctx,
4355 const char *servername,
4356 union spoolss_PrinterInfo **info,
4359 DEBUG(4,("enum_all_printers_info_0\n"));
4361 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4362 servername, 0, flags, info, count);
4366 /********************************************************************
4367 ********************************************************************/
4369 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4370 const struct auth_serversupplied_info *session_info,
4371 struct messaging_context *msg_ctx,
4372 const char *servername,
4374 union spoolss_PrinterInfo **info,
4377 DEBUG(4,("enum_all_printers_info_1\n"));
4379 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380 servername, 1, flags, info, count);
4383 /********************************************************************
4384 enum_all_printers_info_1_local.
4385 *********************************************************************/
4387 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4388 const struct auth_serversupplied_info *session_info,
4389 struct messaging_context *msg_ctx,
4390 const char *servername,
4391 union spoolss_PrinterInfo **info,
4394 DEBUG(4,("enum_all_printers_info_1_local\n"));
4396 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4397 servername, PRINTER_ENUM_ICON8, info, count);
4400 /********************************************************************
4401 enum_all_printers_info_1_name.
4402 *********************************************************************/
4404 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4405 const struct auth_serversupplied_info *session_info,
4406 struct messaging_context *msg_ctx,
4407 const char *servername,
4408 union spoolss_PrinterInfo **info,
4411 const char *s = servername;
4413 DEBUG(4,("enum_all_printers_info_1_name\n"));
4415 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4419 if (!is_myname_or_ipaddr(s)) {
4420 return WERR_INVALID_NAME;
4423 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4424 servername, PRINTER_ENUM_ICON8, info, count);
4427 /********************************************************************
4428 enum_all_printers_info_1_network.
4429 *********************************************************************/
4431 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4432 const struct auth_serversupplied_info *session_info,
4433 struct messaging_context *msg_ctx,
4434 const char *servername,
4435 union spoolss_PrinterInfo **info,
4438 const char *s = servername;
4440 DEBUG(4,("enum_all_printers_info_1_network\n"));
4442 /* If we respond to a enum_printers level 1 on our name with flags
4443 set to PRINTER_ENUM_REMOTE with a list of printers then these
4444 printers incorrectly appear in the APW browse list.
4445 Specifically the printers for the server appear at the workgroup
4446 level where all the other servers in the domain are
4447 listed. Windows responds to this call with a
4448 WERR_CAN_NOT_COMPLETE so we should do the same. */
4450 if (servername[0] == '\\' && servername[1] == '\\') {
4454 if (is_myname_or_ipaddr(s)) {
4455 return WERR_CAN_NOT_COMPLETE;
4458 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4459 servername, PRINTER_ENUM_NAME, info, count);
4462 /********************************************************************
4463 * api_spoolss_enumprinters
4465 * called from api_spoolss_enumprinters (see this to understand)
4466 ********************************************************************/
4468 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4469 const struct auth_serversupplied_info *session_info,
4470 struct messaging_context *msg_ctx,
4471 const char *servername,
4472 union spoolss_PrinterInfo **info,
4475 DEBUG(4,("enum_all_printers_info_2\n"));
4477 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4478 servername, 2, 0, info, count);
4481 /********************************************************************
4482 * handle enumeration of printers at level 1
4483 ********************************************************************/
4485 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4486 const struct auth_serversupplied_info *session_info,
4487 struct messaging_context *msg_ctx,
4489 const char *servername,
4490 union spoolss_PrinterInfo **info,
4493 /* Not all the flags are equals */
4495 if (flags & PRINTER_ENUM_LOCAL) {
4496 return enum_all_printers_info_1_local(mem_ctx, session_info,
4497 msg_ctx, servername, info, count);
4500 if (flags & PRINTER_ENUM_NAME) {
4501 return enum_all_printers_info_1_name(mem_ctx, session_info,
4502 msg_ctx, servername, info,
4506 if (flags & PRINTER_ENUM_NETWORK) {
4507 return enum_all_printers_info_1_network(mem_ctx, session_info,
4508 msg_ctx, servername, info,
4512 return WERR_OK; /* NT4sp5 does that */
4515 /********************************************************************
4516 * handle enumeration of printers at level 2
4517 ********************************************************************/
4519 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4520 const struct auth_serversupplied_info *session_info,
4521 struct messaging_context *msg_ctx,
4523 const char *servername,
4524 union spoolss_PrinterInfo **info,
4527 if (flags & PRINTER_ENUM_LOCAL) {
4529 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4534 if (flags & PRINTER_ENUM_NAME) {
4535 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4536 return WERR_INVALID_NAME;
4539 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4544 if (flags & PRINTER_ENUM_REMOTE) {
4545 return WERR_UNKNOWN_LEVEL;
4551 /********************************************************************
4552 * handle enumeration of printers at level 4
4553 ********************************************************************/
4555 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4556 const struct auth_serversupplied_info *session_info,
4557 struct messaging_context *msg_ctx,
4559 const char *servername,
4560 union spoolss_PrinterInfo **info,
4563 DEBUG(4,("enum_all_printers_info_4\n"));
4565 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4566 servername, 4, flags, info, count);
4570 /********************************************************************
4571 * handle enumeration of printers at level 5
4572 ********************************************************************/
4574 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4575 const struct auth_serversupplied_info *session_info,
4576 struct messaging_context *msg_ctx,
4578 const char *servername,
4579 union spoolss_PrinterInfo **info,
4582 DEBUG(4,("enum_all_printers_info_5\n"));
4584 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585 servername, 5, flags, info, count);
4588 /****************************************************************
4589 _spoolss_EnumPrinters
4590 ****************************************************************/
4592 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4593 struct spoolss_EnumPrinters *r)
4595 const struct auth_serversupplied_info *session_info = get_session_info_system();
4598 /* that's an [in out] buffer */
4600 if (!r->in.buffer && (r->in.offered != 0)) {
4601 return WERR_INVALID_PARAM;
4604 DEBUG(4,("_spoolss_EnumPrinters\n"));
4608 *r->out.info = NULL;
4612 * flags==PRINTER_ENUM_NAME
4613 * if name=="" then enumerates all printers
4614 * if name!="" then enumerate the printer
4615 * flags==PRINTER_ENUM_REMOTE
4616 * name is NULL, enumerate printers
4617 * Level 2: name!="" enumerates printers, name can't be NULL
4618 * Level 3: doesn't exist
4619 * Level 4: does a local registry lookup
4620 * Level 5: same as Level 2
4623 if (r->in.server && r->in.server[0] == '\0') {
4624 r->in.server = NULL;
4627 switch (r->in.level) {
4629 result = enumprinters_level0(p->mem_ctx, session_info,
4630 p->msg_ctx, r->in.flags,
4632 r->out.info, r->out.count);
4635 result = enumprinters_level1(p->mem_ctx, session_info,
4636 p->msg_ctx, r->in.flags,
4638 r->out.info, r->out.count);
4641 result = enumprinters_level2(p->mem_ctx, session_info,
4642 p->msg_ctx, r->in.flags,
4644 r->out.info, r->out.count);
4647 result = enumprinters_level4(p->mem_ctx, session_info,
4648 p->msg_ctx, r->in.flags,
4650 r->out.info, r->out.count);
4653 result = enumprinters_level5(p->mem_ctx, session_info,
4654 p->msg_ctx, r->in.flags,
4656 r->out.info, r->out.count);
4659 return WERR_UNKNOWN_LEVEL;
4662 if (!W_ERROR_IS_OK(result)) {
4666 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4667 spoolss_EnumPrinters,
4668 *r->out.info, r->in.level,
4670 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4671 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4673 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4676 /****************************************************************
4678 ****************************************************************/
4680 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4681 struct spoolss_GetPrinter *r)
4683 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4684 struct spoolss_PrinterInfo2 *info2 = NULL;
4685 WERROR result = WERR_OK;
4688 /* that's an [in out] buffer */
4690 if (!r->in.buffer && (r->in.offered != 0)) {
4691 return WERR_INVALID_PARAM;
4696 if (Printer == NULL) {
4700 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4704 result = winreg_get_printer(p->mem_ctx,
4705 get_session_info_system(),
4707 lp_const_servicename(snum),
4709 if (!W_ERROR_IS_OK(result)) {
4713 switch (r->in.level) {
4715 result = construct_printer_info0(p->mem_ctx,
4716 get_session_info_system(),
4719 Printer->servername,
4720 &r->out.info->info0,
4724 result = construct_printer_info1(p->mem_ctx, info2,
4726 Printer->servername,
4727 &r->out.info->info1, snum);
4730 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4731 Printer->servername,
4732 &r->out.info->info2, snum);
4735 result = construct_printer_info3(p->mem_ctx, info2,
4736 Printer->servername,
4737 &r->out.info->info3, snum);
4740 result = construct_printer_info4(p->mem_ctx, info2,
4741 Printer->servername,
4742 &r->out.info->info4, snum);
4745 result = construct_printer_info5(p->mem_ctx, info2,
4746 Printer->servername,
4747 &r->out.info->info5, snum);
4750 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4751 Printer->servername,
4752 &r->out.info->info6, snum);
4755 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4756 Printer->servername,
4757 &r->out.info->info7, snum);
4760 result = construct_printer_info8(p->mem_ctx, info2,
4761 Printer->servername,
4762 &r->out.info->info8, snum);
4765 result = WERR_UNKNOWN_LEVEL;
4770 if (!W_ERROR_IS_OK(result)) {
4771 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4772 r->in.level, win_errstr(result)));
4773 TALLOC_FREE(r->out.info);
4777 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4778 r->out.info, r->in.level);
4779 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4781 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4784 /********************************************************************
4785 ********************************************************************/
4787 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4789 if (in && strlen(in)) { \
4790 out = talloc_strdup(mem_ctx, in); \
4792 out = talloc_strdup(mem_ctx, ""); \
4794 W_ERROR_HAVE_NO_MEMORY(out); \
4797 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4799 if (in && strlen(in)) { \
4800 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4802 out = talloc_strdup(mem_ctx, ""); \
4804 W_ERROR_HAVE_NO_MEMORY(out); \
4807 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4808 const char **string_array,
4809 const char ***presult,
4810 const char *cservername,
4814 int i, num_strings = 0;
4815 const char **array = NULL;
4817 if (string_array == NULL) {
4818 return WERR_INVALID_PARAMETER;
4821 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4822 const char *str = NULL;
4824 if (cservername == NULL || arch == NULL) {
4825 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4827 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4830 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4837 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4838 &array, &num_strings);
4848 /********************************************************************
4849 * fill a spoolss_DriverInfo1 struct
4850 ********************************************************************/
4852 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4853 struct spoolss_DriverInfo1 *r,
4854 const struct spoolss_DriverInfo8 *driver,
4855 const char *servername)
4857 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4858 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4863 /********************************************************************
4864 * fill a spoolss_DriverInfo2 struct
4865 ********************************************************************/
4867 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4868 struct spoolss_DriverInfo2 *r,
4869 const struct spoolss_DriverInfo8 *driver,
4870 const char *servername)
4873 const char *cservername = canon_servername(servername);
4875 r->version = driver->version;
4877 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4878 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4879 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4880 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4882 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4883 driver->architecture,
4885 driver->driver_path,
4888 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4889 driver->architecture,
4894 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4895 driver->architecture,
4897 driver->config_file,
4903 /********************************************************************
4904 * fill a spoolss_DriverInfo3 struct
4905 ********************************************************************/
4907 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4908 struct spoolss_DriverInfo3 *r,
4909 const struct spoolss_DriverInfo8 *driver,
4910 const char *servername)
4912 const char *cservername = canon_servername(servername);
4914 r->version = driver->version;
4916 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4917 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4918 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4919 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4921 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4922 driver->architecture,
4924 driver->driver_path,
4927 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4928 driver->architecture,
4933 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4934 driver->architecture,
4936 driver->config_file,
4939 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4940 driver->architecture,
4945 FILL_DRIVER_STRING(mem_ctx,
4946 driver->monitor_name,
4949 FILL_DRIVER_STRING(mem_ctx,
4950 driver->default_datatype,
4951 r->default_datatype);
4953 return string_array_from_driver_info(mem_ctx,
4954 driver->dependent_files,
4955 &r->dependent_files,
4957 driver->architecture,
4961 /********************************************************************
4962 * fill a spoolss_DriverInfo4 struct
4963 ********************************************************************/
4965 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4966 struct spoolss_DriverInfo4 *r,
4967 const struct spoolss_DriverInfo8 *driver,
4968 const char *servername)
4970 const char *cservername = canon_servername(servername);
4973 r->version = driver->version;
4975 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4976 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4977 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4978 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4980 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4981 driver->architecture,
4983 driver->driver_path,
4986 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4987 driver->architecture,
4992 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4993 driver->architecture,
4995 driver->config_file,
4998 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4999 driver->architecture,
5004 result = string_array_from_driver_info(mem_ctx,
5005 driver->dependent_files,
5006 &r->dependent_files,
5008 driver->architecture,
5010 if (!W_ERROR_IS_OK(result)) {
5014 FILL_DRIVER_STRING(mem_ctx,
5015 driver->monitor_name,
5018 FILL_DRIVER_STRING(mem_ctx,
5019 driver->default_datatype,
5020 r->default_datatype);
5023 result = string_array_from_driver_info(mem_ctx,
5024 driver->previous_names,
5031 /********************************************************************
5032 * fill a spoolss_DriverInfo5 struct
5033 ********************************************************************/
5035 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5036 struct spoolss_DriverInfo5 *r,
5037 const struct spoolss_DriverInfo8 *driver,
5038 const char *servername)
5040 const char *cservername = canon_servername(servername);
5042 r->version = driver->version;
5044 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5045 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5046 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5047 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5049 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050 driver->architecture,
5052 driver->driver_path,
5055 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056 driver->architecture,
5061 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5062 driver->architecture,
5064 driver->config_file,
5067 r->driver_attributes = 0;
5068 r->config_version = 0;
5069 r->driver_version = 0;
5073 /********************************************************************
5074 * fill a spoolss_DriverInfo6 struct
5075 ********************************************************************/
5077 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5078 struct spoolss_DriverInfo6 *r,
5079 const struct spoolss_DriverInfo8 *driver,
5080 const char *servername)
5082 const char *cservername = canon_servername(servername);
5085 r->version = driver->version;
5087 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5088 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5089 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5090 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5092 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093 driver->architecture,
5095 driver->driver_path,
5098 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5099 driver->architecture,
5104 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105 driver->architecture,
5107 driver->config_file,
5110 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5111 driver->architecture,
5116 FILL_DRIVER_STRING(mem_ctx,
5117 driver->monitor_name,
5120 FILL_DRIVER_STRING(mem_ctx,
5121 driver->default_datatype,
5122 r->default_datatype);
5124 result = string_array_from_driver_info(mem_ctx,
5125 driver->dependent_files,
5126 &r->dependent_files,
5128 driver->architecture,
5130 if (!W_ERROR_IS_OK(result)) {
5134 result = string_array_from_driver_info(mem_ctx,
5135 driver->previous_names,
5138 if (!W_ERROR_IS_OK(result)) {
5142 r->driver_date = driver->driver_date;
5143 r->driver_version = driver->driver_version;
5145 FILL_DRIVER_STRING(mem_ctx,
5146 driver->manufacturer_name,
5147 r->manufacturer_name);
5148 FILL_DRIVER_STRING(mem_ctx,
5149 driver->manufacturer_url,
5150 r->manufacturer_url);
5151 FILL_DRIVER_STRING(mem_ctx,
5152 driver->hardware_id,
5154 FILL_DRIVER_STRING(mem_ctx,
5161 /********************************************************************
5162 * fill a spoolss_DriverInfo8 struct
5163 ********************************************************************/
5165 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5166 struct spoolss_DriverInfo8 *r,
5167 const struct spoolss_DriverInfo8 *driver,
5168 const char *servername)
5170 const char *cservername = canon_servername(servername);
5173 r->version = driver->version;
5175 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5176 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5177 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5178 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5180 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181 driver->architecture,
5183 driver->driver_path,
5186 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187 driver->architecture,
5192 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5193 driver->architecture,
5195 driver->config_file,
5198 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5199 driver->architecture,
5204 FILL_DRIVER_STRING(mem_ctx,
5205 driver->monitor_name,
5208 FILL_DRIVER_STRING(mem_ctx,
5209 driver->default_datatype,
5210 r->default_datatype);
5212 result = string_array_from_driver_info(mem_ctx,
5213 driver->dependent_files,
5214 &r->dependent_files,
5216 driver->architecture,
5218 if (!W_ERROR_IS_OK(result)) {
5222 result = string_array_from_driver_info(mem_ctx,
5223 driver->previous_names,
5226 if (!W_ERROR_IS_OK(result)) {
5230 r->driver_date = driver->driver_date;
5231 r->driver_version = driver->driver_version;
5233 FILL_DRIVER_STRING(mem_ctx,
5234 driver->manufacturer_name,
5235 r->manufacturer_name);
5236 FILL_DRIVER_STRING(mem_ctx,
5237 driver->manufacturer_url,
5238 r->manufacturer_url);
5239 FILL_DRIVER_STRING(mem_ctx,
5240 driver->hardware_id,
5242 FILL_DRIVER_STRING(mem_ctx,
5246 FILL_DRIVER_STRING(mem_ctx,
5247 driver->print_processor,
5248 r->print_processor);
5249 FILL_DRIVER_STRING(mem_ctx,
5250 driver->vendor_setup,
5253 result = string_array_from_driver_info(mem_ctx,
5254 driver->color_profiles,
5257 if (!W_ERROR_IS_OK(result)) {
5261 FILL_DRIVER_STRING(mem_ctx,
5265 r->printer_driver_attributes = driver->printer_driver_attributes;
5267 result = string_array_from_driver_info(mem_ctx,
5268 driver->core_driver_dependencies,
5269 &r->core_driver_dependencies,
5271 if (!W_ERROR_IS_OK(result)) {
5275 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5276 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5281 #if 0 /* disabled until marshalling issues are resolved - gd */
5282 /********************************************************************
5283 ********************************************************************/
5285 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5286 struct spoolss_DriverFileInfo *r,
5287 const char *cservername,
5288 const char *file_name,
5289 enum spoolss_DriverFileType file_type,
5290 uint32_t file_version)
5292 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5293 cservername, file_name);
5294 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5295 r->file_type = file_type;
5296 r->file_version = file_version;
5301 /********************************************************************
5302 ********************************************************************/
5304 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5305 const struct spoolss_DriverInfo8 *driver,
5306 const char *cservername,
5307 struct spoolss_DriverFileInfo **info_p,
5310 struct spoolss_DriverFileInfo *info = NULL;
5318 if (strlen(driver->driver_path)) {
5319 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5320 struct spoolss_DriverFileInfo,
5322 W_ERROR_HAVE_NO_MEMORY(info);
5323 result = fill_spoolss_DriverFileInfo(info,
5326 driver->driver_path,
5327 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5329 W_ERROR_NOT_OK_RETURN(result);
5333 if (strlen(driver->config_file)) {
5334 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5335 struct spoolss_DriverFileInfo,
5337 W_ERROR_HAVE_NO_MEMORY(info);
5338 result = fill_spoolss_DriverFileInfo(info,
5341 driver->config_file,
5342 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5344 W_ERROR_NOT_OK_RETURN(result);
5348 if (strlen(driver->data_file)) {
5349 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5350 struct spoolss_DriverFileInfo,
5352 W_ERROR_HAVE_NO_MEMORY(info);
5353 result = fill_spoolss_DriverFileInfo(info,
5357 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5359 W_ERROR_NOT_OK_RETURN(result);
5363 if (strlen(driver->help_file)) {
5364 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5365 struct spoolss_DriverFileInfo,
5367 W_ERROR_HAVE_NO_MEMORY(info);
5368 result = fill_spoolss_DriverFileInfo(info,
5372 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5374 W_ERROR_NOT_OK_RETURN(result);
5378 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5379 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5380 struct spoolss_DriverFileInfo,
5382 W_ERROR_HAVE_NO_MEMORY(info);
5383 result = fill_spoolss_DriverFileInfo(info,
5386 driver->dependent_files[i],
5387 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5389 W_ERROR_NOT_OK_RETURN(result);
5399 /********************************************************************
5400 * fill a spoolss_DriverInfo101 struct
5401 ********************************************************************/
5403 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5404 struct spoolss_DriverInfo101 *r,
5405 const struct spoolss_DriverInfo8 *driver,
5406 const char *servername)
5408 const char *cservername = canon_servername(servername);
5411 r->version = driver->version;
5413 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5414 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5415 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5416 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5418 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5422 if (!W_ERROR_IS_OK(result)) {
5426 FILL_DRIVER_STRING(mem_ctx,
5427 driver->monitor_name,
5430 FILL_DRIVER_STRING(mem_ctx,
5431 driver->default_datatype,
5432 r->default_datatype);
5434 result = string_array_from_driver_info(mem_ctx,
5435 driver->previous_names,
5438 if (!W_ERROR_IS_OK(result)) {
5442 r->driver_date = driver->driver_date;
5443 r->driver_version = driver->driver_version;
5445 FILL_DRIVER_STRING(mem_ctx,
5446 driver->manufacturer_name,
5447 r->manufacturer_name);
5448 FILL_DRIVER_STRING(mem_ctx,
5449 driver->manufacturer_url,
5450 r->manufacturer_url);
5451 FILL_DRIVER_STRING(mem_ctx,
5452 driver->hardware_id,
5454 FILL_DRIVER_STRING(mem_ctx,
5461 /********************************************************************
5462 ********************************************************************/
5464 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5465 const struct auth_serversupplied_info *session_info,
5466 struct messaging_context *msg_ctx,
5468 union spoolss_DriverInfo *r,
5470 const char *servername,
5471 const char *architecture,
5474 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5475 struct spoolss_DriverInfo8 *driver;
5479 return WERR_UNKNOWN_LEVEL;
5482 result = winreg_get_printer(mem_ctx,
5485 lp_const_servicename(snum),
5488 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5489 win_errstr(result)));
5491 if (!W_ERROR_IS_OK(result)) {
5492 return WERR_INVALID_PRINTER_NAME;
5495 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5497 pinfo2->drivername, version, &driver);
5499 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5500 win_errstr(result)));
5502 if (!W_ERROR_IS_OK(result)) {
5504 * Is this a W2k client ?
5508 talloc_free(pinfo2);
5509 return WERR_UNKNOWN_PRINTER_DRIVER;
5512 /* Yes - try again with a WinNT driver. */
5514 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5518 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5519 win_errstr(result)));
5520 if (!W_ERROR_IS_OK(result)) {
5521 talloc_free(pinfo2);
5522 return WERR_UNKNOWN_PRINTER_DRIVER;
5528 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5531 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5534 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5537 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5540 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5543 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5546 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5548 #if 0 /* disabled until marshalling issues are resolved - gd */
5550 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5554 result = WERR_UNKNOWN_LEVEL;
5558 talloc_free(pinfo2);
5559 talloc_free(driver);
5564 /****************************************************************
5565 _spoolss_GetPrinterDriver2
5566 ****************************************************************/
5568 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5569 struct spoolss_GetPrinterDriver2 *r)
5571 struct printer_handle *printer;
5576 /* that's an [in out] buffer */
5578 if (!r->in.buffer && (r->in.offered != 0)) {
5579 return WERR_INVALID_PARAM;
5582 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5584 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5585 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5586 return WERR_INVALID_PRINTER_NAME;
5590 *r->out.server_major_version = 0;
5591 *r->out.server_minor_version = 0;
5593 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5597 result = construct_printer_driver_info_level(p->mem_ctx,
5598 get_session_info_system(),
5600 r->in.level, r->out.info,
5601 snum, printer->servername,
5603 r->in.client_major_version);
5604 if (!W_ERROR_IS_OK(result)) {
5605 TALLOC_FREE(r->out.info);
5609 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5610 r->out.info, r->in.level);
5611 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5613 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5617 /****************************************************************
5618 _spoolss_StartPagePrinter
5619 ****************************************************************/
5621 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5622 struct spoolss_StartPagePrinter *r)
5624 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5627 DEBUG(3,("_spoolss_StartPagePrinter: "
5628 "Error in startpageprinter printer handle\n"));
5632 Printer->page_started = true;
5636 /****************************************************************
5637 _spoolss_EndPagePrinter
5638 ****************************************************************/
5640 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5641 struct spoolss_EndPagePrinter *r)
5645 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5648 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5649 OUR_HANDLE(r->in.handle)));
5653 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5656 Printer->page_started = false;
5657 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5662 /****************************************************************
5663 _spoolss_StartDocPrinter
5664 ****************************************************************/
5666 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5667 struct spoolss_StartDocPrinter *r)
5669 struct spoolss_DocumentInfo1 *info_1;
5671 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5675 DEBUG(2,("_spoolss_StartDocPrinter: "
5676 "Invalid handle (%s:%u:%u)\n",
5677 OUR_HANDLE(r->in.handle)));
5681 if (Printer->jobid) {
5682 DEBUG(2, ("_spoolss_StartDocPrinter: "
5683 "StartDocPrinter called twice! "
5684 "(existing jobid = %d)\n", Printer->jobid));
5685 return WERR_INVALID_HANDLE;
5688 if (r->in.level != 1) {
5689 return WERR_UNKNOWN_LEVEL;
5692 info_1 = r->in.info.info1;
5695 * a nice thing with NT is it doesn't listen to what you tell it.
5696 * when asked to send _only_ RAW datas, it tries to send datas
5699 * So I add checks like in NT Server ...
5702 if (info_1->datatype) {
5703 if (strcmp(info_1->datatype, "RAW") != 0) {
5705 return WERR_INVALID_DATATYPE;
5709 /* get the share number of the printer */
5710 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5714 werr = print_job_start(p->session_info,
5718 info_1->document_name,
5719 info_1->output_file,
5723 /* An error occured in print_job_start() so return an appropriate
5726 if (!W_ERROR_IS_OK(werr)) {
5730 Printer->document_started = true;
5731 *r->out.job_id = Printer->jobid;
5736 /****************************************************************
5737 _spoolss_EndDocPrinter
5738 ****************************************************************/
5740 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5741 struct spoolss_EndDocPrinter *r)
5743 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5748 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5749 OUR_HANDLE(r->in.handle)));
5753 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5757 Printer->document_started = false;
5758 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5759 if (!NT_STATUS_IS_OK(status)) {
5760 DEBUG(2, ("_spoolss_EndDocPrinter: "
5761 "print_job_end failed [%s]\n",
5762 nt_errstr(status)));
5766 return ntstatus_to_werror(status);
5769 /****************************************************************
5770 _spoolss_WritePrinter
5771 ****************************************************************/
5773 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5774 struct spoolss_WritePrinter *r)
5776 ssize_t buffer_written;
5778 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5781 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5782 OUR_HANDLE(r->in.handle)));
5783 *r->out.num_written = r->in._data_size;
5787 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5790 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5791 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5792 snum, Printer->jobid,
5793 (const char *)r->in.data.data,
5794 (size_t)r->in._data_size);
5795 if (buffer_written == (ssize_t)-1) {
5796 *r->out.num_written = 0;
5797 if (errno == ENOSPC)
5798 return WERR_NO_SPOOL_SPACE;
5800 return WERR_ACCESS_DENIED;
5803 *r->out.num_written = r->in._data_size;
5808 /********************************************************************
5809 * api_spoolss_getprinter
5810 * called from the spoolss dispatcher
5812 ********************************************************************/
5814 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5815 struct pipes_struct *p)
5817 const struct auth_serversupplied_info *session_info = p->session_info;
5819 WERROR errcode = WERR_BADFUNC;
5820 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5823 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5824 OUR_HANDLE(handle)));
5828 if (!get_printer_snum(p, handle, &snum, NULL))
5832 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5833 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5835 case SPOOLSS_PRINTER_CONTROL_RESUME:
5836 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5837 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5839 case SPOOLSS_PRINTER_CONTROL_PURGE:
5840 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5843 return WERR_UNKNOWN_LEVEL;
5850 /****************************************************************
5851 _spoolss_AbortPrinter
5852 * From MSDN: "Deletes printer's spool file if printer is configured
5854 ****************************************************************/
5856 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5857 struct spoolss_AbortPrinter *r)
5859 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5861 WERROR errcode = WERR_OK;
5864 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5865 OUR_HANDLE(r->in.handle)));
5869 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5872 if (!Printer->document_started) {
5873 return WERR_SPL_NO_STARTDOC;
5876 errcode = print_job_delete(p->session_info,
5884 /********************************************************************
5885 * called by spoolss_api_setprinter
5886 * when updating a printer description
5887 ********************************************************************/
5889 static WERROR update_printer_sec(struct policy_handle *handle,
5890 struct pipes_struct *p,
5891 struct sec_desc_buf *secdesc_ctr)
5893 struct spoolss_security_descriptor *new_secdesc = NULL;
5894 struct spoolss_security_descriptor *old_secdesc = NULL;
5895 const char *printer;
5899 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5901 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5902 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5903 OUR_HANDLE(handle)));
5905 result = WERR_BADFID;
5909 if (secdesc_ctr == NULL) {
5910 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5911 result = WERR_INVALID_PARAM;
5914 printer = lp_const_servicename(snum);
5916 /* Check the user has permissions to change the security
5917 descriptor. By experimentation with two NT machines, the user
5918 requires Full Access to the printer to change security
5921 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5922 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5923 result = WERR_ACCESS_DENIED;
5927 /* NT seems to like setting the security descriptor even though
5928 nothing may have actually changed. */
5929 result = winreg_get_printer_secdesc(p->mem_ctx,
5930 get_session_info_system(),
5934 if (!W_ERROR_IS_OK(result)) {
5935 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5936 result = WERR_BADFID;
5940 if (DEBUGLEVEL >= 10) {
5941 struct security_acl *the_acl;
5944 the_acl = old_secdesc->dacl;
5945 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5946 printer, the_acl->num_aces));
5948 for (i = 0; i < the_acl->num_aces; i++) {
5949 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5950 &the_acl->aces[i].trustee),
5951 the_acl->aces[i].access_mask));
5954 the_acl = secdesc_ctr->sd->dacl;
5957 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5958 printer, the_acl->num_aces));
5960 for (i = 0; i < the_acl->num_aces; i++) {
5961 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5962 &the_acl->aces[i].trustee),
5963 the_acl->aces[i].access_mask));
5966 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5970 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5971 if (new_secdesc == NULL) {
5972 result = WERR_NOMEM;
5976 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5981 result = winreg_set_printer_secdesc(p->mem_ctx,
5982 get_session_info_system(),
5991 /********************************************************************
5992 Canonicalize printer info from a client
5993 ********************************************************************/
5995 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5996 struct spoolss_SetPrinterInfo2 *info2,
5999 fstring printername;
6002 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6003 "portname=%s drivername=%s comment=%s location=%s\n",
6004 info2->servername, info2->printername, info2->sharename,
6005 info2->portname, info2->drivername, info2->comment,
6008 /* we force some elements to "correct" values */
6009 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6010 if (info2->servername == NULL) {
6013 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6014 if (info2->sharename == NULL) {
6018 /* check to see if we allow printername != sharename */
6019 if (lp_force_printername(snum)) {
6020 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6021 global_myname(), info2->sharename);
6023 /* make sure printername is in \\server\printername format */
6024 fstrcpy(printername, info2->printername);
6026 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6027 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6031 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6032 global_myname(), p);
6034 if (info2->printername == NULL) {
6038 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6039 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6044 /****************************************************************************
6045 ****************************************************************************/
6047 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6049 char *cmd = lp_addport_cmd();
6050 char *command = NULL;
6052 bool is_print_op = false;
6055 return WERR_ACCESS_DENIED;
6058 command = talloc_asprintf(ctx,
6059 "%s \"%s\" \"%s\"", cmd, portname, uri );
6065 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6067 DEBUG(10,("Running [%s]\n", command));
6069 /********* BEGIN SePrintOperatorPrivilege **********/
6074 ret = smbrun(command, NULL);
6079 /********* END SePrintOperatorPrivilege **********/
6081 DEBUGADD(10,("returned [%d]\n", ret));
6083 TALLOC_FREE(command);
6086 return WERR_ACCESS_DENIED;
6092 /****************************************************************************
6093 ****************************************************************************/
6095 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6096 struct spoolss_SetPrinterInfo2 *info2,
6097 const char *remote_machine,
6098 struct messaging_context *msg_ctx)
6100 char *cmd = lp_addprinter_cmd();
6102 char *command = NULL;
6106 bool is_print_op = false;
6108 if (!remote_machine) {
6112 command = talloc_asprintf(ctx,
6113 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6114 cmd, info2->printername, info2->sharename,
6115 info2->portname, info2->drivername,
6116 info2->location, info2->comment, remote_machine);
6122 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6124 DEBUG(10,("Running [%s]\n", command));
6126 /********* BEGIN SePrintOperatorPrivilege **********/
6131 if ( (ret = smbrun(command, &fd)) == 0 ) {
6132 /* Tell everyone we updated smb.conf. */
6133 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6139 /********* END SePrintOperatorPrivilege **********/
6141 DEBUGADD(10,("returned [%d]\n", ret));
6143 TALLOC_FREE(command);
6151 /* reload our services immediately */
6153 reload_services(msg_ctx, -1, false);
6157 /* Get lines and convert them back to dos-codepage */
6158 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6159 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6162 /* Set the portname to what the script says the portname should be. */
6163 /* but don't require anything to be return from the script exit a good error code */
6166 /* Set the portname to what the script says the portname should be. */
6167 info2->portname = talloc_strdup(ctx, qlines[0]);
6168 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6171 TALLOC_FREE(qlines);
6175 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6176 const struct auth_serversupplied_info *session_info,
6177 struct messaging_context *msg_ctx,
6179 struct spoolss_SetPrinterInfo2 *printer,
6180 struct spoolss_PrinterInfo2 *old_printer)
6182 bool force_update = (old_printer == NULL);
6183 const char *dnsdomname;
6184 const char *longname;
6185 const char *uncname;
6186 const char *spooling;
6188 WERROR result = WERR_OK;
6190 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6191 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6192 winreg_set_printer_dataex(mem_ctx,
6196 SPOOL_DSSPOOLER_KEY,
6197 SPOOL_REG_DRIVERNAME,
6202 if (!force_update) {
6203 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6204 printer->drivername));
6206 notify_printer_driver(server_event_context(), msg_ctx,
6207 snum, printer->drivername ?
6208 printer->drivername : "");
6212 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6213 push_reg_sz(mem_ctx, &buffer, printer->comment);
6214 winreg_set_printer_dataex(mem_ctx,
6218 SPOOL_DSSPOOLER_KEY,
6219 SPOOL_REG_DESCRIPTION,
6224 if (!force_update) {
6225 notify_printer_comment(server_event_context(), msg_ctx,
6226 snum, printer->comment ?
6227 printer->comment : "");
6231 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6232 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6233 winreg_set_printer_dataex(mem_ctx,
6237 SPOOL_DSSPOOLER_KEY,
6238 SPOOL_REG_PRINTSHARENAME,
6243 if (!force_update) {
6244 notify_printer_sharename(server_event_context(),
6246 snum, printer->sharename ?
6247 printer->sharename : "");
6251 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6254 p = strrchr(printer->printername, '\\' );
6258 p = printer->printername;
6261 push_reg_sz(mem_ctx, &buffer, p);
6262 winreg_set_printer_dataex(mem_ctx,
6266 SPOOL_DSSPOOLER_KEY,
6267 SPOOL_REG_PRINTERNAME,
6272 if (!force_update) {
6273 notify_printer_printername(server_event_context(),
6274 msg_ctx, snum, p ? p : "");
6278 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6279 push_reg_sz(mem_ctx, &buffer, printer->portname);
6280 winreg_set_printer_dataex(mem_ctx,
6284 SPOOL_DSSPOOLER_KEY,
6290 if (!force_update) {
6291 notify_printer_port(server_event_context(),
6292 msg_ctx, snum, printer->portname ?
6293 printer->portname : "");
6297 if (force_update || !strequal(printer->location, old_printer->location)) {
6298 push_reg_sz(mem_ctx, &buffer, printer->location);
6299 winreg_set_printer_dataex(mem_ctx,
6303 SPOOL_DSSPOOLER_KEY,
6309 if (!force_update) {
6310 notify_printer_location(server_event_context(),
6313 printer->location : "");
6317 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6318 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6319 winreg_set_printer_dataex(mem_ctx,
6323 SPOOL_DSSPOOLER_KEY,
6324 SPOOL_REG_PRINTSEPARATORFILE,
6329 if (!force_update) {
6330 notify_printer_sepfile(server_event_context(),
6333 printer->sepfile : "");
6337 if (force_update || printer->starttime != old_printer->starttime) {
6338 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6339 SIVAL(buffer.data, 0, printer->starttime);
6340 winreg_set_printer_dataex(mem_ctx,
6344 SPOOL_DSSPOOLER_KEY,
6345 SPOOL_REG_PRINTSTARTTIME,
6351 if (force_update || printer->untiltime != old_printer->untiltime) {
6352 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6353 SIVAL(buffer.data, 0, printer->untiltime);
6354 winreg_set_printer_dataex(mem_ctx,
6358 SPOOL_DSSPOOLER_KEY,
6359 SPOOL_REG_PRINTENDTIME,
6365 if (force_update || printer->priority != old_printer->priority) {
6366 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6367 SIVAL(buffer.data, 0, printer->priority);
6368 winreg_set_printer_dataex(mem_ctx,
6372 SPOOL_DSSPOOLER_KEY,
6379 if (force_update || printer->attributes != old_printer->attributes) {
6380 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6381 SIVAL(buffer.data, 0, (printer->attributes &
6382 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6383 winreg_set_printer_dataex(mem_ctx,
6387 SPOOL_DSSPOOLER_KEY,
6388 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6393 switch (printer->attributes & 0x3) {
6395 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6398 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6401 spooling = SPOOL_REGVAL_PRINTDIRECT;
6404 spooling = "unknown";
6406 push_reg_sz(mem_ctx, &buffer, spooling);
6407 winreg_set_printer_dataex(mem_ctx,
6411 SPOOL_DSSPOOLER_KEY,
6412 SPOOL_REG_PRINTSPOOLING,
6418 push_reg_sz(mem_ctx, &buffer, global_myname());
6419 winreg_set_printer_dataex(mem_ctx,
6423 SPOOL_DSSPOOLER_KEY,
6424 SPOOL_REG_SHORTSERVERNAME,
6429 dnsdomname = get_mydnsfullname();
6430 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6431 longname = talloc_strdup(mem_ctx, dnsdomname);
6433 longname = talloc_strdup(mem_ctx, global_myname());
6435 if (longname == NULL) {
6436 result = WERR_NOMEM;
6440 push_reg_sz(mem_ctx, &buffer, longname);
6441 winreg_set_printer_dataex(mem_ctx,
6445 SPOOL_DSSPOOLER_KEY,
6446 SPOOL_REG_SERVERNAME,
6451 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6452 global_myname(), printer->sharename);
6453 push_reg_sz(mem_ctx, &buffer, uncname);
6454 winreg_set_printer_dataex(mem_ctx,
6458 SPOOL_DSSPOOLER_KEY,
6468 /********************************************************************
6469 * Called by spoolss_api_setprinter
6470 * when updating a printer description.
6471 ********************************************************************/
6473 static WERROR update_printer(struct pipes_struct *p,
6474 struct policy_handle *handle,
6475 struct spoolss_SetPrinterInfoCtr *info_ctr,
6476 struct spoolss_DeviceMode *devmode)
6478 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6479 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6480 struct spoolss_PrinterInfo2 *old_printer;
6481 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6483 WERROR result = WERR_OK;
6484 TALLOC_CTX *tmp_ctx;
6486 DEBUG(8,("update_printer\n"));
6488 tmp_ctx = talloc_new(p->mem_ctx);
6489 if (tmp_ctx == NULL) {
6494 result = WERR_BADFID;
6498 if (!get_printer_snum(p, handle, &snum, NULL)) {
6499 result = WERR_BADFID;
6503 result = winreg_get_printer(tmp_ctx,
6504 get_session_info_system(),
6506 lp_const_servicename(snum),
6508 if (!W_ERROR_IS_OK(result)) {
6509 result = WERR_BADFID;
6513 /* Do sanity check on the requested changes for Samba */
6514 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6515 result = WERR_INVALID_PARAM;
6519 /* FIXME!!! If the driver has changed we really should verify that
6520 it is installed before doing much else --jerry */
6522 /* Check calling user has permission to update printer description */
6523 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6524 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6525 result = WERR_ACCESS_DENIED;
6529 /* Call addprinter hook */
6530 /* Check changes to see if this is really needed */
6532 if (*lp_addprinter_cmd() &&
6533 (!strequal(printer->drivername, old_printer->drivername) ||
6534 !strequal(printer->comment, old_printer->comment) ||
6535 !strequal(printer->portname, old_printer->portname) ||
6536 !strequal(printer->location, old_printer->location)) )
6538 /* add_printer_hook() will call reload_services() */
6539 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6540 printer, p->client_id->addr,
6542 result = WERR_ACCESS_DENIED;
6547 update_dsspooler(tmp_ctx,
6548 get_session_info_system(),
6554 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6556 if (devmode == NULL) {
6557 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6559 result = winreg_update_printer(tmp_ctx,
6560 get_session_info_system(),
6569 talloc_free(tmp_ctx);
6574 /****************************************************************************
6575 ****************************************************************************/
6576 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6577 struct policy_handle *handle,
6578 struct spoolss_SetPrinterInfo7 *info7)
6581 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6584 struct printer_handle *Printer;
6586 if ( lp_security() != SEC_ADS ) {
6587 return WERR_UNKNOWN_LEVEL;
6590 Printer = find_printer_index_by_hnd(p, handle);
6592 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6597 if (!get_printer_snum(p, handle, &snum, NULL))
6600 result = winreg_get_printer(p->mem_ctx,
6601 get_session_info_system(),
6603 lp_servicename(snum),
6605 if (!W_ERROR_IS_OK(result)) {
6609 nt_printer_publish(pinfo2,
6610 get_session_info_system(),
6615 TALLOC_FREE(pinfo2);
6618 return WERR_UNKNOWN_LEVEL;
6622 /********************************************************************
6623 ********************************************************************/
6625 static WERROR update_printer_devmode(struct pipes_struct *p,
6626 struct policy_handle *handle,
6627 struct spoolss_DeviceMode *devmode)
6630 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6631 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6633 DEBUG(8,("update_printer_devmode\n"));
6639 if (!get_printer_snum(p, handle, &snum, NULL)) {
6643 /* Check calling user has permission to update printer description */
6644 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6645 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6646 return WERR_ACCESS_DENIED;
6649 return winreg_update_printer(p->mem_ctx,
6650 get_session_info_system(),
6652 lp_const_servicename(snum),
6660 /****************************************************************
6662 ****************************************************************/
6664 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6665 struct spoolss_SetPrinter *r)
6669 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6672 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6673 OUR_HANDLE(r->in.handle)));
6677 /* check the level */
6678 switch (r->in.info_ctr->level) {
6680 return control_printer(r->in.handle, r->in.command, p);
6682 result = update_printer(p, r->in.handle,
6684 r->in.devmode_ctr->devmode);
6685 if (!W_ERROR_IS_OK(result))
6687 if (r->in.secdesc_ctr->sd)
6688 result = update_printer_sec(r->in.handle, p,
6692 return update_printer_sec(r->in.handle, p,
6695 return publish_or_unpublish_printer(p, r->in.handle,
6696 r->in.info_ctr->info.info7);
6698 return update_printer_devmode(p, r->in.handle,
6699 r->in.devmode_ctr->devmode);
6701 return WERR_UNKNOWN_LEVEL;
6705 /****************************************************************
6706 _spoolss_FindClosePrinterNotify
6707 ****************************************************************/
6709 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6710 struct spoolss_FindClosePrinterNotify *r)
6712 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6715 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6716 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6720 if (Printer->notify.cli_chan != NULL &&
6721 Printer->notify.cli_chan->active_connections > 0) {
6724 if (Printer->printer_type == SPLHND_PRINTER) {
6725 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6730 srv_spoolss_replycloseprinter(snum, Printer);
6733 Printer->notify.flags=0;
6734 Printer->notify.options=0;
6735 Printer->notify.localmachine[0]='\0';
6736 Printer->notify.printerlocal=0;
6737 TALLOC_FREE(Printer->notify.option);
6742 /****************************************************************
6744 ****************************************************************/
6746 WERROR _spoolss_AddJob(struct pipes_struct *p,
6747 struct spoolss_AddJob *r)
6749 if (!r->in.buffer && (r->in.offered != 0)) {
6750 return WERR_INVALID_PARAM;
6753 /* this is what a NT server returns for AddJob. AddJob must fail on
6754 * non-local printers */
6756 if (r->in.level != 1) {
6757 return WERR_UNKNOWN_LEVEL;
6760 return WERR_INVALID_PARAM;
6763 /****************************************************************************
6765 ****************************************************************************/
6767 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6768 struct spoolss_JobInfo1 *r,
6769 const print_queue_struct *queue,
6770 int position, int snum,
6771 struct spoolss_PrinterInfo2 *pinfo2)
6775 t = gmtime(&queue->time);
6777 r->job_id = queue->job;
6779 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6780 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6781 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6782 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6783 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6784 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6785 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6786 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6787 r->data_type = talloc_strdup(mem_ctx, "RAW");
6788 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6789 r->text_status = talloc_strdup(mem_ctx, "");
6790 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6792 r->status = nt_printj_status(queue->status);
6793 r->priority = queue->priority;
6794 r->position = position;
6795 r->total_pages = queue->page_count;
6796 r->pages_printed = 0; /* ??? */
6798 init_systemtime(&r->submitted, t);
6803 /****************************************************************************
6805 ****************************************************************************/
6807 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6808 struct spoolss_JobInfo2 *r,
6809 const print_queue_struct *queue,
6810 int position, int snum,
6811 struct spoolss_PrinterInfo2 *pinfo2,
6812 struct spoolss_DeviceMode *devmode)
6816 t = gmtime(&queue->time);
6818 r->job_id = queue->job;
6820 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6821 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6822 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6823 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6824 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6825 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6826 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6827 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6828 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6829 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6830 r->data_type = talloc_strdup(mem_ctx, "RAW");
6831 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6832 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6833 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6834 r->parameters = talloc_strdup(mem_ctx, "");
6835 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6836 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6837 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6839 r->devmode = devmode;
6841 r->text_status = talloc_strdup(mem_ctx, "");
6842 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6846 r->status = nt_printj_status(queue->status);
6847 r->priority = queue->priority;
6848 r->position = position;
6851 r->total_pages = queue->page_count;
6852 r->size = queue->size;
6853 init_systemtime(&r->submitted, t);
6855 r->pages_printed = 0; /* ??? */
6860 /****************************************************************************
6862 ****************************************************************************/
6864 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6865 struct spoolss_JobInfo3 *r,
6866 const print_queue_struct *queue,
6867 const print_queue_struct *next_queue,
6868 int position, int snum,
6869 struct spoolss_PrinterInfo2 *pinfo2)
6871 r->job_id = queue->job;
6874 r->next_job_id = next_queue->job;
6881 /****************************************************************************
6882 Enumjobs at level 1.
6883 ****************************************************************************/
6885 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6886 const print_queue_struct *queue,
6887 uint32_t num_queues, int snum,
6888 struct spoolss_PrinterInfo2 *pinfo2,
6889 union spoolss_JobInfo **info_p,
6892 union spoolss_JobInfo *info;
6894 WERROR result = WERR_OK;
6896 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6897 W_ERROR_HAVE_NO_MEMORY(info);
6899 *count = num_queues;
6901 for (i=0; i<*count; i++) {
6902 result = fill_job_info1(info,
6908 if (!W_ERROR_IS_OK(result)) {
6914 if (!W_ERROR_IS_OK(result)) {
6925 /****************************************************************************
6926 Enumjobs at level 2.
6927 ****************************************************************************/
6929 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6930 const print_queue_struct *queue,
6931 uint32_t num_queues, int snum,
6932 struct spoolss_PrinterInfo2 *pinfo2,
6933 union spoolss_JobInfo **info_p,
6936 union spoolss_JobInfo *info;
6938 WERROR result = WERR_OK;
6940 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6941 W_ERROR_HAVE_NO_MEMORY(info);
6943 *count = num_queues;
6945 for (i=0; i<*count; i++) {
6946 struct spoolss_DeviceMode *devmode;
6948 result = spoolss_create_default_devmode(info,
6949 pinfo2->printername,
6951 if (!W_ERROR_IS_OK(result)) {
6952 DEBUG(3, ("Can't proceed w/o a devmode!"));
6956 result = fill_job_info2(info,
6963 if (!W_ERROR_IS_OK(result)) {
6969 if (!W_ERROR_IS_OK(result)) {
6980 /****************************************************************************
6981 Enumjobs at level 3.
6982 ****************************************************************************/
6984 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6985 const print_queue_struct *queue,
6986 uint32_t num_queues, int snum,
6987 struct spoolss_PrinterInfo2 *pinfo2,
6988 union spoolss_JobInfo **info_p,
6991 union spoolss_JobInfo *info;
6993 WERROR result = WERR_OK;
6995 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6996 W_ERROR_HAVE_NO_MEMORY(info);
6998 *count = num_queues;
7000 for (i=0; i<*count; i++) {
7001 const print_queue_struct *next_queue = NULL;
7004 next_queue = &queue[i+1];
7007 result = fill_job_info3(info,
7014 if (!W_ERROR_IS_OK(result)) {
7020 if (!W_ERROR_IS_OK(result)) {
7031 /****************************************************************
7033 ****************************************************************/
7035 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7036 struct spoolss_EnumJobs *r)
7039 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7041 print_status_struct prt_status;
7042 print_queue_struct *queue = NULL;
7045 /* that's an [in out] buffer */
7047 if (!r->in.buffer && (r->in.offered != 0)) {
7048 return WERR_INVALID_PARAM;
7051 DEBUG(4,("_spoolss_EnumJobs\n"));
7055 *r->out.info = NULL;
7057 /* lookup the printer snum and tdb entry */
7059 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7063 result = winreg_get_printer(p->mem_ctx,
7064 get_session_info_system(),
7066 lp_const_servicename(snum),
7068 if (!W_ERROR_IS_OK(result)) {
7072 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7073 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7074 count, prt_status.status, prt_status.message));
7078 TALLOC_FREE(pinfo2);
7082 switch (r->in.level) {
7084 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7085 pinfo2, r->out.info, r->out.count);
7088 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7089 pinfo2, r->out.info, r->out.count);
7092 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7093 pinfo2, r->out.info, r->out.count);
7096 result = WERR_UNKNOWN_LEVEL;
7101 TALLOC_FREE(pinfo2);
7103 if (!W_ERROR_IS_OK(result)) {
7107 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7109 *r->out.info, r->in.level,
7111 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7112 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7114 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7117 /****************************************************************
7118 _spoolss_ScheduleJob
7119 ****************************************************************/
7121 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7122 struct spoolss_ScheduleJob *r)
7127 /****************************************************************
7128 ****************************************************************/
7130 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7131 struct messaging_context *msg_ctx,
7132 const char *printer_name,
7134 struct spoolss_SetJobInfo1 *r)
7138 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7142 if (strequal(old_doc_name, r->document_name)) {
7146 if (!print_job_set_name(server_event_context(), msg_ctx,
7147 printer_name, job_id, r->document_name)) {
7154 /****************************************************************
7156 ****************************************************************/
7158 WERROR _spoolss_SetJob(struct pipes_struct *p,
7159 struct spoolss_SetJob *r)
7161 const struct auth_serversupplied_info *session_info = p->session_info;
7163 WERROR errcode = WERR_BADFUNC;
7165 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7169 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7170 return WERR_INVALID_PRINTER_NAME;
7173 switch (r->in.command) {
7174 case SPOOLSS_JOB_CONTROL_CANCEL:
7175 case SPOOLSS_JOB_CONTROL_DELETE:
7176 errcode = print_job_delete(session_info, p->msg_ctx,
7177 snum, r->in.job_id);
7178 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7182 case SPOOLSS_JOB_CONTROL_PAUSE:
7183 if (print_job_pause(session_info, p->msg_ctx,
7184 snum, r->in.job_id, &errcode)) {
7188 case SPOOLSS_JOB_CONTROL_RESTART:
7189 case SPOOLSS_JOB_CONTROL_RESUME:
7190 if (print_job_resume(session_info, p->msg_ctx,
7191 snum, r->in.job_id, &errcode)) {
7199 return WERR_UNKNOWN_LEVEL;
7202 if (!W_ERROR_IS_OK(errcode)) {
7206 if (r->in.ctr == NULL) {
7210 switch (r->in.ctr->level) {
7212 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7213 lp_const_servicename(snum),
7215 r->in.ctr->info.info1);
7221 return WERR_UNKNOWN_LEVEL;
7227 /****************************************************************************
7228 Enumerates all printer drivers by level and architecture.
7229 ****************************************************************************/
7231 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7232 const struct auth_serversupplied_info *session_info,
7233 struct messaging_context *msg_ctx,
7234 const char *servername,
7235 const char *architecture,
7237 union spoolss_DriverInfo **info_p,
7242 struct spoolss_DriverInfo8 *driver;
7243 union spoolss_DriverInfo *info = NULL;
7245 WERROR result = WERR_OK;
7246 uint32_t num_drivers;
7247 const char **drivers;
7252 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7253 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7254 architecture, version,
7255 &num_drivers, &drivers);
7256 if (!W_ERROR_IS_OK(result)) {
7259 DEBUG(4, ("we have:[%d] drivers in environment"
7260 " [%s] and version [%d]\n",
7261 num_drivers, architecture, version));
7263 if (num_drivers != 0) {
7264 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7265 union spoolss_DriverInfo,
7266 count + num_drivers);
7268 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7269 "failed to enlarge driver info buffer!\n"));
7270 result = WERR_NOMEM;
7275 for (i = 0; i < num_drivers; i++) {
7276 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7278 result = winreg_get_driver(mem_ctx, session_info,
7280 architecture, drivers[i],
7282 if (!W_ERROR_IS_OK(result)) {
7288 result = fill_printer_driver_info1(info, &info[count+i].info1,
7289 driver, servername);
7292 result = fill_printer_driver_info2(info, &info[count+i].info2,
7293 driver, servername);
7296 result = fill_printer_driver_info3(info, &info[count+i].info3,
7297 driver, servername);
7300 result = fill_printer_driver_info4(info, &info[count+i].info4,
7301 driver, servername);
7304 result = fill_printer_driver_info5(info, &info[count+i].info5,
7305 driver, servername);
7308 result = fill_printer_driver_info6(info, &info[count+i].info6,
7309 driver, servername);
7312 result = fill_printer_driver_info8(info, &info[count+i].info8,
7313 driver, servername);
7316 result = WERR_UNKNOWN_LEVEL;
7320 TALLOC_FREE(driver);
7322 if (!W_ERROR_IS_OK(result)) {
7327 count += num_drivers;
7328 TALLOC_FREE(drivers);
7332 TALLOC_FREE(drivers);
7334 if (!W_ERROR_IS_OK(result)) {
7345 /****************************************************************************
7346 Enumerates all printer drivers by level.
7347 ****************************************************************************/
7349 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7350 const struct auth_serversupplied_info *session_info,
7351 struct messaging_context *msg_ctx,
7352 const char *servername,
7353 const char *architecture,
7355 union spoolss_DriverInfo **info_p,
7359 WERROR result = WERR_OK;
7361 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7363 for (a=0; archi_table[a].long_archi != NULL; a++) {
7365 union spoolss_DriverInfo *info = NULL;
7368 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7372 archi_table[a].long_archi,
7376 if (!W_ERROR_IS_OK(result)) {
7380 for (i=0; i < count; i++) {
7381 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7382 info[i], info_p, count_p);
7389 return enumprinterdrivers_level_by_architecture(mem_ctx,
7399 /****************************************************************
7400 _spoolss_EnumPrinterDrivers
7401 ****************************************************************/
7403 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7404 struct spoolss_EnumPrinterDrivers *r)
7406 const char *cservername;
7409 /* that's an [in out] buffer */
7411 if (!r->in.buffer && (r->in.offered != 0)) {
7412 return WERR_INVALID_PARAM;
7415 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7419 *r->out.info = NULL;
7421 cservername = canon_servername(r->in.server);
7423 if (!is_myname_or_ipaddr(cservername)) {
7424 return WERR_UNKNOWN_PRINTER_DRIVER;
7427 result = enumprinterdrivers_level(p->mem_ctx,
7428 get_session_info_system(),
7435 if (!W_ERROR_IS_OK(result)) {
7439 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7440 spoolss_EnumPrinterDrivers,
7441 *r->out.info, r->in.level,
7443 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7444 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7446 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7449 /****************************************************************
7451 ****************************************************************/
7453 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7454 struct spoolss_EnumForms *r)
7460 *r->out.info = NULL;
7462 /* that's an [in out] buffer */
7464 if (!r->in.buffer && (r->in.offered != 0) ) {
7465 return WERR_INVALID_PARAM;
7468 DEBUG(4,("_spoolss_EnumForms\n"));
7469 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7470 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7472 switch (r->in.level) {
7474 result = winreg_printer_enumforms1(p->mem_ctx,
7475 get_session_info_system(),
7481 result = WERR_UNKNOWN_LEVEL;
7485 if (!W_ERROR_IS_OK(result)) {
7489 if (*r->out.count == 0) {
7490 return WERR_NO_MORE_ITEMS;
7493 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7495 *r->out.info, r->in.level,
7497 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7498 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7500 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7503 /****************************************************************
7505 ****************************************************************/
7507 WERROR _spoolss_GetForm(struct pipes_struct *p,
7508 struct spoolss_GetForm *r)
7512 /* that's an [in out] buffer */
7514 if (!r->in.buffer && (r->in.offered != 0)) {
7515 return WERR_INVALID_PARAM;
7518 DEBUG(4,("_spoolss_GetForm\n"));
7519 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7520 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7522 switch (r->in.level) {
7524 result = winreg_printer_getform1(p->mem_ctx,
7525 get_session_info_system(),
7528 &r->out.info->info1);
7531 result = WERR_UNKNOWN_LEVEL;
7535 if (!W_ERROR_IS_OK(result)) {
7536 TALLOC_FREE(r->out.info);
7540 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7541 r->out.info, r->in.level);
7542 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7544 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7547 /****************************************************************************
7548 ****************************************************************************/
7550 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7551 struct spoolss_PortInfo1 *r,
7554 r->port_name = talloc_strdup(mem_ctx, name);
7555 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7560 /****************************************************************************
7561 TODO: This probably needs distinguish between TCP/IP and Local ports
7563 ****************************************************************************/
7565 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7566 struct spoolss_PortInfo2 *r,
7569 r->port_name = talloc_strdup(mem_ctx, name);
7570 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7572 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7573 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7575 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7576 W_ERROR_HAVE_NO_MEMORY(r->description);
7578 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7585 /****************************************************************************
7586 wrapper around the enumer ports command
7587 ****************************************************************************/
7589 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7591 char *cmd = lp_enumports_cmd();
7592 char **qlines = NULL;
7593 char *command = NULL;
7601 /* if no hook then just fill in the default port */
7604 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7607 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7608 TALLOC_FREE(qlines);
7615 /* we have a valid enumport command */
7617 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7622 DEBUG(10,("Running [%s]\n", command));
7623 ret = smbrun(command, &fd);
7624 DEBUG(10,("Returned [%d]\n", ret));
7625 TALLOC_FREE(command);
7630 return WERR_ACCESS_DENIED;
7634 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7635 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7645 /****************************************************************************
7647 ****************************************************************************/
7649 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7650 union spoolss_PortInfo **info_p,
7653 union spoolss_PortInfo *info = NULL;
7655 WERROR result = WERR_OK;
7656 char **qlines = NULL;
7659 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7660 if (!W_ERROR_IS_OK(result)) {
7665 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7667 DEBUG(10,("Returning WERR_NOMEM\n"));
7668 result = WERR_NOMEM;
7672 for (i=0; i<numlines; i++) {
7673 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7674 result = fill_port_1(info, &info[i].info1, qlines[i]);
7675 if (!W_ERROR_IS_OK(result)) {
7680 TALLOC_FREE(qlines);
7683 if (!W_ERROR_IS_OK(result)) {
7685 TALLOC_FREE(qlines);
7697 /****************************************************************************
7699 ****************************************************************************/
7701 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7702 union spoolss_PortInfo **info_p,
7705 union spoolss_PortInfo *info = NULL;
7707 WERROR result = WERR_OK;
7708 char **qlines = NULL;
7711 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7712 if (!W_ERROR_IS_OK(result)) {
7717 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7719 DEBUG(10,("Returning WERR_NOMEM\n"));
7720 result = WERR_NOMEM;
7724 for (i=0; i<numlines; i++) {
7725 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7726 result = fill_port_2(info, &info[i].info2, qlines[i]);
7727 if (!W_ERROR_IS_OK(result)) {
7732 TALLOC_FREE(qlines);
7735 if (!W_ERROR_IS_OK(result)) {
7737 TALLOC_FREE(qlines);
7749 /****************************************************************
7751 ****************************************************************/
7753 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7754 struct spoolss_EnumPorts *r)
7758 /* that's an [in out] buffer */
7760 if (!r->in.buffer && (r->in.offered != 0)) {
7761 return WERR_INVALID_PARAM;
7764 DEBUG(4,("_spoolss_EnumPorts\n"));
7768 *r->out.info = NULL;
7770 switch (r->in.level) {
7772 result = enumports_level_1(p->mem_ctx, r->out.info,
7776 result = enumports_level_2(p->mem_ctx, r->out.info,
7780 return WERR_UNKNOWN_LEVEL;
7783 if (!W_ERROR_IS_OK(result)) {
7787 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7789 *r->out.info, r->in.level,
7791 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7792 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7794 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7797 /****************************************************************************
7798 ****************************************************************************/
7800 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7802 struct spoolss_SetPrinterInfoCtr *info_ctr,
7803 struct spoolss_DeviceMode *devmode,
7804 struct security_descriptor *secdesc,
7805 struct spoolss_UserLevelCtr *user_ctr,
7806 struct policy_handle *handle)
7808 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7809 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7811 WERROR err = WERR_OK;
7813 /* samba does not have a concept of local, non-shared printers yet, so
7814 * make sure we always setup sharename - gd */
7815 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7816 (info2->printername != NULL && info2->printername[0] != '\0')) {
7817 DEBUG(5, ("spoolss_addprinterex_level_2: "
7818 "no sharename has been set, setting printername %s as sharename\n",
7819 info2->printername));
7820 info2->sharename = info2->printername;
7823 /* check to see if the printer already exists */
7824 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7825 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7827 return WERR_PRINTER_ALREADY_EXISTS;
7830 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7831 if ((snum = print_queue_snum(info2->printername)) != -1) {
7832 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7833 info2->printername));
7834 return WERR_PRINTER_ALREADY_EXISTS;
7838 /* validate printer info struct */
7839 if (!info2->printername || strlen(info2->printername) == 0) {
7840 return WERR_INVALID_PRINTER_NAME;
7842 if (!info2->portname || strlen(info2->portname) == 0) {
7843 return WERR_UNKNOWN_PORT;
7845 if (!info2->drivername || strlen(info2->drivername) == 0) {
7846 return WERR_UNKNOWN_PRINTER_DRIVER;
7848 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7849 return WERR_UNKNOWN_PRINTPROCESSOR;
7852 /* FIXME!!! smbd should check to see if the driver is installed before
7853 trying to add a printer like this --jerry */
7855 if (*lp_addprinter_cmd() ) {
7856 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7857 info2, p->client_id->addr,
7859 return WERR_ACCESS_DENIED;
7862 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7863 "smb.conf parameter \"addprinter command\" is defined. This "
7864 "parameter must exist for this call to succeed\n",
7865 info2->sharename ));
7868 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7869 return WERR_ACCESS_DENIED;
7872 /* you must be a printer admin to add a new printer */
7873 if (!print_access_check(p->session_info,
7876 PRINTER_ACCESS_ADMINISTER)) {
7877 return WERR_ACCESS_DENIED;
7881 * Do sanity check on the requested changes for Samba.
7884 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7885 return WERR_INVALID_PARAM;
7888 if (devmode == NULL) {
7889 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7892 update_dsspooler(p->mem_ctx,
7893 get_session_info_system(),
7899 err = winreg_update_printer(p->mem_ctx,
7900 get_session_info_system(),
7907 if (!W_ERROR_IS_OK(err)) {
7911 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7912 if (!W_ERROR_IS_OK(err)) {
7913 /* Handle open failed - remove addition. */
7914 ZERO_STRUCTP(handle);
7921 /****************************************************************
7922 _spoolss_AddPrinterEx
7923 ****************************************************************/
7925 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7926 struct spoolss_AddPrinterEx *r)
7928 switch (r->in.info_ctr->level) {
7930 /* we don't handle yet */
7931 /* but I know what to do ... */
7932 return WERR_UNKNOWN_LEVEL;
7934 return spoolss_addprinterex_level_2(p, r->in.server,
7936 r->in.devmode_ctr->devmode,
7937 r->in.secdesc_ctr->sd,
7938 r->in.userlevel_ctr,
7941 return WERR_UNKNOWN_LEVEL;
7945 /****************************************************************
7947 ****************************************************************/
7949 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7950 struct spoolss_AddPrinter *r)
7952 struct spoolss_AddPrinterEx a;
7953 struct spoolss_UserLevelCtr userlevel_ctr;
7955 ZERO_STRUCT(userlevel_ctr);
7957 userlevel_ctr.level = 1;
7959 a.in.server = r->in.server;
7960 a.in.info_ctr = r->in.info_ctr;
7961 a.in.devmode_ctr = r->in.devmode_ctr;
7962 a.in.secdesc_ctr = r->in.secdesc_ctr;
7963 a.in.userlevel_ctr = &userlevel_ctr;
7964 a.out.handle = r->out.handle;
7966 return _spoolss_AddPrinterEx(p, &a);
7969 /****************************************************************
7970 _spoolss_AddPrinterDriverEx
7971 ****************************************************************/
7973 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7974 struct spoolss_AddPrinterDriverEx *r)
7976 WERROR err = WERR_OK;
7977 const char *driver_name = NULL;
7982 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7983 fn = "_spoolss_AddPrinterDriver";
7985 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7986 fn = "_spoolss_AddPrinterDriverEx";
7989 return WERR_INVALID_PARAM;
7993 * we only support the semantics of AddPrinterDriver()
7994 * i.e. only copy files that are newer than existing ones
7997 if (r->in.flags == 0) {
7998 return WERR_INVALID_PARAM;
8001 if (r->in.flags != APD_COPY_NEW_FILES) {
8002 return WERR_ACCESS_DENIED;
8006 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8007 /* Clever hack from Martin Zielinski <mz@seh.de>
8008 * to allow downgrade from level 8 (Vista).
8010 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8011 r->in.info_ctr->level));
8012 return WERR_UNKNOWN_LEVEL;
8015 DEBUG(5,("Cleaning driver's information\n"));
8016 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8017 if (!W_ERROR_IS_OK(err))
8020 DEBUG(5,("Moving driver to final destination\n"));
8021 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8022 if (!W_ERROR_IS_OK(err)) {
8026 err = winreg_add_driver(p->mem_ctx,
8027 get_session_info_system(),
8032 if (!W_ERROR_IS_OK(err)) {
8037 * I think this is where he DrvUpgradePrinter() hook would be
8038 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8039 * server. Right now, we just need to send ourselves a message
8040 * to update each printer bound to this driver. --jerry
8043 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8044 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8052 /****************************************************************
8053 _spoolss_AddPrinterDriver
8054 ****************************************************************/
8056 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8057 struct spoolss_AddPrinterDriver *r)
8059 struct spoolss_AddPrinterDriverEx a;
8061 switch (r->in.info_ctr->level) {
8068 return WERR_UNKNOWN_LEVEL;
8071 a.in.servername = r->in.servername;
8072 a.in.info_ctr = r->in.info_ctr;
8073 a.in.flags = APD_COPY_NEW_FILES;
8075 return _spoolss_AddPrinterDriverEx(p, &a);
8078 /****************************************************************************
8079 ****************************************************************************/
8081 struct _spoolss_paths {
8087 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8089 static const struct _spoolss_paths spoolss_paths[]= {
8090 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8091 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8094 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8095 const char *servername,
8096 const char *environment,
8100 const char *pservername = NULL;
8101 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8102 const char *short_archi;
8106 /* environment may be empty */
8107 if (environment && strlen(environment)) {
8108 long_archi = environment;
8111 /* servername may be empty */
8112 if (servername && strlen(servername)) {
8113 pservername = canon_servername(servername);
8115 if (!is_myname_or_ipaddr(pservername)) {
8116 return WERR_INVALID_PARAM;
8120 if (!(short_archi = get_short_archi(long_archi))) {
8121 return WERR_INVALID_ENVIRONMENT;
8124 switch (component) {
8125 case SPOOLSS_PRTPROCS_PATH:
8126 case SPOOLSS_DRIVER_PATH:
8128 *path = talloc_asprintf(mem_ctx,
8131 spoolss_paths[component].share,
8134 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8135 SPOOLSS_DEFAULT_SERVER_PATH,
8136 spoolss_paths[component].dir,
8141 return WERR_INVALID_PARAM;
8151 /****************************************************************************
8152 ****************************************************************************/
8154 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8155 const char *servername,
8156 const char *environment,
8157 struct spoolss_DriverDirectoryInfo1 *r)
8162 werr = compose_spoolss_server_path(mem_ctx,
8165 SPOOLSS_DRIVER_PATH,
8167 if (!W_ERROR_IS_OK(werr)) {
8171 DEBUG(4,("printer driver directory: [%s]\n", path));
8173 r->directory_name = path;
8178 /****************************************************************
8179 _spoolss_GetPrinterDriverDirectory
8180 ****************************************************************/
8182 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8183 struct spoolss_GetPrinterDriverDirectory *r)
8187 /* that's an [in out] buffer */
8189 if (!r->in.buffer && (r->in.offered != 0)) {
8190 return WERR_INVALID_PARAM;
8193 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8198 /* r->in.level is ignored */
8200 werror = getprinterdriverdir_level_1(p->mem_ctx,
8203 &r->out.info->info1);
8204 if (!W_ERROR_IS_OK(werror)) {
8205 TALLOC_FREE(r->out.info);
8209 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8210 r->out.info, r->in.level);
8211 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8213 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8216 /****************************************************************
8217 _spoolss_EnumPrinterData
8218 ****************************************************************/
8220 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8221 struct spoolss_EnumPrinterData *r)
8224 struct spoolss_EnumPrinterDataEx r2;
8226 struct spoolss_PrinterEnumValues *info, *val = NULL;
8229 r2.in.handle = r->in.handle;
8230 r2.in.key_name = "PrinterDriverData";
8232 r2.out.count = &count;
8233 r2.out.info = &info;
8234 r2.out.needed = &needed;
8236 result = _spoolss_EnumPrinterDataEx(p, &r2);
8237 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8238 r2.in.offered = needed;
8239 result = _spoolss_EnumPrinterDataEx(p, &r2);
8241 if (!W_ERROR_IS_OK(result)) {
8246 * The NT machine wants to know the biggest size of value and data
8248 * cf: MSDN EnumPrinterData remark section
8251 if (!r->in.value_offered && !r->in.data_offered) {
8252 uint32_t biggest_valuesize = 0;
8253 uint32_t biggest_datasize = 0;
8256 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8258 for (i=0; i<count; i++) {
8260 name_length = strlen(info[i].value_name);
8261 if (strlen(info[i].value_name) > biggest_valuesize) {
8262 biggest_valuesize = name_length;
8265 if (info[i].data_length > biggest_datasize) {
8266 biggest_datasize = info[i].data_length;
8269 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8273 /* the value is an UNICODE string but real_value_size is the length
8274 in bytes including the trailing 0 */
8276 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8277 *r->out.data_needed = biggest_datasize;
8279 DEBUG(6,("final values: [%d], [%d]\n",
8280 *r->out.value_needed, *r->out.data_needed));
8285 if (r->in.enum_index < count) {
8286 val = &info[r->in.enum_index];
8290 /* out_value should default to "" or else NT4 has
8291 problems unmarshalling the response */
8293 if (r->in.value_offered) {
8294 *r->out.value_needed = 1;
8295 r->out.value_name = talloc_strdup(r, "");
8296 if (!r->out.value_name) {
8300 r->out.value_name = NULL;
8301 *r->out.value_needed = 0;
8304 /* the data is counted in bytes */
8306 *r->out.data_needed = r->in.data_offered;
8308 result = WERR_NO_MORE_ITEMS;
8312 * - counted in bytes in the request
8313 * - counted in UNICODE chars in the max reply
8314 * - counted in bytes in the real size
8316 * take a pause *before* coding not *during* coding
8320 if (r->in.value_offered) {
8321 r->out.value_name = talloc_strdup(r, val->value_name);
8322 if (!r->out.value_name) {
8325 *r->out.value_needed = val->value_name_len;
8327 r->out.value_name = NULL;
8328 *r->out.value_needed = 0;
8333 *r->out.type = val->type;
8335 /* data - counted in bytes */
8338 * See the section "Dynamically Typed Query Parameters"
8342 if (r->out.data && val->data && val->data->data &&
8343 val->data_length && r->in.data_offered) {
8344 memcpy(r->out.data, val->data->data,
8345 MIN(val->data_length,r->in.data_offered));
8348 *r->out.data_needed = val->data_length;
8356 /****************************************************************
8357 _spoolss_SetPrinterData
8358 ****************************************************************/
8360 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8361 struct spoolss_SetPrinterData *r)
8363 struct spoolss_SetPrinterDataEx r2;
8365 r2.in.handle = r->in.handle;
8366 r2.in.key_name = "PrinterDriverData";
8367 r2.in.value_name = r->in.value_name;
8368 r2.in.type = r->in.type;
8369 r2.in.data = r->in.data;
8370 r2.in.offered = r->in.offered;
8372 return _spoolss_SetPrinterDataEx(p, &r2);
8375 /****************************************************************
8376 _spoolss_ResetPrinter
8377 ****************************************************************/
8379 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8380 struct spoolss_ResetPrinter *r)
8382 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8385 DEBUG(5,("_spoolss_ResetPrinter\n"));
8388 * All we do is to check to see if the handle and queue is valid.
8389 * This call really doesn't mean anything to us because we only
8390 * support RAW printing. --jerry
8394 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8395 OUR_HANDLE(r->in.handle)));
8399 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8403 /* blindly return success */
8407 /****************************************************************
8408 _spoolss_DeletePrinterData
8409 ****************************************************************/
8411 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8412 struct spoolss_DeletePrinterData *r)
8414 struct spoolss_DeletePrinterDataEx r2;
8416 r2.in.handle = r->in.handle;
8417 r2.in.key_name = "PrinterDriverData";
8418 r2.in.value_name = r->in.value_name;
8420 return _spoolss_DeletePrinterDataEx(p, &r2);
8423 /****************************************************************
8425 ****************************************************************/
8427 WERROR _spoolss_AddForm(struct pipes_struct *p,
8428 struct spoolss_AddForm *r)
8430 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8432 WERROR status = WERR_OK;
8434 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8436 DEBUG(5,("_spoolss_AddForm\n"));
8439 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8440 OUR_HANDLE(r->in.handle)));
8444 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8445 and not a printer admin, then fail */
8447 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8448 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8449 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8450 p->session_info->info3->base.domain.string,
8452 p->session_info->security_token,
8453 lp_printer_admin(snum))) {
8454 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8455 return WERR_ACCESS_DENIED;
8458 switch (form->flags) {
8459 case SPOOLSS_FORM_USER:
8460 case SPOOLSS_FORM_BUILTIN:
8461 case SPOOLSS_FORM_PRINTER:
8464 return WERR_INVALID_PARAM;
8467 status = winreg_printer_addform1(p->mem_ctx,
8468 get_session_info_system(),
8471 if (!W_ERROR_IS_OK(status)) {
8476 * ChangeID must always be set if this is a printer
8478 if (Printer->printer_type == SPLHND_PRINTER) {
8479 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8483 status = winreg_printer_update_changeid(p->mem_ctx,
8484 get_session_info_system(),
8486 lp_const_servicename(snum));
8487 if (!W_ERROR_IS_OK(status)) {
8495 /****************************************************************
8497 ****************************************************************/
8499 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8500 struct spoolss_DeleteForm *r)
8502 const char *form_name = r->in.form_name;
8503 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8505 WERROR status = WERR_OK;
8507 DEBUG(5,("_spoolss_DeleteForm\n"));
8510 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8511 OUR_HANDLE(r->in.handle)));
8515 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8516 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8517 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8518 p->session_info->info3->base.domain.string,
8520 p->session_info->security_token,
8521 lp_printer_admin(snum))) {
8522 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8523 return WERR_ACCESS_DENIED;
8526 status = winreg_printer_deleteform1(p->mem_ctx,
8527 get_session_info_system(),
8530 if (!W_ERROR_IS_OK(status)) {
8535 * ChangeID must always be set if this is a printer
8537 if (Printer->printer_type == SPLHND_PRINTER) {
8538 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8542 status = winreg_printer_update_changeid(p->mem_ctx,
8543 get_session_info_system(),
8545 lp_const_servicename(snum));
8546 if (!W_ERROR_IS_OK(status)) {
8554 /****************************************************************
8556 ****************************************************************/
8558 WERROR _spoolss_SetForm(struct pipes_struct *p,
8559 struct spoolss_SetForm *r)
8561 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8562 const char *form_name = r->in.form_name;
8564 WERROR status = WERR_OK;
8566 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8568 DEBUG(5,("_spoolss_SetForm\n"));
8571 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8572 OUR_HANDLE(r->in.handle)));
8576 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8577 and not a printer admin, then fail */
8579 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8580 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8581 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8582 p->session_info->info3->base.domain.string,
8584 p->session_info->security_token,
8585 lp_printer_admin(snum))) {
8586 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8587 return WERR_ACCESS_DENIED;
8590 status = winreg_printer_setform1(p->mem_ctx,
8591 get_session_info_system(),
8595 if (!W_ERROR_IS_OK(status)) {
8600 * ChangeID must always be set if this is a printer
8602 if (Printer->printer_type == SPLHND_PRINTER) {
8603 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8607 status = winreg_printer_update_changeid(p->mem_ctx,
8608 get_session_info_system(),
8610 lp_const_servicename(snum));
8611 if (!W_ERROR_IS_OK(status)) {
8619 /****************************************************************************
8620 fill_print_processor1
8621 ****************************************************************************/
8623 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8624 struct spoolss_PrintProcessorInfo1 *r,
8625 const char *print_processor_name)
8627 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8628 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8633 /****************************************************************************
8634 enumprintprocessors level 1.
8635 ****************************************************************************/
8637 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8638 union spoolss_PrintProcessorInfo **info_p,
8641 union spoolss_PrintProcessorInfo *info;
8644 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8645 W_ERROR_HAVE_NO_MEMORY(info);
8649 result = fill_print_processor1(info, &info[0].info1, "winprint");
8650 if (!W_ERROR_IS_OK(result)) {
8655 if (!W_ERROR_IS_OK(result)) {
8666 /****************************************************************
8667 _spoolss_EnumPrintProcessors
8668 ****************************************************************/
8670 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8671 struct spoolss_EnumPrintProcessors *r)
8675 /* that's an [in out] buffer */
8677 if (!r->in.buffer && (r->in.offered != 0)) {
8678 return WERR_INVALID_PARAM;
8681 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8684 * Enumerate the print processors ...
8686 * Just reply with "winprint", to keep NT happy
8687 * and I can use my nice printer checker.
8692 *r->out.info = NULL;
8694 if (!get_short_archi(r->in.environment)) {
8695 return WERR_INVALID_ENVIRONMENT;
8698 switch (r->in.level) {
8700 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8704 return WERR_UNKNOWN_LEVEL;
8707 if (!W_ERROR_IS_OK(result)) {
8711 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8712 spoolss_EnumPrintProcessors,
8713 *r->out.info, r->in.level,
8715 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8716 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8718 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8721 /****************************************************************************
8722 fill_printprocdatatype1
8723 ****************************************************************************/
8725 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8726 struct spoolss_PrintProcDataTypesInfo1 *r,
8727 const char *name_array)
8729 r->name_array = talloc_strdup(mem_ctx, name_array);
8730 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8735 /****************************************************************************
8736 enumprintprocdatatypes level 1.
8737 ****************************************************************************/
8739 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8740 union spoolss_PrintProcDataTypesInfo **info_p,
8744 union spoolss_PrintProcDataTypesInfo *info;
8746 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8747 W_ERROR_HAVE_NO_MEMORY(info);
8751 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8752 if (!W_ERROR_IS_OK(result)) {
8757 if (!W_ERROR_IS_OK(result)) {
8768 /****************************************************************
8769 _spoolss_EnumPrintProcDataTypes
8770 ****************************************************************/
8772 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8773 struct spoolss_EnumPrintProcDataTypes *r)
8777 /* that's an [in out] buffer */
8779 if (!r->in.buffer && (r->in.offered != 0)) {
8780 return WERR_INVALID_PARAM;
8783 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8787 *r->out.info = NULL;
8789 if (r->in.print_processor_name == NULL ||
8790 !strequal(r->in.print_processor_name, "winprint")) {
8791 return WERR_UNKNOWN_PRINTPROCESSOR;
8794 switch (r->in.level) {
8796 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8800 return WERR_UNKNOWN_LEVEL;
8803 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8804 spoolss_EnumPrintProcDataTypes,
8805 *r->out.info, r->in.level,
8807 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8808 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8810 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8813 /****************************************************************************
8815 ****************************************************************************/
8817 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8818 struct spoolss_MonitorInfo1 *r,
8819 const char *monitor_name)
8821 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8822 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8827 /****************************************************************************
8829 ****************************************************************************/
8831 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8832 struct spoolss_MonitorInfo2 *r,
8833 const char *monitor_name,
8834 const char *environment,
8835 const char *dll_name)
8837 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8838 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8839 r->environment = talloc_strdup(mem_ctx, environment);
8840 W_ERROR_HAVE_NO_MEMORY(r->environment);
8841 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8842 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8847 /****************************************************************************
8848 enumprintmonitors level 1.
8849 ****************************************************************************/
8851 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8852 union spoolss_MonitorInfo **info_p,
8855 union spoolss_MonitorInfo *info;
8856 WERROR result = WERR_OK;
8858 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8859 W_ERROR_HAVE_NO_MEMORY(info);
8863 result = fill_monitor_1(info, &info[0].info1,
8865 if (!W_ERROR_IS_OK(result)) {
8869 result = fill_monitor_1(info, &info[1].info1,
8871 if (!W_ERROR_IS_OK(result)) {
8876 if (!W_ERROR_IS_OK(result)) {
8887 /****************************************************************************
8888 enumprintmonitors level 2.
8889 ****************************************************************************/
8891 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8892 union spoolss_MonitorInfo **info_p,
8895 union spoolss_MonitorInfo *info;
8896 WERROR result = WERR_OK;
8898 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8899 W_ERROR_HAVE_NO_MEMORY(info);
8903 result = fill_monitor_2(info, &info[0].info2,
8905 "Windows NT X86", /* FIXME */
8907 if (!W_ERROR_IS_OK(result)) {
8911 result = fill_monitor_2(info, &info[1].info2,
8913 "Windows NT X86", /* FIXME */
8915 if (!W_ERROR_IS_OK(result)) {
8920 if (!W_ERROR_IS_OK(result)) {
8931 /****************************************************************
8932 _spoolss_EnumMonitors
8933 ****************************************************************/
8935 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8936 struct spoolss_EnumMonitors *r)
8940 /* that's an [in out] buffer */
8942 if (!r->in.buffer && (r->in.offered != 0)) {
8943 return WERR_INVALID_PARAM;
8946 DEBUG(5,("_spoolss_EnumMonitors\n"));
8949 * Enumerate the print monitors ...
8951 * Just reply with "Local Port", to keep NT happy
8952 * and I can use my nice printer checker.
8957 *r->out.info = NULL;
8959 switch (r->in.level) {
8961 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8965 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8969 return WERR_UNKNOWN_LEVEL;
8972 if (!W_ERROR_IS_OK(result)) {
8976 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8977 spoolss_EnumMonitors,
8978 *r->out.info, r->in.level,
8980 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8981 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8983 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8986 /****************************************************************************
8987 ****************************************************************************/
8989 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8990 const print_queue_struct *queue,
8991 int count, int snum,
8992 struct spoolss_PrinterInfo2 *pinfo2,
8994 struct spoolss_JobInfo1 *r)
8999 for (i=0; i<count; i++) {
9000 if (queue[i].job == (int)jobid) {
9006 if (found == false) {
9007 /* NT treats not found as bad param... yet another bad choice */
9008 return WERR_INVALID_PARAM;
9011 return fill_job_info1(mem_ctx,
9019 /****************************************************************************
9020 ****************************************************************************/
9022 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9023 const print_queue_struct *queue,
9024 int count, int snum,
9025 struct spoolss_PrinterInfo2 *pinfo2,
9027 struct spoolss_JobInfo2 *r)
9031 struct spoolss_DeviceMode *devmode;
9034 for (i=0; i<count; i++) {
9035 if (queue[i].job == (int)jobid) {
9041 if (found == false) {
9042 /* NT treats not found as bad param... yet another bad
9044 return WERR_INVALID_PARAM;
9048 * if the print job does not have a DEVMODE associated with it,
9049 * just use the one for the printer. A NULL devicemode is not
9050 * a failure condition
9053 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9055 result = spoolss_create_default_devmode(mem_ctx,
9056 pinfo2->printername,
9058 if (!W_ERROR_IS_OK(result)) {
9059 DEBUG(3, ("Can't proceed w/o a devmode!"));
9064 return fill_job_info2(mem_ctx,
9073 /****************************************************************
9075 ****************************************************************/
9077 WERROR _spoolss_GetJob(struct pipes_struct *p,
9078 struct spoolss_GetJob *r)
9080 WERROR result = WERR_OK;
9081 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9084 print_queue_struct *queue = NULL;
9085 print_status_struct prt_status;
9087 /* that's an [in out] buffer */
9089 if (!r->in.buffer && (r->in.offered != 0)) {
9090 return WERR_INVALID_PARAM;
9093 DEBUG(5,("_spoolss_GetJob\n"));
9097 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9101 result = winreg_get_printer(p->mem_ctx,
9102 get_session_info_system(),
9104 lp_const_servicename(snum),
9106 if (!W_ERROR_IS_OK(result)) {
9110 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9112 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9113 count, prt_status.status, prt_status.message));
9115 switch (r->in.level) {
9117 result = getjob_level_1(p->mem_ctx,
9118 queue, count, snum, pinfo2,
9119 r->in.job_id, &r->out.info->info1);
9122 result = getjob_level_2(p->mem_ctx,
9123 queue, count, snum, pinfo2,
9124 r->in.job_id, &r->out.info->info2);
9127 result = WERR_UNKNOWN_LEVEL;
9132 TALLOC_FREE(pinfo2);
9134 if (!W_ERROR_IS_OK(result)) {
9135 TALLOC_FREE(r->out.info);
9139 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9141 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9143 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9146 /****************************************************************
9147 _spoolss_GetPrinterDataEx
9148 ****************************************************************/
9150 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9151 struct spoolss_GetPrinterDataEx *r)
9154 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9155 const char *printer;
9157 WERROR result = WERR_OK;
9159 enum winreg_Type val_type;
9164 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9166 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9167 r->in.key_name, r->in.value_name));
9169 /* in case of problem, return some default values */
9172 *r->out.type = REG_NONE;
9175 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9176 OUR_HANDLE(r->in.handle)));
9177 result = WERR_BADFID;
9181 /* Is the handle to a printer or to the server? */
9183 if (Printer->printer_type == SPLHND_SERVER) {
9185 union spoolss_PrinterData data;
9187 result = getprinterdata_printer_server(p->mem_ctx,
9191 if (!W_ERROR_IS_OK(result)) {
9195 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9196 *r->out.type, &data);
9197 if (!W_ERROR_IS_OK(result)) {
9201 *r->out.needed = blob.length;
9203 if (r->in.offered >= *r->out.needed) {
9204 memcpy(r->out.data, blob.data, blob.length);
9207 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9210 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9213 printer = lp_const_servicename(snum);
9215 /* check to see if the keyname is valid */
9216 if (!strlen(r->in.key_name)) {
9217 return WERR_INVALID_PARAM;
9220 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9221 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9222 strequal(r->in.value_name, "ChangeId")) {
9223 *r->out.type = REG_DWORD;
9225 if (r->in.offered >= *r->out.needed) {
9226 uint32_t changeid = 0;
9228 result = winreg_printer_get_changeid(p->mem_ctx,
9229 get_session_info_system(),
9233 if (!W_ERROR_IS_OK(result)) {
9237 SIVAL(r->out.data, 0, changeid);
9243 result = winreg_get_printer_dataex(p->mem_ctx,
9244 get_session_info_system(),
9252 if (!W_ERROR_IS_OK(result)) {
9256 *r->out.needed = val_size;
9257 *r->out.type = val_type;
9259 if (r->in.offered >= *r->out.needed) {
9260 memcpy(r->out.data, val_data, val_size);
9264 /* retain type when returning WERR_MORE_DATA */
9265 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9267 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9270 /****************************************************************
9271 _spoolss_SetPrinterDataEx
9272 ****************************************************************/
9274 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9275 struct spoolss_SetPrinterDataEx *r)
9277 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9279 WERROR result = WERR_OK;
9280 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9283 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9285 /* From MSDN documentation of SetPrinterDataEx: pass request to
9286 SetPrinterData if key is "PrinterDriverData" */
9289 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9290 OUR_HANDLE(r->in.handle)));
9294 if (Printer->printer_type == SPLHND_SERVER) {
9295 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9296 "Not implemented for server handles yet\n"));
9297 return WERR_INVALID_PARAM;
9300 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9305 * Access check : NT returns "access denied" if you make a
9306 * SetPrinterData call without the necessary privildge.
9307 * we were originally returning OK if nothing changed
9308 * which made Win2k issue **a lot** of SetPrinterData
9309 * when connecting to a printer --jerry
9312 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9313 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9314 "change denied by handle access permissions\n"));
9315 return WERR_ACCESS_DENIED;
9318 result = winreg_get_printer(Printer,
9319 get_session_info_system(),
9321 lp_servicename(snum),
9323 if (!W_ERROR_IS_OK(result)) {
9327 /* check for OID in valuename */
9329 oid_string = strchr(r->in.value_name, ',');
9335 /* save the registry data */
9337 result = winreg_set_printer_dataex(p->mem_ctx,
9338 get_session_info_system(),
9347 if (W_ERROR_IS_OK(result)) {
9348 /* save the OID if one was specified */
9350 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9351 r->in.key_name, SPOOL_OID_KEY);
9353 result = WERR_NOMEM;
9358 * I'm not checking the status here on purpose. Don't know
9359 * if this is right, but I'm returning the status from the
9360 * previous set_printer_dataex() call. I have no idea if
9361 * this is right. --jerry
9363 winreg_set_printer_dataex(p->mem_ctx,
9364 get_session_info_system(),
9370 (uint8_t *) oid_string,
9371 strlen(oid_string) + 1);
9374 result = winreg_printer_update_changeid(p->mem_ctx,
9375 get_session_info_system(),
9377 lp_const_servicename(snum));
9382 talloc_free(pinfo2);
9386 /****************************************************************
9387 _spoolss_DeletePrinterDataEx
9388 ****************************************************************/
9390 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9391 struct spoolss_DeletePrinterDataEx *r)
9393 const char *printer;
9395 WERROR status = WERR_OK;
9396 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9398 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9401 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9402 "Invalid handle (%s:%u:%u).\n",
9403 OUR_HANDLE(r->in.handle)));
9407 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9408 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9409 "printer properties change denied by handle\n"));
9410 return WERR_ACCESS_DENIED;
9413 if (!r->in.value_name || !r->in.key_name) {
9417 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9420 printer = lp_const_servicename(snum);
9422 status = winreg_delete_printer_dataex(p->mem_ctx,
9423 get_session_info_system(),
9428 if (W_ERROR_IS_OK(status)) {
9429 status = winreg_printer_update_changeid(p->mem_ctx,
9430 get_session_info_system(),
9438 /****************************************************************
9439 _spoolss_EnumPrinterKey
9440 ****************************************************************/
9442 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9443 struct spoolss_EnumPrinterKey *r)
9446 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9448 WERROR result = WERR_BADFILE;
9449 const char **array = NULL;
9452 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9455 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9456 OUR_HANDLE(r->in.handle)));
9460 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9464 result = winreg_enum_printer_key(p->mem_ctx,
9465 get_session_info_system(),
9467 lp_const_servicename(snum),
9471 if (!W_ERROR_IS_OK(result)) {
9475 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9476 result = WERR_NOMEM;
9480 *r->out._ndr_size = r->in.offered / 2;
9481 *r->out.needed = blob.length;
9483 if (r->in.offered < *r->out.needed) {
9484 result = WERR_MORE_DATA;
9487 r->out.key_buffer->string_array = array;
9491 if (!W_ERROR_IS_OK(result)) {
9493 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9501 /****************************************************************
9502 _spoolss_DeletePrinterKey
9503 ****************************************************************/
9505 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9506 struct spoolss_DeletePrinterKey *r)
9508 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9511 const char *printer;
9513 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9516 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9517 OUR_HANDLE(r->in.handle)));
9521 /* if keyname == NULL, return error */
9522 if ( !r->in.key_name )
9523 return WERR_INVALID_PARAM;
9525 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9529 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9530 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9531 "printer properties change denied by handle\n"));
9532 return WERR_ACCESS_DENIED;
9535 printer = lp_const_servicename(snum);
9537 /* delete the key and all subkeys */
9538 status = winreg_delete_printer_key(p->mem_ctx,
9539 get_session_info_system(),
9543 if (W_ERROR_IS_OK(status)) {
9544 status = winreg_printer_update_changeid(p->mem_ctx,
9545 get_session_info_system(),
9553 /****************************************************************
9554 _spoolss_EnumPrinterDataEx
9555 ****************************************************************/
9557 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9558 struct spoolss_EnumPrinterDataEx *r)
9561 struct spoolss_PrinterEnumValues *info = NULL;
9562 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9566 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9570 *r->out.info = NULL;
9573 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9574 OUR_HANDLE(r->in.handle)));
9579 * first check for a keyname of NULL or "". Win2k seems to send
9580 * this a lot and we should send back WERR_INVALID_PARAM
9581 * no need to spend time looking up the printer in this case.
9585 if (!strlen(r->in.key_name)) {
9586 result = WERR_INVALID_PARAM;
9590 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9594 /* now look for a match on the key name */
9595 result = winreg_enum_printer_dataex(p->mem_ctx,
9596 get_session_info_system(),
9598 lp_const_servicename(snum),
9602 if (!W_ERROR_IS_OK(result)) {
9606 #if 0 /* FIXME - gd */
9607 /* housekeeping information in the reply */
9609 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9610 * the hand marshalled container size is a multiple
9611 * of 4 bytes for RPC alignment.
9615 needed += 4-(needed % 4);
9618 *r->out.count = count;
9619 *r->out.info = info;
9622 if (!W_ERROR_IS_OK(result)) {
9626 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9627 spoolss_EnumPrinterDataEx,
9630 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9631 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9633 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9636 /****************************************************************************
9637 ****************************************************************************/
9639 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9640 const char *servername,
9641 const char *environment,
9642 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9647 werr = compose_spoolss_server_path(mem_ctx,
9650 SPOOLSS_PRTPROCS_PATH,
9652 if (!W_ERROR_IS_OK(werr)) {
9656 DEBUG(4,("print processor directory: [%s]\n", path));
9658 r->directory_name = path;
9663 /****************************************************************
9664 _spoolss_GetPrintProcessorDirectory
9665 ****************************************************************/
9667 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9668 struct spoolss_GetPrintProcessorDirectory *r)
9671 char *prnproc_share = NULL;
9672 bool prnproc_share_exists = false;
9675 /* that's an [in out] buffer */
9677 if (!r->in.buffer && (r->in.offered != 0)) {
9678 return WERR_INVALID_PARAM;
9681 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9686 /* r->in.level is ignored */
9688 /* We always should reply with a local print processor directory so that
9689 * users are not forced to have a [prnproc$] share on the Samba spoolss
9690 * server, if users decide to do so, lets announce it though - Guenther */
9692 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9693 if (!prnproc_share) {
9697 prnproc_share_exists = true;
9700 result = getprintprocessordirectory_level_1(p->mem_ctx,
9701 prnproc_share_exists ? r->in.server : NULL,
9703 &r->out.info->info1);
9704 if (!W_ERROR_IS_OK(result)) {
9705 TALLOC_FREE(r->out.info);
9709 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9710 r->out.info, r->in.level);
9711 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9713 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9716 /*******************************************************************
9717 ********************************************************************/
9719 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9720 const char *dllname)
9722 enum ndr_err_code ndr_err;
9723 struct spoolss_MonitorUi ui;
9725 ui.dll_name = dllname;
9727 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9728 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9729 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9730 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9732 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9735 /*******************************************************************
9736 Streams the monitor UI DLL name in UNICODE
9737 *******************************************************************/
9739 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9740 struct security_token *token, DATA_BLOB *in,
9741 DATA_BLOB *out, uint32_t *needed)
9743 const char *dllname = "tcpmonui.dll";
9745 *needed = (strlen(dllname)+1) * 2;
9747 if (out->length < *needed) {
9748 return WERR_INSUFFICIENT_BUFFER;
9751 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9758 /*******************************************************************
9759 ********************************************************************/
9761 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9762 struct spoolss_PortData1 *port1,
9763 const DATA_BLOB *buf)
9765 enum ndr_err_code ndr_err;
9766 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9767 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9768 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9769 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9771 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9774 /*******************************************************************
9775 ********************************************************************/
9777 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9778 struct spoolss_PortData2 *port2,
9779 const DATA_BLOB *buf)
9781 enum ndr_err_code ndr_err;
9782 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9783 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9784 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9785 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9787 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9790 /*******************************************************************
9791 Create a new TCP/IP port
9792 *******************************************************************/
9794 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9795 struct security_token *token, DATA_BLOB *in,
9796 DATA_BLOB *out, uint32_t *needed)
9798 struct spoolss_PortData1 port1;
9799 struct spoolss_PortData2 port2;
9800 char *device_uri = NULL;
9803 const char *portname;
9804 const char *hostaddress;
9806 uint32_t port_number;
9809 /* peek for spoolss_PortData version */
9811 if (!in || (in->length < (128 + 4))) {
9812 return WERR_GENERAL_FAILURE;
9815 version = IVAL(in->data, 128);
9821 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9825 portname = port1.portname;
9826 hostaddress = port1.hostaddress;
9827 queue = port1.queue;
9828 protocol = port1.protocol;
9829 port_number = port1.port_number;
9835 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9839 portname = port2.portname;
9840 hostaddress = port2.hostaddress;
9841 queue = port2.queue;
9842 protocol = port2.protocol;
9843 port_number = port2.port_number;
9847 DEBUG(1,("xcvtcp_addport: "
9848 "unknown version of port_data: %d\n", version));
9849 return WERR_UNKNOWN_PORT;
9852 /* create the device URI and call the add_port_hook() */
9855 case PROTOCOL_RAWTCP_TYPE:
9856 device_uri = talloc_asprintf(mem_ctx,
9857 "socket://%s:%d/", hostaddress,
9861 case PROTOCOL_LPR_TYPE:
9862 device_uri = talloc_asprintf(mem_ctx,
9863 "lpr://%s/%s", hostaddress, queue );
9867 return WERR_UNKNOWN_PORT;
9874 return add_port_hook(mem_ctx, token, portname, device_uri);
9877 /*******************************************************************
9878 *******************************************************************/
9880 struct xcv_api_table xcvtcp_cmds[] = {
9881 { "MonitorUI", xcvtcp_monitorui },
9882 { "AddPort", xcvtcp_addport},
9886 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9887 struct security_token *token, const char *command,
9894 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9896 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9897 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9898 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9901 return WERR_BADFUNC;
9904 /*******************************************************************
9905 *******************************************************************/
9906 #if 0 /* don't support management using the "Local Port" monitor */
9908 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9909 struct security_token *token, DATA_BLOB *in,
9910 DATA_BLOB *out, uint32_t *needed)
9912 const char *dllname = "localui.dll";
9914 *needed = (strlen(dllname)+1) * 2;
9916 if (out->length < *needed) {
9917 return WERR_INSUFFICIENT_BUFFER;
9920 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9927 /*******************************************************************
9928 *******************************************************************/
9930 struct xcv_api_table xcvlocal_cmds[] = {
9931 { "MonitorUI", xcvlocal_monitorui },
9935 struct xcv_api_table xcvlocal_cmds[] = {
9942 /*******************************************************************
9943 *******************************************************************/
9945 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9946 struct security_token *token, const char *command,
9947 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9952 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9954 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9955 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9956 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9958 return WERR_BADFUNC;
9961 /****************************************************************
9963 ****************************************************************/
9965 WERROR _spoolss_XcvData(struct pipes_struct *p,
9966 struct spoolss_XcvData *r)
9968 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9969 DATA_BLOB out_data = data_blob_null;
9973 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9974 OUR_HANDLE(r->in.handle)));
9978 /* Has to be a handle to the TCP/IP port monitor */
9980 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9981 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9985 /* requires administrative access to the server */
9987 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9988 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9989 return WERR_ACCESS_DENIED;
9992 /* Allocate the outgoing buffer */
9994 if (r->in.out_data_size) {
9995 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9996 if (out_data.data == NULL) {
10001 switch ( Printer->printer_type ) {
10002 case SPLHND_PORTMON_TCP:
10003 werror = process_xcvtcp_command(p->mem_ctx,
10004 p->session_info->security_token,
10005 r->in.function_name,
10006 &r->in.in_data, &out_data,
10009 case SPLHND_PORTMON_LOCAL:
10010 werror = process_xcvlocal_command(p->mem_ctx,
10011 p->session_info->security_token,
10012 r->in.function_name,
10013 &r->in.in_data, &out_data,
10017 werror = WERR_INVALID_PRINT_MONITOR;
10020 if (!W_ERROR_IS_OK(werror)) {
10024 *r->out.status_code = 0;
10026 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10027 memcpy(r->out.out_data, out_data.data,
10028 MIN(r->in.out_data_size, out_data.length));
10034 /****************************************************************
10035 _spoolss_AddPrintProcessor
10036 ****************************************************************/
10038 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10039 struct spoolss_AddPrintProcessor *r)
10041 /* for now, just indicate success and ignore the add. We'll
10042 automatically set the winprint processor for printer
10043 entries later. Used to debug the LexMark Optra S 1855 PCL
10049 /****************************************************************
10051 ****************************************************************/
10053 WERROR _spoolss_AddPort(struct pipes_struct *p,
10054 struct spoolss_AddPort *r)
10056 /* do what w2k3 does */
10058 return WERR_NOT_SUPPORTED;
10061 /****************************************************************
10062 _spoolss_GetPrinterDriver
10063 ****************************************************************/
10065 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10066 struct spoolss_GetPrinterDriver *r)
10068 p->rng_fault_state = true;
10069 return WERR_NOT_SUPPORTED;
10072 /****************************************************************
10073 _spoolss_ReadPrinter
10074 ****************************************************************/
10076 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10077 struct spoolss_ReadPrinter *r)
10079 p->rng_fault_state = true;
10080 return WERR_NOT_SUPPORTED;
10083 /****************************************************************
10084 _spoolss_WaitForPrinterChange
10085 ****************************************************************/
10087 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10088 struct spoolss_WaitForPrinterChange *r)
10090 p->rng_fault_state = true;
10091 return WERR_NOT_SUPPORTED;
10094 /****************************************************************
10095 _spoolss_ConfigurePort
10096 ****************************************************************/
10098 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10099 struct spoolss_ConfigurePort *r)
10101 p->rng_fault_state = true;
10102 return WERR_NOT_SUPPORTED;
10105 /****************************************************************
10106 _spoolss_DeletePort
10107 ****************************************************************/
10109 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10110 struct spoolss_DeletePort *r)
10112 p->rng_fault_state = true;
10113 return WERR_NOT_SUPPORTED;
10116 /****************************************************************
10117 _spoolss_CreatePrinterIC
10118 ****************************************************************/
10120 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10121 struct spoolss_CreatePrinterIC *r)
10123 p->rng_fault_state = true;
10124 return WERR_NOT_SUPPORTED;
10127 /****************************************************************
10128 _spoolss_PlayGDIScriptOnPrinterIC
10129 ****************************************************************/
10131 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10132 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10134 p->rng_fault_state = true;
10135 return WERR_NOT_SUPPORTED;
10138 /****************************************************************
10139 _spoolss_DeletePrinterIC
10140 ****************************************************************/
10142 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10143 struct spoolss_DeletePrinterIC *r)
10145 p->rng_fault_state = true;
10146 return WERR_NOT_SUPPORTED;
10149 /****************************************************************
10150 _spoolss_AddPrinterConnection
10151 ****************************************************************/
10153 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10154 struct spoolss_AddPrinterConnection *r)
10156 p->rng_fault_state = true;
10157 return WERR_NOT_SUPPORTED;
10160 /****************************************************************
10161 _spoolss_DeletePrinterConnection
10162 ****************************************************************/
10164 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10165 struct spoolss_DeletePrinterConnection *r)
10167 p->rng_fault_state = true;
10168 return WERR_NOT_SUPPORTED;
10171 /****************************************************************
10172 _spoolss_PrinterMessageBox
10173 ****************************************************************/
10175 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10176 struct spoolss_PrinterMessageBox *r)
10178 p->rng_fault_state = true;
10179 return WERR_NOT_SUPPORTED;
10182 /****************************************************************
10183 _spoolss_AddMonitor
10184 ****************************************************************/
10186 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10187 struct spoolss_AddMonitor *r)
10189 p->rng_fault_state = true;
10190 return WERR_NOT_SUPPORTED;
10193 /****************************************************************
10194 _spoolss_DeleteMonitor
10195 ****************************************************************/
10197 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10198 struct spoolss_DeleteMonitor *r)
10200 p->rng_fault_state = true;
10201 return WERR_NOT_SUPPORTED;
10204 /****************************************************************
10205 _spoolss_DeletePrintProcessor
10206 ****************************************************************/
10208 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10209 struct spoolss_DeletePrintProcessor *r)
10211 p->rng_fault_state = true;
10212 return WERR_NOT_SUPPORTED;
10215 /****************************************************************
10216 _spoolss_AddPrintProvidor
10217 ****************************************************************/
10219 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10220 struct spoolss_AddPrintProvidor *r)
10222 p->rng_fault_state = true;
10223 return WERR_NOT_SUPPORTED;
10226 /****************************************************************
10227 _spoolss_DeletePrintProvidor
10228 ****************************************************************/
10230 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10231 struct spoolss_DeletePrintProvidor *r)
10233 p->rng_fault_state = true;
10234 return WERR_NOT_SUPPORTED;
10237 /****************************************************************
10238 _spoolss_FindFirstPrinterChangeNotification
10239 ****************************************************************/
10241 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10242 struct spoolss_FindFirstPrinterChangeNotification *r)
10244 p->rng_fault_state = true;
10245 return WERR_NOT_SUPPORTED;
10248 /****************************************************************
10249 _spoolss_FindNextPrinterChangeNotification
10250 ****************************************************************/
10252 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10253 struct spoolss_FindNextPrinterChangeNotification *r)
10255 p->rng_fault_state = true;
10256 return WERR_NOT_SUPPORTED;
10259 /****************************************************************
10260 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10261 ****************************************************************/
10263 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10264 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10266 p->rng_fault_state = true;
10267 return WERR_NOT_SUPPORTED;
10270 /****************************************************************
10271 _spoolss_ReplyOpenPrinter
10272 ****************************************************************/
10274 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10275 struct spoolss_ReplyOpenPrinter *r)
10277 p->rng_fault_state = true;
10278 return WERR_NOT_SUPPORTED;
10281 /****************************************************************
10282 _spoolss_RouterReplyPrinter
10283 ****************************************************************/
10285 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10286 struct spoolss_RouterReplyPrinter *r)
10288 p->rng_fault_state = true;
10289 return WERR_NOT_SUPPORTED;
10292 /****************************************************************
10293 _spoolss_ReplyClosePrinter
10294 ****************************************************************/
10296 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10297 struct spoolss_ReplyClosePrinter *r)
10299 p->rng_fault_state = true;
10300 return WERR_NOT_SUPPORTED;
10303 /****************************************************************
10305 ****************************************************************/
10307 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10308 struct spoolss_AddPortEx *r)
10310 p->rng_fault_state = true;
10311 return WERR_NOT_SUPPORTED;
10314 /****************************************************************
10315 _spoolss_RouterFindFirstPrinterChangeNotification
10316 ****************************************************************/
10318 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10319 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10321 p->rng_fault_state = true;
10322 return WERR_NOT_SUPPORTED;
10325 /****************************************************************
10326 _spoolss_SpoolerInit
10327 ****************************************************************/
10329 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10330 struct spoolss_SpoolerInit *r)
10332 p->rng_fault_state = true;
10333 return WERR_NOT_SUPPORTED;
10336 /****************************************************************
10337 _spoolss_ResetPrinterEx
10338 ****************************************************************/
10340 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10341 struct spoolss_ResetPrinterEx *r)
10343 p->rng_fault_state = true;
10344 return WERR_NOT_SUPPORTED;
10347 /****************************************************************
10348 _spoolss_RouterReplyPrinterEx
10349 ****************************************************************/
10351 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10352 struct spoolss_RouterReplyPrinterEx *r)
10354 p->rng_fault_state = true;
10355 return WERR_NOT_SUPPORTED;
10358 /****************************************************************
10360 ****************************************************************/
10362 WERROR _spoolss_44(struct pipes_struct *p,
10363 struct spoolss_44 *r)
10365 p->rng_fault_state = true;
10366 return WERR_NOT_SUPPORTED;
10369 /****************************************************************
10371 ****************************************************************/
10373 WERROR _spoolss_SetPort(struct pipes_struct *p,
10374 struct spoolss_SetPort *r)
10376 p->rng_fault_state = true;
10377 return WERR_NOT_SUPPORTED;
10380 /****************************************************************
10382 ****************************************************************/
10384 WERROR _spoolss_4a(struct pipes_struct *p,
10385 struct spoolss_4a *r)
10387 p->rng_fault_state = true;
10388 return WERR_NOT_SUPPORTED;
10391 /****************************************************************
10393 ****************************************************************/
10395 WERROR _spoolss_4b(struct pipes_struct *p,
10396 struct spoolss_4b *r)
10398 p->rng_fault_state = true;
10399 return WERR_NOT_SUPPORTED;
10402 /****************************************************************
10404 ****************************************************************/
10406 WERROR _spoolss_4c(struct pipes_struct *p,
10407 struct spoolss_4c *r)
10409 p->rng_fault_state = true;
10410 return WERR_NOT_SUPPORTED;
10413 /****************************************************************
10415 ****************************************************************/
10417 WERROR _spoolss_53(struct pipes_struct *p,
10418 struct spoolss_53 *r)
10420 p->rng_fault_state = true;
10421 return WERR_NOT_SUPPORTED;
10424 /****************************************************************
10425 _spoolss_AddPerMachineConnection
10426 ****************************************************************/
10428 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10429 struct spoolss_AddPerMachineConnection *r)
10431 p->rng_fault_state = true;
10432 return WERR_NOT_SUPPORTED;
10435 /****************************************************************
10436 _spoolss_DeletePerMachineConnection
10437 ****************************************************************/
10439 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10440 struct spoolss_DeletePerMachineConnection *r)
10442 p->rng_fault_state = true;
10443 return WERR_NOT_SUPPORTED;
10446 /****************************************************************
10447 _spoolss_EnumPerMachineConnections
10448 ****************************************************************/
10450 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10451 struct spoolss_EnumPerMachineConnections *r)
10453 p->rng_fault_state = true;
10454 return WERR_NOT_SUPPORTED;
10457 /****************************************************************
10459 ****************************************************************/
10461 WERROR _spoolss_5a(struct pipes_struct *p,
10462 struct spoolss_5a *r)
10464 p->rng_fault_state = true;
10465 return WERR_NOT_SUPPORTED;
10468 /****************************************************************
10470 ****************************************************************/
10472 WERROR _spoolss_5b(struct pipes_struct *p,
10473 struct spoolss_5b *r)
10475 p->rng_fault_state = true;
10476 return WERR_NOT_SUPPORTED;
10479 /****************************************************************
10481 ****************************************************************/
10483 WERROR _spoolss_5c(struct pipes_struct *p,
10484 struct spoolss_5c *r)
10486 p->rng_fault_state = true;
10487 return WERR_NOT_SUPPORTED;
10490 /****************************************************************
10492 ****************************************************************/
10494 WERROR _spoolss_5d(struct pipes_struct *p,
10495 struct spoolss_5d *r)
10497 p->rng_fault_state = true;
10498 return WERR_NOT_SUPPORTED;
10501 /****************************************************************
10503 ****************************************************************/
10505 WERROR _spoolss_5e(struct pipes_struct *p,
10506 struct spoolss_5e *r)
10508 p->rng_fault_state = true;
10509 return WERR_NOT_SUPPORTED;
10512 /****************************************************************
10514 ****************************************************************/
10516 WERROR _spoolss_5f(struct pipes_struct *p,
10517 struct spoolss_5f *r)
10519 p->rng_fault_state = true;
10520 return WERR_NOT_SUPPORTED;
10523 /****************************************************************
10525 ****************************************************************/
10527 WERROR _spoolss_60(struct pipes_struct *p,
10528 struct spoolss_60 *r)
10530 p->rng_fault_state = true;
10531 return WERR_NOT_SUPPORTED;
10534 /****************************************************************
10536 ****************************************************************/
10538 WERROR _spoolss_61(struct pipes_struct *p,
10539 struct spoolss_61 *r)
10541 p->rng_fault_state = true;
10542 return WERR_NOT_SUPPORTED;
10545 /****************************************************************
10547 ****************************************************************/
10549 WERROR _spoolss_62(struct pipes_struct *p,
10550 struct spoolss_62 *r)
10552 p->rng_fault_state = true;
10553 return WERR_NOT_SUPPORTED;
10556 /****************************************************************
10558 ****************************************************************/
10560 WERROR _spoolss_63(struct pipes_struct *p,
10561 struct spoolss_63 *r)
10563 p->rng_fault_state = true;
10564 return WERR_NOT_SUPPORTED;
10567 /****************************************************************
10569 ****************************************************************/
10571 WERROR _spoolss_64(struct pipes_struct *p,
10572 struct spoolss_64 *r)
10574 p->rng_fault_state = true;
10575 return WERR_NOT_SUPPORTED;
10578 /****************************************************************
10580 ****************************************************************/
10582 WERROR _spoolss_65(struct pipes_struct *p,
10583 struct spoolss_65 *r)
10585 p->rng_fault_state = true;
10586 return WERR_NOT_SUPPORTED;
10589 /****************************************************************
10590 _spoolss_GetCorePrinterDrivers
10591 ****************************************************************/
10593 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10594 struct spoolss_GetCorePrinterDrivers *r)
10596 p->rng_fault_state = true;
10597 return WERR_NOT_SUPPORTED;
10600 /****************************************************************
10602 ****************************************************************/
10604 WERROR _spoolss_67(struct pipes_struct *p,
10605 struct spoolss_67 *r)
10607 p->rng_fault_state = true;
10608 return WERR_NOT_SUPPORTED;
10611 /****************************************************************
10612 _spoolss_GetPrinterDriverPackagePath
10613 ****************************************************************/
10615 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10616 struct spoolss_GetPrinterDriverPackagePath *r)
10618 p->rng_fault_state = true;
10619 return WERR_NOT_SUPPORTED;
10622 /****************************************************************
10624 ****************************************************************/
10626 WERROR _spoolss_69(struct pipes_struct *p,
10627 struct spoolss_69 *r)
10629 p->rng_fault_state = true;
10630 return WERR_NOT_SUPPORTED;
10633 /****************************************************************
10635 ****************************************************************/
10637 WERROR _spoolss_6a(struct pipes_struct *p,
10638 struct spoolss_6a *r)
10640 p->rng_fault_state = true;
10641 return WERR_NOT_SUPPORTED;
10644 /****************************************************************
10646 ****************************************************************/
10648 WERROR _spoolss_6b(struct pipes_struct *p,
10649 struct spoolss_6b *r)
10651 p->rng_fault_state = true;
10652 return WERR_NOT_SUPPORTED;
10655 /****************************************************************
10657 ****************************************************************/
10659 WERROR _spoolss_6c(struct pipes_struct *p,
10660 struct spoolss_6c *r)
10662 p->rng_fault_state = true;
10663 return WERR_NOT_SUPPORTED;
10666 /****************************************************************
10668 ****************************************************************/
10670 WERROR _spoolss_6d(struct pipes_struct *p,
10671 struct spoolss_6d *r)
10673 p->rng_fault_state = true;
10674 return WERR_NOT_SUPPORTED;