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"
54 #include "libsmb/libsmb.h"
56 /* macros stolen from s4 spoolss server */
57 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
58 ((info)?ndr_size_##fn(info, level, 0):0)
60 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
61 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
63 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
64 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
66 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
69 #define DBGC_CLASS DBGC_RPC_SRV
71 #ifndef MAX_OPEN_PRINTER_EXS
72 #define MAX_OPEN_PRINTER_EXS 50
75 struct notify_back_channel;
77 /* structure to store the printer handles */
78 /* and a reference to what it's pointing to */
79 /* and the notify info asked about */
80 /* that's the central struct */
81 struct printer_handle {
82 struct printer_handle *prev, *next;
83 bool document_started;
85 uint32 jobid; /* jobid in printing backend */
87 const char *servername;
90 uint32 access_granted;
96 struct spoolss_NotifyOption *option;
97 struct policy_handle cli_hnd;
98 struct notify_back_channel *cli_chan;
100 /* are we in a FindNextPrinterChangeNotify() call? */
102 struct messaging_context *msg_ctx;
109 /* devmode sent in the OpenPrinter() call */
110 struct spoolss_DeviceMode *devmode;
112 /* TODO cache the printer info2 structure */
113 struct spoolss_PrinterInfo2 *info2;
117 static struct printer_handle *printers_list;
119 struct printer_session_counter {
120 struct printer_session_counter *next;
121 struct printer_session_counter *prev;
127 static struct printer_session_counter *counter_list;
129 struct notify_back_channel {
130 struct notify_back_channel *prev, *next;
132 /* associated client */
133 struct sockaddr_storage client_address;
135 /* print notify back-channel pipe handle*/
136 struct rpc_pipe_client *cli_pipe;
137 struct dcerpc_binding_handle *binding_handle;
138 uint32_t active_connections;
141 static struct notify_back_channel *back_channels;
143 /* Map generic permissions to printer object specific permissions */
145 const struct standard_mapping printer_std_mapping = {
152 /* Map generic permissions to print server object specific permissions */
154 const struct standard_mapping printserver_std_mapping = {
161 /* API table for Xcv Monitor functions */
163 struct xcv_api_table {
165 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
168 static void prune_printername_cache(void);
170 /********************************************************************
171 * Canonicalize servername.
172 ********************************************************************/
174 static const char *canon_servername(const char *servername)
176 const char *pservername = servername;
177 while (*pservername == '\\') {
183 /* translate between internal status numbers and NT status numbers */
184 static int nt_printj_status(int v)
190 return JOB_STATUS_PAUSED;
192 return JOB_STATUS_SPOOLING;
194 return JOB_STATUS_PRINTING;
196 return JOB_STATUS_ERROR;
198 return JOB_STATUS_DELETING;
200 return JOB_STATUS_OFFLINE;
202 return JOB_STATUS_PAPEROUT;
204 return JOB_STATUS_PRINTED;
206 return JOB_STATUS_DELETED;
208 return JOB_STATUS_BLOCKED_DEVQ;
209 case LPQ_USER_INTERVENTION:
210 return JOB_STATUS_USER_INTERVENTION;
215 static int nt_printq_status(int v)
219 return PRINTER_STATUS_PAUSED;
228 /***************************************************************************
229 Disconnect from the client
230 ****************************************************************************/
232 static void srv_spoolss_replycloseprinter(int snum,
233 struct printer_handle *prn_hnd)
239 * Tell the specific printing tdb we no longer want messages for this printer
240 * by deregistering our PID.
243 if (!print_notify_deregister_pid(snum)) {
244 DEBUG(0, ("Failed to register our pid for printer %s\n",
245 lp_const_servicename(snum)));
248 /* weird if the test succeeds !!! */
249 if (prn_hnd->notify.cli_chan == NULL ||
250 prn_hnd->notify.cli_chan->active_connections == 0) {
251 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
252 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
253 TALLOC_FREE(prn_hnd->notify.cli_chan);
257 status = dcerpc_spoolss_ReplyClosePrinter(
258 prn_hnd->notify.cli_chan->binding_handle,
260 &prn_hnd->notify.cli_hnd,
262 if (!NT_STATUS_IS_OK(status)) {
263 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
265 result = ntstatus_to_werror(status);
266 } else if (!W_ERROR_IS_OK(result)) {
267 DEBUG(0, ("reply_close_printer failed [%s].\n",
268 win_errstr(result)));
271 /* if it's the last connection, deconnect the IPC$ share */
272 if (prn_hnd->notify.cli_chan->active_connections == 1) {
274 prn_hnd->notify.cli_chan->binding_handle = NULL;
275 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
276 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
277 TALLOC_FREE(prn_hnd->notify.cli_chan);
279 if (prn_hnd->notify.msg_ctx != NULL) {
280 messaging_deregister(prn_hnd->notify.msg_ctx,
281 MSG_PRINTER_NOTIFY2, NULL);
284 * Tell the serverid.tdb we're no longer
285 * interested in printer notify messages.
288 serverid_register_msg_flags(
289 messaging_server_id(prn_hnd->notify.msg_ctx),
290 false, FLAG_MSG_PRINT_NOTIFY);
294 if (prn_hnd->notify.cli_chan) {
295 prn_hnd->notify.cli_chan->active_connections--;
299 /****************************************************************************
300 Functions to free a printer entry datastruct.
301 ****************************************************************************/
303 static int printer_entry_destructor(struct printer_handle *Printer)
305 if (Printer->notify.cli_chan != NULL &&
306 Printer->notify.cli_chan->active_connections > 0) {
309 switch(Printer->printer_type) {
311 srv_spoolss_replycloseprinter(snum, Printer);
315 snum = print_queue_snum(Printer->sharename);
317 srv_spoolss_replycloseprinter(snum, Printer);
325 Printer->notify.flags=0;
326 Printer->notify.options=0;
327 Printer->notify.localmachine[0]='\0';
328 Printer->notify.printerlocal=0;
329 TALLOC_FREE(Printer->notify.option);
330 TALLOC_FREE(Printer->devmode);
332 /* Remove from the internal list. */
333 DLIST_REMOVE(printers_list, Printer);
337 /****************************************************************************
338 find printer index by handle
339 ****************************************************************************/
341 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
342 struct policy_handle *hnd)
344 struct printer_handle *find_printer = NULL;
346 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
347 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
354 /****************************************************************************
355 Close printer index by handle.
356 ****************************************************************************/
358 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
360 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
363 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
368 close_policy_hnd(p, hnd);
373 /****************************************************************************
374 Delete a printer given a handle.
375 ****************************************************************************/
377 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
378 const char *sharename,
379 struct messaging_context *msg_ctx)
381 char *cmd = lp_deleteprinter_cmd();
382 char *command = NULL;
384 bool is_print_op = false;
386 /* can't fail if we don't try */
391 command = talloc_asprintf(ctx,
398 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
400 DEBUG(10,("Running [%s]\n", command));
402 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
407 if ( (ret = smbrun(command, NULL)) == 0 ) {
408 /* Tell everyone we updated smb.conf. */
409 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
415 /********** END SePrintOperatorPrivlege BLOCK **********/
417 DEBUGADD(10,("returned [%d]\n", ret));
419 TALLOC_FREE(command);
422 return WERR_BADFID; /* What to return here? */
424 /* go ahead and re-read the services immediately */
426 reload_services(msg_ctx, -1, false);
429 if ( lp_servicenumber( sharename ) >= 0 )
430 return WERR_ACCESS_DENIED;
435 /****************************************************************************
436 Delete a printer given a handle.
437 ****************************************************************************/
439 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
441 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
445 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
451 * It turns out that Windows allows delete printer on a handle
452 * opened by an admin user, then used on a pipe handle created
453 * by an anonymous user..... but they're working on security.... riiight !
457 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
458 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
459 return WERR_ACCESS_DENIED;
462 /* this does not need a become root since the access check has been
463 done on the handle already */
465 result = winreg_delete_printer_key(p->mem_ctx,
466 get_session_info_system(),
470 if (!W_ERROR_IS_OK(result)) {
471 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
475 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
476 Printer->sharename, p->msg_ctx);
477 if (!W_ERROR_IS_OK(result)) {
480 prune_printername_cache();
484 /****************************************************************************
485 Return the snum of a printer corresponding to an handle.
486 ****************************************************************************/
488 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
489 int *number, struct share_params **params)
491 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
494 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
499 switch (Printer->printer_type) {
501 DEBUG(4,("short name:%s\n", Printer->sharename));
502 *number = print_queue_snum(Printer->sharename);
503 return (*number != -1);
511 /****************************************************************************
512 Set printer handle type.
513 Check if it's \\server or \\server\printer
514 ****************************************************************************/
516 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
518 DEBUG(3,("Setting printer type=%s\n", handlename));
520 /* it's a print server */
521 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
522 DEBUGADD(4,("Printer is a print server\n"));
523 Printer->printer_type = SPLHND_SERVER;
525 /* it's a printer (set_printer_hnd_name() will handle port monitors */
527 DEBUGADD(4,("Printer is a printer\n"));
528 Printer->printer_type = SPLHND_PRINTER;
534 static void prune_printername_cache_fn(const char *key, const char *value,
535 time_t timeout, void *private_data)
540 static void prune_printername_cache(void)
542 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
545 /****************************************************************************
546 Set printer handle name.. Accept names like \\server, \\server\printer,
547 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
548 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
549 XcvDataPort() interface.
550 ****************************************************************************/
552 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
553 const struct auth_serversupplied_info *session_info,
554 struct messaging_context *msg_ctx,
555 struct printer_handle *Printer,
556 const char *handlename)
559 int n_services=lp_numservices();
561 const char *printername;
562 const char *servername = NULL;
565 struct spoolss_PrinterInfo2 *info2 = NULL;
570 * Hopefully nobody names his printers like this. Maybe \ or ,
571 * are illegal in printer names even?
573 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
577 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
578 (unsigned long)strlen(handlename)));
580 aprinter = discard_const_p(char, handlename);
581 if ( *handlename == '\\' ) {
582 servername = canon_servername(handlename);
583 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
587 if (!is_myname_or_ipaddr(servername)) {
588 return WERR_INVALID_PRINTER_NAME;
590 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
591 if (Printer->servername == NULL) {
596 if (Printer->printer_type == SPLHND_SERVER) {
600 if (Printer->printer_type != SPLHND_PRINTER) {
601 return WERR_INVALID_HANDLE;
604 DEBUGADD(5, ("searching for [%s]\n", aprinter));
606 p = strchr(aprinter, ',');
613 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
615 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
621 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
624 /* check for the Port Monitor Interface */
625 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
626 Printer->printer_type = SPLHND_PORTMON_TCP;
627 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
630 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
631 Printer->printer_type = SPLHND_PORTMON_LOCAL;
632 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
637 * With hundreds of printers, the "for" loop iterating all
638 * shares can be quite expensive, as it is done on every
639 * OpenPrinter. The loop maps "aprinter" to "sname", the
640 * result of which we cache in gencache.
643 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
645 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
647 found = (strcmp(tmp, printer_not_found) != 0);
649 DEBUG(4, ("Printer %s not found\n", aprinter));
651 return WERR_INVALID_PRINTER_NAME;
657 /* Search all sharenames first as this is easier than pulling
658 the printer_info_2 off of disk. Don't use find_service() since
659 that calls out to map_username() */
661 /* do another loop to look for printernames */
662 for (snum = 0; !found && snum < n_services; snum++) {
663 const char *printer = lp_const_servicename(snum);
665 /* no point going on if this is not a printer */
666 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
670 /* ignore [printers] share */
671 if (strequal(printer, "printers")) {
675 fstrcpy(sname, printer);
676 if (strequal(aprinter, printer)) {
681 /* no point looking up the printer object if
682 we aren't allowing printername != sharename */
683 if (lp_force_printername(snum)) {
687 result = winreg_get_printer(mem_ctx,
692 if ( !W_ERROR_IS_OK(result) ) {
693 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
694 sname, win_errstr(result)));
698 printername = strrchr(info2->printername, '\\');
699 if (printername == NULL) {
700 printername = info2->printername;
705 if (strequal(printername, aprinter)) {
710 DEBUGADD(10, ("printername: %s\n", printername));
716 if (cache_key != NULL) {
717 gencache_set(cache_key, printer_not_found,
719 TALLOC_FREE(cache_key);
721 DEBUGADD(4,("Printer not found\n"));
722 return WERR_INVALID_PRINTER_NAME;
725 if (cache_key != NULL) {
726 gencache_set(cache_key, sname, time(NULL)+300);
727 TALLOC_FREE(cache_key);
730 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
732 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
737 /****************************************************************************
738 Find first available printer slot. creates a printer handle for you.
739 ****************************************************************************/
741 static WERROR open_printer_hnd(struct pipes_struct *p,
742 struct policy_handle *hnd,
744 uint32_t access_granted)
746 struct printer_handle *new_printer;
749 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
751 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
752 if (new_printer == NULL) {
755 talloc_set_destructor(new_printer, printer_entry_destructor);
757 /* This also steals the printer_handle on the policy_handle */
758 if (!create_policy_hnd(p, hnd, new_printer)) {
759 TALLOC_FREE(new_printer);
760 return WERR_INVALID_HANDLE;
763 /* Add to the internal list. */
764 DLIST_ADD(printers_list, new_printer);
766 new_printer->notify.option=NULL;
768 if (!set_printer_hnd_printertype(new_printer, name)) {
769 close_printer_handle(p, hnd);
770 return WERR_INVALID_HANDLE;
773 result = set_printer_hnd_name(p->mem_ctx,
774 get_session_info_system(),
777 if (!W_ERROR_IS_OK(result)) {
778 close_printer_handle(p, hnd);
782 new_printer->access_granted = access_granted;
784 DEBUG(5, ("%d printer handles active\n",
785 (int)num_pipe_handles(p)));
790 /***************************************************************************
791 check to see if the client motify handle is monitoring the notification
792 given by (notify_type, notify_field).
793 **************************************************************************/
795 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
796 uint16_t notify_field)
801 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
802 uint16_t notify_field)
804 struct spoolss_NotifyOption *option = p->notify.option;
808 * Flags should always be zero when the change notify
809 * is registered by the client's spooler. A user Win32 app
810 * might use the flags though instead of the NOTIFY_OPTION_INFO
819 return is_monitoring_event_flags(
820 p->notify.flags, notify_type, notify_field);
822 for (i = 0; i < option->count; i++) {
824 /* Check match for notify_type */
826 if (option->types[i].type != notify_type)
829 /* Check match for field */
831 for (j = 0; j < option->types[i].count; j++) {
832 if (option->types[i].fields[j].field == notify_field) {
838 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
839 p->servername, p->sharename, notify_type, notify_field));
844 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
845 _data->data.integer[0] = _integer; \
846 _data->data.integer[1] = 0;
849 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
850 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
851 if (!_data->data.string.string) {\
852 _data->data.string.size = 0; \
854 _data->data.string.size = strlen_m_term(_p) * 2;
856 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
857 _data->data.devmode.devmode = _devmode;
859 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
860 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
861 if (!_data->data.sd.sd) { \
862 _data->data.sd.sd_size = 0; \
864 _data->data.sd.sd_size = \
865 ndr_size_security_descriptor(_data->data.sd.sd, 0);
867 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
872 struct spoolss_Time st;
876 if (!init_systemtime(&st, t)) {
880 p = talloc_array(mem_ctx, char, len);
886 * Systemtime must be linearized as a set of UINT16's.
887 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
890 SSVAL(p, 0, st.year);
891 SSVAL(p, 2, st.month);
892 SSVAL(p, 4, st.day_of_week);
894 SSVAL(p, 8, st.hour);
895 SSVAL(p, 10, st.minute);
896 SSVAL(p, 12, st.second);
897 SSVAL(p, 14, st.millisecond);
903 /* Convert a notification message to a struct spoolss_Notify */
905 static void notify_one_value(struct spoolss_notify_msg *msg,
906 struct spoolss_Notify *data,
909 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
912 static void notify_string(struct spoolss_notify_msg *msg,
913 struct spoolss_Notify *data,
916 /* The length of the message includes the trailing \0 */
918 data->data.string.size = msg->len * 2;
919 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
920 if (!data->data.string.string) {
921 data->data.string.size = 0;
926 static void notify_system_time(struct spoolss_notify_msg *msg,
927 struct spoolss_Notify *data,
930 data->data.string.string = NULL;
931 data->data.string.size = 0;
933 if (msg->len != sizeof(time_t)) {
934 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
939 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
940 &data->data.string.string,
941 &data->data.string.size);
944 struct notify2_message_table {
946 void (*fn)(struct spoolss_notify_msg *msg,
947 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
950 static struct notify2_message_table printer_notify_table[] = {
951 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
952 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
953 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
954 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
955 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
956 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
957 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
958 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
959 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
960 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
961 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
962 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
963 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
964 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
965 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
966 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
967 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
968 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
969 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
972 static struct notify2_message_table job_notify_table[] = {
973 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
974 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
975 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
976 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
977 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
978 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
979 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
980 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
981 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
982 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
983 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
984 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
985 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
986 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
987 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
988 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
989 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
990 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
991 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
992 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
993 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
994 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
995 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
996 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1000 /***********************************************************************
1001 Allocate talloc context for container object
1002 **********************************************************************/
1004 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1014 /***********************************************************************
1015 release all allocated memory and zero out structure
1016 **********************************************************************/
1018 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1024 talloc_destroy(ctr->ctx);
1031 /***********************************************************************
1032 **********************************************************************/
1034 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1042 /***********************************************************************
1043 **********************************************************************/
1045 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1047 if ( !ctr || !ctr->msg_groups )
1050 if ( idx >= ctr->num_groups )
1053 return &ctr->msg_groups[idx];
1057 /***********************************************************************
1058 How many groups of change messages do we have ?
1059 **********************************************************************/
1061 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1066 return ctr->num_groups;
1069 /***********************************************************************
1070 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1071 **********************************************************************/
1073 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1075 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1076 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1077 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1083 /* loop over all groups looking for a matching printer name */
1085 for ( i=0; i<ctr->num_groups; i++ ) {
1086 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1090 /* add a new group? */
1092 if ( i == ctr->num_groups ) {
1095 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1096 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1099 ctr->msg_groups = groups;
1101 /* clear the new entry and set the printer name */
1103 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1104 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1107 /* add the change messages; 'i' is the correct index now regardless */
1109 msg_grp = &ctr->msg_groups[i];
1111 msg_grp->num_msgs++;
1113 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1114 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1117 msg_grp->msgs = msg_list;
1119 new_slot = msg_grp->num_msgs-1;
1120 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1122 /* need to allocate own copy of data */
1124 if ( msg->len != 0 )
1125 msg_grp->msgs[new_slot].notify.data = (char *)
1126 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1128 return ctr->num_groups;
1131 static void construct_info_data(struct spoolss_Notify *info_data,
1132 enum spoolss_NotifyType type,
1133 uint16_t field, int id);
1135 /***********************************************************************
1136 Send a change notication message on all handles which have a call
1138 **********************************************************************/
1140 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1141 struct printer_handle *prn_hnd,
1142 SPOOLSS_NOTIFY_MSG *messages,
1144 struct spoolss_Notify **_notifies,
1147 struct spoolss_Notify *notifies;
1148 SPOOLSS_NOTIFY_MSG *msg;
1153 notifies = talloc_zero_array(mem_ctx,
1154 struct spoolss_Notify, num_msgs);
1159 for (i = 0; i < num_msgs; i++) {
1163 /* Are we monitoring this event? */
1165 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1169 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1170 "for printer [%s]\n",
1171 msg->type, msg->field, prn_hnd->sharename));
1174 * if the is a printer notification handle and not a job
1175 * notification type, then set the id to 0.
1176 * Otherwise just use what was specified in the message.
1178 * When registering change notification on a print server
1179 * handle we always need to send back the id (snum) matching
1180 * the printer for which the change took place.
1181 * For change notify registered on a printer handle,
1182 * this does not matter and the id should be 0.
1187 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1188 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1194 /* Convert unix jobid to smb jobid */
1196 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1197 id = sysjob_to_jobid(msg->id);
1200 DEBUG(3, ("no such unix jobid %d\n",
1206 construct_info_data(¬ifies[count],
1207 msg->type, msg->field, id);
1210 case PRINTER_NOTIFY_TYPE:
1211 if (printer_notify_table[msg->field].fn) {
1212 printer_notify_table[msg->field].fn(msg,
1213 ¬ifies[count], mem_ctx);
1217 case JOB_NOTIFY_TYPE:
1218 if (job_notify_table[msg->field].fn) {
1219 job_notify_table[msg->field].fn(msg,
1220 ¬ifies[count], mem_ctx);
1225 DEBUG(5, ("Unknown notification type %d\n",
1233 *_notifies = notifies;
1239 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1240 struct printer_handle *prn_hnd,
1241 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1243 struct spoolss_Notify *notifies;
1245 union spoolss_ReplyPrinterInfo info;
1246 struct spoolss_NotifyInfo info0;
1247 uint32_t reply_result;
1252 /* Is there notification on this handle? */
1253 if (prn_hnd->notify.cli_chan == NULL ||
1254 prn_hnd->notify.cli_chan->active_connections == 0) {
1258 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1259 prn_hnd->servername, prn_hnd->sharename));
1261 /* For this printer? Print servers always receive notifications. */
1262 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1263 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1267 DEBUG(10,("Our printer\n"));
1269 /* build the array of change notifications */
1270 ret = build_notify2_messages(mem_ctx, prn_hnd,
1272 msg_group->num_msgs,
1278 info0.version = 0x2;
1279 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1280 info0.count = count;
1281 info0.notifies = notifies;
1283 info.info0 = &info0;
1285 status = dcerpc_spoolss_RouterReplyPrinterEx(
1286 prn_hnd->notify.cli_chan->binding_handle,
1288 &prn_hnd->notify.cli_hnd,
1289 prn_hnd->notify.change, /* color */
1290 prn_hnd->notify.flags,
1292 0, /* reply_type, must be 0 */
1294 if (!NT_STATUS_IS_OK(status)) {
1295 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1297 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1298 nt_errstr(status)));
1299 werr = ntstatus_to_werror(status);
1300 } else if (!W_ERROR_IS_OK(werr)) {
1301 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1303 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1306 switch (reply_result) {
1309 case PRINTER_NOTIFY_INFO_DISCARDED:
1310 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1311 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1320 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1322 struct printer_handle *p;
1323 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1324 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1328 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1332 if (!msg_group->msgs) {
1333 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1337 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1339 /* loop over all printers */
1341 for (p = printers_list; p; p = p->next) {
1342 ret = send_notify2_printer(mem_ctx, p, msg_group);
1349 DEBUG(8,("send_notify2_changes: Exit...\n"));
1353 /***********************************************************************
1354 **********************************************************************/
1356 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1359 uint32_t tv_sec, tv_usec;
1362 /* Unpack message */
1364 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1367 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1369 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1372 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1373 &msg->notify.value[0], &msg->notify.value[1]);
1375 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1376 &msg->len, &msg->notify.data);
1378 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1379 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1381 tv->tv_sec = tv_sec;
1382 tv->tv_usec = tv_usec;
1385 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1386 msg->notify.value[1]));
1388 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1393 /********************************************************************
1394 Receive a notify2 message list
1395 ********************************************************************/
1397 static void receive_notify2_message_list(struct messaging_context *msg,
1400 struct server_id server_id,
1403 size_t msg_count, i;
1404 char *buf = (char *)data->data;
1407 SPOOLSS_NOTIFY_MSG notify;
1408 SPOOLSS_NOTIFY_MSG_CTR messages;
1411 if (data->length < 4) {
1412 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1416 msg_count = IVAL(buf, 0);
1419 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1421 if (msg_count == 0) {
1422 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1426 /* initialize the container */
1428 ZERO_STRUCT( messages );
1429 notify_msg_ctr_init( &messages );
1432 * build message groups for each printer identified
1433 * in a change_notify msg. Remember that a PCN message
1434 * includes the handle returned for the srv_spoolss_replyopenprinter()
1435 * call. Therefore messages are grouped according to printer handle.
1438 for ( i=0; i<msg_count; i++ ) {
1439 struct timeval msg_tv;
1441 if (msg_ptr + 4 - buf > data->length) {
1442 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1446 msg_len = IVAL(msg_ptr,0);
1449 if (msg_ptr + msg_len - buf > data->length) {
1450 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1454 /* unpack messages */
1456 ZERO_STRUCT( notify );
1457 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1460 /* add to correct list in container */
1462 notify_msg_ctr_addmsg( &messages, ¬ify );
1464 /* free memory that might have been allocated by notify2_unpack_msg() */
1466 if ( notify.len != 0 )
1467 SAFE_FREE( notify.notify.data );
1470 /* process each group of messages */
1472 num_groups = notify_msg_ctr_numgroups( &messages );
1473 for ( i=0; i<num_groups; i++ )
1474 send_notify2_changes( &messages, i );
1479 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1480 (uint32_t)msg_count ));
1482 notify_msg_ctr_destroy( &messages );
1487 /********************************************************************
1488 Send a message to ourself about new driver being installed
1489 so we can upgrade the information for each printer bound to this
1491 ********************************************************************/
1493 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1494 struct messaging_context *msg_ctx)
1496 int len = strlen(drivername);
1501 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1504 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1505 MSG_PRINTER_DRVUPGRADE,
1506 (const uint8_t *)drivername, len+1);
1511 void srv_spoolss_cleanup(void)
1513 struct printer_session_counter *session_counter;
1515 for (session_counter = counter_list;
1516 session_counter != NULL;
1517 session_counter = counter_list) {
1518 DLIST_REMOVE(counter_list, session_counter);
1519 TALLOC_FREE(session_counter);
1523 /**********************************************************************
1524 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1525 over all printers, upgrading ones as necessary
1526 **********************************************************************/
1528 void do_drv_upgrade_printer(struct messaging_context *msg,
1531 struct server_id server_id,
1534 TALLOC_CTX *tmp_ctx;
1535 struct auth_serversupplied_info *session_info = NULL;
1536 struct spoolss_PrinterInfo2 *pinfo2;
1539 const char *drivername;
1541 int n_services = lp_numservices();
1543 tmp_ctx = talloc_new(NULL);
1544 if (!tmp_ctx) return;
1546 status = make_session_info_system(tmp_ctx, &session_info);
1547 if (!NT_STATUS_IS_OK(status)) {
1548 DEBUG(0, ("do_drv_upgrade_printer: "
1549 "Could not create system session_info\n"));
1553 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1555 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1559 DEBUG(10, ("do_drv_upgrade_printer: "
1560 "Got message for new driver [%s]\n", drivername));
1562 /* Iterate the printer list */
1564 for (snum = 0; snum < n_services; snum++) {
1565 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1569 /* ignore [printers] share */
1570 if (strequal(lp_const_servicename(snum), "printers")) {
1574 result = winreg_get_printer(tmp_ctx, session_info, msg,
1575 lp_const_servicename(snum),
1578 if (!W_ERROR_IS_OK(result)) {
1582 if (!pinfo2->drivername) {
1586 if (strcmp(drivername, pinfo2->drivername) != 0) {
1590 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1592 /* all we care about currently is the change_id */
1593 result = winreg_printer_update_changeid(tmp_ctx,
1596 pinfo2->printername);
1598 if (!W_ERROR_IS_OK(result)) {
1599 DEBUG(3, ("do_drv_upgrade_printer: "
1600 "Failed to update changeid [%s]\n",
1601 win_errstr(result)));
1607 talloc_free(tmp_ctx);
1610 /********************************************************************
1611 Update the cache for all printq's with a registered client
1613 ********************************************************************/
1615 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1617 struct printer_handle *printer = printers_list;
1620 /* loop through all printers and update the cache where
1621 a client is connected */
1623 if ((printer->printer_type == SPLHND_PRINTER) &&
1624 ((printer->notify.cli_chan != NULL) &&
1625 (printer->notify.cli_chan->active_connections > 0))) {
1626 snum = print_queue_snum(printer->sharename);
1627 print_queue_status(msg_ctx, snum, NULL, NULL);
1630 printer = printer->next;
1636 /****************************************************************
1637 _spoolss_OpenPrinter
1638 ****************************************************************/
1640 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1641 struct spoolss_OpenPrinter *r)
1643 struct spoolss_OpenPrinterEx e;
1646 ZERO_STRUCT(e.in.userlevel);
1648 e.in.printername = r->in.printername;
1649 e.in.datatype = r->in.datatype;
1650 e.in.devmode_ctr = r->in.devmode_ctr;
1651 e.in.access_mask = r->in.access_mask;
1654 e.out.handle = r->out.handle;
1656 werr = _spoolss_OpenPrinterEx(p, &e);
1658 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1659 /* OpenPrinterEx returns this for a bad
1660 * printer name. We must return WERR_INVALID_PRINTER_NAME
1663 werr = WERR_INVALID_PRINTER_NAME;
1669 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1670 struct spoolss_DeviceMode *orig,
1671 struct spoolss_DeviceMode **dest)
1673 struct spoolss_DeviceMode *dm;
1675 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1680 /* copy all values, then duplicate strings and structs */
1683 dm->devicename = talloc_strdup(dm, orig->devicename);
1684 if (!dm->devicename) {
1687 dm->formname = talloc_strdup(dm, orig->formname);
1688 if (!dm->formname) {
1691 if (orig->driverextra_data.data) {
1692 dm->driverextra_data.data =
1693 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1694 orig->driverextra_data.length);
1695 if (!dm->driverextra_data.data) {
1704 /****************************************************************
1705 _spoolss_OpenPrinterEx
1706 ****************************************************************/
1708 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1709 struct spoolss_OpenPrinterEx *r)
1712 struct printer_handle *Printer=NULL;
1715 if (!r->in.printername) {
1716 return WERR_INVALID_PARAM;
1719 if (r->in.level > 3) {
1720 return WERR_INVALID_PARAM;
1722 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1723 (r->in.level == 2 && !r->in.userlevel.level2) ||
1724 (r->in.level == 3 && !r->in.userlevel.level3)) {
1725 return WERR_INVALID_PARAM;
1728 /* some sanity check because you can open a printer or a print server */
1729 /* aka: \\server\printer or \\server */
1731 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1733 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1734 if (!W_ERROR_IS_OK(result)) {
1735 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1736 "for printer %s\n", r->in.printername));
1737 ZERO_STRUCTP(r->out.handle);
1741 Printer = find_printer_index_by_hnd(p, r->out.handle);
1743 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1744 "handle we created for printer %s\n", r->in.printername));
1745 close_printer_handle(p, r->out.handle);
1746 ZERO_STRUCTP(r->out.handle);
1747 return WERR_INVALID_PARAM;
1751 * First case: the user is opening the print server:
1753 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1754 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1756 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1757 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1758 * or if the user is listed in the smb.conf printer admin parameter.
1760 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1761 * client view printer folder, but does not show the MSAPW.
1763 * Note: this test needs code to check access rights here too. Jeremy
1764 * could you look at this?
1766 * Second case: the user is opening a printer:
1767 * NT doesn't let us connect to a printer if the connecting user
1768 * doesn't have print permission.
1770 * Third case: user is opening a Port Monitor
1771 * access checks same as opening a handle to the print server.
1774 switch (Printer->printer_type )
1777 case SPLHND_PORTMON_TCP:
1778 case SPLHND_PORTMON_LOCAL:
1779 /* Printserver handles use global struct... */
1783 /* Map standard access rights to object specific access rights */
1785 se_map_standard(&r->in.access_mask,
1786 &printserver_std_mapping);
1788 /* Deny any object specific bits that don't apply to print
1789 servers (i.e printer and job specific bits) */
1791 r->in.access_mask &= SEC_MASK_SPECIFIC;
1793 if (r->in.access_mask &
1794 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1795 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1796 close_printer_handle(p, r->out.handle);
1797 ZERO_STRUCTP(r->out.handle);
1798 return WERR_ACCESS_DENIED;
1801 /* Allow admin access */
1803 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1805 if (!lp_ms_add_printer_wizard()) {
1806 close_printer_handle(p, r->out.handle);
1807 ZERO_STRUCTP(r->out.handle);
1808 return WERR_ACCESS_DENIED;
1811 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1812 and not a printer admin, then fail */
1814 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1815 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1816 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1817 !token_contains_name_in_list(
1818 uidtoname(p->session_info->utok.uid),
1819 p->session_info->info3->base.domain.string,
1821 p->session_info->security_token,
1822 lp_printer_admin(snum))) {
1823 close_printer_handle(p, r->out.handle);
1824 ZERO_STRUCTP(r->out.handle);
1825 DEBUG(3,("access DENIED as user is not root, "
1826 "has no printoperator privilege, "
1827 "not a member of the printoperator builtin group and "
1828 "is not in printer admin list"));
1829 return WERR_ACCESS_DENIED;
1832 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1836 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1839 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1840 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1842 /* We fall through to return WERR_OK */
1845 case SPLHND_PRINTER:
1846 /* NT doesn't let us connect to a printer if the connecting user
1847 doesn't have print permission. */
1849 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1850 close_printer_handle(p, r->out.handle);
1851 ZERO_STRUCTP(r->out.handle);
1855 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1856 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1859 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1861 /* map an empty access mask to the minimum access mask */
1862 if (r->in.access_mask == 0x0)
1863 r->in.access_mask = PRINTER_ACCESS_USE;
1866 * If we are not serving the printer driver for this printer,
1867 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1868 * will keep NT clients happy --jerry
1871 if (lp_use_client_driver(snum)
1872 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1874 r->in.access_mask = PRINTER_ACCESS_USE;
1877 /* check smb.conf parameters and the the sec_desc */
1879 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1880 p->client_id->name, p->client_id->addr)) {
1881 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1882 ZERO_STRUCTP(r->out.handle);
1883 return WERR_ACCESS_DENIED;
1886 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1887 p->session_info->security_token, snum) ||
1888 !print_access_check(p->session_info,
1891 r->in.access_mask)) {
1892 DEBUG(3, ("access DENIED for printer open\n"));
1893 close_printer_handle(p, r->out.handle);
1894 ZERO_STRUCTP(r->out.handle);
1895 return WERR_ACCESS_DENIED;
1898 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1899 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1900 close_printer_handle(p, r->out.handle);
1901 ZERO_STRUCTP(r->out.handle);
1902 return WERR_ACCESS_DENIED;
1905 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1906 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1908 r->in.access_mask = PRINTER_ACCESS_USE;
1910 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1911 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1913 winreg_create_printer(p->mem_ctx,
1914 get_session_info_system(),
1916 lp_const_servicename(snum));
1921 /* sanity check to prevent programmer error */
1922 ZERO_STRUCTP(r->out.handle);
1926 Printer->access_granted = r->in.access_mask;
1929 * If the client sent a devmode in the OpenPrinter() call, then
1930 * save it here in case we get a job submission on this handle
1933 if ((Printer->printer_type != SPLHND_SERVER) &&
1934 r->in.devmode_ctr.devmode) {
1935 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1939 #if 0 /* JERRY -- I'm doubtful this is really effective */
1940 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1941 optimization in Windows 2000 clients --jerry */
1943 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1944 && (RA_WIN2K == get_remote_arch()) )
1946 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1947 sys_usleep( 500000 );
1954 /****************************************************************
1955 _spoolss_ClosePrinter
1956 ****************************************************************/
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959 struct spoolss_ClosePrinter *r)
1961 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1963 if (Printer && Printer->document_started) {
1964 struct spoolss_EndDocPrinter e;
1966 e.in.handle = r->in.handle;
1968 _spoolss_EndDocPrinter(p, &e);
1971 if (!close_printer_handle(p, r->in.handle))
1974 /* clear the returned printer handle. Observed behavior
1975 from Win2k server. Don't think this really matters.
1976 Previous code just copied the value of the closed
1979 ZERO_STRUCTP(r->out.handle);
1984 /****************************************************************
1985 _spoolss_DeletePrinter
1986 ****************************************************************/
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989 struct spoolss_DeletePrinter *r)
1991 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1995 if (Printer && Printer->document_started) {
1996 struct spoolss_EndDocPrinter e;
1998 e.in.handle = r->in.handle;
2000 _spoolss_EndDocPrinter(p, &e);
2003 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004 winreg_delete_printer_key(p->mem_ctx,
2005 get_session_info_system(),
2007 lp_const_servicename(snum),
2011 result = delete_printer_handle(p, r->in.handle);
2016 /*******************************************************************
2017 * static function to lookup the version id corresponding to an
2018 * long architecture string
2019 ******************************************************************/
2021 static const struct print_architecture_table_node archi_table[]= {
2023 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2024 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2025 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2026 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2027 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2028 {"Windows IA64", SPL_ARCH_IA64, 3 },
2029 {"Windows x64", SPL_ARCH_X64, 3 },
2033 static int get_version_id(const char *arch)
2037 for (i=0; archi_table[i].long_archi != NULL; i++)
2039 if (strcmp(arch, archi_table[i].long_archi) == 0)
2040 return (archi_table[i].version);
2046 /****************************************************************
2047 _spoolss_DeletePrinterDriver
2048 ****************************************************************/
2050 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2051 struct spoolss_DeletePrinterDriver *r)
2054 struct spoolss_DriverInfo8 *info = NULL;
2055 struct spoolss_DriverInfo8 *info_win2k = NULL;
2059 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060 and not a printer admin, then fail */
2062 if ( (p->session_info->utok.uid != sec_initial_uid())
2063 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2064 && !token_contains_name_in_list(
2065 uidtoname(p->session_info->utok.uid),
2066 p->session_info->info3->base.domain.string,
2068 p->session_info->security_token,
2069 lp_printer_admin(-1)) )
2071 return WERR_ACCESS_DENIED;
2074 /* check that we have a valid driver name first */
2076 if ((version = get_version_id(r->in.architecture)) == -1)
2077 return WERR_INVALID_ENVIRONMENT;
2079 status = winreg_get_driver(p->mem_ctx,
2080 get_session_info_system(),
2082 r->in.architecture, r->in.driver,
2084 if (!W_ERROR_IS_OK(status)) {
2085 /* try for Win2k driver if "Windows NT x86" */
2087 if ( version == 2 ) {
2090 status = winreg_get_driver(p->mem_ctx,
2091 get_session_info_system(),
2096 if (!W_ERROR_IS_OK(status)) {
2097 status = WERR_UNKNOWN_PRINTER_DRIVER;
2101 /* otherwise it was a failure */
2103 status = WERR_UNKNOWN_PRINTER_DRIVER;
2109 if (printer_driver_in_use(p->mem_ctx,
2110 get_session_info_system(),
2113 status = WERR_PRINTER_DRIVER_IN_USE;
2118 status = winreg_get_driver(p->mem_ctx,
2119 get_session_info_system(),
2122 r->in.driver, 3, &info_win2k);
2123 if (W_ERROR_IS_OK(status)) {
2124 /* if we get to here, we now have 2 driver info structures to remove */
2125 /* remove the Win2k driver first*/
2127 status = winreg_del_driver(p->mem_ctx,
2128 get_session_info_system(),
2131 talloc_free(info_win2k);
2133 /* this should not have failed---if it did, report to client */
2134 if (!W_ERROR_IS_OK(status)) {
2140 status = winreg_del_driver(p->mem_ctx,
2141 get_session_info_system(),
2151 /****************************************************************
2152 _spoolss_DeletePrinterDriverEx
2153 ****************************************************************/
2155 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2156 struct spoolss_DeletePrinterDriverEx *r)
2158 struct spoolss_DriverInfo8 *info = NULL;
2159 struct spoolss_DriverInfo8 *info_win2k = NULL;
2164 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2165 and not a printer admin, then fail */
2167 if ( (p->session_info->utok.uid != sec_initial_uid())
2168 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2169 && !token_contains_name_in_list(
2170 uidtoname(p->session_info->utok.uid),
2171 p->session_info->info3->base.domain.string,
2173 p->session_info->security_token, lp_printer_admin(-1)) )
2175 return WERR_ACCESS_DENIED;
2178 /* check that we have a valid driver name first */
2179 if ((version = get_version_id(r->in.architecture)) == -1) {
2180 /* this is what NT returns */
2181 return WERR_INVALID_ENVIRONMENT;
2184 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2185 version = r->in.version;
2187 status = winreg_get_driver(p->mem_ctx,
2188 get_session_info_system(),
2194 if (!W_ERROR_IS_OK(status)) {
2195 status = WERR_UNKNOWN_PRINTER_DRIVER;
2198 * if the client asked for a specific version,
2199 * or this is something other than Windows NT x86,
2203 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2206 /* try for Win2k driver if "Windows NT x86" */
2209 status = winreg_get_driver(info,
2210 get_session_info_system(),
2215 if (!W_ERROR_IS_OK(status)) {
2216 status = WERR_UNKNOWN_PRINTER_DRIVER;
2221 if (printer_driver_in_use(info,
2222 get_session_info_system(),
2225 status = WERR_PRINTER_DRIVER_IN_USE;
2230 * we have a couple of cases to consider.
2231 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2232 * then the delete should fail if **any** files overlap with
2234 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2235 * non-overlapping files
2236 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2237 * is set, the do not delete any files
2238 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2241 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2243 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2246 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2247 printer_driver_files_in_use(info,
2248 get_session_info_system(),
2251 /* no idea of the correct error here */
2252 status = WERR_ACCESS_DENIED;
2257 /* also check for W32X86/3 if necessary; maybe we already have? */
2259 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2260 status = winreg_get_driver(info,
2261 get_session_info_system(),
2264 r->in.driver, 3, &info_win2k);
2265 if (W_ERROR_IS_OK(status)) {
2268 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2269 printer_driver_files_in_use(info,
2270 get_session_info_system(),
2273 /* no idea of the correct error here */
2274 talloc_free(info_win2k);
2275 status = WERR_ACCESS_DENIED;
2279 /* if we get to here, we now have 2 driver info structures to remove */
2280 /* remove the Win2k driver first*/
2282 status = winreg_del_driver(info,
2283 get_session_info_system(),
2288 /* this should not have failed---if it did, report to client */
2290 if (!W_ERROR_IS_OK(status)) {
2295 * now delete any associated files if delete_files is
2296 * true. Even if this part failes, we return succes
2297 * because the driver doesn not exist any more
2300 delete_driver_files(get_session_info_system(),
2306 status = winreg_del_driver(info,
2307 get_session_info_system(),
2311 if (!W_ERROR_IS_OK(status)) {
2316 * now delete any associated files if delete_files is
2317 * true. Even if this part failes, we return succes
2318 * because the driver doesn not exist any more
2321 delete_driver_files(get_session_info_system(), info);
2330 /********************************************************************
2331 GetPrinterData on a printer server Handle.
2332 ********************************************************************/
2334 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2336 enum winreg_Type *type,
2337 union spoolss_PrinterData *data)
2339 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2341 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2347 if (!StrCaseCmp(value, "BeepEnabled")) {
2353 if (!StrCaseCmp(value, "EventLog")) {
2355 /* formally was 0x1b */
2360 if (!StrCaseCmp(value, "NetPopup")) {
2366 if (!StrCaseCmp(value, "MajorVersion")) {
2369 /* Windows NT 4.0 seems to not allow uploading of drivers
2370 to a server that reports 0x3 as the MajorVersion.
2371 need to investigate more how Win2k gets around this .
2374 if (RA_WINNT == get_remote_arch()) {
2383 if (!StrCaseCmp(value, "MinorVersion")) {
2390 * uint32_t size = 0x114
2391 * uint32_t major = 5
2392 * uint32_t minor = [0|1]
2393 * uint32_t build = [2195|2600]
2394 * extra unicode string = e.g. "Service Pack 3"
2396 if (!StrCaseCmp(value, "OSVersion")) {
2398 enum ndr_err_code ndr_err;
2399 struct spoolss_OSVersion os;
2401 os.major = 5; /* Windows 2000 == 5.0 */
2403 os.build = 2195; /* build */
2404 os.extra_string = ""; /* leave extra string empty */
2406 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2407 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2408 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2409 return WERR_GENERAL_FAILURE;
2413 data->binary = blob;
2419 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2422 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2423 W_ERROR_HAVE_NO_MEMORY(data->string);
2428 if (!StrCaseCmp(value, "Architecture")) {
2430 data->string = talloc_strdup(mem_ctx,
2431 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2432 W_ERROR_HAVE_NO_MEMORY(data->string);
2437 if (!StrCaseCmp(value, "DsPresent")) {
2440 /* only show the publish check box if we are a
2441 member of a AD domain */
2443 if (lp_security() == SEC_ADS) {
2451 if (!StrCaseCmp(value, "DNSMachineName")) {
2452 const char *hostname = get_mydnsfullname();
2455 return WERR_BADFILE;
2459 data->string = talloc_strdup(mem_ctx, hostname);
2460 W_ERROR_HAVE_NO_MEMORY(data->string);
2467 return WERR_INVALID_PARAM;
2470 /****************************************************************
2471 _spoolss_GetPrinterData
2472 ****************************************************************/
2474 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2475 struct spoolss_GetPrinterData *r)
2477 struct spoolss_GetPrinterDataEx r2;
2479 r2.in.handle = r->in.handle;
2480 r2.in.key_name = "PrinterDriverData";
2481 r2.in.value_name = r->in.value_name;
2482 r2.in.offered = r->in.offered;
2483 r2.out.type = r->out.type;
2484 r2.out.data = r->out.data;
2485 r2.out.needed = r->out.needed;
2487 return _spoolss_GetPrinterDataEx(p, &r2);
2490 /*********************************************************
2491 Connect to the client machine.
2492 **********************************************************/
2494 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2495 struct sockaddr_storage *client_ss, const char *remote_machine)
2498 struct cli_state *the_cli;
2499 struct sockaddr_storage rm_addr;
2500 char addr[INET6_ADDRSTRLEN];
2502 if ( is_zero_addr(client_ss) ) {
2503 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2505 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2506 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2509 print_sockaddr(addr, sizeof(addr), &rm_addr);
2511 rm_addr = *client_ss;
2512 print_sockaddr(addr, sizeof(addr), &rm_addr);
2513 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2517 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2518 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2523 /* setup the connection */
2524 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2525 &rm_addr, 0, "IPC$", "IPC",
2529 0, lp_client_signing());
2531 if ( !NT_STATUS_IS_OK( ret ) ) {
2532 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2537 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2538 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2539 cli_shutdown(the_cli);
2544 * Ok - we have an anonymous connection to the IPC$ share.
2545 * Now start the NT Domain stuff :-).
2548 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2549 if (!NT_STATUS_IS_OK(ret)) {
2550 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2551 remote_machine, nt_errstr(ret)));
2552 cli_shutdown(the_cli);
2559 /***************************************************************************
2560 Connect to the client.
2561 ****************************************************************************/
2563 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2564 uint32_t localprinter,
2565 enum winreg_Type type,
2566 struct policy_handle *handle,
2567 struct notify_back_channel **_chan,
2568 struct sockaddr_storage *client_ss,
2569 struct messaging_context *msg_ctx)
2573 struct notify_back_channel *chan;
2575 for (chan = back_channels; chan; chan = chan->next) {
2576 if (memcmp(&chan->client_address, client_ss,
2577 sizeof(struct sockaddr_storage)) == 0) {
2583 * If it's the first connection, contact the client
2584 * and connect to the IPC$ share anonymously
2587 fstring unix_printer;
2589 /* the +2 is to strip the leading 2 backslashs */
2590 fstrcpy(unix_printer, printer + 2);
2592 chan = talloc_zero(back_channels, struct notify_back_channel);
2596 chan->client_address = *client_ss;
2598 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2602 chan->binding_handle = chan->cli_pipe->binding_handle;
2604 DLIST_ADD(back_channels, chan);
2606 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2607 receive_notify2_message_list);
2608 /* Tell the connections db we're now interested in printer
2609 * notify messages. */
2610 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2611 true, FLAG_MSG_PRINT_NOTIFY);
2615 * Tell the specific printing tdb we want messages for this printer
2616 * by registering our PID.
2619 if (!print_notify_register_pid(snum)) {
2620 DEBUG(0, ("Failed to register our pid for printer %s\n",
2624 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2633 if (!NT_STATUS_IS_OK(status)) {
2634 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2635 result = ntstatus_to_werror(status);
2636 } else if (!W_ERROR_IS_OK(result)) {
2637 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2640 chan->active_connections++;
2643 return (W_ERROR_IS_OK(result));
2646 /****************************************************************
2647 ****************************************************************/
2649 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2650 const struct spoolss_NotifyOption *r)
2652 struct spoolss_NotifyOption *option;
2659 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2666 if (!option->count) {
2670 option->types = talloc_zero_array(option,
2671 struct spoolss_NotifyOptionType, option->count);
2672 if (!option->types) {
2673 talloc_free(option);
2677 for (i=0; i < option->count; i++) {
2678 option->types[i] = r->types[i];
2680 if (option->types[i].count) {
2681 option->types[i].fields = talloc_zero_array(option,
2682 union spoolss_Field, option->types[i].count);
2683 if (!option->types[i].fields) {
2684 talloc_free(option);
2687 for (k=0; k<option->types[i].count; k++) {
2688 option->types[i].fields[k] =
2689 r->types[i].fields[k];
2697 /****************************************************************
2698 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2700 * before replying OK: status=0 a rpc call is made to the workstation
2701 * asking ReplyOpenPrinter
2703 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2704 * called from api_spoolss_rffpcnex
2705 ****************************************************************/
2707 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2708 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2711 struct spoolss_NotifyOption *option = r->in.notify_options;
2712 struct sockaddr_storage client_ss;
2714 /* store the notify value in the printer struct */
2716 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2719 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720 "Invalid handle (%s:%u:%u).\n",
2721 OUR_HANDLE(r->in.handle)));
2725 Printer->notify.flags = r->in.flags;
2726 Printer->notify.options = r->in.options;
2727 Printer->notify.printerlocal = r->in.printer_local;
2728 Printer->notify.msg_ctx = p->msg_ctx;
2730 TALLOC_FREE(Printer->notify.option);
2731 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2733 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2735 /* Connect to the client machine and send a ReplyOpenPrinter */
2737 if ( Printer->printer_type == SPLHND_SERVER)
2739 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2740 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2743 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2744 "client_address is %s\n", p->client_id->addr));
2746 if (!lp_print_notify_backchannel(snum)) {
2747 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2748 "backchannel disabled\n"));
2749 return WERR_SERVER_UNAVAILABLE;
2752 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2754 return WERR_SERVER_UNAVAILABLE;
2757 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2758 Printer->notify.printerlocal, REG_SZ,
2759 &Printer->notify.cli_hnd,
2760 &Printer->notify.cli_chan,
2761 &client_ss, p->msg_ctx)) {
2762 return WERR_SERVER_UNAVAILABLE;
2768 /*******************************************************************
2769 * fill a notify_info_data with the servername
2770 ********************************************************************/
2772 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2774 struct spoolss_Notify *data,
2775 print_queue_struct *queue,
2776 struct spoolss_PrinterInfo2 *pinfo2,
2777 TALLOC_CTX *mem_ctx)
2779 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2782 /*******************************************************************
2783 * fill a notify_info_data with the printername (not including the servername).
2784 ********************************************************************/
2786 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2788 struct spoolss_Notify *data,
2789 print_queue_struct *queue,
2790 struct spoolss_PrinterInfo2 *pinfo2,
2791 TALLOC_CTX *mem_ctx)
2793 /* the notify name should not contain the \\server\ part */
2794 const char *p = strrchr(pinfo2->printername, '\\');
2797 p = pinfo2->printername;
2802 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2805 /*******************************************************************
2806 * fill a notify_info_data with the servicename
2807 ********************************************************************/
2809 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2811 struct spoolss_Notify *data,
2812 print_queue_struct *queue,
2813 struct spoolss_PrinterInfo2 *pinfo2,
2814 TALLOC_CTX *mem_ctx)
2816 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2819 /*******************************************************************
2820 * fill a notify_info_data with the port name
2821 ********************************************************************/
2823 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2825 struct spoolss_Notify *data,
2826 print_queue_struct *queue,
2827 struct spoolss_PrinterInfo2 *pinfo2,
2828 TALLOC_CTX *mem_ctx)
2830 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2833 /*******************************************************************
2834 * fill a notify_info_data with the printername
2835 * but it doesn't exist, have to see what to do
2836 ********************************************************************/
2838 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2840 struct spoolss_Notify *data,
2841 print_queue_struct *queue,
2842 struct spoolss_PrinterInfo2 *pinfo2,
2843 TALLOC_CTX *mem_ctx)
2845 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2848 /*******************************************************************
2849 * fill a notify_info_data with the comment
2850 ********************************************************************/
2852 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2854 struct spoolss_Notify *data,
2855 print_queue_struct *queue,
2856 struct spoolss_PrinterInfo2 *pinfo2,
2857 TALLOC_CTX *mem_ctx)
2861 if (*pinfo2->comment == '\0') {
2862 p = lp_comment(snum);
2864 p = pinfo2->comment;
2867 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2870 /*******************************************************************
2871 * fill a notify_info_data with the comment
2872 * location = "Room 1, floor 2, building 3"
2873 ********************************************************************/
2875 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2877 struct spoolss_Notify *data,
2878 print_queue_struct *queue,
2879 struct spoolss_PrinterInfo2 *pinfo2,
2880 TALLOC_CTX *mem_ctx)
2882 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2885 /*******************************************************************
2886 * fill a notify_info_data with the device mode
2887 * jfm:xxxx don't to it for know but that's a real problem !!!
2888 ********************************************************************/
2890 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2892 struct spoolss_Notify *data,
2893 print_queue_struct *queue,
2894 struct spoolss_PrinterInfo2 *pinfo2,
2895 TALLOC_CTX *mem_ctx)
2897 /* for a dummy implementation we have to zero the fields */
2898 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2901 /*******************************************************************
2902 * fill a notify_info_data with the separator file name
2903 ********************************************************************/
2905 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2907 struct spoolss_Notify *data,
2908 print_queue_struct *queue,
2909 struct spoolss_PrinterInfo2 *pinfo2,
2910 TALLOC_CTX *mem_ctx)
2912 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2915 /*******************************************************************
2916 * fill a notify_info_data with the print processor
2917 * jfm:xxxx return always winprint to indicate we don't do anything to it
2918 ********************************************************************/
2920 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2922 struct spoolss_Notify *data,
2923 print_queue_struct *queue,
2924 struct spoolss_PrinterInfo2 *pinfo2,
2925 TALLOC_CTX *mem_ctx)
2927 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2930 /*******************************************************************
2931 * fill a notify_info_data with the print processor options
2932 * jfm:xxxx send an empty string
2933 ********************************************************************/
2935 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2937 struct spoolss_Notify *data,
2938 print_queue_struct *queue,
2939 struct spoolss_PrinterInfo2 *pinfo2,
2940 TALLOC_CTX *mem_ctx)
2942 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2945 /*******************************************************************
2946 * fill a notify_info_data with the data type
2947 * jfm:xxxx always send RAW as data type
2948 ********************************************************************/
2950 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2952 struct spoolss_Notify *data,
2953 print_queue_struct *queue,
2954 struct spoolss_PrinterInfo2 *pinfo2,
2955 TALLOC_CTX *mem_ctx)
2957 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2960 /*******************************************************************
2961 * fill a notify_info_data with the security descriptor
2962 * jfm:xxxx send an null pointer to say no security desc
2963 * have to implement security before !
2964 ********************************************************************/
2966 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2968 struct spoolss_Notify *data,
2969 print_queue_struct *queue,
2970 struct spoolss_PrinterInfo2 *pinfo2,
2971 TALLOC_CTX *mem_ctx)
2973 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2976 /*******************************************************************
2977 * fill a notify_info_data with the attributes
2978 * jfm:xxxx a samba printer is always shared
2979 ********************************************************************/
2981 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2983 struct spoolss_Notify *data,
2984 print_queue_struct *queue,
2985 struct spoolss_PrinterInfo2 *pinfo2,
2986 TALLOC_CTX *mem_ctx)
2988 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2991 /*******************************************************************
2992 * fill a notify_info_data with the priority
2993 ********************************************************************/
2995 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2997 struct spoolss_Notify *data,
2998 print_queue_struct *queue,
2999 struct spoolss_PrinterInfo2 *pinfo2,
3000 TALLOC_CTX *mem_ctx)
3002 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3005 /*******************************************************************
3006 * fill a notify_info_data with the default priority
3007 ********************************************************************/
3009 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3011 struct spoolss_Notify *data,
3012 print_queue_struct *queue,
3013 struct spoolss_PrinterInfo2 *pinfo2,
3014 TALLOC_CTX *mem_ctx)
3016 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3019 /*******************************************************************
3020 * fill a notify_info_data with the start time
3021 ********************************************************************/
3023 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3025 struct spoolss_Notify *data,
3026 print_queue_struct *queue,
3027 struct spoolss_PrinterInfo2 *pinfo2,
3028 TALLOC_CTX *mem_ctx)
3030 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3033 /*******************************************************************
3034 * fill a notify_info_data with the until time
3035 ********************************************************************/
3037 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3039 struct spoolss_Notify *data,
3040 print_queue_struct *queue,
3041 struct spoolss_PrinterInfo2 *pinfo2,
3042 TALLOC_CTX *mem_ctx)
3044 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3047 /*******************************************************************
3048 * fill a notify_info_data with the status
3049 ********************************************************************/
3051 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3053 struct spoolss_Notify *data,
3054 print_queue_struct *queue,
3055 struct spoolss_PrinterInfo2 *pinfo2,
3056 TALLOC_CTX *mem_ctx)
3058 print_status_struct status;
3060 print_queue_length(msg_ctx, snum, &status);
3061 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3064 /*******************************************************************
3065 * fill a notify_info_data with the number of jobs queued
3066 ********************************************************************/
3068 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3070 struct spoolss_Notify *data,
3071 print_queue_struct *queue,
3072 struct spoolss_PrinterInfo2 *pinfo2,
3073 TALLOC_CTX *mem_ctx)
3075 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3076 data, print_queue_length(msg_ctx, snum, NULL));
3079 /*******************************************************************
3080 * fill a notify_info_data with the average ppm
3081 ********************************************************************/
3083 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3085 struct spoolss_Notify *data,
3086 print_queue_struct *queue,
3087 struct spoolss_PrinterInfo2 *pinfo2,
3088 TALLOC_CTX *mem_ctx)
3090 /* always respond 8 pages per minutes */
3091 /* a little hard ! */
3092 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3095 /*******************************************************************
3096 * fill a notify_info_data with username
3097 ********************************************************************/
3099 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3101 struct spoolss_Notify *data,
3102 print_queue_struct *queue,
3103 struct spoolss_PrinterInfo2 *pinfo2,
3104 TALLOC_CTX *mem_ctx)
3106 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3109 /*******************************************************************
3110 * fill a notify_info_data with job status
3111 ********************************************************************/
3113 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3115 struct spoolss_Notify *data,
3116 print_queue_struct *queue,
3117 struct spoolss_PrinterInfo2 *pinfo2,
3118 TALLOC_CTX *mem_ctx)
3120 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3123 /*******************************************************************
3124 * fill a notify_info_data with job name
3125 ********************************************************************/
3127 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3129 struct spoolss_Notify *data,
3130 print_queue_struct *queue,
3131 struct spoolss_PrinterInfo2 *pinfo2,
3132 TALLOC_CTX *mem_ctx)
3134 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3137 /*******************************************************************
3138 * fill a notify_info_data with job status
3139 ********************************************************************/
3141 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3143 struct spoolss_Notify *data,
3144 print_queue_struct *queue,
3145 struct spoolss_PrinterInfo2 *pinfo2,
3146 TALLOC_CTX *mem_ctx)
3149 * Now we're returning job status codes we just return a "" here. JRA.
3154 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3157 switch (queue->status) {
3162 p = ""; /* NT provides the paused string */
3171 #endif /* NO LONGER NEEDED. */
3173 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3176 /*******************************************************************
3177 * fill a notify_info_data with job time
3178 ********************************************************************/
3180 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3182 struct spoolss_Notify *data,
3183 print_queue_struct *queue,
3184 struct spoolss_PrinterInfo2 *pinfo2,
3185 TALLOC_CTX *mem_ctx)
3187 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3190 /*******************************************************************
3191 * fill a notify_info_data with job size
3192 ********************************************************************/
3194 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3196 struct spoolss_Notify *data,
3197 print_queue_struct *queue,
3198 struct spoolss_PrinterInfo2 *pinfo2,
3199 TALLOC_CTX *mem_ctx)
3201 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3204 /*******************************************************************
3205 * fill a notify_info_data with page info
3206 ********************************************************************/
3207 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3209 struct spoolss_Notify *data,
3210 print_queue_struct *queue,
3211 struct spoolss_PrinterInfo2 *pinfo2,
3212 TALLOC_CTX *mem_ctx)
3214 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3217 /*******************************************************************
3218 * fill a notify_info_data with pages printed info.
3219 ********************************************************************/
3220 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3222 struct spoolss_Notify *data,
3223 print_queue_struct *queue,
3224 struct spoolss_PrinterInfo2 *pinfo2,
3225 TALLOC_CTX *mem_ctx)
3227 /* Add code when back-end tracks this */
3228 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3231 /*******************************************************************
3232 Fill a notify_info_data with job position.
3233 ********************************************************************/
3235 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3237 struct spoolss_Notify *data,
3238 print_queue_struct *queue,
3239 struct spoolss_PrinterInfo2 *pinfo2,
3240 TALLOC_CTX *mem_ctx)
3242 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3245 /*******************************************************************
3246 Fill a notify_info_data with submitted time.
3247 ********************************************************************/
3249 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3251 struct spoolss_Notify *data,
3252 print_queue_struct *queue,
3253 struct spoolss_PrinterInfo2 *pinfo2,
3254 TALLOC_CTX *mem_ctx)
3256 data->data.string.string = NULL;
3257 data->data.string.size = 0;
3259 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3260 &data->data.string.string,
3261 &data->data.string.size);
3265 struct s_notify_info_data_table
3267 enum spoolss_NotifyType type;
3270 enum spoolss_NotifyTable variable_type;
3271 void (*fn) (struct messaging_context *msg_ctx,
3272 int snum, struct spoolss_Notify *data,
3273 print_queue_struct *queue,
3274 struct spoolss_PrinterInfo2 *pinfo2,
3275 TALLOC_CTX *mem_ctx);
3278 /* A table describing the various print notification constants and
3279 whether the notification data is a pointer to a variable sized
3280 buffer, a one value uint32_t or a two value uint32_t. */
3282 static const struct s_notify_info_data_table notify_info_data_table[] =
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3335 /*******************************************************************
3336 Return the variable_type of info_data structure.
3337 ********************************************************************/
3339 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3344 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3345 if ( (notify_info_data_table[i].type == type) &&
3346 (notify_info_data_table[i].field == field) ) {
3347 return notify_info_data_table[i].variable_type;
3351 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3353 return (enum spoolss_NotifyTable) 0;
3356 /****************************************************************************
3357 ****************************************************************************/
3359 static bool search_notify(enum spoolss_NotifyType type,
3365 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3366 if (notify_info_data_table[i].type == type &&
3367 notify_info_data_table[i].field == field &&
3368 notify_info_data_table[i].fn != NULL) {
3377 /****************************************************************************
3378 ****************************************************************************/
3380 static void construct_info_data(struct spoolss_Notify *info_data,
3381 enum spoolss_NotifyType type,
3382 uint16_t field, int id)
3384 info_data->type = type;
3385 info_data->field.field = field;
3386 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3387 info_data->job_id = id;
3390 /*******************************************************************
3392 * fill a notify_info struct with info asked
3394 ********************************************************************/
3396 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3397 struct printer_handle *print_hnd,
3398 struct spoolss_NotifyInfo *info,
3399 struct spoolss_PrinterInfo2 *pinfo2,
3401 const struct spoolss_NotifyOptionType *option_type,
3403 TALLOC_CTX *mem_ctx)
3406 enum spoolss_NotifyType type;
3409 struct spoolss_Notify *current_data;
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 NULL, 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;