2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
31 #include "srv_spoolss_util.h"
32 #include "../librpc/gen_ndr/srv_spoolss.h"
33 #include "../librpc/gen_ndr/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "librpc/gen_ndr/messaging.h"
37 #include "registry/reg_objects.h"
39 /* macros stolen from s4 spoolss server */
40 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
41 ((info)?ndr_size_##fn(info, level, 0):0)
43 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
44 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
46 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
47 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
49 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
52 extern userdom_struct current_user_info;
55 #define DBGC_CLASS DBGC_RPC_SRV
57 #ifndef MAX_OPEN_PRINTER_EXS
58 #define MAX_OPEN_PRINTER_EXS 50
61 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
63 static Printer_entry *printers_list;
65 typedef struct _counter_printer_0 {
66 struct _counter_printer_0 *next;
67 struct _counter_printer_0 *prev;
73 static counter_printer_0 *counter_list;
75 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
76 static uint32_t smb_connections = 0;
79 /* in printing/nt_printing.c */
81 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
83 /* API table for Xcv Monitor functions */
85 struct xcv_api_table {
87 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
90 /********************************************************************
91 * Canonicalize servername.
92 ********************************************************************/
94 static const char *canon_servername(const char *servername)
96 const char *pservername = servername;
97 while (*pservername == '\\') {
103 /* translate between internal status numbers and NT status numbers */
104 static int nt_printj_status(int v)
110 return JOB_STATUS_PAUSED;
112 return JOB_STATUS_SPOOLING;
114 return JOB_STATUS_PRINTING;
116 return JOB_STATUS_ERROR;
118 return JOB_STATUS_DELETING;
120 return JOB_STATUS_OFFLINE;
122 return JOB_STATUS_PAPEROUT;
124 return JOB_STATUS_PRINTED;
126 return JOB_STATUS_DELETED;
128 return JOB_STATUS_BLOCKED_DEVQ;
129 case LPQ_USER_INTERVENTION:
130 return JOB_STATUS_USER_INTERVENTION;
135 static int nt_printq_status(int v)
139 return PRINTER_STATUS_PAUSED;
148 /***************************************************************************
149 Disconnect from the client
150 ****************************************************************************/
152 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
158 * Tell the specific printing tdb we no longer want messages for this printer
159 * by deregistering our PID.
162 if (!print_notify_deregister_pid(snum))
163 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
165 /* weird if the test succeds !!! */
166 if (smb_connections==0) {
167 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
171 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
174 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
175 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
176 win_errstr(result)));
178 /* if it's the last connection, deconnect the IPC$ share */
179 if (smb_connections==1) {
181 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
182 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
184 messaging_deregister(smbd_messaging_context(),
185 MSG_PRINTER_NOTIFY2, NULL);
187 /* Tell the connections db we're no longer interested in
188 * printer notify messages. */
190 serverid_register_msg_flags(
191 messaging_server_id(smbd_messaging_context()),
192 false, FLAG_MSG_PRINT_NOTIFY);
198 /****************************************************************************
199 Functions to free a printer entry datastruct.
200 ****************************************************************************/
202 static int printer_entry_destructor(Printer_entry *Printer)
204 if (Printer->notify.client_connected == true) {
207 if ( Printer->printer_type == SPLHND_SERVER) {
209 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
210 } else if (Printer->printer_type == SPLHND_PRINTER) {
211 snum = print_queue_snum(Printer->sharename);
213 srv_spoolss_replycloseprinter(snum,
214 &Printer->notify.client_hnd);
218 Printer->notify.flags=0;
219 Printer->notify.options=0;
220 Printer->notify.localmachine[0]='\0';
221 Printer->notify.printerlocal=0;
222 TALLOC_FREE(Printer->notify.option);
223 Printer->notify.client_connected = false;
225 TALLOC_FREE(Printer->devmode);
226 free_a_printer( &Printer->printer_info, 2 );
228 /* Remove from the internal list. */
229 DLIST_REMOVE(printers_list, Printer);
233 /****************************************************************************
234 find printer index by handle
235 ****************************************************************************/
237 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
238 struct policy_handle *hnd)
240 Printer_entry *find_printer = NULL;
242 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
243 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
250 /****************************************************************************
251 Close printer index by handle.
252 ****************************************************************************/
254 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
256 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
259 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
264 close_policy_hnd(p, hnd);
269 /****************************************************************************
270 Delete a printer given a handle.
271 ****************************************************************************/
273 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
275 char *cmd = lp_deleteprinter_cmd();
276 char *command = NULL;
278 SE_PRIV se_printop = SE_PRINT_OPERATOR;
279 bool is_print_op = false;
281 /* can't fail if we don't try */
286 command = talloc_asprintf(ctx,
293 is_print_op = user_has_privileges( token, &se_printop );
295 DEBUG(10,("Running [%s]\n", command));
297 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
302 if ( (ret = smbrun(command, NULL)) == 0 ) {
303 /* Tell everyone we updated smb.conf. */
304 message_send_all(smbd_messaging_context(),
305 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
311 /********** END SePrintOperatorPrivlege BLOCK **********/
313 DEBUGADD(10,("returned [%d]\n", ret));
315 TALLOC_FREE(command);
318 return WERR_BADFID; /* What to return here? */
320 /* go ahead and re-read the services immediately */
322 reload_services(false);
325 if ( lp_servicenumber( sharename ) > 0 )
326 return WERR_ACCESS_DENIED;
331 /****************************************************************************
332 Delete a printer given a handle.
333 ****************************************************************************/
335 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
337 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
340 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
346 * It turns out that Windows allows delete printer on a handle
347 * opened by an admin user, then used on a pipe handle created
348 * by an anonymous user..... but they're working on security.... riiight !
352 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
353 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
354 return WERR_ACCESS_DENIED;
357 /* this does not need a become root since the access check has been
358 done on the handle already */
360 if (del_a_printer( Printer->sharename ) != 0) {
361 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
365 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
366 Printer->sharename );
369 /****************************************************************************
370 Return the snum of a printer corresponding to an handle.
371 ****************************************************************************/
373 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
374 int *number, struct share_params **params)
376 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
379 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
384 switch (Printer->printer_type) {
386 DEBUG(4,("short name:%s\n", Printer->sharename));
387 *number = print_queue_snum(Printer->sharename);
388 return (*number != -1);
396 /****************************************************************************
397 Set printer handle type.
398 Check if it's \\server or \\server\printer
399 ****************************************************************************/
401 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
403 DEBUG(3,("Setting printer type=%s\n", handlename));
405 if ( strlen(handlename) < 3 ) {
406 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
410 /* it's a print server */
411 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
412 DEBUGADD(4,("Printer is a print server\n"));
413 Printer->printer_type = SPLHND_SERVER;
415 /* it's a printer (set_printer_hnd_name() will handle port monitors */
417 DEBUGADD(4,("Printer is a printer\n"));
418 Printer->printer_type = SPLHND_PRINTER;
424 /****************************************************************************
425 Set printer handle name.. Accept names like \\server, \\server\printer,
426 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
427 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
428 XcvDataPort() interface.
429 ****************************************************************************/
431 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
432 struct auth_serversupplied_info *server_info,
433 Printer_entry *Printer,
434 const char *handlename)
437 int n_services=lp_numservices();
439 const char *printername;
440 const char *servername;
443 struct spoolss_PrinterInfo2 *info2 = NULL;
446 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
447 (unsigned long)strlen(handlename)));
449 aprinter = CONST_DISCARD(char *, handlename);
450 if ( *handlename == '\\' ) {
451 servername = canon_servername(handlename);
452 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
456 if (!is_myname_or_ipaddr(servername)) {
460 fstrcpy(Printer->servername, servername);
463 if (Printer->printer_type == SPLHND_SERVER) {
467 if (Printer->printer_type != SPLHND_PRINTER) {
471 DEBUGADD(5, ("searching for [%s]\n", aprinter));
473 /* check for the Port Monitor Interface */
474 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
475 Printer->printer_type = SPLHND_PORTMON_TCP;
476 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
479 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
480 Printer->printer_type = SPLHND_PORTMON_LOCAL;
481 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
485 /* Search all sharenames first as this is easier than pulling
486 the printer_info_2 off of disk. Don't use find_service() since
487 that calls out to map_username() */
489 /* do another loop to look for printernames */
490 for (snum = 0; !found && snum < n_services; snum++) {
491 const char *printer = lp_const_servicename(snum);
493 /* no point going on if this is not a printer */
494 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
498 /* ignore [printers] share */
499 if (strequal(printer, "printers")) {
503 fstrcpy(sname, printer);
504 if (strequal(aprinter, printer)) {
509 /* no point looking up the printer object if
510 we aren't allowing printername != sharename */
511 if (lp_force_printername(snum)) {
515 result = winreg_get_printer(mem_ctx,
520 if ( !W_ERROR_IS_OK(result) ) {
521 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
522 sname, win_errstr(result)));
526 printername = strrchr(info2->printername, '\\');
527 if (printername == NULL) {
528 printername = info2->printername;
533 if (strequal(printername, aprinter)) {
538 DEBUGADD(10, ("printername: %s\n", printername));
544 DEBUGADD(4,("Printer not found\n"));
548 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
550 fstrcpy(Printer->sharename, sname);
555 /****************************************************************************
556 Find first available printer slot. creates a printer handle for you.
557 ****************************************************************************/
559 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
560 const char *name, uint32_t access_granted)
562 Printer_entry *new_printer;
564 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
566 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
567 if (new_printer == NULL) {
570 talloc_set_destructor(new_printer, printer_entry_destructor);
572 if (!create_policy_hnd(p, hnd, new_printer)) {
573 TALLOC_FREE(new_printer);
577 /* Add to the internal list. */
578 DLIST_ADD(printers_list, new_printer);
580 new_printer->notify.option=NULL;
582 if (!set_printer_hnd_printertype(new_printer, name)) {
583 close_printer_handle(p, hnd);
587 if (!set_printer_hnd_name(p->mem_ctx, p->server_info, new_printer, name)) {
588 close_printer_handle(p, hnd);
592 new_printer->access_granted = access_granted;
594 DEBUG(5, ("%d printer handles active\n",
595 (int)num_pipe_handles(p)));
600 /***************************************************************************
601 check to see if the client motify handle is monitoring the notification
602 given by (notify_type, notify_field).
603 **************************************************************************/
605 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
606 uint16_t notify_field)
611 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
612 uint16_t notify_field)
614 struct spoolss_NotifyOption *option = p->notify.option;
618 * Flags should always be zero when the change notify
619 * is registered by the client's spooler. A user Win32 app
620 * might use the flags though instead of the NOTIFY_OPTION_INFO
629 return is_monitoring_event_flags(
630 p->notify.flags, notify_type, notify_field);
632 for (i = 0; i < option->count; i++) {
634 /* Check match for notify_type */
636 if (option->types[i].type != notify_type)
639 /* Check match for field */
641 for (j = 0; j < option->types[i].count; j++) {
642 if (option->types[i].fields[j].field == notify_field) {
648 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
649 p->servername, p->sharename, notify_type, notify_field));
654 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
655 _data->data.integer[0] = _integer; \
656 _data->data.integer[1] = 0;
659 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
660 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
661 if (!_data->data.string.string) {\
662 _data->data.string.size = 0; \
664 _data->data.string.size = strlen_m_term(_p) * 2;
666 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
667 _data->data.devmode.devmode = _devmode;
669 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
670 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
671 if (!_data->data.sd.sd) { \
672 _data->data.sd.sd_size = 0; \
674 _data->data.sd.sd_size = _size;
676 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
681 struct spoolss_Time st;
685 if (!init_systemtime(&st, t)) {
689 p = talloc_array(mem_ctx, char, len);
695 * Systemtime must be linearized as a set of UINT16's.
696 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
699 SSVAL(p, 0, st.year);
700 SSVAL(p, 2, st.month);
701 SSVAL(p, 4, st.day_of_week);
703 SSVAL(p, 8, st.hour);
704 SSVAL(p, 10, st.minute);
705 SSVAL(p, 12, st.second);
706 SSVAL(p, 14, st.millisecond);
712 /* Convert a notification message to a struct spoolss_Notify */
714 static void notify_one_value(struct spoolss_notify_msg *msg,
715 struct spoolss_Notify *data,
718 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
721 static void notify_string(struct spoolss_notify_msg *msg,
722 struct spoolss_Notify *data,
725 /* The length of the message includes the trailing \0 */
727 data->data.string.size = msg->len * 2;
728 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
729 if (!data->data.string.string) {
730 data->data.string.size = 0;
735 static void notify_system_time(struct spoolss_notify_msg *msg,
736 struct spoolss_Notify *data,
739 data->data.string.string = NULL;
740 data->data.string.size = 0;
742 if (msg->len != sizeof(time_t)) {
743 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
748 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
749 &data->data.string.string,
750 &data->data.string.size);
753 struct notify2_message_table {
755 void (*fn)(struct spoolss_notify_msg *msg,
756 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
759 static struct notify2_message_table printer_notify_table[] = {
760 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
761 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
762 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
763 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
764 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
765 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
766 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
767 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
768 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
769 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
770 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
771 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
772 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
773 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
774 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
775 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
776 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
777 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
778 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
781 static struct notify2_message_table job_notify_table[] = {
782 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
783 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
784 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
785 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
786 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
787 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
788 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
789 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
790 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
791 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
792 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
793 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
794 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
795 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
796 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
797 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
798 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
799 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
800 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
801 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
802 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
803 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
804 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
805 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
809 /***********************************************************************
810 Allocate talloc context for container object
811 **********************************************************************/
813 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
818 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
823 /***********************************************************************
824 release all allocated memory and zero out structure
825 **********************************************************************/
827 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 talloc_destroy(ctr->ctx);
840 /***********************************************************************
841 **********************************************************************/
843 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
851 /***********************************************************************
852 **********************************************************************/
854 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
856 if ( !ctr || !ctr->msg_groups )
859 if ( idx >= ctr->num_groups )
862 return &ctr->msg_groups[idx];
866 /***********************************************************************
867 How many groups of change messages do we have ?
868 **********************************************************************/
870 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
875 return ctr->num_groups;
878 /***********************************************************************
879 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
880 **********************************************************************/
882 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
884 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
885 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
886 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
892 /* loop over all groups looking for a matching printer name */
894 for ( i=0; i<ctr->num_groups; i++ ) {
895 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
899 /* add a new group? */
901 if ( i == ctr->num_groups ) {
904 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
905 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
908 ctr->msg_groups = groups;
910 /* clear the new entry and set the printer name */
912 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
913 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
916 /* add the change messages; 'i' is the correct index now regardless */
918 msg_grp = &ctr->msg_groups[i];
922 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
923 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
926 msg_grp->msgs = msg_list;
928 new_slot = msg_grp->num_msgs-1;
929 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
931 /* need to allocate own copy of data */
934 msg_grp->msgs[new_slot].notify.data = (char *)
935 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
937 return ctr->num_groups;
940 void construct_info_data(struct spoolss_Notify *info_data,
941 enum spoolss_NotifyType type,
945 /***********************************************************************
946 Send a change notication message on all handles which have a call
948 **********************************************************************/
950 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
953 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
954 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
955 SPOOLSS_NOTIFY_MSG *messages;
956 int sending_msg_count;
959 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
963 messages = msg_group->msgs;
966 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
970 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
972 /* loop over all printers */
974 for (p = printers_list; p; p = p->next) {
975 struct spoolss_Notify *notifies;
980 /* Is there notification on this handle? */
982 if ( !p->notify.client_connected )
985 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
987 /* For this printer? Print servers always receive
990 if ( ( p->printer_type == SPLHND_PRINTER ) &&
991 ( !strequal(msg_group->printername, p->sharename) ) )
994 DEBUG(10,("Our printer\n"));
996 /* allocate the max entries possible */
998 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1003 /* build the array of change notifications */
1005 sending_msg_count = 0;
1007 for ( i=0; i<msg_group->num_msgs; i++ ) {
1008 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1010 /* Are we monitoring this event? */
1012 if (!is_monitoring_event(p, msg->type, msg->field))
1015 sending_msg_count++;
1018 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1019 msg->type, msg->field, p->sharename));
1022 * if the is a printer notification handle and not a job notification
1023 * type, then set the id to 0. Other wise just use what was specified
1026 * When registering change notification on a print server handle
1027 * we always need to send back the id (snum) matching the printer
1028 * for which the change took place. For change notify registered
1029 * on a printer handle, this does not matter and the id should be 0.
1034 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1040 /* Convert unix jobid to smb jobid */
1042 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1043 id = sysjob_to_jobid(msg->id);
1046 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1051 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1054 case PRINTER_NOTIFY_TYPE:
1055 if ( printer_notify_table[msg->field].fn )
1056 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1059 case JOB_NOTIFY_TYPE:
1060 if ( job_notify_table[msg->field].fn )
1061 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1065 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1072 if ( sending_msg_count ) {
1075 union spoolss_ReplyPrinterInfo info;
1076 struct spoolss_NotifyInfo info0;
1077 uint32_t reply_result;
1079 info0.version = 0x2;
1080 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1081 info0.count = count;
1082 info0.notifies = notifies;
1084 info.info0 = &info0;
1086 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1087 &p->notify.client_hnd,
1088 p->notify.change, /* color */
1091 0, /* reply_type, must be 0 */
1094 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1095 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1096 notify_cli_pipe->srv_name_slash,
1099 switch (reply_result) {
1102 case PRINTER_NOTIFY_INFO_DISCARDED:
1103 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1104 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1113 DEBUG(8,("send_notify2_changes: Exit...\n"));
1117 /***********************************************************************
1118 **********************************************************************/
1120 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1123 uint32_t tv_sec, tv_usec;
1126 /* Unpack message */
1128 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1131 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1133 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1136 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1137 &msg->notify.value[0], &msg->notify.value[1]);
1139 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1140 &msg->len, &msg->notify.data);
1142 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1143 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1145 tv->tv_sec = tv_sec;
1146 tv->tv_usec = tv_usec;
1149 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1150 msg->notify.value[1]));
1152 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1157 /********************************************************************
1158 Receive a notify2 message list
1159 ********************************************************************/
1161 static void receive_notify2_message_list(struct messaging_context *msg,
1164 struct server_id server_id,
1167 size_t msg_count, i;
1168 char *buf = (char *)data->data;
1171 SPOOLSS_NOTIFY_MSG notify;
1172 SPOOLSS_NOTIFY_MSG_CTR messages;
1175 if (data->length < 4) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1180 msg_count = IVAL(buf, 0);
1183 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1185 if (msg_count == 0) {
1186 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1190 /* initialize the container */
1192 ZERO_STRUCT( messages );
1193 notify_msg_ctr_init( &messages );
1196 * build message groups for each printer identified
1197 * in a change_notify msg. Remember that a PCN message
1198 * includes the handle returned for the srv_spoolss_replyopenprinter()
1199 * call. Therefore messages are grouped according to printer handle.
1202 for ( i=0; i<msg_count; i++ ) {
1203 struct timeval msg_tv;
1205 if (msg_ptr + 4 - buf > data->length) {
1206 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1210 msg_len = IVAL(msg_ptr,0);
1213 if (msg_ptr + msg_len - buf > data->length) {
1214 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1218 /* unpack messages */
1220 ZERO_STRUCT( notify );
1221 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1224 /* add to correct list in container */
1226 notify_msg_ctr_addmsg( &messages, ¬ify );
1228 /* free memory that might have been allocated by notify2_unpack_msg() */
1230 if ( notify.len != 0 )
1231 SAFE_FREE( notify.notify.data );
1234 /* process each group of messages */
1236 num_groups = notify_msg_ctr_numgroups( &messages );
1237 for ( i=0; i<num_groups; i++ )
1238 send_notify2_changes( &messages, i );
1243 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1244 (uint32_t)msg_count ));
1246 notify_msg_ctr_destroy( &messages );
1251 /********************************************************************
1252 Send a message to ourself about new driver being installed
1253 so we can upgrade the information for each printer bound to this
1255 ********************************************************************/
1257 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1259 int len = strlen(drivername);
1264 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1267 messaging_send_buf(smbd_messaging_context(),
1268 messaging_server_id(smbd_messaging_context()),
1269 MSG_PRINTER_DRVUPGRADE,
1270 (uint8_t *)drivername, len+1);
1275 /**********************************************************************
1276 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1277 over all printers, upgrading ones as necessary
1278 **********************************************************************/
1280 void do_drv_upgrade_printer(struct messaging_context *msg,
1283 struct server_id server_id,
1286 TALLOC_CTX *tmp_ctx;
1287 struct auth_serversupplied_info *server_info = NULL;
1288 struct spoolss_PrinterInfo2 *pinfo2;
1291 const char *drivername;
1293 int n_services = lp_numservices();
1296 tmp_ctx = talloc_new(NULL);
1297 if (!tmp_ctx) return;
1299 status = make_server_info_system(tmp_ctx, &server_info);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 DEBUG(0, ("do_drv_upgrade_printer: "
1302 "Could not create system server_info\n"));
1306 len = MIN(data->length,sizeof(drivername)-1);
1307 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1309 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1313 DEBUG(10, ("do_drv_upgrade_printer: "
1314 "Got message for new driver [%s]\n", drivername));
1316 /* Iterate the printer list */
1318 for (snum = 0; snum < n_services; snum++) {
1319 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1323 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1324 lp_const_servicename(snum),
1327 if (!W_ERROR_IS_OK(result)) {
1331 if (strcmp(drivername, pinfo2->drivername) != 0) {
1335 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1337 /* all we care about currently is the change_id */
1338 result = winreg_printer_update_changeid(tmp_ctx,
1340 pinfo2->printername);
1342 if (!W_ERROR_IS_OK(result)) {
1343 DEBUG(3, ("do_drv_upgrade_printer: "
1344 "Failed to update changeid [%s]\n",
1345 win_errstr(result)));
1351 talloc_free(tmp_ctx);
1354 /********************************************************************
1355 Update the cache for all printq's with a registered client
1357 ********************************************************************/
1359 void update_monitored_printq_cache( void )
1361 Printer_entry *printer = printers_list;
1364 /* loop through all printers and update the cache where
1365 client_connected == true */
1368 if ( (printer->printer_type == SPLHND_PRINTER)
1369 && printer->notify.client_connected )
1371 snum = print_queue_snum(printer->sharename);
1372 print_queue_status( snum, NULL, NULL );
1375 printer = printer->next;
1381 /****************************************************************
1382 _spoolss_OpenPrinter
1383 ****************************************************************/
1385 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1386 struct spoolss_OpenPrinter *r)
1388 struct spoolss_OpenPrinterEx e;
1391 ZERO_STRUCT(e.in.userlevel);
1393 e.in.printername = r->in.printername;
1394 e.in.datatype = r->in.datatype;
1395 e.in.devmode_ctr = r->in.devmode_ctr;
1396 e.in.access_mask = r->in.access_mask;
1399 e.out.handle = r->out.handle;
1401 werr = _spoolss_OpenPrinterEx(p, &e);
1403 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1404 /* OpenPrinterEx returns this for a bad
1405 * printer name. We must return WERR_INVALID_PRINTER_NAME
1408 werr = WERR_INVALID_PRINTER_NAME;
1414 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1415 struct spoolss_DeviceMode *orig,
1416 struct spoolss_DeviceMode **dest)
1418 struct spoolss_DeviceMode *dm;
1420 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1425 /* copy all values, then duplicate strings and structs */
1428 dm->devicename = talloc_strdup(dm, orig->devicename);
1429 if (!dm->devicename) {
1432 dm->formname = talloc_strdup(dm, orig->formname);
1433 if (!dm->formname) {
1436 if (orig->driverextra_data.data) {
1437 dm->driverextra_data.data =
1438 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1439 orig->driverextra_data.length);
1440 if (!dm->driverextra_data.data) {
1449 /****************************************************************
1450 _spoolss_OpenPrinterEx
1451 ****************************************************************/
1453 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1454 struct spoolss_OpenPrinterEx *r)
1457 Printer_entry *Printer=NULL;
1459 if (!r->in.printername) {
1460 return WERR_INVALID_PARAM;
1463 /* some sanity check because you can open a printer or a print server */
1464 /* aka: \\server\printer or \\server */
1466 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1468 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1469 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1470 " for printer %s\n", r->in.printername));
1471 ZERO_STRUCTP(r->out.handle);
1472 return WERR_INVALID_PARAM;
1475 Printer = find_printer_index_by_hnd(p, r->out.handle);
1477 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1478 "handle we created for printer %s\n", r->in.printername));
1479 close_printer_handle(p, r->out.handle);
1480 ZERO_STRUCTP(r->out.handle);
1481 return WERR_INVALID_PARAM;
1485 * First case: the user is opening the print server:
1487 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1488 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1490 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1491 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1492 * or if the user is listed in the smb.conf printer admin parameter.
1494 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1495 * client view printer folder, but does not show the MSAPW.
1497 * Note: this test needs code to check access rights here too. Jeremy
1498 * could you look at this?
1500 * Second case: the user is opening a printer:
1501 * NT doesn't let us connect to a printer if the connecting user
1502 * doesn't have print permission.
1504 * Third case: user is opening a Port Monitor
1505 * access checks same as opening a handle to the print server.
1508 switch (Printer->printer_type )
1511 case SPLHND_PORTMON_TCP:
1512 case SPLHND_PORTMON_LOCAL:
1513 /* Printserver handles use global struct... */
1517 /* Map standard access rights to object specific access rights */
1519 se_map_standard(&r->in.access_mask,
1520 &printserver_std_mapping);
1522 /* Deny any object specific bits that don't apply to print
1523 servers (i.e printer and job specific bits) */
1525 r->in.access_mask &= SEC_MASK_SPECIFIC;
1527 if (r->in.access_mask &
1528 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1529 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1530 close_printer_handle(p, r->out.handle);
1531 ZERO_STRUCTP(r->out.handle);
1532 return WERR_ACCESS_DENIED;
1535 /* Allow admin access */
1537 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1539 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1541 if (!lp_ms_add_printer_wizard()) {
1542 close_printer_handle(p, r->out.handle);
1543 ZERO_STRUCTP(r->out.handle);
1544 return WERR_ACCESS_DENIED;
1547 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1548 and not a printer admin, then fail */
1550 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1551 !user_has_privileges(p->server_info->ptok,
1553 !token_contains_name_in_list(
1554 uidtoname(p->server_info->utok.uid),
1555 p->server_info->info3->base.domain.string,
1557 p->server_info->ptok,
1558 lp_printer_admin(snum))) {
1559 close_printer_handle(p, r->out.handle);
1560 ZERO_STRUCTP(r->out.handle);
1561 return WERR_ACCESS_DENIED;
1564 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1568 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1571 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1572 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1574 /* We fall through to return WERR_OK */
1577 case SPLHND_PRINTER:
1578 /* NT doesn't let us connect to a printer if the connecting user
1579 doesn't have print permission. */
1581 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1582 close_printer_handle(p, r->out.handle);
1583 ZERO_STRUCTP(r->out.handle);
1587 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1588 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1591 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1593 /* map an empty access mask to the minimum access mask */
1594 if (r->in.access_mask == 0x0)
1595 r->in.access_mask = PRINTER_ACCESS_USE;
1598 * If we are not serving the printer driver for this printer,
1599 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1600 * will keep NT clients happy --jerry
1603 if (lp_use_client_driver(snum)
1604 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1606 r->in.access_mask = PRINTER_ACCESS_USE;
1609 /* check smb.conf parameters and the the sec_desc */
1611 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1612 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1613 ZERO_STRUCTP(r->out.handle);
1614 return WERR_ACCESS_DENIED;
1617 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1618 p->server_info->ptok, snum) ||
1619 !print_access_check(p->server_info, snum,
1620 r->in.access_mask)) {
1621 DEBUG(3, ("access DENIED for printer open\n"));
1622 close_printer_handle(p, r->out.handle);
1623 ZERO_STRUCTP(r->out.handle);
1624 return WERR_ACCESS_DENIED;
1627 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1628 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1629 close_printer_handle(p, r->out.handle);
1630 ZERO_STRUCTP(r->out.handle);
1631 return WERR_ACCESS_DENIED;
1634 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1635 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1637 r->in.access_mask = PRINTER_ACCESS_USE;
1639 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1640 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1642 winreg_create_printer(p->mem_ctx,
1644 Printer->servername,
1645 lp_const_servicename(snum));
1650 /* sanity check to prevent programmer error */
1651 ZERO_STRUCTP(r->out.handle);
1655 Printer->access_granted = r->in.access_mask;
1658 * If the client sent a devmode in the OpenPrinter() call, then
1659 * save it here in case we get a job submission on this handle
1662 if ((Printer->printer_type != SPLHND_SERVER) &&
1663 r->in.devmode_ctr.devmode) {
1664 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1668 #if 0 /* JERRY -- I'm doubtful this is really effective */
1669 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1670 optimization in Windows 2000 clients --jerry */
1672 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1673 && (RA_WIN2K == get_remote_arch()) )
1675 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1676 sys_usleep( 500000 );
1683 /****************************************************************
1684 _spoolss_ClosePrinter
1685 ****************************************************************/
1687 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1688 struct spoolss_ClosePrinter *r)
1690 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1692 if (Printer && Printer->document_started) {
1693 struct spoolss_EndDocPrinter e;
1695 e.in.handle = r->in.handle;
1697 _spoolss_EndDocPrinter(p, &e);
1700 if (!close_printer_handle(p, r->in.handle))
1703 /* clear the returned printer handle. Observed behavior
1704 from Win2k server. Don't think this really matters.
1705 Previous code just copied the value of the closed
1708 ZERO_STRUCTP(r->out.handle);
1713 /****************************************************************
1714 _spoolss_DeletePrinter
1715 ****************************************************************/
1717 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1718 struct spoolss_DeletePrinter *r)
1720 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1724 if (Printer && Printer->document_started) {
1725 struct spoolss_EndDocPrinter e;
1727 e.in.handle = r->in.handle;
1729 _spoolss_EndDocPrinter(p, &e);
1732 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1733 winreg_delete_printer_key(p->mem_ctx,
1735 lp_const_servicename(snum),
1739 result = delete_printer_handle(p, r->in.handle);
1744 /*******************************************************************
1745 * static function to lookup the version id corresponding to an
1746 * long architecture string
1747 ******************************************************************/
1749 static const struct print_architecture_table_node archi_table[]= {
1751 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1752 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1753 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1754 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1755 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1756 {"Windows IA64", SPL_ARCH_IA64, 3 },
1757 {"Windows x64", SPL_ARCH_X64, 3 },
1761 static int get_version_id(const char *arch)
1765 for (i=0; archi_table[i].long_archi != NULL; i++)
1767 if (strcmp(arch, archi_table[i].long_archi) == 0)
1768 return (archi_table[i].version);
1774 /****************************************************************
1775 _spoolss_DeletePrinterDriver
1776 ****************************************************************/
1778 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1779 struct spoolss_DeletePrinterDriver *r)
1782 struct spoolss_DriverInfo8 *info = NULL;
1783 struct spoolss_DriverInfo8 *info_win2k = NULL;
1786 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1788 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1789 and not a printer admin, then fail */
1791 if ( (p->server_info->utok.uid != sec_initial_uid())
1792 && !user_has_privileges(p->server_info->ptok, &se_printop )
1793 && !token_contains_name_in_list(
1794 uidtoname(p->server_info->utok.uid),
1795 p->server_info->info3->base.domain.string,
1797 p->server_info->ptok,
1798 lp_printer_admin(-1)) )
1800 return WERR_ACCESS_DENIED;
1803 /* check that we have a valid driver name first */
1805 if ((version = get_version_id(r->in.architecture)) == -1)
1806 return WERR_INVALID_ENVIRONMENT;
1808 status = winreg_get_driver(p->mem_ctx, p->server_info,
1809 r->in.architecture, r->in.driver,
1811 if (!W_ERROR_IS_OK(status)) {
1812 /* try for Win2k driver if "Windows NT x86" */
1814 if ( version == 2 ) {
1817 status = winreg_get_driver(p->mem_ctx, p->server_info,
1821 if (!W_ERROR_IS_OK(status)) {
1822 status = WERR_UNKNOWN_PRINTER_DRIVER;
1826 /* otherwise it was a failure */
1828 status = WERR_UNKNOWN_PRINTER_DRIVER;
1834 if (printer_driver_in_use(p->mem_ctx, p->server_info, info)) {
1835 status = WERR_PRINTER_DRIVER_IN_USE;
1840 status = winreg_get_driver(p->mem_ctx, p->server_info,
1842 r->in.driver, 3, &info_win2k);
1843 if (W_ERROR_IS_OK(status)) {
1844 /* if we get to here, we now have 2 driver info structures to remove */
1845 /* remove the Win2k driver first*/
1847 status = winreg_del_driver(p->mem_ctx,
1850 talloc_free(info_win2k);
1852 /* this should not have failed---if it did, report to client */
1853 if (!W_ERROR_IS_OK(status)) {
1859 status = winreg_del_driver(p->mem_ctx, p->server_info, info, version);
1867 /****************************************************************
1868 _spoolss_DeletePrinterDriverEx
1869 ****************************************************************/
1871 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1872 struct spoolss_DeletePrinterDriverEx *r)
1874 struct spoolss_DriverInfo8 *info = NULL;
1875 struct spoolss_DriverInfo8 *info_win2k = NULL;
1879 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1881 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1882 and not a printer admin, then fail */
1884 if ( (p->server_info->utok.uid != sec_initial_uid())
1885 && !user_has_privileges(p->server_info->ptok, &se_printop )
1886 && !token_contains_name_in_list(
1887 uidtoname(p->server_info->utok.uid),
1888 p->server_info->info3->base.domain.string,
1890 p->server_info->ptok, lp_printer_admin(-1)) )
1892 return WERR_ACCESS_DENIED;
1895 /* check that we have a valid driver name first */
1896 if ((version = get_version_id(r->in.architecture)) == -1) {
1897 /* this is what NT returns */
1898 return WERR_INVALID_ENVIRONMENT;
1901 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1902 version = r->in.version;
1904 status = winreg_get_driver(p->mem_ctx, p->server_info,
1905 r->in.architecture, r->in.driver,
1907 if (!W_ERROR_IS_OK(status)) {
1908 status = WERR_UNKNOWN_PRINTER_DRIVER;
1911 * if the client asked for a specific version,
1912 * or this is something other than Windows NT x86,
1916 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1919 /* try for Win2k driver if "Windows NT x86" */
1922 status = winreg_get_driver(info, p->server_info,
1926 if (!W_ERROR_IS_OK(status)) {
1927 status = WERR_UNKNOWN_PRINTER_DRIVER;
1932 if (printer_driver_in_use(info, p->server_info, info)) {
1933 status = WERR_PRINTER_DRIVER_IN_USE;
1938 * we have a couple of cases to consider.
1939 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1940 * then the delete should fail if **any** files overlap with
1942 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1943 * non-overlapping files
1944 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1945 * is set, the do not delete any files
1946 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1949 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1951 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1954 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1955 printer_driver_files_in_use(info, p->server_info, info)) {
1956 /* no idea of the correct error here */
1957 status = WERR_ACCESS_DENIED;
1962 /* also check for W32X86/3 if necessary; maybe we already have? */
1964 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
1965 status = winreg_get_driver(info, p->server_info,
1967 r->in.driver, 3, &info_win2k);
1968 if (W_ERROR_IS_OK(status)) {
1971 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1972 printer_driver_files_in_use(info, p->server_info,
1974 /* no idea of the correct error here */
1975 talloc_free(info_win2k);
1976 status = WERR_ACCESS_DENIED;
1980 /* if we get to here, we now have 2 driver info structures to remove */
1981 /* remove the Win2k driver first*/
1983 status = winreg_del_driver(info, p->server_info,
1986 /* this should not have failed---if it did, report to client */
1988 if (!W_ERROR_IS_OK(status)) {
1993 * now delete any associated files if delete_files is
1994 * true. Even if this part failes, we return succes
1995 * because the driver doesn not exist any more
1998 delete_driver_files(p->server_info,
2004 status = winreg_del_driver(info, p->server_info, info, version);
2005 if (!W_ERROR_IS_OK(status)) {
2010 * now delete any associated files if delete_files is
2011 * true. Even if this part failes, we return succes
2012 * because the driver doesn not exist any more
2015 delete_driver_files(p->server_info, info);
2024 /****************************************************************************
2025 Internal routine for storing printerdata
2026 ***************************************************************************/
2028 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2029 const char *key, const char *value,
2030 uint32_t type, uint8_t *data, int real_len)
2032 /* the registry objects enforce uniqueness based on value name */
2034 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2037 /********************************************************************
2038 GetPrinterData on a printer server Handle.
2039 ********************************************************************/
2041 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2043 enum winreg_Type *type,
2044 union spoolss_PrinterData *data)
2046 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2048 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2054 if (!StrCaseCmp(value, "BeepEnabled")) {
2060 if (!StrCaseCmp(value, "EventLog")) {
2062 /* formally was 0x1b */
2067 if (!StrCaseCmp(value, "NetPopup")) {
2073 if (!StrCaseCmp(value, "MajorVersion")) {
2076 /* Windows NT 4.0 seems to not allow uploading of drivers
2077 to a server that reports 0x3 as the MajorVersion.
2078 need to investigate more how Win2k gets around this .
2081 if (RA_WINNT == get_remote_arch()) {
2090 if (!StrCaseCmp(value, "MinorVersion")) {
2097 * uint32_t size = 0x114
2098 * uint32_t major = 5
2099 * uint32_t minor = [0|1]
2100 * uint32_t build = [2195|2600]
2101 * extra unicode string = e.g. "Service Pack 3"
2103 if (!StrCaseCmp(value, "OSVersion")) {
2105 enum ndr_err_code ndr_err;
2106 struct spoolss_OSVersion os;
2108 os.major = 5; /* Windows 2000 == 5.0 */
2110 os.build = 2195; /* build */
2111 os.extra_string = ""; /* leave extra string empty */
2113 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2114 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2115 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2116 return WERR_GENERAL_FAILURE;
2120 data->binary = blob;
2126 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2129 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2130 W_ERROR_HAVE_NO_MEMORY(data->string);
2135 if (!StrCaseCmp(value, "Architecture")) {
2137 data->string = talloc_strdup(mem_ctx,
2138 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2139 W_ERROR_HAVE_NO_MEMORY(data->string);
2144 if (!StrCaseCmp(value, "DsPresent")) {
2147 /* only show the publish check box if we are a
2148 member of a AD domain */
2150 if (lp_security() == SEC_ADS) {
2158 if (!StrCaseCmp(value, "DNSMachineName")) {
2159 const char *hostname = get_mydnsfullname();
2162 return WERR_BADFILE;
2166 data->string = talloc_strdup(mem_ctx, hostname);
2167 W_ERROR_HAVE_NO_MEMORY(data->string);
2174 return WERR_INVALID_PARAM;
2177 /****************************************************************
2178 _spoolss_GetPrinterData
2179 ****************************************************************/
2181 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2182 struct spoolss_GetPrinterData *r)
2184 struct spoolss_GetPrinterDataEx r2;
2186 r2.in.handle = r->in.handle;
2187 r2.in.key_name = "PrinterDriverData";
2188 r2.in.value_name = r->in.value_name;
2189 r2.in.offered = r->in.offered;
2190 r2.out.type = r->out.type;
2191 r2.out.data = r->out.data;
2192 r2.out.needed = r->out.needed;
2194 return _spoolss_GetPrinterDataEx(p, &r2);
2197 /*********************************************************
2198 Connect to the client machine.
2199 **********************************************************/
2201 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2202 struct sockaddr_storage *client_ss, const char *remote_machine)
2205 struct cli_state *the_cli;
2206 struct sockaddr_storage rm_addr;
2207 char addr[INET6_ADDRSTRLEN];
2209 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2210 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2212 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2213 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2216 print_sockaddr(addr, sizeof(addr), &rm_addr);
2218 rm_addr = *client_ss;
2219 print_sockaddr(addr, sizeof(addr), &rm_addr);
2220 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2224 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2225 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2230 /* setup the connection */
2231 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2232 &rm_addr, 0, "IPC$", "IPC",
2236 0, lp_client_signing(), NULL );
2238 if ( !NT_STATUS_IS_OK( ret ) ) {
2239 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2244 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2245 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2246 cli_shutdown(the_cli);
2251 * Ok - we have an anonymous connection to the IPC$ share.
2252 * Now start the NT Domain stuff :-).
2255 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2256 if (!NT_STATUS_IS_OK(ret)) {
2257 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2258 remote_machine, nt_errstr(ret)));
2259 cli_shutdown(the_cli);
2266 /***************************************************************************
2267 Connect to the client.
2268 ****************************************************************************/
2270 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2271 uint32_t localprinter, uint32_t type,
2272 struct policy_handle *handle,
2273 struct sockaddr_storage *client_ss)
2279 * If it's the first connection, contact the client
2280 * and connect to the IPC$ share anonymously
2282 if (smb_connections==0) {
2283 fstring unix_printer;
2285 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2287 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2290 messaging_register(smbd_messaging_context(), NULL,
2291 MSG_PRINTER_NOTIFY2,
2292 receive_notify2_message_list);
2293 /* Tell the connections db we're now interested in printer
2294 * notify messages. */
2295 serverid_register_msg_flags(
2296 messaging_server_id(smbd_messaging_context()),
2297 true, FLAG_MSG_PRINT_NOTIFY);
2301 * Tell the specific printing tdb we want messages for this printer
2302 * by registering our PID.
2305 if (!print_notify_register_pid(snum))
2306 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2310 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2318 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2319 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2320 win_errstr(result)));
2322 return (W_ERROR_IS_OK(result));
2325 /****************************************************************
2326 ****************************************************************/
2328 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2329 const struct spoolss_NotifyOption *r)
2331 struct spoolss_NotifyOption *option;
2338 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2345 if (!option->count) {
2349 option->types = talloc_zero_array(option,
2350 struct spoolss_NotifyOptionType, option->count);
2351 if (!option->types) {
2352 talloc_free(option);
2356 for (i=0; i < option->count; i++) {
2357 option->types[i] = r->types[i];
2359 if (option->types[i].count) {
2360 option->types[i].fields = talloc_zero_array(option,
2361 union spoolss_Field, option->types[i].count);
2362 if (!option->types[i].fields) {
2363 talloc_free(option);
2366 for (k=0; k<option->types[i].count; k++) {
2367 option->types[i].fields[k] =
2368 r->types[i].fields[k];
2376 /****************************************************************
2377 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2379 * before replying OK: status=0 a rpc call is made to the workstation
2380 * asking ReplyOpenPrinter
2382 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2383 * called from api_spoolss_rffpcnex
2384 ****************************************************************/
2386 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2387 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2390 struct spoolss_NotifyOption *option = r->in.notify_options;
2391 struct sockaddr_storage client_ss;
2393 /* store the notify value in the printer struct */
2395 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2398 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2399 "Invalid handle (%s:%u:%u).\n",
2400 OUR_HANDLE(r->in.handle)));
2404 Printer->notify.flags = r->in.flags;
2405 Printer->notify.options = r->in.options;
2406 Printer->notify.printerlocal = r->in.printer_local;
2408 TALLOC_FREE(Printer->notify.option);
2409 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2411 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2413 /* Connect to the client machine and send a ReplyOpenPrinter */
2415 if ( Printer->printer_type == SPLHND_SERVER)
2417 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2418 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2421 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2422 "client_address is %s\n", p->client_address));
2424 if (!interpret_string_addr(&client_ss, p->client_address,
2426 return WERR_SERVER_UNAVAILABLE;
2429 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2430 Printer->notify.printerlocal, 1,
2431 &Printer->notify.client_hnd, &client_ss))
2432 return WERR_SERVER_UNAVAILABLE;
2434 Printer->notify.client_connected = true;
2439 /*******************************************************************
2440 * fill a notify_info_data with the servername
2441 ********************************************************************/
2443 static void spoolss_notify_server_name(int snum,
2444 struct spoolss_Notify *data,
2445 print_queue_struct *queue,
2446 NT_PRINTER_INFO_LEVEL *printer,
2447 TALLOC_CTX *mem_ctx)
2449 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2452 /*******************************************************************
2453 * fill a notify_info_data with the printername (not including the servername).
2454 ********************************************************************/
2456 static void spoolss_notify_printer_name(int snum,
2457 struct spoolss_Notify *data,
2458 print_queue_struct *queue,
2459 NT_PRINTER_INFO_LEVEL *printer,
2460 TALLOC_CTX *mem_ctx)
2462 /* the notify name should not contain the \\server\ part */
2463 char *p = strrchr(printer->info_2->printername, '\\');
2466 p = printer->info_2->printername;
2471 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2474 /*******************************************************************
2475 * fill a notify_info_data with the servicename
2476 ********************************************************************/
2478 static void spoolss_notify_share_name(int snum,
2479 struct spoolss_Notify *data,
2480 print_queue_struct *queue,
2481 NT_PRINTER_INFO_LEVEL *printer,
2482 TALLOC_CTX *mem_ctx)
2484 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2487 /*******************************************************************
2488 * fill a notify_info_data with the port name
2489 ********************************************************************/
2491 static void spoolss_notify_port_name(int snum,
2492 struct spoolss_Notify *data,
2493 print_queue_struct *queue,
2494 NT_PRINTER_INFO_LEVEL *printer,
2495 TALLOC_CTX *mem_ctx)
2497 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2500 /*******************************************************************
2501 * fill a notify_info_data with the printername
2502 * but it doesn't exist, have to see what to do
2503 ********************************************************************/
2505 static void spoolss_notify_driver_name(int snum,
2506 struct spoolss_Notify *data,
2507 print_queue_struct *queue,
2508 NT_PRINTER_INFO_LEVEL *printer,
2509 TALLOC_CTX *mem_ctx)
2511 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2514 /*******************************************************************
2515 * fill a notify_info_data with the comment
2516 ********************************************************************/
2518 static void spoolss_notify_comment(int snum,
2519 struct spoolss_Notify *data,
2520 print_queue_struct *queue,
2521 NT_PRINTER_INFO_LEVEL *printer,
2522 TALLOC_CTX *mem_ctx)
2526 if (*printer->info_2->comment == '\0') {
2527 p = lp_comment(snum);
2529 p = printer->info_2->comment;
2532 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2535 /*******************************************************************
2536 * fill a notify_info_data with the comment
2537 * location = "Room 1, floor 2, building 3"
2538 ********************************************************************/
2540 static void spoolss_notify_location(int snum,
2541 struct spoolss_Notify *data,
2542 print_queue_struct *queue,
2543 NT_PRINTER_INFO_LEVEL *printer,
2544 TALLOC_CTX *mem_ctx)
2546 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2549 /*******************************************************************
2550 * fill a notify_info_data with the device mode
2551 * jfm:xxxx don't to it for know but that's a real problem !!!
2552 ********************************************************************/
2554 static void spoolss_notify_devmode(int snum,
2555 struct spoolss_Notify *data,
2556 print_queue_struct *queue,
2557 NT_PRINTER_INFO_LEVEL *printer,
2558 TALLOC_CTX *mem_ctx)
2560 /* for a dummy implementation we have to zero the fields */
2561 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2564 /*******************************************************************
2565 * fill a notify_info_data with the separator file name
2566 ********************************************************************/
2568 static void spoolss_notify_sepfile(int snum,
2569 struct spoolss_Notify *data,
2570 print_queue_struct *queue,
2571 NT_PRINTER_INFO_LEVEL *printer,
2572 TALLOC_CTX *mem_ctx)
2574 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2577 /*******************************************************************
2578 * fill a notify_info_data with the print processor
2579 * jfm:xxxx return always winprint to indicate we don't do anything to it
2580 ********************************************************************/
2582 static void spoolss_notify_print_processor(int snum,
2583 struct spoolss_Notify *data,
2584 print_queue_struct *queue,
2585 NT_PRINTER_INFO_LEVEL *printer,
2586 TALLOC_CTX *mem_ctx)
2588 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2591 /*******************************************************************
2592 * fill a notify_info_data with the print processor options
2593 * jfm:xxxx send an empty string
2594 ********************************************************************/
2596 static void spoolss_notify_parameters(int snum,
2597 struct spoolss_Notify *data,
2598 print_queue_struct *queue,
2599 NT_PRINTER_INFO_LEVEL *printer,
2600 TALLOC_CTX *mem_ctx)
2602 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2605 /*******************************************************************
2606 * fill a notify_info_data with the data type
2607 * jfm:xxxx always send RAW as data type
2608 ********************************************************************/
2610 static void spoolss_notify_datatype(int snum,
2611 struct spoolss_Notify *data,
2612 print_queue_struct *queue,
2613 NT_PRINTER_INFO_LEVEL *printer,
2614 TALLOC_CTX *mem_ctx)
2616 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2619 /*******************************************************************
2620 * fill a notify_info_data with the security descriptor
2621 * jfm:xxxx send an null pointer to say no security desc
2622 * have to implement security before !
2623 ********************************************************************/
2625 static void spoolss_notify_security_desc(int snum,
2626 struct spoolss_Notify *data,
2627 print_queue_struct *queue,
2628 NT_PRINTER_INFO_LEVEL *printer,
2629 TALLOC_CTX *mem_ctx)
2631 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2632 printer->info_2->secdesc_buf->sd_size,
2633 printer->info_2->secdesc_buf->sd);
2636 /*******************************************************************
2637 * fill a notify_info_data with the attributes
2638 * jfm:xxxx a samba printer is always shared
2639 ********************************************************************/
2641 static void spoolss_notify_attributes(int snum,
2642 struct spoolss_Notify *data,
2643 print_queue_struct *queue,
2644 NT_PRINTER_INFO_LEVEL *printer,
2645 TALLOC_CTX *mem_ctx)
2647 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2650 /*******************************************************************
2651 * fill a notify_info_data with the priority
2652 ********************************************************************/
2654 static void spoolss_notify_priority(int snum,
2655 struct spoolss_Notify *data,
2656 print_queue_struct *queue,
2657 NT_PRINTER_INFO_LEVEL *printer,
2658 TALLOC_CTX *mem_ctx)
2660 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2663 /*******************************************************************
2664 * fill a notify_info_data with the default priority
2665 ********************************************************************/
2667 static void spoolss_notify_default_priority(int snum,
2668 struct spoolss_Notify *data,
2669 print_queue_struct *queue,
2670 NT_PRINTER_INFO_LEVEL *printer,
2671 TALLOC_CTX *mem_ctx)
2673 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2676 /*******************************************************************
2677 * fill a notify_info_data with the start time
2678 ********************************************************************/
2680 static void spoolss_notify_start_time(int snum,
2681 struct spoolss_Notify *data,
2682 print_queue_struct *queue,
2683 NT_PRINTER_INFO_LEVEL *printer,
2684 TALLOC_CTX *mem_ctx)
2686 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2689 /*******************************************************************
2690 * fill a notify_info_data with the until time
2691 ********************************************************************/
2693 static void spoolss_notify_until_time(int snum,
2694 struct spoolss_Notify *data,
2695 print_queue_struct *queue,
2696 NT_PRINTER_INFO_LEVEL *printer,
2697 TALLOC_CTX *mem_ctx)
2699 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2702 /*******************************************************************
2703 * fill a notify_info_data with the status
2704 ********************************************************************/
2706 static void spoolss_notify_status(int snum,
2707 struct spoolss_Notify *data,
2708 print_queue_struct *queue,
2709 NT_PRINTER_INFO_LEVEL *printer,
2710 TALLOC_CTX *mem_ctx)
2712 print_status_struct status;
2714 print_queue_length(snum, &status);
2715 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2718 /*******************************************************************
2719 * fill a notify_info_data with the number of jobs queued
2720 ********************************************************************/
2722 static void spoolss_notify_cjobs(int snum,
2723 struct spoolss_Notify *data,
2724 print_queue_struct *queue,
2725 NT_PRINTER_INFO_LEVEL *printer,
2726 TALLOC_CTX *mem_ctx)
2728 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2731 /*******************************************************************
2732 * fill a notify_info_data with the average ppm
2733 ********************************************************************/
2735 static void spoolss_notify_average_ppm(int snum,
2736 struct spoolss_Notify *data,
2737 print_queue_struct *queue,
2738 NT_PRINTER_INFO_LEVEL *printer,
2739 TALLOC_CTX *mem_ctx)
2741 /* always respond 8 pages per minutes */
2742 /* a little hard ! */
2743 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2746 /*******************************************************************
2747 * fill a notify_info_data with username
2748 ********************************************************************/
2750 static void spoolss_notify_username(int snum,
2751 struct spoolss_Notify *data,
2752 print_queue_struct *queue,
2753 NT_PRINTER_INFO_LEVEL *printer,
2754 TALLOC_CTX *mem_ctx)
2756 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2759 /*******************************************************************
2760 * fill a notify_info_data with job status
2761 ********************************************************************/
2763 static void spoolss_notify_job_status(int snum,
2764 struct spoolss_Notify *data,
2765 print_queue_struct *queue,
2766 NT_PRINTER_INFO_LEVEL *printer,
2767 TALLOC_CTX *mem_ctx)
2769 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2772 /*******************************************************************
2773 * fill a notify_info_data with job name
2774 ********************************************************************/
2776 static void spoolss_notify_job_name(int snum,
2777 struct spoolss_Notify *data,
2778 print_queue_struct *queue,
2779 NT_PRINTER_INFO_LEVEL *printer,
2780 TALLOC_CTX *mem_ctx)
2782 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2785 /*******************************************************************
2786 * fill a notify_info_data with job status
2787 ********************************************************************/
2789 static void spoolss_notify_job_status_string(int snum,
2790 struct spoolss_Notify *data,
2791 print_queue_struct *queue,
2792 NT_PRINTER_INFO_LEVEL *printer,
2793 TALLOC_CTX *mem_ctx)
2796 * Now we're returning job status codes we just return a "" here. JRA.
2801 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2804 switch (queue->status) {
2809 p = ""; /* NT provides the paused string */
2818 #endif /* NO LONGER NEEDED. */
2820 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2823 /*******************************************************************
2824 * fill a notify_info_data with job time
2825 ********************************************************************/
2827 static void spoolss_notify_job_time(int snum,
2828 struct spoolss_Notify *data,
2829 print_queue_struct *queue,
2830 NT_PRINTER_INFO_LEVEL *printer,
2831 TALLOC_CTX *mem_ctx)
2833 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2836 /*******************************************************************
2837 * fill a notify_info_data with job size
2838 ********************************************************************/
2840 static void spoolss_notify_job_size(int snum,
2841 struct spoolss_Notify *data,
2842 print_queue_struct *queue,
2843 NT_PRINTER_INFO_LEVEL *printer,
2844 TALLOC_CTX *mem_ctx)
2846 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2849 /*******************************************************************
2850 * fill a notify_info_data with page info
2851 ********************************************************************/
2852 static void spoolss_notify_total_pages(int snum,
2853 struct spoolss_Notify *data,
2854 print_queue_struct *queue,
2855 NT_PRINTER_INFO_LEVEL *printer,
2856 TALLOC_CTX *mem_ctx)
2858 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2861 /*******************************************************************
2862 * fill a notify_info_data with pages printed info.
2863 ********************************************************************/
2864 static void spoolss_notify_pages_printed(int snum,
2865 struct spoolss_Notify *data,
2866 print_queue_struct *queue,
2867 NT_PRINTER_INFO_LEVEL *printer,
2868 TALLOC_CTX *mem_ctx)
2870 /* Add code when back-end tracks this */
2871 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2874 /*******************************************************************
2875 Fill a notify_info_data with job position.
2876 ********************************************************************/
2878 static void spoolss_notify_job_position(int snum,
2879 struct spoolss_Notify *data,
2880 print_queue_struct *queue,
2881 NT_PRINTER_INFO_LEVEL *printer,
2882 TALLOC_CTX *mem_ctx)
2884 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2887 /*******************************************************************
2888 Fill a notify_info_data with submitted time.
2889 ********************************************************************/
2891 static void spoolss_notify_submitted_time(int snum,
2892 struct spoolss_Notify *data,
2893 print_queue_struct *queue,
2894 NT_PRINTER_INFO_LEVEL *printer,
2895 TALLOC_CTX *mem_ctx)
2897 data->data.string.string = NULL;
2898 data->data.string.size = 0;
2900 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2901 &data->data.string.string,
2902 &data->data.string.size);
2906 struct s_notify_info_data_table
2908 enum spoolss_NotifyType type;
2911 enum spoolss_NotifyTable variable_type;
2912 void (*fn) (int snum, struct spoolss_Notify *data,
2913 print_queue_struct *queue,
2914 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2917 /* A table describing the various print notification constants and
2918 whether the notification data is a pointer to a variable sized
2919 buffer, a one value uint32_t or a two value uint32_t. */
2921 static const struct s_notify_info_data_table notify_info_data_table[] =
2923 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2924 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2925 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2926 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2927 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2928 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2929 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2930 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2931 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2932 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2933 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2934 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2935 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2936 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2937 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2938 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2939 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2940 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2941 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2942 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2943 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2944 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
2945 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
2946 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
2948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2949 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2950 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2951 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2952 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2953 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2954 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2955 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2956 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2957 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2958 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2959 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
2960 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
2961 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
2962 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
2963 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2964 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
2965 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
2966 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2967 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2968 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
2969 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
2970 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
2971 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
2974 /*******************************************************************
2975 Return the variable_type of info_data structure.
2976 ********************************************************************/
2978 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
2983 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2984 if ( (notify_info_data_table[i].type == type) &&
2985 (notify_info_data_table[i].field == field) ) {
2986 return notify_info_data_table[i].variable_type;
2990 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2995 /****************************************************************************
2996 ****************************************************************************/
2998 static bool search_notify(enum spoolss_NotifyType type,
3004 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3005 if (notify_info_data_table[i].type == type &&
3006 notify_info_data_table[i].field == field &&
3007 notify_info_data_table[i].fn != NULL) {
3016 /****************************************************************************
3017 ****************************************************************************/
3019 void construct_info_data(struct spoolss_Notify *info_data,
3020 enum spoolss_NotifyType type,
3024 info_data->type = type;
3025 info_data->field.field = field;
3026 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3027 info_data->job_id = id;
3030 /*******************************************************************
3032 * fill a notify_info struct with info asked
3034 ********************************************************************/
3036 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3037 struct spoolss_NotifyInfo *info,
3039 const struct spoolss_NotifyOptionType *option_type,
3041 TALLOC_CTX *mem_ctx)
3044 enum spoolss_NotifyType type;
3047 struct spoolss_Notify *current_data;
3048 NT_PRINTER_INFO_LEVEL *printer = NULL;
3049 print_queue_struct *queue=NULL;
3051 type = option_type->type;
3053 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3054 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3055 option_type->count, lp_servicename(snum)));
3057 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3060 for(field_num=0; field_num < option_type->count; field_num++) {
3061 field = option_type->fields[field_num].field;
3063 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3065 if (!search_notify(type, field, &j) )
3068 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3069 struct spoolss_Notify,
3071 if (info->notifies == NULL) {
3072 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3073 free_a_printer(&printer, 2);
3077 current_data = &info->notifies[info->count];
3079 construct_info_data(current_data, type, field, id);
3081 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3082 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3084 notify_info_data_table[j].fn(snum, current_data, queue,
3090 free_a_printer(&printer, 2);
3094 /*******************************************************************
3096 * fill a notify_info struct with info asked
3098 ********************************************************************/
3100 static bool construct_notify_jobs_info(print_queue_struct *queue,
3101 struct spoolss_NotifyInfo *info,
3102 NT_PRINTER_INFO_LEVEL *printer,
3104 const struct spoolss_NotifyOptionType *option_type,
3106 TALLOC_CTX *mem_ctx)
3109 enum spoolss_NotifyType type;
3111 struct spoolss_Notify *current_data;
3113 DEBUG(4,("construct_notify_jobs_info\n"));
3115 type = option_type->type;
3117 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3118 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3119 option_type->count));
3121 for(field_num=0; field_num<option_type->count; field_num++) {
3122 field = option_type->fields[field_num].field;
3124 if (!search_notify(type, field, &j) )
3127 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3128 struct spoolss_Notify,
3130 if (info->notifies == NULL) {
3131 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3135 current_data=&(info->notifies[info->count]);
3137 construct_info_data(current_data, type, field, id);
3138 notify_info_data_table[j].fn(snum, current_data, queue,
3147 * JFM: The enumeration is not that simple, it's even non obvious.
3149 * let's take an example: I want to monitor the PRINTER SERVER for
3150 * the printer's name and the number of jobs currently queued.
3151 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3152 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3154 * I have 3 printers on the back of my server.
3156 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3159 * 1 printer 1 name 1
3160 * 2 printer 1 cjob 1
3161 * 3 printer 2 name 2
3162 * 4 printer 2 cjob 2
3163 * 5 printer 3 name 3
3164 * 6 printer 3 name 3
3166 * that's the print server case, the printer case is even worse.
3169 /*******************************************************************
3171 * enumerate all printers on the printserver
3172 * fill a notify_info struct with info asked
3174 ********************************************************************/
3176 static WERROR printserver_notify_info(pipes_struct *p,
3177 struct policy_handle *hnd,
3178 struct spoolss_NotifyInfo *info,
3179 TALLOC_CTX *mem_ctx)
3182 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3183 int n_services=lp_numservices();
3185 struct spoolss_NotifyOption *option;
3186 struct spoolss_NotifyOptionType option_type;
3188 DEBUG(4,("printserver_notify_info\n"));
3193 option = Printer->notify.option;
3196 info->notifies = NULL;
3199 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3200 sending a ffpcn() request first */
3205 for (i=0; i<option->count; i++) {
3206 option_type = option->types[i];
3208 if (option_type.type != PRINTER_NOTIFY_TYPE)
3211 for (snum=0; snum<n_services; snum++)
3213 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3214 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3220 * Debugging information, don't delete.
3223 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3224 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3225 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3227 for (i=0; i<info->count; i++) {
3228 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3229 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3230 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3237 /*******************************************************************
3239 * fill a notify_info struct with info asked
3241 ********************************************************************/
3243 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3244 struct spoolss_NotifyInfo *info,
3245 TALLOC_CTX *mem_ctx)
3248 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3251 struct spoolss_NotifyOption *option;
3252 struct spoolss_NotifyOptionType option_type;
3254 print_queue_struct *queue=NULL;
3255 print_status_struct status;
3257 DEBUG(4,("printer_notify_info\n"));
3262 option = Printer->notify.option;
3266 info->notifies = NULL;
3269 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3270 sending a ffpcn() request first */
3275 get_printer_snum(p, hnd, &snum, NULL);
3277 for (i=0; i<option->count; i++) {
3278 option_type = option->types[i];
3280 switch (option_type.type) {
3281 case PRINTER_NOTIFY_TYPE:
3282 if(construct_notify_printer_info(Printer, info, snum,
3288 case JOB_NOTIFY_TYPE: {
3289 NT_PRINTER_INFO_LEVEL *printer = NULL;
3291 count = print_queue_status(snum, &queue, &status);
3293 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3296 for (j=0; j<count; j++) {
3297 construct_notify_jobs_info(&queue[j], info,
3304 free_a_printer(&printer, 2);
3314 * Debugging information, don't delete.
3317 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3318 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3319 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3321 for (i=0; i<info->count; i++) {
3322 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3323 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3324 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3330 /****************************************************************
3331 _spoolss_RouterRefreshPrinterChangeNotify
3332 ****************************************************************/
3334 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3335 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3337 struct spoolss_NotifyInfo *info;
3339 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3340 WERROR result = WERR_BADFID;
3342 /* we always have a spoolss_NotifyInfo struct */
3343 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3345 result = WERR_NOMEM;
3349 *r->out.info = info;
3352 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3353 "Invalid handle (%s:%u:%u).\n",
3354 OUR_HANDLE(r->in.handle)));
3358 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3361 * We are now using the change value, and
3362 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3363 * I don't have a global notification system, I'm sending back all the
3364 * informations even when _NOTHING_ has changed.
3367 /* We need to keep track of the change value to send back in
3368 RRPCN replies otherwise our updates are ignored. */
3370 Printer->notify.fnpcn = true;
3372 if (Printer->notify.client_connected) {
3373 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3374 "Saving change value in request [%x]\n",
3376 Printer->notify.change = r->in.change_low;
3379 /* just ignore the spoolss_NotifyOption */
3381 switch (Printer->printer_type) {
3383 result = printserver_notify_info(p, r->in.handle,
3387 case SPLHND_PRINTER:
3388 result = printer_notify_info(p, r->in.handle,
3393 Printer->notify.fnpcn = false;
3399 /********************************************************************
3400 * construct_printer_info_0
3401 * fill a printer_info_0 struct
3402 ********************************************************************/
3404 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3405 struct auth_serversupplied_info *server_info,
3406 struct spoolss_PrinterInfo2 *info2,
3407 struct spoolss_PrinterInfo0 *r,
3411 counter_printer_0 *session_counter;
3412 struct timeval setuptime;
3413 print_status_struct status;
3415 r->printername = talloc_strdup(mem_ctx, info2->printername);
3416 W_ERROR_HAVE_NO_MEMORY(r->printername);
3418 r->servername = talloc_strdup(mem_ctx, info2->servername);
3419 W_ERROR_HAVE_NO_MEMORY(r->servername);
3421 count = print_queue_length(snum, &status);
3423 /* check if we already have a counter for this printer */
3424 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3425 if (session_counter->snum == snum)
3429 /* it's the first time, add it to the list */
3430 if (session_counter == NULL) {
3431 session_counter = SMB_MALLOC_P(counter_printer_0);
3432 W_ERROR_HAVE_NO_MEMORY(session_counter);
3433 ZERO_STRUCTP(session_counter);
3434 session_counter->snum = snum;
3435 session_counter->counter = 0;
3436 DLIST_ADD(counter_list, session_counter);
3440 session_counter->counter++;
3446 get_startup_time(&setuptime);
3447 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3450 * the global_counter should be stored in a TDB as it's common to all the clients
3451 * and should be zeroed on samba startup
3453 r->global_counter = session_counter->counter;
3455 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3456 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3457 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3458 r->free_build = SPOOLSS_RELEASE_BUILD;
3460 r->max_spooling = 0;
3461 r->session_counter = session_counter->counter;
3462 r->num_error_out_of_paper = 0x0;
3463 r->num_error_not_ready = 0x0; /* number of print failure */
3465 r->number_of_processors = 0x1;
3466 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3467 r->high_part_total_bytes = 0x0;
3468 winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3469 r->last_error = WERR_OK;
3470 r->status = nt_printq_status(status.status);
3471 r->enumerate_network_printers = 0x0;
3472 r->c_setprinter = 0x0;
3473 r->processor_architecture = 0x0;
3474 r->processor_level = 0x6; /* 6 ???*/
3483 /********************************************************************
3484 * construct_printer_info1
3485 * fill a spoolss_PrinterInfo1 struct
3486 ********************************************************************/
3488 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3489 const struct spoolss_PrinterInfo2 *info2,
3491 struct spoolss_PrinterInfo1 *r,
3496 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3500 W_ERROR_HAVE_NO_MEMORY(r->description);
3502 if (info2->comment == NULL || info2->comment[0] == '\0') {
3503 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3505 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3507 W_ERROR_HAVE_NO_MEMORY(r->comment);
3509 r->name = talloc_strdup(mem_ctx, info2->printername);
3510 W_ERROR_HAVE_NO_MEMORY(r->name);
3515 /********************************************************************
3516 * construct_printer_info2
3517 * fill a spoolss_PrinterInfo2 struct
3518 ********************************************************************/
3520 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3521 const struct spoolss_PrinterInfo2 *info2,
3522 struct spoolss_PrinterInfo2 *r,
3526 print_status_struct status;
3528 count = print_queue_length(snum, &status);
3530 r->servername = talloc_strdup(mem_ctx, info2->servername);
3531 W_ERROR_HAVE_NO_MEMORY(r->servername);
3532 r->printername = talloc_strdup(mem_ctx, info2->printername);
3533 W_ERROR_HAVE_NO_MEMORY(r->printername);
3534 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3535 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3536 r->portname = talloc_strdup(mem_ctx, info2->portname);
3537 W_ERROR_HAVE_NO_MEMORY(r->portname);
3538 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3539 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3541 if (info2->comment[0] == '\0') {
3542 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3544 r->comment = talloc_strdup(mem_ctx, info2->comment);
3546 W_ERROR_HAVE_NO_MEMORY(r->comment);
3548 r->location = talloc_strdup(mem_ctx, info2->location);
3549 W_ERROR_HAVE_NO_MEMORY(r->location);
3550 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
3551 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3552 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
3553 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3554 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
3555 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3556 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
3557 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3559 r->attributes = info2->attributes;
3561 r->priority = info2->priority;
3562 r->defaultpriority = info2->defaultpriority;
3563 r->starttime = info2->starttime;
3564 r->untiltime = info2->untiltime;
3565 r->status = nt_printq_status(status.status);
3567 r->averageppm = info2->averageppm;
3569 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3571 DEBUG(8,("Returning NULL Devicemode!\n"));
3576 if (info2->secdesc != NULL) {
3577 /* don't use talloc_steal() here unless you do a deep steal of all
3578 the SEC_DESC members */
3580 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3586 /********************************************************************
3587 * construct_printer_info3
3588 * fill a spoolss_PrinterInfo3 struct
3589 ********************************************************************/
3591 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3592 const struct spoolss_PrinterInfo2 *info2,
3593 struct spoolss_PrinterInfo3 *r,
3596 /* These are the components of the SD we are returning. */
3598 if (info2->secdesc != NULL) {
3599 /* don't use talloc_steal() here unless you do a deep steal of all
3600 the SEC_DESC members */
3602 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3603 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3609 /********************************************************************
3610 * construct_printer_info4
3611 * fill a spoolss_PrinterInfo4 struct
3612 ********************************************************************/
3614 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3615 const struct spoolss_PrinterInfo2 *info2,
3616 struct spoolss_PrinterInfo4 *r,
3619 r->printername = talloc_strdup(mem_ctx, info2->printername);
3620 W_ERROR_HAVE_NO_MEMORY(r->printername);
3621 r->servername = talloc_strdup(mem_ctx, info2->servername);
3622 W_ERROR_HAVE_NO_MEMORY(r->servername);
3624 r->attributes = info2->attributes;
3629 /********************************************************************
3630 * construct_printer_info5
3631 * fill a spoolss_PrinterInfo5 struct
3632 ********************************************************************/
3634 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3635 const struct spoolss_PrinterInfo2 *info2,
3636 struct spoolss_PrinterInfo5 *r,
3639 r->printername = talloc_strdup(mem_ctx, info2->printername);
3640 W_ERROR_HAVE_NO_MEMORY(r->printername);
3641 r->portname = talloc_strdup(mem_ctx, info2->portname);
3642 W_ERROR_HAVE_NO_MEMORY(r->portname);
3644 r->attributes = info2->attributes;
3646 /* these two are not used by NT+ according to MSDN */
3647 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3648 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3653 /********************************************************************
3654 * construct_printer_info_6
3655 * fill a spoolss_PrinterInfo6 struct
3656 ********************************************************************/
3658 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3659 const struct spoolss_PrinterInfo2 *info2,
3660 struct spoolss_PrinterInfo6 *r,
3664 print_status_struct status;
3666 count = print_queue_length(snum, &status);
3668 r->status = nt_printq_status(status.status);
3673 /********************************************************************
3674 * construct_printer_info7
3675 * fill a spoolss_PrinterInfo7 struct
3676 ********************************************************************/
3678 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3679 Printer_entry *print_hnd,
3680 struct spoolss_PrinterInfo7 *r,
3685 if (is_printer_published(print_hnd, snum, &guid)) {
3686 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3687 r->action = DSPRINT_PUBLISH;
3689 r->guid = talloc_strdup(mem_ctx, "");
3690 r->action = DSPRINT_UNPUBLISH;
3692 W_ERROR_HAVE_NO_MEMORY(r->guid);
3697 /********************************************************************
3698 * construct_printer_info8
3699 * fill a spoolss_PrinterInfo8 struct
3700 ********************************************************************/
3702 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3703 const struct spoolss_PrinterInfo2 *info2,
3704 struct spoolss_DeviceModeInfo *r,
3707 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3709 DEBUG(8,("Returning NULL Devicemode!\n"));
3716 /********************************************************************
3717 ********************************************************************/
3719 static bool snum_is_shared_printer(int snum)
3721 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3724 /********************************************************************
3725 Spoolss_enumprinters.
3726 ********************************************************************/
3728 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3729 struct auth_serversupplied_info *server_info,
3732 union spoolss_PrinterInfo **info_p,
3736 int n_services = lp_numservices();
3737 union spoolss_PrinterInfo *info = NULL;
3739 WERROR result = WERR_OK;
3744 for (snum = 0; snum < n_services; snum++) {
3746 const char *printer;
3747 struct spoolss_PrinterInfo2 *info2;
3749 if (!snum_is_shared_printer(snum)) {
3753 printer = lp_const_servicename(snum);
3755 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3758 result = winreg_create_printer(mem_ctx,
3762 if (!W_ERROR_IS_OK(result)) {
3766 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3767 union spoolss_PrinterInfo,
3770 result = WERR_NOMEM;
3774 result = winreg_get_printer(mem_ctx, server_info,
3775 NULL, printer, &info2);
3776 if (!W_ERROR_IS_OK(result)) {
3782 result = construct_printer_info0(info, server_info, info2,
3783 &info[count].info0, snum);
3786 result = construct_printer_info1(info, info2, flags,
3787 &info[count].info1, snum);
3790 result = construct_printer_info2(info, info2,
3791 &info[count].info2, snum);
3794 result = construct_printer_info4(info, info2,
3795 &info[count].info4, snum);
3798 result = construct_printer_info5(info, info2,
3799 &info[count].info5, snum);
3803 result = WERR_UNKNOWN_LEVEL;
3807 if (!W_ERROR_IS_OK(result)) {
3818 if (!W_ERROR_IS_OK(result)) {
3828 /********************************************************************
3829 * handle enumeration of printers at level 0
3830 ********************************************************************/
3832 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3833 struct auth_serversupplied_info *server_info,
3835 const char *servername,
3836 union spoolss_PrinterInfo **info,
3839 DEBUG(4,("enum_all_printers_info_0\n"));
3841 return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3845 /********************************************************************
3846 ********************************************************************/
3848 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3849 struct auth_serversupplied_info *server_info,
3851 union spoolss_PrinterInfo **info,
3854 DEBUG(4,("enum_all_printers_info_1\n"));
3856 return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3859 /********************************************************************
3860 enum_all_printers_info_1_local.
3861 *********************************************************************/
3863 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3864 struct auth_serversupplied_info *server_info,
3865 union spoolss_PrinterInfo **info,
3868 DEBUG(4,("enum_all_printers_info_1_local\n"));
3870 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3873 /********************************************************************
3874 enum_all_printers_info_1_name.
3875 *********************************************************************/
3877 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3878 struct auth_serversupplied_info *server_info,
3880 union spoolss_PrinterInfo **info,
3883 const char *s = name;
3885 DEBUG(4,("enum_all_printers_info_1_name\n"));
3887 if ((name[0] == '\\') && (name[1] == '\\')) {
3891 if (!is_myname_or_ipaddr(s)) {
3892 return WERR_INVALID_NAME;
3895 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3898 /********************************************************************
3899 enum_all_printers_info_1_network.
3900 *********************************************************************/
3902 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3903 struct auth_serversupplied_info *server_info,
3905 union spoolss_PrinterInfo **info,
3908 const char *s = name;
3910 DEBUG(4,("enum_all_printers_info_1_network\n"));
3912 /* If we respond to a enum_printers level 1 on our name with flags
3913 set to PRINTER_ENUM_REMOTE with a list of printers then these
3914 printers incorrectly appear in the APW browse list.
3915 Specifically the printers for the server appear at the workgroup
3916 level where all the other servers in the domain are
3917 listed. Windows responds to this call with a
3918 WERR_CAN_NOT_COMPLETE so we should do the same. */
3920 if (name[0] == '\\' && name[1] == '\\') {
3924 if (is_myname_or_ipaddr(s)) {
3925 return WERR_CAN_NOT_COMPLETE;
3928 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
3931 /********************************************************************
3932 * api_spoolss_enumprinters
3934 * called from api_spoolss_enumprinters (see this to understand)
3935 ********************************************************************/
3937 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3938 struct auth_serversupplied_info *server_info,
3939 union spoolss_PrinterInfo **info,
3942 DEBUG(4,("enum_all_printers_info_2\n"));
3944 return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
3947 /********************************************************************
3948 * handle enumeration of printers at level 1
3949 ********************************************************************/
3951 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3952 struct auth_serversupplied_info *server_info,
3955 union spoolss_PrinterInfo **info,
3958 /* Not all the flags are equals */
3960 if (flags & PRINTER_ENUM_LOCAL) {
3961 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
3964 if (flags & PRINTER_ENUM_NAME) {
3965 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
3968 if (flags & PRINTER_ENUM_NETWORK) {
3969 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
3972 return WERR_OK; /* NT4sp5 does that */
3975 /********************************************************************
3976 * handle enumeration of printers at level 2
3977 ********************************************************************/
3979 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
3980 struct auth_serversupplied_info *server_info,
3982 const char *servername,
3983 union spoolss_PrinterInfo **info,
3986 if (flags & PRINTER_ENUM_LOCAL) {
3987 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
3990 if (flags & PRINTER_ENUM_NAME) {
3991 if (!is_myname_or_ipaddr(canon_servername(servername))) {
3992 return WERR_INVALID_NAME;
3995 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
3998 if (flags & PRINTER_ENUM_REMOTE) {
3999 return WERR_UNKNOWN_LEVEL;
4005 /********************************************************************
4006 * handle enumeration of printers at level 4
4007 ********************************************************************/
4009 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4010 struct auth_serversupplied_info *server_info,
4012 const char *servername,
4013 union spoolss_PrinterInfo **info,
4016 DEBUG(4,("enum_all_printers_info_4\n"));
4018 return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4022 /********************************************************************
4023 * handle enumeration of printers at level 5
4024 ********************************************************************/
4026 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4027 struct auth_serversupplied_info *server_info,
4029 const char *servername,
4030 union spoolss_PrinterInfo **info,
4033 DEBUG(4,("enum_all_printers_info_5\n"));
4035 return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4038 /****************************************************************
4039 _spoolss_EnumPrinters
4040 ****************************************************************/
4042 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4043 struct spoolss_EnumPrinters *r)
4045 const char *name = NULL;
4048 /* that's an [in out] buffer */
4050 if (!r->in.buffer && (r->in.offered != 0)) {
4051 return WERR_INVALID_PARAM;
4054 DEBUG(4,("_spoolss_EnumPrinters\n"));
4058 *r->out.info = NULL;
4062 * flags==PRINTER_ENUM_NAME
4063 * if name=="" then enumerates all printers
4064 * if name!="" then enumerate the printer
4065 * flags==PRINTER_ENUM_REMOTE
4066 * name is NULL, enumerate printers
4067 * Level 2: name!="" enumerates printers, name can't be NULL
4068 * Level 3: doesn't exist
4069 * Level 4: does a local registry lookup
4070 * Level 5: same as Level 2
4074 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4075 W_ERROR_HAVE_NO_MEMORY(name);
4078 switch (r->in.level) {
4080 result = enumprinters_level0(p->mem_ctx, p->server_info,
4082 r->out.info, r->out.count);
4085 result = enumprinters_level1(p->mem_ctx, p->server_info,
4087 r->out.info, r->out.count);
4090 result = enumprinters_level2(p->mem_ctx, p->server_info,
4092 r->out.info, r->out.count);
4095 result = enumprinters_level4(p->mem_ctx, p->server_info,
4097 r->out.info, r->out.count);
4100 result = enumprinters_level5(p->mem_ctx, p->server_info,
4102 r->out.info, r->out.count);
4105 return WERR_UNKNOWN_LEVEL;
4108 if (!W_ERROR_IS_OK(result)) {
4112 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4113 spoolss_EnumPrinters,
4114 *r->out.info, r->in.level,
4116 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4117 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4119 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4122 /****************************************************************
4124 ****************************************************************/
4126 WERROR _spoolss_GetPrinter(pipes_struct *p,
4127 struct spoolss_GetPrinter *r)
4129 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4130 struct spoolss_PrinterInfo2 *info2 = NULL;
4131 WERROR result = WERR_OK;
4132 const char *servername = NULL;
4135 /* that's an [in out] buffer */
4137 if (!r->in.buffer && (r->in.offered != 0)) {
4138 return WERR_INVALID_PARAM;
4143 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4147 if (Printer != NULL || Printer->servername != NULL) {
4148 servername = Printer->servername;
4151 result = winreg_get_printer(p->mem_ctx,
4154 lp_const_servicename(snum),
4156 if (!W_ERROR_IS_OK(result)) {
4160 switch (r->in.level) {
4162 result = construct_printer_info0(p->mem_ctx, p->server_info,
4164 &r->out.info->info0, snum);
4167 result = construct_printer_info1(p->mem_ctx, info2,
4169 &r->out.info->info1, snum);
4172 result = construct_printer_info2(p->mem_ctx, info2,
4173 &r->out.info->info2, snum);
4176 result = construct_printer_info3(p->mem_ctx, info2,
4177 &r->out.info->info3, snum);
4180 result = construct_printer_info4(p->mem_ctx, info2,
4181 &r->out.info->info4, snum);
4184 result = construct_printer_info5(p->mem_ctx, info2,
4185 &r->out.info->info5, snum);
4188 result = construct_printer_info6(p->mem_ctx, info2,
4189 &r->out.info->info6, snum);
4192 result = construct_printer_info7(p->mem_ctx, Printer,
4193 &r->out.info->info7, snum);
4196 result = construct_printer_info8(p->mem_ctx, info2,
4197 &r->out.info->info8, snum);
4200 result = WERR_UNKNOWN_LEVEL;
4204 if (!W_ERROR_IS_OK(result)) {
4205 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4206 r->in.level, win_errstr(result)));
4207 TALLOC_FREE(r->out.info);
4211 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4212 r->out.info, r->in.level);
4213 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4215 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4218 /********************************************************************
4219 ********************************************************************/
4221 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4222 const char **string_array,
4223 const char *cservername)
4225 int i, num_strings = 0;
4226 const char **array = NULL;
4228 if (!string_array) {
4232 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4234 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4235 cservername, string_array[i]);
4242 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4249 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4250 &array, &num_strings);
4256 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4258 if (in && strlen(in)) { \
4259 out = talloc_strdup(mem_ctx, in); \
4260 W_ERROR_HAVE_NO_MEMORY(out); \
4266 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4268 if (in && strlen(in)) { \
4269 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4271 out = talloc_strdup(mem_ctx, ""); \
4273 W_ERROR_HAVE_NO_MEMORY(out); \
4276 /********************************************************************
4277 * fill a spoolss_DriverInfo1 struct
4278 ********************************************************************/
4280 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4281 struct spoolss_DriverInfo1 *r,
4282 const struct spoolss_DriverInfo8 *driver,
4283 const char *servername)
4285 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4286 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4291 /********************************************************************
4292 * fill a spoolss_DriverInfo2 struct
4293 ********************************************************************/
4295 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4296 struct spoolss_DriverInfo2 *r,
4297 const struct spoolss_DriverInfo8 *driver,
4298 const char *servername)
4301 const char *cservername = canon_servername(servername);
4303 r->version = driver->version;
4305 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4306 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4307 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4308 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4310 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4311 driver->driver_path,
4314 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4318 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4319 driver->config_file,
4325 /********************************************************************
4326 * fill a spoolss_DriverInfo3 struct
4327 ********************************************************************/
4329 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4330 struct spoolss_DriverInfo3 *r,
4331 const struct spoolss_DriverInfo8 *driver,
4332 const char *servername)
4334 const char *cservername = canon_servername(servername);
4336 r->version = driver->version;
4338 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4339 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4340 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4341 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4343 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4344 driver->driver_path,
4347 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4351 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4352 driver->config_file,
4355 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4359 FILL_DRIVER_STRING(mem_ctx,
4360 driver->monitor_name,
4363 FILL_DRIVER_STRING(mem_ctx,
4364 driver->default_datatype,
4365 r->default_datatype);
4367 r->dependent_files = string_array_from_driver_info(mem_ctx,
4368 driver->dependent_files,
4373 /********************************************************************
4374 * fill a spoolss_DriverInfo4 struct
4375 ********************************************************************/
4377 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4378 struct spoolss_DriverInfo4 *r,
4379 const struct spoolss_DriverInfo8 *driver,
4380 const char *servername)
4382 const char *cservername = canon_servername(servername);
4384 r->version = driver->version;
4386 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4387 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4388 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4389 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4391 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4392 driver->driver_path,
4395 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4399 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4400 driver->config_file,
4403 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4407 r->dependent_files = string_array_from_driver_info(mem_ctx,
4408 driver->dependent_files,
4411 FILL_DRIVER_STRING(mem_ctx,
4412 driver->monitor_name,
4415 FILL_DRIVER_STRING(mem_ctx,
4416 driver->default_datatype,
4417 r->default_datatype);
4419 r->previous_names = string_array_from_driver_info(mem_ctx,
4420 driver->previous_names,
4426 /********************************************************************
4427 * fill a spoolss_DriverInfo5 struct
4428 ********************************************************************/
4430 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4431 struct spoolss_DriverInfo5 *r,
4432 const struct spoolss_DriverInfo8 *driver,
4433 const char *servername)
4435 const char *cservername = canon_servername(servername);
4437 r->version = driver->version;
4439 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4440 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4441 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4442 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4444 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4445 driver->driver_path,
4448 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4452 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4453 driver->config_file,
4456 r->driver_attributes = 0;
4457 r->config_version = 0;
4458 r->driver_version = 0;
4462 /********************************************************************
4463 * fill a spoolss_DriverInfo6 struct
4464 ********************************************************************/
4466 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4467 struct spoolss_DriverInfo6 *r,
4468 const struct spoolss_DriverInfo8 *driver,
4469 const char *servername)
4471 const char *cservername = canon_servername(servername);
4473 r->version = driver->version;
4475 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4476 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4477 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4478 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4480 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4481 driver->driver_path,
4484 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4488 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4489 driver->config_file,
4492 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4496 FILL_DRIVER_STRING(mem_ctx,
4497 driver->monitor_name,
4500 FILL_DRIVER_STRING(mem_ctx,
4501 driver->default_datatype,
4502 r->default_datatype);
4504 r->dependent_files = string_array_from_driver_info(mem_ctx,
4505 driver->dependent_files,
4507 r->previous_names = string_array_from_driver_info(mem_ctx,
4508 driver->previous_names,
4511 r->driver_date = driver->driver_date;
4512 r->driver_version = driver->driver_version;
4514 FILL_DRIVER_STRING(mem_ctx,
4515 driver->manufacturer_name,
4516 r->manufacturer_name);
4517 FILL_DRIVER_STRING(mem_ctx,
4518 driver->manufacturer_url,
4519 r->manufacturer_url);
4520 FILL_DRIVER_STRING(mem_ctx,
4521 driver->hardware_id,
4523 FILL_DRIVER_STRING(mem_ctx,
4530 /********************************************************************
4531 * fill a spoolss_DriverInfo8 struct
4532 ********************************************************************/
4534 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4535 struct spoolss_DriverInfo8 *r,
4536 const struct spoolss_DriverInfo8 *driver,
4537 const char *servername)
4539 const char *cservername = canon_servername(servername);
4541 r->version = driver->version;
4543 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4544 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4545 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4546 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4548 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4549 driver->driver_path,
4552 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4556 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4557 driver->config_file,
4560 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4564 FILL_DRIVER_STRING(mem_ctx,
4565 driver->monitor_name,
4568 FILL_DRIVER_STRING(mem_ctx,
4569 driver->default_datatype,
4570 r->default_datatype);
4572 r->dependent_files = string_array_from_driver_info(mem_ctx,
4573 driver->dependent_files,
4575 r->previous_names = string_array_from_driver_info(mem_ctx,
4576 driver->previous_names,
4579 r->driver_date = driver->driver_date;
4580 r->driver_version = driver->driver_version;
4582 FILL_DRIVER_STRING(mem_ctx,
4583 driver->manufacturer_name,
4584 r->manufacturer_name);
4585 FILL_DRIVER_STRING(mem_ctx,
4586 driver->manufacturer_url,
4587 r->manufacturer_url);
4588 FILL_DRIVER_STRING(mem_ctx,
4589 driver->hardware_id,
4591 FILL_DRIVER_STRING(mem_ctx,
4595 FILL_DRIVER_STRING(mem_ctx,
4596 driver->print_processor,
4597 r->print_processor);
4598 FILL_DRIVER_STRING(mem_ctx,
4599 driver->vendor_setup,
4602 r->color_profiles = string_array_from_driver_info(mem_ctx,
4603 driver->color_profiles,
4606 FILL_DRIVER_STRING(mem_ctx,
4610 r->printer_driver_attributes = driver->printer_driver_attributes;
4612 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4613 driver->core_driver_dependencies,
4616 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4617 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4622 #if 0 /* disabled until marshalling issues are resolved - gd */
4623 /********************************************************************
4624 ********************************************************************/
4626 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4627 struct spoolss_DriverFileInfo *r,
4628 const char *cservername,
4629 const char *file_name,
4630 enum spoolss_DriverFileType file_type,
4631 uint32_t file_version)
4633 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4634 cservername, file_name);
4635 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4636 r->file_type = file_type;
4637 r->file_version = file_version;
4642 /********************************************************************
4643 ********************************************************************/
4645 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4646 const struct spoolss_DriverInfo8 *driver,
4647 const char *cservername,
4648 struct spoolss_DriverFileInfo **info_p,
4651 struct spoolss_DriverFileInfo *info = NULL;
4659 if (strlen(driver->driver_path)) {
4660 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4661 struct spoolss_DriverFileInfo,
4663 W_ERROR_HAVE_NO_MEMORY(info);
4664 result = fill_spoolss_DriverFileInfo(info,
4667 driver->driver_path,
4668 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4670 W_ERROR_NOT_OK_RETURN(result);
4674 if (strlen(driver->config_file)) {
4675 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4676 struct spoolss_DriverFileInfo,
4678 W_ERROR_HAVE_NO_MEMORY(info);
4679 result = fill_spoolss_DriverFileInfo(info,
4682 driver->config_file,
4683 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4685 W_ERROR_NOT_OK_RETURN(result);
4689 if (strlen(driver->data_file)) {
4690 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4691 struct spoolss_DriverFileInfo,
4693 W_ERROR_HAVE_NO_MEMORY(info);
4694 result = fill_spoolss_DriverFileInfo(info,
4698 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4700 W_ERROR_NOT_OK_RETURN(result);
4704 if (strlen(driver->help_file)) {
4705 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4706 struct spoolss_DriverFileInfo,
4708 W_ERROR_HAVE_NO_MEMORY(info);
4709 result = fill_spoolss_DriverFileInfo(info,
4713 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4715 W_ERROR_NOT_OK_RETURN(result);
4719 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4720 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4721 struct spoolss_DriverFileInfo,
4723 W_ERROR_HAVE_NO_MEMORY(info);
4724 result = fill_spoolss_DriverFileInfo(info,
4727 driver->dependent_files[i],
4728 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4730 W_ERROR_NOT_OK_RETURN(result);
4740 /********************************************************************
4741 * fill a spoolss_DriverInfo101 struct
4742 ********************************************************************/
4744 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4745 struct spoolss_DriverInfo101 *r,
4746 const struct spoolss_DriverInfo8 *driver,
4747 const char *servername)
4749 const char *cservername = canon_servername(servername);
4752 r->version = driver->version;
4754 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4755 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4756 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4757 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4759 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4763 if (!W_ERROR_IS_OK(result)) {
4767 FILL_DRIVER_STRING(mem_ctx,
4768 driver->monitor_name,
4771 FILL_DRIVER_STRING(mem_ctx,
4772 driver->default_datatype,
4773 r->default_datatype);
4775 r->previous_names = string_array_from_driver_info(mem_ctx,
4776 driver->previous_names,
4778 r->driver_date = driver->driver_date;
4779 r->driver_version = driver->driver_version;
4781 FILL_DRIVER_STRING(mem_ctx,
4782 driver->manufacturer_name,
4783 r->manufacturer_name);
4784 FILL_DRIVER_STRING(mem_ctx,
4785 driver->manufacturer_url,
4786 r->manufacturer_url);
4787 FILL_DRIVER_STRING(mem_ctx,
4788 driver->hardware_id,
4790 FILL_DRIVER_STRING(mem_ctx,
4797 /********************************************************************
4798 ********************************************************************/
4800 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4801 struct auth_serversupplied_info *server_info,
4803 union spoolss_DriverInfo *r,
4805 const char *servername,
4806 const char *architecture,
4809 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4810 struct spoolss_DriverInfo8 *driver;
4813 result = winreg_get_printer(mem_ctx,
4816 lp_const_servicename(snum),
4819 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4820 win_errstr(result)));
4822 if (!W_ERROR_IS_OK(result)) {
4823 return WERR_INVALID_PRINTER_NAME;
4826 result = winreg_get_driver(mem_ctx, server_info, architecture,
4827 pinfo2->drivername, version, &driver);
4829 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4830 win_errstr(result)));
4832 if (!W_ERROR_IS_OK(result)) {
4834 * Is this a W2k client ?
4838 talloc_free(pinfo2);
4839 return WERR_UNKNOWN_PRINTER_DRIVER;
4842 /* Yes - try again with a WinNT driver. */
4844 result = winreg_get_driver(mem_ctx, server_info, architecture,
4847 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4848 win_errstr(result)));
4849 if (!W_ERROR_IS_OK(result)) {
4850 talloc_free(pinfo2);
4851 return WERR_UNKNOWN_PRINTER_DRIVER;
4857 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4860 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4863 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4866 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4869 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4872 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4875 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
4877 #if 0 /* disabled until marshalling issues are resolved - gd */
4879 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
4883 result = WERR_UNKNOWN_LEVEL;
4887 talloc_free(pinfo2);
4888 talloc_free(driver);
4893 /****************************************************************
4894 _spoolss_GetPrinterDriver2
4895 ****************************************************************/
4897 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
4898 struct spoolss_GetPrinterDriver2 *r)
4900 Printer_entry *printer;
4903 const char *servername;
4906 /* that's an [in out] buffer */
4908 if (!r->in.buffer && (r->in.offered != 0)) {
4909 return WERR_INVALID_PARAM;
4912 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
4914 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
4915 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
4916 return WERR_INVALID_PRINTER_NAME;
4920 *r->out.server_major_version = 0;
4921 *r->out.server_minor_version = 0;
4923 servername = get_server_name(printer);
4925 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4929 result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
4930 r->in.level, r->out.info,
4933 r->in.client_major_version);
4934 if (!W_ERROR_IS_OK(result)) {
4935 TALLOC_FREE(r->out.info);
4939 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
4940 r->out.info, r->in.level);
4941 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4943 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4947 /****************************************************************
4948 _spoolss_StartPagePrinter
4949 ****************************************************************/
4951 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
4952 struct spoolss_StartPagePrinter *r)
4954 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4957 DEBUG(3,("_spoolss_StartPagePrinter: "
4958 "Error in startpageprinter printer handle\n"));
4962 Printer->page_started = true;
4966 /****************************************************************
4967 _spoolss_EndPagePrinter
4968 ****************************************************************/
4970 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
4971 struct spoolss_EndPagePrinter *r)
4975 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4978 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
4979 OUR_HANDLE(r->in.handle)));
4983 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
4986 Printer->page_started = false;
4987 print_job_endpage(snum, Printer->jobid);
4992 /****************************************************************
4993 _spoolss_StartDocPrinter
4994 ****************************************************************/
4996 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
4997 struct spoolss_StartDocPrinter *r)
4999 struct spoolss_DocumentInfo1 *info_1;
5001 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5004 DEBUG(2,("_spoolss_StartDocPrinter: "
5005 "Invalid handle (%s:%u:%u)\n",
5006 OUR_HANDLE(r->in.handle)));
5010 if (r->in.level != 1) {
5011 return WERR_UNKNOWN_LEVEL;
5014 info_1 = r->in.info.info1;
5017 * a nice thing with NT is it doesn't listen to what you tell it.
5018 * when asked to send _only_ RAW datas, it tries to send datas
5021 * So I add checks like in NT Server ...
5024 if (info_1->datatype) {
5025 if (strcmp(info_1->datatype, "RAW") != 0) {
5027 return WERR_INVALID_DATATYPE;
5031 /* get the share number of the printer */
5032 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5036 Printer->jobid = print_job_start(p->server_info, snum,
5037 info_1->document_name,
5040 /* An error occured in print_job_start() so return an appropriate
5043 if (Printer->jobid == -1) {
5044 return map_werror_from_unix(errno);
5047 Printer->document_started = true;
5048 *r->out.job_id = Printer->jobid;
5053 /****************************************************************
5054 _spoolss_EndDocPrinter
5055 ****************************************************************/
5057 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5058 struct spoolss_EndDocPrinter *r)
5060 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5064 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5065 OUR_HANDLE(r->in.handle)));
5069 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5073 Printer->document_started = false;
5074 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5075 /* error codes unhandled so far ... */
5080 /****************************************************************
5081 _spoolss_WritePrinter
5082 ****************************************************************/
5084 WERROR _spoolss_WritePrinter(pipes_struct *p,
5085 struct spoolss_WritePrinter *r)
5087 ssize_t buffer_written;
5089 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5092 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5093 OUR_HANDLE(r->in.handle)));
5094 *r->out.num_written = r->in._data_size;
5098 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5101 buffer_written = print_job_write(snum, Printer->jobid,
5102 (const char *)r->in.data.data,
5104 (size_t)r->in._data_size);
5105 if (buffer_written == (ssize_t)-1) {
5106 *r->out.num_written = 0;
5107 if (errno == ENOSPC)
5108 return WERR_NO_SPOOL_SPACE;
5110 return WERR_ACCESS_DENIED;
5113 *r->out.num_written = r->in._data_size;
5118 /********************************************************************
5119 * api_spoolss_getprinter
5120 * called from the spoolss dispatcher
5122 ********************************************************************/
5124 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5128 WERROR errcode = WERR_BADFUNC;
5129 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5132 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5133 OUR_HANDLE(handle)));
5137 if (!get_printer_snum(p, handle, &snum, NULL))
5141 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5142 errcode = print_queue_pause(p->server_info, snum);
5144 case SPOOLSS_PRINTER_CONTROL_RESUME:
5145 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5146 errcode = print_queue_resume(p->server_info, snum);
5148 case SPOOLSS_PRINTER_CONTROL_PURGE:
5149 errcode = print_queue_purge(p->server_info, snum);
5152 return WERR_UNKNOWN_LEVEL;
5159 /****************************************************************
5160 _spoolss_AbortPrinter
5161 * From MSDN: "Deletes printer's spool file if printer is configured
5163 ****************************************************************/
5165 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5166 struct spoolss_AbortPrinter *r)
5168 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5170 WERROR errcode = WERR_OK;
5173 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5174 OUR_HANDLE(r->in.handle)));
5178 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5181 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5186 /********************************************************************
5187 * called by spoolss_api_setprinter
5188 * when updating a printer description
5189 ********************************************************************/
5191 static WERROR update_printer_sec(struct policy_handle *handle,
5192 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5194 struct spoolss_security_descriptor *new_secdesc = NULL;
5195 struct spoolss_security_descriptor *old_secdesc = NULL;
5196 const char *printer;
5200 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5202 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5203 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5204 OUR_HANDLE(handle)));
5206 result = WERR_BADFID;
5210 if (secdesc_ctr == NULL) {
5211 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5212 result = WERR_INVALID_PARAM;
5215 printer = lp_const_servicename(snum);
5217 /* Check the user has permissions to change the security
5218 descriptor. By experimentation with two NT machines, the user
5219 requires Full Access to the printer to change security
5222 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5223 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5224 result = WERR_ACCESS_DENIED;
5228 /* NT seems to like setting the security descriptor even though
5229 nothing may have actually changed. */
5230 result = winreg_get_printer_secdesc(p->mem_ctx,
5234 if (!W_ERROR_IS_OK(result)) {
5235 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5236 result = WERR_BADFID;
5240 if (DEBUGLEVEL >= 10) {
5241 struct security_acl *the_acl;
5244 the_acl = secdesc_ctr->sd->dacl;
5245 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5246 printer, the_acl->num_aces));
5248 for (i = 0; i < the_acl->num_aces; i++) {
5249 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5250 &the_acl->aces[i].trustee),
5251 the_acl->aces[i].access_mask));
5254 the_acl = secdesc_ctr->sd->dacl;
5257 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5258 printer, the_acl->num_aces));
5260 for (i = 0; i < the_acl->num_aces; i++) {
5261 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5262 &the_acl->aces[i].trustee),
5263 the_acl->aces[i].access_mask));
5266 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5270 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5271 if (new_secdesc == NULL) {
5272 result = WERR_NOMEM;
5276 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5281 result = winreg_set_printer_secdesc(p->mem_ctx,
5290 /********************************************************************
5291 Canonicalize printer info from a client
5293 ATTN: It does not matter what we set the servername to hear
5294 since we do the necessary work in get_a_printer() to set it to
5295 the correct value based on what the client sent in the
5296 _spoolss_open_printer_ex().
5297 ********************************************************************/
5299 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5300 struct spoolss_SetPrinterInfo2 *info2,
5303 fstring printername;
5306 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5307 "portname=%s drivername=%s comment=%s location=%s\n",
5308 info2->servername, info2->printername, info2->sharename,
5309 info2->portname, info2->drivername, info2->comment,
5312 /* we force some elements to "correct" values */
5313 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5314 if (info2->servername == NULL) {
5317 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5318 if (info2->sharename == NULL) {
5322 /* check to see if we allow printername != sharename */
5323 if (lp_force_printername(snum)) {
5324 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5325 global_myname(), info2->sharename);
5327 /* make sure printername is in \\server\printername format */
5328 fstrcpy(printername, info2->printername);
5330 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5331 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5335 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5336 global_myname(), p);
5338 if (info2->printername == NULL) {
5342 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5343 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5348 /****************************************************************************
5349 ****************************************************************************/
5351 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5353 char *cmd = lp_addport_cmd();
5354 char *command = NULL;
5356 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5357 bool is_print_op = false;
5360 return WERR_ACCESS_DENIED;
5363 command = talloc_asprintf(ctx,
5364 "%s \"%s\" \"%s\"", cmd, portname, uri );
5370 is_print_op = user_has_privileges( token, &se_printop );
5372 DEBUG(10,("Running [%s]\n", command));
5374 /********* BEGIN SePrintOperatorPrivilege **********/
5379 ret = smbrun(command, NULL);
5384 /********* END SePrintOperatorPrivilege **********/
5386 DEBUGADD(10,("returned [%d]\n", ret));
5388 TALLOC_FREE(command);
5391 return WERR_ACCESS_DENIED;
5397 /****************************************************************************
5398 ****************************************************************************/
5400 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5401 struct spoolss_SetPrinterInfo2 *info2)
5403 char *cmd = lp_addprinter_cmd();
5405 char *command = NULL;
5409 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5410 bool is_print_op = false;
5411 char *remote_machine = talloc_strdup(ctx, "%m");
5413 if (!remote_machine) {
5416 remote_machine = talloc_sub_basic(ctx,
5417 current_user_info.smb_name,
5418 current_user_info.domain,
5420 if (!remote_machine) {
5424 command = talloc_asprintf(ctx,
5425 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5426 cmd, info2->printername, info2->sharename,
5427 info2->portname, info2->drivername,
5428 info2->location, info2->comment, remote_machine);
5434 is_print_op = user_has_privileges( token, &se_printop );
5436 DEBUG(10,("Running [%s]\n", command));
5438 /********* BEGIN SePrintOperatorPrivilege **********/
5443 if ( (ret = smbrun(command, &fd)) == 0 ) {
5444 /* Tell everyone we updated smb.conf. */
5445 message_send_all(smbd_messaging_context(),
5446 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5452 /********* END SePrintOperatorPrivilege **********/
5454 DEBUGADD(10,("returned [%d]\n", ret));
5456 TALLOC_FREE(command);
5457 TALLOC_FREE(remote_machine);
5465 /* reload our services immediately */
5467 reload_services(false);
5471 /* Get lines and convert them back to dos-codepage */
5472 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5473 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5476 /* Set the portname to what the script says the portname should be. */
5477 /* but don't require anything to be return from the script exit a good error code */
5480 /* Set the portname to what the script says the portname should be. */
5481 info2->portname = talloc_strdup(ctx, qlines[0]);
5482 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5485 TALLOC_FREE(qlines);
5490 /********************************************************************
5491 * Called by spoolss_api_setprinter
5492 * when updating a printer description.
5493 ********************************************************************/
5495 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5496 struct spoolss_SetPrinterInfoCtr *info_ctr,
5497 struct spoolss_DeviceMode *devmode)
5499 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5500 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5501 struct spoolss_PrinterInfo2 *old_printer;
5502 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5503 const char *servername = NULL;
5509 DEBUG(8,("update_printer\n"));
5514 result = WERR_BADFID;
5518 if (!get_printer_snum(p, handle, &snum, NULL)) {
5519 result = WERR_BADFID;
5523 if (Printer != NULL || Printer->servername != NULL) {
5524 servername = Printer->servername;
5527 result = winreg_get_printer(p->mem_ctx,
5530 lp_const_servicename(snum),
5532 if (!W_ERROR_IS_OK(result)) {
5533 result = WERR_BADFID;
5537 /* Do sanity check on the requested changes for Samba */
5538 if (!check_printer_ok(p->mem_ctx, printer, snum)) {
5539 result = WERR_INVALID_PARAM;
5543 /* FIXME!!! If the driver has changed we really should verify that
5544 it is installed before doing much else --jerry */
5546 /* Check calling user has permission to update printer description */
5547 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5548 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5549 result = WERR_ACCESS_DENIED;
5553 /* Call addprinter hook */
5554 /* Check changes to see if this is really needed */
5556 if (*lp_addprinter_cmd() &&
5557 (!strequal(printer->drivername, old_printer->drivername) ||
5558 !strequal(printer->comment, old_printer->comment) ||
5559 !strequal(printer->portname, old_printer->portname) ||
5560 !strequal(printer->location, old_printer->location)) )
5562 /* add_printer_hook() will call reload_services() */
5563 if (!add_printer_hook(p->mem_ctx, p->server_info->ptok,
5565 result = WERR_ACCESS_DENIED;
5571 * When a *new* driver is bound to a printer, the drivername is used to
5572 * lookup previously saved driver initialization info, which is then
5573 * bound to the printer, simulating what happens in the Windows arch.
5575 if (!strequal(printer->drivername, old_printer->drivername)) {
5576 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5577 printer->drivername));
5579 notify_printer_driver(snum, printer->drivername);
5583 * flag which changes actually occured. This is a small subset of
5584 * all the possible changes. We also have to update things in the
5587 if (!strequal(printer->comment, old_printer->comment)) {
5588 push_reg_sz(talloc_tos(), &buffer, printer->comment);
5589 winreg_set_printer_dataex(p->mem_ctx,
5592 SPOOL_DSSPOOLER_KEY,
5598 notify_printer_comment(snum, printer->comment);
5601 if (!strequal(printer->sharename, old_printer->sharename)) {
5602 push_reg_sz(talloc_tos(), &buffer, printer->sharename);
5603 winreg_set_printer_dataex(p->mem_ctx,
5606 SPOOL_DSSPOOLER_KEY,
5612 notify_printer_sharename(snum, printer->sharename);
5615 if (!strequal(printer->printername, old_printer->printername)) {
5618 if ( (pname = strchr_m( printer->printername+2, '\\' )) != NULL )
5621 pname = printer->printername;
5623 push_reg_sz(talloc_tos(), &buffer, pname);
5624 winreg_set_printer_dataex(p->mem_ctx,
5627 SPOOL_DSSPOOLER_KEY,
5633 notify_printer_printername( snum, pname );
5636 if (!strequal(printer->portname, old_printer->portname)) {
5637 push_reg_sz(talloc_tos(), &buffer, printer->portname);
5638 winreg_set_printer_dataex(p->mem_ctx,
5641 SPOOL_DSSPOOLER_KEY,
5647 notify_printer_port(snum, printer->portname);
5650 if (!strequal(printer->location, old_printer->location)) {
5651 push_reg_sz(talloc_tos(), &buffer, printer->location);
5652 winreg_set_printer_dataex(p->mem_ctx,
5655 SPOOL_DSSPOOLER_KEY,
5661 notify_printer_location(snum, printer->location);
5664 /* here we need to update some more DsSpooler keys */
5665 /* uNCName, serverName, shortServerName */
5667 push_reg_sz(talloc_tos(), &buffer, global_myname());
5668 winreg_set_printer_dataex(p->mem_ctx,
5671 SPOOL_DSSPOOLER_KEY,
5676 winreg_set_printer_dataex(p->mem_ctx,
5679 SPOOL_DSSPOOLER_KEY,
5685 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5686 global_myname(), printer->sharename );
5687 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5688 winreg_set_printer_dataex(p->mem_ctx,
5691 SPOOL_DSSPOOLER_KEY,
5697 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5699 if (devmode == NULL) {
5700 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5702 result = winreg_update_printer(p->mem_ctx,
5711 talloc_free(old_printer);
5716 /****************************************************************************
5717 ****************************************************************************/
5718 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5719 struct policy_handle *handle,
5720 struct spoolss_SetPrinterInfo7 *info7)
5724 Printer_entry *Printer;
5726 if ( lp_security() != SEC_ADS ) {
5727 return WERR_UNKNOWN_LEVEL;
5730 Printer = find_printer_index_by_hnd(p, handle);
5732 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5737 if (!get_printer_snum(p, handle, &snum, NULL))
5740 nt_printer_publish(Printer, snum, info7->action);
5744 return WERR_UNKNOWN_LEVEL;
5748 /********************************************************************
5749 ********************************************************************/
5751 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5752 struct spoolss_DeviceMode *devmode)
5755 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5756 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
5758 DEBUG(8,("update_printer_devmode\n"));
5764 if (!get_printer_snum(p, handle, &snum, NULL)) {
5768 /* Check calling user has permission to update printer description */
5769 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5770 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5771 return WERR_ACCESS_DENIED;
5774 return winreg_update_printer(p->mem_ctx,
5776 lp_const_servicename(snum),
5784 /****************************************************************
5786 ****************************************************************/
5788 WERROR _spoolss_SetPrinter(pipes_struct *p,
5789 struct spoolss_SetPrinter *r)
5793 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5796 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5797 OUR_HANDLE(r->in.handle)));
5801 /* check the level */
5802 switch (r->in.info_ctr->level) {
5804 return control_printer(r->in.handle, r->in.command, p);
5806 result = update_printer(p, r->in.handle,
5808 r->in.devmode_ctr->devmode);
5809 if (!W_ERROR_IS_OK(result))
5811 if (r->in.secdesc_ctr->sd)
5812 result = update_printer_sec(r->in.handle, p,
5816 return update_printer_sec(r->in.handle, p,
5819 return publish_or_unpublish_printer(p, r->in.handle,
5820 r->in.info_ctr->info.info7);
5822 return update_printer_devmode(p, r->in.handle,
5823 r->in.devmode_ctr->devmode);
5825 return WERR_UNKNOWN_LEVEL;
5829 /****************************************************************
5830 _spoolss_FindClosePrinterNotify
5831 ****************************************************************/
5833 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5834 struct spoolss_FindClosePrinterNotify *r)
5836 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5839 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5840 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5844 if (Printer->notify.client_connected == true) {
5847 if ( Printer->printer_type == SPLHND_SERVER)
5849 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5850 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5853 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5856 Printer->notify.flags=0;
5857 Printer->notify.options=0;
5858 Printer->notify.localmachine[0]='\0';
5859 Printer->notify.printerlocal=0;
5860 TALLOC_FREE(Printer->notify.option);
5861 Printer->notify.client_connected = false;
5866 /****************************************************************
5868 ****************************************************************/
5870 WERROR _spoolss_AddJob(pipes_struct *p,
5871 struct spoolss_AddJob *r)
5873 if (!r->in.buffer && (r->in.offered != 0)) {
5874 return WERR_INVALID_PARAM;
5877 /* this is what a NT server returns for AddJob. AddJob must fail on
5878 * non-local printers */
5880 if (r->in.level != 1) {
5881 return WERR_UNKNOWN_LEVEL;
5884 return WERR_INVALID_PARAM;
5887 /****************************************************************************
5889 ****************************************************************************/
5891 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5892 struct spoolss_JobInfo1 *r,
5893 const print_queue_struct *queue,
5894 int position, int snum,
5895 struct spoolss_PrinterInfo2 *pinfo2)
5899 t = gmtime(&queue->time);
5901 r->job_id = queue->job;
5903 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5904 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5905 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
5906 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5907 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5908 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5909 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5910 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5911 r->data_type = talloc_strdup(mem_ctx, "RAW");
5912 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5913 r->text_status = talloc_strdup(mem_ctx, "");
5914 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5916 r->status = nt_printj_status(queue->status);
5917 r->priority = queue->priority;
5918 r->position = position;
5919 r->total_pages = queue->page_count;
5920 r->pages_printed = 0; /* ??? */
5922 init_systemtime(&r->submitted, t);
5927 /****************************************************************************
5929 ****************************************************************************/
5931 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
5932 struct spoolss_JobInfo2 *r,
5933 const print_queue_struct *queue,
5934 int position, int snum,
5935 struct spoolss_PrinterInfo2 *pinfo2,
5936 struct spoolss_DeviceMode *devmode)
5940 t = gmtime(&queue->time);
5942 r->job_id = queue->job;
5944 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5945 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5946 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
5947 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5948 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5949 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5950 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5951 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5952 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
5953 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
5954 r->data_type = talloc_strdup(mem_ctx, "RAW");
5955 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5956 r->print_processor = talloc_strdup(mem_ctx, "winprint");
5957 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
5958 r->parameters = talloc_strdup(mem_ctx, "");
5959 W_ERROR_HAVE_NO_MEMORY(r->parameters);
5960 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
5961 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5963 r->devmode = devmode;
5965 r->text_status = talloc_strdup(mem_ctx, "");
5966 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5970 r->status = nt_printj_status(queue->status);
5971 r->priority = queue->priority;
5972 r->position = position;
5975 r->total_pages = queue->page_count;
5976 r->size = queue->size;
5977 init_systemtime(&r->submitted, t);
5979 r->pages_printed = 0; /* ??? */
5984 /****************************************************************************
5986 ****************************************************************************/
5988 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
5989 struct spoolss_JobInfo3 *r,
5990 const print_queue_struct *queue,
5991 const print_queue_struct *next_queue,
5992 int position, int snum,
5993 struct spoolss_PrinterInfo2 *pinfo2)
5995 r->job_id = queue->job;
5998 r->next_job_id = next_queue->job;
6005 /****************************************************************************
6006 Enumjobs at level 1.
6007 ****************************************************************************/
6009 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6010 const print_queue_struct *queue,
6011 uint32_t num_queues, int snum,
6012 struct spoolss_PrinterInfo2 *pinfo2,
6013 union spoolss_JobInfo **info_p,
6016 union spoolss_JobInfo *info;
6018 WERROR result = WERR_OK;
6020 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6021 W_ERROR_HAVE_NO_MEMORY(info);
6023 *count = num_queues;
6025 for (i=0; i<*count; i++) {
6026 result = fill_job_info1(info,
6032 if (!W_ERROR_IS_OK(result)) {
6038 if (!W_ERROR_IS_OK(result)) {
6049 /****************************************************************************
6050 Enumjobs at level 2.
6051 ****************************************************************************/
6053 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6054 const print_queue_struct *queue,
6055 uint32_t num_queues, int snum,
6056 struct spoolss_PrinterInfo2 *pinfo2,
6057 union spoolss_JobInfo **info_p,
6060 struct spoolss_DeviceMode *devmode;
6061 union spoolss_JobInfo *info;
6063 WERROR result = WERR_OK;
6065 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6066 W_ERROR_HAVE_NO_MEMORY(info);
6068 *count = num_queues;
6070 for (i=0; i<*count; i++) {
6072 if (!pinfo2->devmode) {
6073 result = spoolss_create_default_devmode(info,
6074 pinfo2->printername,
6077 result = copy_devicemode(info,
6081 if (!W_ERROR_IS_OK(result)) {
6082 DEBUG(3, ("Can't proceed w/o a devmode!"));
6086 result = fill_job_info2(info,
6093 if (!W_ERROR_IS_OK(result)) {
6099 if (!W_ERROR_IS_OK(result)) {
6110 /****************************************************************************
6111 Enumjobs at level 3.
6112 ****************************************************************************/
6114 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6115 const print_queue_struct *queue,
6116 uint32_t num_queues, int snum,
6117 struct spoolss_PrinterInfo2 *pinfo2,
6118 union spoolss_JobInfo **info_p,
6121 union spoolss_JobInfo *info;
6123 WERROR result = WERR_OK;
6125 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6126 W_ERROR_HAVE_NO_MEMORY(info);
6128 *count = num_queues;
6130 for (i=0; i<*count; i++) {
6131 const print_queue_struct *next_queue = NULL;
6134 next_queue = &queue[i+1];
6137 result = fill_job_info3(info,
6144 if (!W_ERROR_IS_OK(result)) {
6150 if (!W_ERROR_IS_OK(result)) {
6161 /****************************************************************
6163 ****************************************************************/
6165 WERROR _spoolss_EnumJobs(pipes_struct *p,
6166 struct spoolss_EnumJobs *r)
6169 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6171 print_status_struct prt_status;
6172 print_queue_struct *queue = NULL;
6175 /* that's an [in out] buffer */
6177 if (!r->in.buffer && (r->in.offered != 0)) {
6178 return WERR_INVALID_PARAM;
6181 DEBUG(4,("_spoolss_EnumJobs\n"));
6185 *r->out.info = NULL;
6187 /* lookup the printer snum and tdb entry */
6189 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6193 result = winreg_get_printer(talloc_tos(), p->server_info, NULL,
6194 lp_servicename(snum), &pinfo2);
6195 if (!W_ERROR_IS_OK(result)) {
6199 count = print_queue_status(snum, &queue, &prt_status);
6200 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6201 count, prt_status.status, prt_status.message));
6205 TALLOC_FREE(pinfo2);
6209 switch (r->in.level) {
6211 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6212 pinfo2, r->out.info, r->out.count);
6215 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6216 pinfo2, r->out.info, r->out.count);
6219 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6220 pinfo2, r->out.info, r->out.count);
6223 result = WERR_UNKNOWN_LEVEL;
6228 TALLOC_FREE(pinfo2);
6230 if (!W_ERROR_IS_OK(result)) {
6234 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6236 *r->out.info, r->in.level,
6238 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6239 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6241 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6244 /****************************************************************
6245 _spoolss_ScheduleJob
6246 ****************************************************************/
6248 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6249 struct spoolss_ScheduleJob *r)
6254 /****************************************************************
6255 ****************************************************************/
6257 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6258 const char *printer_name,
6260 struct spoolss_SetJobInfo1 *r)
6264 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6268 if (strequal(old_doc_name, r->document_name)) {
6272 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6279 /****************************************************************
6281 ****************************************************************/
6283 WERROR _spoolss_SetJob(pipes_struct *p,
6284 struct spoolss_SetJob *r)
6287 WERROR errcode = WERR_BADFUNC;
6289 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6293 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6294 return WERR_INVALID_PRINTER_NAME;
6297 switch (r->in.command) {
6298 case SPOOLSS_JOB_CONTROL_CANCEL:
6299 case SPOOLSS_JOB_CONTROL_DELETE:
6300 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6304 case SPOOLSS_JOB_CONTROL_PAUSE:
6305 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6309 case SPOOLSS_JOB_CONTROL_RESTART:
6310 case SPOOLSS_JOB_CONTROL_RESUME:
6311 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6319 return WERR_UNKNOWN_LEVEL;
6322 if (!W_ERROR_IS_OK(errcode)) {
6326 if (r->in.ctr == NULL) {
6330 switch (r->in.ctr->level) {
6332 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6334 r->in.ctr->info.info1);
6340 return WERR_UNKNOWN_LEVEL;
6346 /****************************************************************************
6347 Enumerates all printer drivers by level and architecture.
6348 ****************************************************************************/
6350 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6351 struct auth_serversupplied_info *server_info,
6352 const char *servername,
6353 const char *architecture,
6355 union spoolss_DriverInfo **info_p,
6360 struct spoolss_DriverInfo8 *driver;
6361 union spoolss_DriverInfo *info = NULL;
6363 WERROR result = WERR_OK;
6364 uint32_t num_drivers;
6365 const char **drivers;
6370 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6371 result = winreg_get_driver_list(mem_ctx, server_info,
6372 architecture, version,
6373 &num_drivers, &drivers);
6374 if (!W_ERROR_IS_OK(result)) {
6377 DEBUG(4, ("we have:[%d] drivers in environment"
6378 " [%s] and version [%d]\n",
6379 num_drivers, architecture, version));
6381 if (num_drivers != 0) {
6382 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6383 union spoolss_DriverInfo,
6384 count + num_drivers);
6386 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6387 "failed to enlarge driver info buffer!\n"));
6388 result = WERR_NOMEM;
6393 for (i = 0; i < num_drivers; i++) {
6394 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6396 result = winreg_get_driver(mem_ctx, server_info,
6397 architecture, drivers[i],
6399 if (!W_ERROR_IS_OK(result)) {
6405 result = fill_printer_driver_info1(info, &info[count+i].info1,
6406 driver, servername);
6409 result = fill_printer_driver_info2(info, &info[count+i].info2,
6410 driver, servername);
6413 result = fill_printer_driver_info3(info, &info[count+i].info3,
6414 driver, servername);
6417 result = fill_printer_driver_info4(info, &info[count+i].info4,
6418 driver, servername);
6421 result = fill_printer_driver_info5(info, &info[count+i].info5,
6422 driver, servername);
6425 result = fill_printer_driver_info6(info, &info[count+i].info6,
6426 driver, servername);
6429 result = fill_printer_driver_info8(info, &info[count+i].info8,
6430 driver, servername);
6433 result = WERR_UNKNOWN_LEVEL;
6437 TALLOC_FREE(driver);
6439 if (!W_ERROR_IS_OK(result)) {
6444 count += num_drivers;
6445 TALLOC_FREE(drivers);
6449 TALLOC_FREE(drivers);
6451 if (!W_ERROR_IS_OK(result)) {
6462 /****************************************************************************
6463 Enumerates all printer drivers by level.
6464 ****************************************************************************/
6466 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6467 struct auth_serversupplied_info *server_info,
6468 const char *servername,
6469 const char *architecture,
6471 union spoolss_DriverInfo **info_p,
6475 WERROR result = WERR_OK;
6477 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6479 for (a=0; archi_table[a].long_archi != NULL; a++) {
6481 union spoolss_DriverInfo *info = NULL;
6484 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6487 archi_table[a].long_archi,
6491 if (!W_ERROR_IS_OK(result)) {
6495 for (i=0; i < count; i++) {
6496 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6497 info[i], info_p, count_p);
6504 return enumprinterdrivers_level_by_architecture(mem_ctx,
6513 /****************************************************************
6514 _spoolss_EnumPrinterDrivers
6515 ****************************************************************/
6517 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6518 struct spoolss_EnumPrinterDrivers *r)
6520 const char *cservername;
6523 /* that's an [in out] buffer */
6525 if (!r->in.buffer && (r->in.offered != 0)) {
6526 return WERR_INVALID_PARAM;
6529 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6533 *r->out.info = NULL;
6535 cservername = canon_servername(r->in.server);
6537 if (!is_myname_or_ipaddr(cservername)) {
6538 return WERR_UNKNOWN_PRINTER_DRIVER;
6541 result = enumprinterdrivers_level(p->mem_ctx,
6548 if (!W_ERROR_IS_OK(result)) {
6552 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6553 spoolss_EnumPrinterDrivers,
6554 *r->out.info, r->in.level,
6556 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6557 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6559 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6562 /****************************************************************
6564 ****************************************************************/
6566 WERROR _spoolss_EnumForms(pipes_struct *p,
6567 struct spoolss_EnumForms *r)
6573 *r->out.info = NULL;
6575 /* that's an [in out] buffer */
6577 if (!r->in.buffer && (r->in.offered != 0) ) {
6578 return WERR_INVALID_PARAM;
6581 DEBUG(4,("_spoolss_EnumForms\n"));
6582 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6583 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6585 switch (r->in.level) {
6587 result = winreg_printer_enumforms1(p->mem_ctx,
6593 result = WERR_UNKNOWN_LEVEL;
6597 if (!W_ERROR_IS_OK(result)) {
6601 if (*r->out.count == 0) {
6602 return WERR_NO_MORE_ITEMS;
6605 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6607 *r->out.info, r->in.level,
6609 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6610 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6612 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6615 /****************************************************************
6617 ****************************************************************/
6619 WERROR _spoolss_GetForm(pipes_struct *p,
6620 struct spoolss_GetForm *r)
6624 /* that's an [in out] buffer */
6626 if (!r->in.buffer && (r->in.offered != 0)) {
6627 return WERR_INVALID_PARAM;
6630 DEBUG(4,("_spoolss_GetForm\n"));
6631 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6632 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6634 switch (r->in.level) {
6636 result = winreg_printer_getform1(p->mem_ctx,
6639 &r->out.info->info1);
6642 result = WERR_UNKNOWN_LEVEL;
6646 if (!W_ERROR_IS_OK(result)) {
6647 TALLOC_FREE(r->out.info);
6651 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6652 r->out.info, r->in.level);
6653 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6655 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6658 /****************************************************************************
6659 ****************************************************************************/
6661 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6662 struct spoolss_PortInfo1 *r,
6665 r->port_name = talloc_strdup(mem_ctx, name);
6666 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6671 /****************************************************************************
6672 TODO: This probably needs distinguish between TCP/IP and Local ports
6674 ****************************************************************************/
6676 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6677 struct spoolss_PortInfo2 *r,
6680 r->port_name = talloc_strdup(mem_ctx, name);
6681 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6683 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6684 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6686 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6687 W_ERROR_HAVE_NO_MEMORY(r->description);
6689 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6696 /****************************************************************************
6697 wrapper around the enumer ports command
6698 ****************************************************************************/
6700 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6702 char *cmd = lp_enumports_cmd();
6703 char **qlines = NULL;
6704 char *command = NULL;
6712 /* if no hook then just fill in the default port */
6715 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6718 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6719 TALLOC_FREE(qlines);
6726 /* we have a valid enumport command */
6728 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6733 DEBUG(10,("Running [%s]\n", command));
6734 ret = smbrun(command, &fd);
6735 DEBUG(10,("Returned [%d]\n", ret));
6736 TALLOC_FREE(command);
6741 return WERR_ACCESS_DENIED;
6745 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6746 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6756 /****************************************************************************
6758 ****************************************************************************/
6760 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6761 union spoolss_PortInfo **info_p,
6764 union spoolss_PortInfo *info = NULL;
6766 WERROR result = WERR_OK;
6767 char **qlines = NULL;
6770 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6771 if (!W_ERROR_IS_OK(result)) {
6776 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6778 DEBUG(10,("Returning WERR_NOMEM\n"));
6779 result = WERR_NOMEM;
6783 for (i=0; i<numlines; i++) {
6784 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6785 result = fill_port_1(info, &info[i].info1, qlines[i]);
6786 if (!W_ERROR_IS_OK(result)) {
6791 TALLOC_FREE(qlines);
6794 if (!W_ERROR_IS_OK(result)) {
6796 TALLOC_FREE(qlines);
6808 /****************************************************************************
6810 ****************************************************************************/
6812 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6813 union spoolss_PortInfo **info_p,
6816 union spoolss_PortInfo *info = NULL;
6818 WERROR result = WERR_OK;
6819 char **qlines = NULL;
6822 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6823 if (!W_ERROR_IS_OK(result)) {
6828 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6830 DEBUG(10,("Returning WERR_NOMEM\n"));
6831 result = WERR_NOMEM;
6835 for (i=0; i<numlines; i++) {
6836 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6837 result = fill_port_2(info, &info[i].info2, qlines[i]);
6838 if (!W_ERROR_IS_OK(result)) {
6843 TALLOC_FREE(qlines);
6846 if (!W_ERROR_IS_OK(result)) {
6848 TALLOC_FREE(qlines);
6860 /****************************************************************
6862 ****************************************************************/
6864 WERROR _spoolss_EnumPorts(pipes_struct *p,
6865 struct spoolss_EnumPorts *r)
6869 /* that's an [in out] buffer */
6871 if (!r->in.buffer && (r->in.offered != 0)) {
6872 return WERR_INVALID_PARAM;
6875 DEBUG(4,("_spoolss_EnumPorts\n"));
6879 *r->out.info = NULL;
6881 switch (r->in.level) {
6883 result = enumports_level_1(p->mem_ctx, r->out.info,
6887 result = enumports_level_2(p->mem_ctx, r->out.info,
6891 return WERR_UNKNOWN_LEVEL;
6894 if (!W_ERROR_IS_OK(result)) {
6898 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6900 *r->out.info, r->in.level,
6902 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6903 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6905 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6908 /****************************************************************************
6909 ****************************************************************************/
6911 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
6913 struct spoolss_SetPrinterInfoCtr *info_ctr,
6914 struct spoolss_DeviceMode *devmode,
6915 struct security_descriptor *secdesc,
6916 struct spoolss_UserLevelCtr *user_ctr,
6917 struct policy_handle *handle)
6919 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
6920 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
6922 WERROR err = WERR_OK;
6924 /* samba does not have a concept of local, non-shared printers yet, so
6925 * make sure we always setup sharename - gd */
6926 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
6927 (info2->printername != NULL && info2->printername[0] != '\0')) {
6928 DEBUG(5, ("spoolss_addprinterex_level_2: "
6929 "no sharename has been set, setting printername %s as sharename\n",
6930 info2->printername));
6931 info2->sharename = info2->printername;
6934 /* check to see if the printer already exists */
6935 if ((snum = print_queue_snum(info2->sharename)) != -1) {
6936 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6938 return WERR_PRINTER_ALREADY_EXISTS;
6941 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
6942 if ((snum = print_queue_snum(info2->printername)) != -1) {
6943 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6944 info2->printername));
6945 return WERR_PRINTER_ALREADY_EXISTS;
6949 /* validate printer info struct */
6950 if (!info2->printername || strlen(info2->printername) == 0) {
6951 return WERR_INVALID_PRINTER_NAME;
6953 if (!info2->portname || strlen(info2->portname) == 0) {
6954 return WERR_UNKNOWN_PORT;
6956 if (!info2->drivername || strlen(info2->drivername) == 0) {
6957 return WERR_UNKNOWN_PRINTER_DRIVER;
6959 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
6960 return WERR_UNKNOWN_PRINTPROCESSOR;
6963 /* FIXME!!! smbd should check to see if the driver is installed before
6964 trying to add a printer like this --jerry */
6966 if (*lp_addprinter_cmd() ) {
6967 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6969 return WERR_ACCESS_DENIED;
6972 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
6973 "smb.conf parameter \"addprinter command\" is defined. This"
6974 "parameter must exist for this call to succeed\n",
6975 info2->sharename ));
6978 if ((snum = print_queue_snum(info2->sharename)) == -1) {
6979 return WERR_ACCESS_DENIED;
6982 /* you must be a printer admin to add a new printer */
6983 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
6984 return WERR_ACCESS_DENIED;
6988 * Do sanity check on the requested changes for Samba.
6991 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
6992 return WERR_INVALID_PARAM;
6995 if (devmode == NULL) {
6996 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
6999 err = winreg_update_printer(p->mem_ctx,
7006 if (!W_ERROR_IS_OK(err)) {
7010 if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7011 /* Handle open failed - remove addition. */
7012 ZERO_STRUCTP(handle);
7013 return WERR_ACCESS_DENIED;
7019 /****************************************************************
7020 _spoolss_AddPrinterEx
7021 ****************************************************************/
7023 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7024 struct spoolss_AddPrinterEx *r)
7026 switch (r->in.info_ctr->level) {
7028 /* we don't handle yet */
7029 /* but I know what to do ... */
7030 return WERR_UNKNOWN_LEVEL;
7032 return spoolss_addprinterex_level_2(p, r->in.server,
7034 r->in.devmode_ctr->devmode,
7035 r->in.secdesc_ctr->sd,
7036 r->in.userlevel_ctr,
7039 return WERR_UNKNOWN_LEVEL;
7043 /****************************************************************
7045 ****************************************************************/
7047 WERROR _spoolss_AddPrinter(pipes_struct *p,
7048 struct spoolss_AddPrinter *r)
7050 struct spoolss_AddPrinterEx a;
7051 struct spoolss_UserLevelCtr userlevel_ctr;
7053 ZERO_STRUCT(userlevel_ctr);
7055 userlevel_ctr.level = 1;
7057 a.in.server = r->in.server;
7058 a.in.info_ctr = r->in.info_ctr;
7059 a.in.devmode_ctr = r->in.devmode_ctr;
7060 a.in.secdesc_ctr = r->in.secdesc_ctr;
7061 a.in.userlevel_ctr = &userlevel_ctr;
7062 a.out.handle = r->out.handle;
7064 return _spoolss_AddPrinterEx(p, &a);
7067 /****************************************************************
7068 _spoolss_AddPrinterDriverEx
7069 ****************************************************************/
7071 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7072 struct spoolss_AddPrinterDriverEx *r)
7074 WERROR err = WERR_OK;
7075 const char *driver_name = NULL;
7080 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7081 fn = "_spoolss_AddPrinterDriver";
7083 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7084 fn = "_spoolss_AddPrinterDriverEx";
7087 return WERR_INVALID_PARAM;
7091 * we only support the semantics of AddPrinterDriver()
7092 * i.e. only copy files that are newer than existing ones
7095 if (r->in.flags == 0) {
7096 return WERR_INVALID_PARAM;
7099 if (r->in.flags != APD_COPY_NEW_FILES) {
7100 return WERR_ACCESS_DENIED;
7104 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7105 /* Clever hack from Martin Zielinski <mz@seh.de>
7106 * to allow downgrade from level 8 (Vista).
7108 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7109 r->in.info_ctr->level));
7110 return WERR_UNKNOWN_LEVEL;
7113 DEBUG(5,("Cleaning driver's information\n"));
7114 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7115 if (!W_ERROR_IS_OK(err))
7118 DEBUG(5,("Moving driver to final destination\n"));
7119 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7124 err = winreg_add_driver(p->mem_ctx, p->server_info,
7125 r->in.info_ctr, &driver_name, &version);
7126 if (!W_ERROR_IS_OK(err)) {
7131 * I think this is where he DrvUpgradePrinter() hook would be
7132 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7133 * server. Right now, we just need to send ourselves a message
7134 * to update each printer bound to this driver. --jerry
7137 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7138 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7146 /****************************************************************
7147 _spoolss_AddPrinterDriver
7148 ****************************************************************/
7150 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7151 struct spoolss_AddPrinterDriver *r)
7153 struct spoolss_AddPrinterDriverEx a;
7155 switch (r->in.info_ctr->level) {
7162 return WERR_UNKNOWN_LEVEL;
7165 a.in.servername = r->in.servername;
7166 a.in.info_ctr = r->in.info_ctr;
7167 a.in.flags = APD_COPY_NEW_FILES;
7169 return _spoolss_AddPrinterDriverEx(p, &a);
7172 /****************************************************************************
7173 ****************************************************************************/
7175 struct _spoolss_paths {
7181 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7183 static const struct _spoolss_paths spoolss_paths[]= {
7184 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7185 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7188 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7189 const char *servername,
7190 const char *environment,
7194 const char *pservername = NULL;
7195 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7196 const char *short_archi;
7200 /* environment may be empty */
7201 if (environment && strlen(environment)) {
7202 long_archi = environment;
7205 /* servername may be empty */
7206 if (servername && strlen(servername)) {
7207 pservername = canon_servername(servername);
7209 if (!is_myname_or_ipaddr(pservername)) {
7210 return WERR_INVALID_PARAM;
7214 if (!(short_archi = get_short_archi(long_archi))) {
7215 return WERR_INVALID_ENVIRONMENT;
7218 switch (component) {
7219 case SPOOLSS_PRTPROCS_PATH:
7220 case SPOOLSS_DRIVER_PATH:
7222 *path = talloc_asprintf(mem_ctx,
7225 spoolss_paths[component].share,
7228 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7229 SPOOLSS_DEFAULT_SERVER_PATH,
7230 spoolss_paths[component].dir,
7235 return WERR_INVALID_PARAM;
7245 /****************************************************************************
7246 ****************************************************************************/
7248 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7249 const char *servername,
7250 const char *environment,
7251 struct spoolss_DriverDirectoryInfo1 *r)
7256 werr = compose_spoolss_server_path(mem_ctx,
7259 SPOOLSS_DRIVER_PATH,
7261 if (!W_ERROR_IS_OK(werr)) {
7265 DEBUG(4,("printer driver directory: [%s]\n", path));
7267 r->directory_name = path;
7272 /****************************************************************
7273 _spoolss_GetPrinterDriverDirectory
7274 ****************************************************************/
7276 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7277 struct spoolss_GetPrinterDriverDirectory *r)
7281 /* that's an [in out] buffer */
7283 if (!r->in.buffer && (r->in.offered != 0)) {
7284 return WERR_INVALID_PARAM;
7287 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7292 /* r->in.level is ignored */
7294 werror = getprinterdriverdir_level_1(p->mem_ctx,
7297 &r->out.info->info1);
7298 if (!W_ERROR_IS_OK(werror)) {
7299 TALLOC_FREE(r->out.info);
7303 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7304 r->out.info, r->in.level);
7305 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7307 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7310 /****************************************************************
7311 _spoolss_EnumPrinterData
7312 ****************************************************************/
7314 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7315 struct spoolss_EnumPrinterData *r)
7318 struct spoolss_EnumPrinterDataEx r2;
7320 struct spoolss_PrinterEnumValues *info, *val = NULL;
7323 r2.in.handle = r->in.handle;
7324 r2.in.key_name = "PrinterDriverData";
7326 r2.out.count = &count;
7327 r2.out.info = &info;
7328 r2.out.needed = &needed;
7330 result = _spoolss_EnumPrinterDataEx(p, &r2);
7331 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7332 r2.in.offered = needed;
7333 result = _spoolss_EnumPrinterDataEx(p, &r2);
7335 if (!W_ERROR_IS_OK(result)) {
7340 * The NT machine wants to know the biggest size of value and data
7342 * cf: MSDN EnumPrinterData remark section
7345 if (!r->in.value_offered && !r->in.data_offered) {
7346 uint32_t biggest_valuesize = 0;
7347 uint32_t biggest_datasize = 0;
7350 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7352 for (i=0; i<count; i++) {
7354 name_length = strlen(info[i].value_name);
7355 if (strlen(info[i].value_name) > biggest_valuesize) {
7356 biggest_valuesize = name_length;
7359 if (info[i].data_length > biggest_datasize) {
7360 biggest_datasize = info[i].data_length;
7363 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7367 /* the value is an UNICODE string but real_value_size is the length
7368 in bytes including the trailing 0 */
7370 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7371 *r->out.data_needed = biggest_datasize;
7373 DEBUG(6,("final values: [%d], [%d]\n",
7374 *r->out.value_needed, *r->out.data_needed));
7379 if (r->in.enum_index < count) {
7380 val = &info[r->in.enum_index];
7384 /* out_value should default to "" or else NT4 has
7385 problems unmarshalling the response */
7387 if (r->in.value_offered) {
7388 *r->out.value_needed = 1;
7389 r->out.value_name = talloc_strdup(r, "");
7390 if (!r->out.value_name) {
7394 r->out.value_name = NULL;
7395 *r->out.value_needed = 0;
7398 /* the data is counted in bytes */
7400 *r->out.data_needed = r->in.data_offered;
7402 result = WERR_NO_MORE_ITEMS;
7406 * - counted in bytes in the request
7407 * - counted in UNICODE chars in the max reply
7408 * - counted in bytes in the real size
7410 * take a pause *before* coding not *during* coding
7414 if (r->in.value_offered) {
7415 r->out.value_name = talloc_strdup(r, val->value_name);
7416 if (!r->out.value_name) {
7419 *r->out.value_needed = val->value_name_len;
7421 r->out.value_name = NULL;
7422 *r->out.value_needed = 0;
7427 *r->out.type = val->type;
7429 /* data - counted in bytes */
7432 * See the section "Dynamically Typed Query Parameters"
7436 if (r->out.data && val->data && val->data->data &&
7437 val->data_length && r->in.data_offered) {
7438 memcpy(r->out.data, val->data->data,
7439 MIN(val->data_length,r->in.data_offered));
7442 *r->out.data_needed = val->data_length;
7450 /****************************************************************
7451 _spoolss_SetPrinterData
7452 ****************************************************************/
7454 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7455 struct spoolss_SetPrinterData *r)
7457 struct spoolss_SetPrinterDataEx r2;
7459 r2.in.handle = r->in.handle;
7460 r2.in.key_name = "PrinterDriverData";
7461 r2.in.value_name = r->in.value_name;
7462 r2.in.type = r->in.type;
7463 r2.in.data = r->in.data;
7464 r2.in.offered = r->in.offered;
7466 return _spoolss_SetPrinterDataEx(p, &r2);
7469 /****************************************************************
7470 _spoolss_ResetPrinter
7471 ****************************************************************/
7473 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7474 struct spoolss_ResetPrinter *r)
7476 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7479 DEBUG(5,("_spoolss_ResetPrinter\n"));
7482 * All we do is to check to see if the handle and queue is valid.
7483 * This call really doesn't mean anything to us because we only
7484 * support RAW printing. --jerry
7488 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7489 OUR_HANDLE(r->in.handle)));
7493 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7497 /* blindly return success */
7501 /****************************************************************
7502 _spoolss_DeletePrinterData
7503 ****************************************************************/
7505 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7506 struct spoolss_DeletePrinterData *r)
7508 struct spoolss_DeletePrinterDataEx r2;
7510 r2.in.handle = r->in.handle;
7511 r2.in.key_name = "PrinterDriverData";
7512 r2.in.value_name = r->in.value_name;
7514 return _spoolss_DeletePrinterDataEx(p, &r2);
7517 /****************************************************************
7519 ****************************************************************/
7521 WERROR _spoolss_AddForm(pipes_struct *p,
7522 struct spoolss_AddForm *r)
7524 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7526 WERROR status = WERR_OK;
7527 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7529 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7531 DEBUG(5,("_spoolss_AddForm\n"));
7534 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7535 OUR_HANDLE(r->in.handle)));
7539 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7540 and not a printer admin, then fail */
7542 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7543 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7544 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7545 p->server_info->info3->base.domain.string,
7547 p->server_info->ptok,
7548 lp_printer_admin(snum))) {
7549 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7550 return WERR_ACCESS_DENIED;
7553 switch (form->flags) {
7554 case SPOOLSS_FORM_USER:
7555 case SPOOLSS_FORM_BUILTIN:
7556 case SPOOLSS_FORM_PRINTER:
7559 return WERR_INVALID_PARAM;
7562 status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7563 if (!W_ERROR_IS_OK(status)) {
7568 * ChangeID must always be set if this is a printer
7570 if (Printer->printer_type == SPLHND_PRINTER) {
7571 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7575 status = winreg_printer_update_changeid(p->mem_ctx,
7577 lp_const_servicename(snum));
7578 if (!W_ERROR_IS_OK(status)) {
7586 /****************************************************************
7588 ****************************************************************/
7590 WERROR _spoolss_DeleteForm(pipes_struct *p,
7591 struct spoolss_DeleteForm *r)
7593 const char *form_name = r->in.form_name;
7594 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7596 WERROR status = WERR_OK;
7597 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7599 DEBUG(5,("_spoolss_DeleteForm\n"));
7602 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7603 OUR_HANDLE(r->in.handle)));
7607 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7608 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7609 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7610 p->server_info->info3->base.domain.string,
7612 p->server_info->ptok,
7613 lp_printer_admin(snum))) {
7614 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7615 return WERR_ACCESS_DENIED;
7618 status = winreg_printer_deleteform1(p->mem_ctx,
7621 if (!W_ERROR_IS_OK(status)) {
7626 * ChangeID must always be set if this is a printer
7628 if (Printer->printer_type == SPLHND_PRINTER) {
7629 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7633 status = winreg_printer_update_changeid(p->mem_ctx,
7635 lp_const_servicename(snum));
7636 if (!W_ERROR_IS_OK(status)) {
7644 /****************************************************************
7646 ****************************************************************/
7648 WERROR _spoolss_SetForm(pipes_struct *p,
7649 struct spoolss_SetForm *r)
7651 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7652 const char *form_name = r->in.form_name;
7654 WERROR status = WERR_OK;
7655 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7657 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7659 DEBUG(5,("_spoolss_SetForm\n"));
7662 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7663 OUR_HANDLE(r->in.handle)));
7667 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7668 and not a printer admin, then fail */
7670 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7671 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7672 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7673 p->server_info->info3->base.domain.string,
7675 p->server_info->ptok,
7676 lp_printer_admin(snum))) {
7677 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7678 return WERR_ACCESS_DENIED;
7681 status = winreg_printer_setform1(p->mem_ctx,
7685 if (!W_ERROR_IS_OK(status)) {
7690 * ChangeID must always be set if this is a printer
7692 if (Printer->printer_type == SPLHND_PRINTER) {
7693 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7697 status = winreg_printer_update_changeid(p->mem_ctx,
7699 lp_const_servicename(snum));
7700 if (!W_ERROR_IS_OK(status)) {
7708 /****************************************************************************
7709 fill_print_processor1
7710 ****************************************************************************/
7712 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7713 struct spoolss_PrintProcessorInfo1 *r,
7714 const char *print_processor_name)
7716 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7717 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7722 /****************************************************************************
7723 enumprintprocessors level 1.
7724 ****************************************************************************/
7726 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7727 union spoolss_PrintProcessorInfo **info_p,
7730 union spoolss_PrintProcessorInfo *info;
7733 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7734 W_ERROR_HAVE_NO_MEMORY(info);
7738 result = fill_print_processor1(info, &info[0].info1, "winprint");
7739 if (!W_ERROR_IS_OK(result)) {
7744 if (!W_ERROR_IS_OK(result)) {
7755 /****************************************************************
7756 _spoolss_EnumPrintProcessors
7757 ****************************************************************/
7759 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7760 struct spoolss_EnumPrintProcessors *r)
7764 /* that's an [in out] buffer */
7766 if (!r->in.buffer && (r->in.offered != 0)) {
7767 return WERR_INVALID_PARAM;
7770 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7773 * Enumerate the print processors ...
7775 * Just reply with "winprint", to keep NT happy
7776 * and I can use my nice printer checker.
7781 *r->out.info = NULL;
7783 switch (r->in.level) {
7785 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7789 return WERR_UNKNOWN_LEVEL;
7792 if (!W_ERROR_IS_OK(result)) {
7796 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7797 spoolss_EnumPrintProcessors,
7798 *r->out.info, r->in.level,
7800 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7801 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7803 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7806 /****************************************************************************
7807 fill_printprocdatatype1
7808 ****************************************************************************/
7810 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
7811 struct spoolss_PrintProcDataTypesInfo1 *r,
7812 const char *name_array)
7814 r->name_array = talloc_strdup(mem_ctx, name_array);
7815 W_ERROR_HAVE_NO_MEMORY(r->name_array);
7820 /****************************************************************************
7821 enumprintprocdatatypes level 1.
7822 ****************************************************************************/
7824 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
7825 union spoolss_PrintProcDataTypesInfo **info_p,
7829 union spoolss_PrintProcDataTypesInfo *info;
7831 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
7832 W_ERROR_HAVE_NO_MEMORY(info);
7836 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
7837 if (!W_ERROR_IS_OK(result)) {
7842 if (!W_ERROR_IS_OK(result)) {
7853 /****************************************************************
7854 _spoolss_EnumPrintProcDataTypes
7855 ****************************************************************/
7857 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
7858 struct spoolss_EnumPrintProcDataTypes *r)
7862 /* that's an [in out] buffer */
7864 if (!r->in.buffer && (r->in.offered != 0)) {
7865 return WERR_INVALID_PARAM;
7868 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
7872 *r->out.info = NULL;
7874 switch (r->in.level) {
7876 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
7880 return WERR_UNKNOWN_LEVEL;
7883 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7884 spoolss_EnumPrintProcDataTypes,
7885 *r->out.info, r->in.level,
7887 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7888 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7890 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7893 /****************************************************************************
7895 ****************************************************************************/
7897 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
7898 struct spoolss_MonitorInfo1 *r,
7899 const char *monitor_name)
7901 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
7902 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7907 /****************************************************************************
7909 ****************************************************************************/
7911 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
7912 struct spoolss_MonitorInfo2 *r,
7913 const char *monitor_name,
7914 const char *environment,
7915 const char *dll_name)
7917 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
7918 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7919 r->environment = talloc_strdup(mem_ctx, environment);
7920 W_ERROR_HAVE_NO_MEMORY(r->environment);
7921 r->dll_name = talloc_strdup(mem_ctx, dll_name);
7922 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
7927 /****************************************************************************
7928 enumprintmonitors level 1.
7929 ****************************************************************************/
7931 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
7932 union spoolss_MonitorInfo **info_p,
7935 union spoolss_MonitorInfo *info;
7936 WERROR result = WERR_OK;
7938 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
7939 W_ERROR_HAVE_NO_MEMORY(info);
7943 result = fill_monitor_1(info, &info[0].info1,
7945 if (!W_ERROR_IS_OK(result)) {
7949 result = fill_monitor_1(info, &info[1].info1,
7951 if (!W_ERROR_IS_OK(result)) {
7956 if (!W_ERROR_IS_OK(result)) {
7967 /****************************************************************************
7968 enumprintmonitors level 2.
7969 ****************************************************************************/
7971 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
7972 union spoolss_MonitorInfo **info_p,
7975 union spoolss_MonitorInfo *info;
7976 WERROR result = WERR_OK;
7978 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
7979 W_ERROR_HAVE_NO_MEMORY(info);
7983 result = fill_monitor_2(info, &info[0].info2,
7985 "Windows NT X86", /* FIXME */
7987 if (!W_ERROR_IS_OK(result)) {
7991 result = fill_monitor_2(info, &info[1].info2,
7993 "Windows NT X86", /* FIXME */
7995 if (!W_ERROR_IS_OK(result)) {
8000 if (!W_ERROR_IS_OK(result)) {
8011 /****************************************************************
8012 _spoolss_EnumMonitors
8013 ****************************************************************/
8015 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8016 struct spoolss_EnumMonitors *r)
8020 /* that's an [in out] buffer */
8022 if (!r->in.buffer && (r->in.offered != 0)) {
8023 return WERR_INVALID_PARAM;
8026 DEBUG(5,("_spoolss_EnumMonitors\n"));
8029 * Enumerate the print monitors ...
8031 * Just reply with "Local Port", to keep NT happy
8032 * and I can use my nice printer checker.
8037 *r->out.info = NULL;
8039 switch (r->in.level) {
8041 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8045 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8049 return WERR_UNKNOWN_LEVEL;
8052 if (!W_ERROR_IS_OK(result)) {
8056 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8057 spoolss_EnumMonitors,
8058 *r->out.info, r->in.level,
8060 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8061 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8063 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8066 /****************************************************************************
8067 ****************************************************************************/
8069 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8070 const print_queue_struct *queue,
8071 int count, int snum,
8072 struct spoolss_PrinterInfo2 *pinfo2,
8074 struct spoolss_JobInfo1 *r)
8079 for (i=0; i<count; i++) {
8080 if (queue[i].job == (int)jobid) {
8086 if (found == false) {
8087 /* NT treats not found as bad param... yet another bad choice */
8088 return WERR_INVALID_PARAM;
8091 return fill_job_info1(mem_ctx,
8099 /****************************************************************************
8100 ****************************************************************************/
8102 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8103 const print_queue_struct *queue,
8104 int count, int snum,
8105 struct spoolss_PrinterInfo2 *pinfo2,
8107 struct spoolss_JobInfo2 *r)
8111 struct spoolss_DeviceMode *devmode;
8114 for (i=0; i<count; i++) {
8115 if (queue[i].job == (int)jobid) {
8121 if (found == false) {
8122 /* NT treats not found as bad param... yet another bad
8124 return WERR_INVALID_PARAM;
8128 * if the print job does not have a DEVMODE associated with it,
8129 * just use the one for the printer. A NULL devicemode is not
8130 * a failure condition
8133 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8135 result = spoolss_create_default_devmode(mem_ctx,
8136 pinfo2->printername,
8138 if (!W_ERROR_IS_OK(result)) {
8139 DEBUG(3, ("Can't proceed w/o a devmode!"));
8144 return fill_job_info2(mem_ctx,
8153 /****************************************************************
8155 ****************************************************************/
8157 WERROR _spoolss_GetJob(pipes_struct *p,
8158 struct spoolss_GetJob *r)
8160 WERROR result = WERR_OK;
8161 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8164 print_queue_struct *queue = NULL;
8165 print_status_struct prt_status;
8167 /* that's an [in out] buffer */
8169 if (!r->in.buffer && (r->in.offered != 0)) {
8170 return WERR_INVALID_PARAM;
8173 DEBUG(5,("_spoolss_GetJob\n"));
8177 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8181 result = winreg_get_printer(talloc_tos(), p->server_info, NULL,
8182 lp_servicename(snum), &pinfo2);
8183 if (!W_ERROR_IS_OK(result)) {
8187 count = print_queue_status(snum, &queue, &prt_status);
8189 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8190 count, prt_status.status, prt_status.message));
8192 switch (r->in.level) {
8194 result = getjob_level_1(p->mem_ctx,
8195 queue, count, snum, pinfo2,
8196 r->in.job_id, &r->out.info->info1);
8199 result = getjob_level_2(p->mem_ctx,
8200 queue, count, snum, pinfo2,
8201 r->in.job_id, &r->out.info->info2);
8204 result = WERR_UNKNOWN_LEVEL;
8209 TALLOC_FREE(pinfo2);
8211 if (!W_ERROR_IS_OK(result)) {
8212 TALLOC_FREE(r->out.info);
8216 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8218 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8220 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8223 /****************************************************************
8224 _spoolss_GetPrinterDataEx
8225 ****************************************************************/
8227 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8228 struct spoolss_GetPrinterDataEx *r)
8231 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8232 const char *printer;
8234 WERROR result = WERR_OK;
8236 enum winreg_Type val_type;
8241 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8243 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8244 r->in.key_name, r->in.value_name));
8246 /* in case of problem, return some default values */
8249 *r->out.type = REG_NONE;
8252 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8253 OUR_HANDLE(r->in.handle)));
8254 result = WERR_BADFID;
8258 /* Is the handle to a printer or to the server? */
8260 if (Printer->printer_type == SPLHND_SERVER) {
8262 union spoolss_PrinterData data;
8264 result = getprinterdata_printer_server(p->mem_ctx,
8268 if (!W_ERROR_IS_OK(result)) {
8272 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8273 *r->out.type, &data);
8274 if (!W_ERROR_IS_OK(result)) {
8278 *r->out.needed = blob.length;
8280 if (r->in.offered >= *r->out.needed) {
8281 memcpy(r->out.data, blob.data, blob.length);
8284 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8287 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8290 printer = lp_const_servicename(snum);
8292 /* check to see if the keyname is valid */
8293 if (!strlen(r->in.key_name)) {
8294 return WERR_INVALID_PARAM;
8297 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8298 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8299 strequal(r->in.value_name, "ChangeId")) {
8300 *r->out.type = REG_DWORD;
8302 if (r->in.offered >= *r->out.needed) {
8303 uint32_t changeid = 0;
8305 result = winreg_printer_get_changeid(p->mem_ctx,
8309 if (!W_ERROR_IS_OK(result)) {
8313 SIVAL(r->out.data, 0, changeid);
8319 result = winreg_get_printer_dataex(p->mem_ctx,
8327 if (!W_ERROR_IS_OK(result)) {
8331 *r->out.needed = val_size;
8332 *r->out.type = val_type;
8334 if (r->in.offered >= *r->out.needed) {
8335 memcpy(r->out.data, val_data, val_size);
8339 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8340 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8342 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8345 /****************************************************************
8346 _spoolss_SetPrinterDataEx
8347 ****************************************************************/
8349 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8350 struct spoolss_SetPrinterDataEx *r)
8352 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8354 WERROR result = WERR_OK;
8355 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8358 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8360 /* From MSDN documentation of SetPrinterDataEx: pass request to
8361 SetPrinterData if key is "PrinterDriverData" */
8364 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8365 OUR_HANDLE(r->in.handle)));
8369 if (Printer->printer_type == SPLHND_SERVER) {
8370 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8371 "Not implemented for server handles yet\n"));
8372 return WERR_INVALID_PARAM;
8375 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8380 * Access check : NT returns "access denied" if you make a
8381 * SetPrinterData call without the necessary privildge.
8382 * we were originally returning OK if nothing changed
8383 * which made Win2k issue **a lot** of SetPrinterData
8384 * when connecting to a printer --jerry
8387 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8388 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8389 "change denied by handle access permissions\n"));
8390 return WERR_ACCESS_DENIED;
8393 result = winreg_get_printer(Printer, p->server_info,
8394 Printer->servername,
8395 lp_servicename(snum),
8397 if (!W_ERROR_IS_OK(result)) {
8401 /* check for OID in valuename */
8403 oid_string = strchr(r->in.value_name, ',');
8409 /* save the registry data */
8411 result = winreg_set_printer_dataex(p->mem_ctx,
8420 if (W_ERROR_IS_OK(result)) {
8421 /* save the OID if one was specified */
8423 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8424 r->in.key_name, SPOOL_OID_KEY);
8426 result = WERR_NOMEM;
8431 * I'm not checking the status here on purpose. Don't know
8432 * if this is right, but I'm returning the status from the
8433 * previous set_printer_dataex() call. I have no idea if
8434 * this is right. --jerry
8436 winreg_set_printer_dataex(p->mem_ctx,
8442 (uint8_t *) oid_string,
8443 strlen(oid_string) + 1);
8446 result = winreg_printer_update_changeid(p->mem_ctx,
8448 lp_const_servicename(snum));
8453 talloc_free(pinfo2);
8457 /****************************************************************
8458 _spoolss_DeletePrinterDataEx
8459 ****************************************************************/
8461 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8462 struct spoolss_DeletePrinterDataEx *r)
8464 const char *printer;
8466 WERROR status = WERR_OK;
8467 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8469 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8472 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8473 "Invalid handle (%s:%u:%u).\n",
8474 OUR_HANDLE(r->in.handle)));
8478 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8479 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8480 "printer properties change denied by handle\n"));
8481 return WERR_ACCESS_DENIED;
8484 if (!r->in.value_name || !r->in.key_name) {
8488 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8491 printer = lp_const_servicename(snum);
8493 status = winreg_delete_printer_dataex(p->mem_ctx,
8498 if (W_ERROR_IS_OK(status)) {
8499 status = winreg_printer_update_changeid(p->mem_ctx,
8507 /****************************************************************
8508 _spoolss_EnumPrinterKey
8509 ****************************************************************/
8511 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8512 struct spoolss_EnumPrinterKey *r)
8515 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8517 WERROR result = WERR_BADFILE;
8518 const char **array = NULL;
8521 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8524 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8525 OUR_HANDLE(r->in.handle)));
8529 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8533 result = winreg_enum_printer_key(p->mem_ctx,
8535 lp_const_servicename(snum),
8539 if (!W_ERROR_IS_OK(result)) {
8543 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8544 result = WERR_NOMEM;
8548 *r->out._ndr_size = r->in.offered / 2;
8549 *r->out.needed = blob.length;
8551 if (r->in.offered < *r->out.needed) {
8552 result = WERR_MORE_DATA;
8555 r->out.key_buffer->string_array = array;
8559 if (!W_ERROR_IS_OK(result)) {
8561 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8569 /****************************************************************
8570 _spoolss_DeletePrinterKey
8571 ****************************************************************/
8573 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8574 struct spoolss_DeletePrinterKey *r)
8576 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8579 const char *printer;
8581 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8584 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8585 OUR_HANDLE(r->in.handle)));
8589 /* if keyname == NULL, return error */
8590 if ( !r->in.key_name )
8591 return WERR_INVALID_PARAM;
8593 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8597 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8598 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8599 "printer properties change denied by handle\n"));
8600 return WERR_ACCESS_DENIED;
8603 printer = lp_const_servicename(snum);
8605 /* delete the key and all subkeys */
8606 status = winreg_delete_printer_key(p->mem_ctx,
8610 if (W_ERROR_IS_OK(status)) {
8611 status = winreg_printer_update_changeid(p->mem_ctx,
8619 /****************************************************************
8620 _spoolss_EnumPrinterDataEx
8621 ****************************************************************/
8623 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8624 struct spoolss_EnumPrinterDataEx *r)
8627 struct spoolss_PrinterEnumValues *info = NULL;
8628 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8632 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8636 *r->out.info = NULL;
8639 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8640 OUR_HANDLE(r->in.handle)));
8645 * first check for a keyname of NULL or "". Win2k seems to send
8646 * this a lot and we should send back WERR_INVALID_PARAM
8647 * no need to spend time looking up the printer in this case.
8651 if (!strlen(r->in.key_name)) {
8652 result = WERR_INVALID_PARAM;
8656 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8660 /* now look for a match on the key name */
8661 result = winreg_enum_printer_dataex(p->mem_ctx,
8663 lp_const_servicename(snum),
8667 if (!W_ERROR_IS_OK(result)) {
8671 #if 0 /* FIXME - gd */
8672 /* housekeeping information in the reply */
8674 /* Fix from Martin Zielinski <mz@seh.de> - ensure
8675 * the hand marshalled container size is a multiple
8676 * of 4 bytes for RPC alignment.
8680 needed += 4-(needed % 4);
8683 *r->out.count = count;
8684 *r->out.info = info;
8687 if (!W_ERROR_IS_OK(result)) {
8691 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8692 spoolss_EnumPrinterDataEx,
8695 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8696 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8698 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8701 /****************************************************************************
8702 ****************************************************************************/
8704 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8705 const char *servername,
8706 const char *environment,
8707 struct spoolss_PrintProcessorDirectoryInfo1 *r)
8712 werr = compose_spoolss_server_path(mem_ctx,
8715 SPOOLSS_PRTPROCS_PATH,
8717 if (!W_ERROR_IS_OK(werr)) {
8721 DEBUG(4,("print processor directory: [%s]\n", path));
8723 r->directory_name = path;
8728 /****************************************************************
8729 _spoolss_GetPrintProcessorDirectory
8730 ****************************************************************/
8732 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8733 struct spoolss_GetPrintProcessorDirectory *r)
8737 /* that's an [in out] buffer */
8739 if (!r->in.buffer && (r->in.offered != 0)) {
8740 return WERR_INVALID_PARAM;
8743 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8748 /* r->in.level is ignored */
8750 /* We always should reply with a local print processor directory so that
8751 * users are not forced to have a [prnproc$] share on the Samba spoolss
8752 * server - Guenther */
8754 result = getprintprocessordirectory_level_1(p->mem_ctx,
8755 NULL, /* r->in.server */
8757 &r->out.info->info1);
8758 if (!W_ERROR_IS_OK(result)) {
8759 TALLOC_FREE(r->out.info);
8763 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8764 r->out.info, r->in.level);
8765 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8767 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8770 /*******************************************************************
8771 ********************************************************************/
8773 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8774 const char *dllname)
8776 enum ndr_err_code ndr_err;
8777 struct spoolss_MonitorUi ui;
8779 ui.dll_name = dllname;
8781 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8782 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8783 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8784 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8786 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8789 /*******************************************************************
8790 Streams the monitor UI DLL name in UNICODE
8791 *******************************************************************/
8793 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8794 NT_USER_TOKEN *token, DATA_BLOB *in,
8795 DATA_BLOB *out, uint32_t *needed)
8797 const char *dllname = "tcpmonui.dll";
8799 *needed = (strlen(dllname)+1) * 2;
8801 if (out->length < *needed) {
8802 return WERR_INSUFFICIENT_BUFFER;
8805 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8812 /*******************************************************************
8813 ********************************************************************/
8815 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
8816 struct spoolss_PortData1 *port1,
8817 const DATA_BLOB *buf)
8819 enum ndr_err_code ndr_err;
8820 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
8821 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
8822 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8823 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
8825 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8828 /*******************************************************************
8829 ********************************************************************/
8831 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
8832 struct spoolss_PortData2 *port2,
8833 const DATA_BLOB *buf)
8835 enum ndr_err_code ndr_err;
8836 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
8837 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
8838 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8839 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
8841 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8844 /*******************************************************************
8845 Create a new TCP/IP port
8846 *******************************************************************/
8848 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
8849 NT_USER_TOKEN *token, DATA_BLOB *in,
8850 DATA_BLOB *out, uint32_t *needed)
8852 struct spoolss_PortData1 port1;
8853 struct spoolss_PortData2 port2;
8854 char *device_uri = NULL;
8857 const char *portname;
8858 const char *hostaddress;
8860 uint32_t port_number;
8863 /* peek for spoolss_PortData version */
8865 if (!in || (in->length < (128 + 4))) {
8866 return WERR_GENERAL_FAILURE;
8869 version = IVAL(in->data, 128);
8875 if (!pull_port_data_1(mem_ctx, &port1, in)) {
8879 portname = port1.portname;
8880 hostaddress = port1.hostaddress;
8881 queue = port1.queue;
8882 protocol = port1.protocol;
8883 port_number = port1.port_number;
8889 if (!pull_port_data_2(mem_ctx, &port2, in)) {
8893 portname = port2.portname;
8894 hostaddress = port2.hostaddress;
8895 queue = port2.queue;
8896 protocol = port2.protocol;
8897 port_number = port2.port_number;
8901 DEBUG(1,("xcvtcp_addport: "
8902 "unknown version of port_data: %d\n", version));
8903 return WERR_UNKNOWN_PORT;
8906 /* create the device URI and call the add_port_hook() */
8909 case PROTOCOL_RAWTCP_TYPE:
8910 device_uri = talloc_asprintf(mem_ctx,
8911 "socket://%s:%d/", hostaddress,
8915 case PROTOCOL_LPR_TYPE:
8916 device_uri = talloc_asprintf(mem_ctx,
8917 "lpr://%s/%s", hostaddress, queue );
8921 return WERR_UNKNOWN_PORT;
8928 return add_port_hook(mem_ctx, token, portname, device_uri);
8931 /*******************************************************************
8932 *******************************************************************/
8934 struct xcv_api_table xcvtcp_cmds[] = {
8935 { "MonitorUI", xcvtcp_monitorui },
8936 { "AddPort", xcvtcp_addport},
8940 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
8941 NT_USER_TOKEN *token, const char *command,
8948 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
8950 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
8951 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
8952 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
8955 return WERR_BADFUNC;
8958 /*******************************************************************
8959 *******************************************************************/
8960 #if 0 /* don't support management using the "Local Port" monitor */
8962 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
8963 NT_USER_TOKEN *token, DATA_BLOB *in,
8964 DATA_BLOB *out, uint32_t *needed)
8966 const char *dllname = "localui.dll";
8968 *needed = (strlen(dllname)+1) * 2;
8970 if (out->length < *needed) {
8971 return WERR_INSUFFICIENT_BUFFER;
8974 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8981 /*******************************************************************
8982 *******************************************************************/
8984 struct xcv_api_table xcvlocal_cmds[] = {
8985 { "MonitorUI", xcvlocal_monitorui },
8989 struct xcv_api_table xcvlocal_cmds[] = {
8996 /*******************************************************************
8997 *******************************************************************/
8999 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9000 NT_USER_TOKEN *token, const char *command,
9001 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9006 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9008 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9009 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9010 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9012 return WERR_BADFUNC;
9015 /****************************************************************
9017 ****************************************************************/
9019 WERROR _spoolss_XcvData(pipes_struct *p,
9020 struct spoolss_XcvData *r)
9022 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9023 DATA_BLOB out_data = data_blob_null;
9027 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9028 OUR_HANDLE(r->in.handle)));
9032 /* Has to be a handle to the TCP/IP port monitor */
9034 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9035 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9039 /* requires administrative access to the server */
9041 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9042 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9043 return WERR_ACCESS_DENIED;
9046 /* Allocate the outgoing buffer */
9048 if (r->in.out_data_size) {
9049 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9050 if (out_data.data == NULL) {
9055 switch ( Printer->printer_type ) {
9056 case SPLHND_PORTMON_TCP:
9057 werror = process_xcvtcp_command(p->mem_ctx,
9058 p->server_info->ptok,
9059 r->in.function_name,
9060 &r->in.in_data, &out_data,
9063 case SPLHND_PORTMON_LOCAL:
9064 werror = process_xcvlocal_command(p->mem_ctx,
9065 p->server_info->ptok,
9066 r->in.function_name,
9067 &r->in.in_data, &out_data,
9071 werror = WERR_INVALID_PRINT_MONITOR;
9074 if (!W_ERROR_IS_OK(werror)) {
9078 *r->out.status_code = 0;
9080 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9081 memcpy(r->out.out_data, out_data.data,
9082 MIN(r->in.out_data_size, out_data.length));
9088 /****************************************************************
9089 _spoolss_AddPrintProcessor
9090 ****************************************************************/
9092 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9093 struct spoolss_AddPrintProcessor *r)
9095 /* for now, just indicate success and ignore the add. We'll
9096 automatically set the winprint processor for printer
9097 entries later. Used to debug the LexMark Optra S 1855 PCL
9103 /****************************************************************
9105 ****************************************************************/
9107 WERROR _spoolss_AddPort(pipes_struct *p,
9108 struct spoolss_AddPort *r)
9110 /* do what w2k3 does */
9112 return WERR_NOT_SUPPORTED;
9115 /****************************************************************
9116 _spoolss_GetPrinterDriver
9117 ****************************************************************/
9119 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9120 struct spoolss_GetPrinterDriver *r)
9122 p->rng_fault_state = true;
9123 return WERR_NOT_SUPPORTED;
9126 /****************************************************************
9127 _spoolss_ReadPrinter
9128 ****************************************************************/
9130 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9131 struct spoolss_ReadPrinter *r)
9133 p->rng_fault_state = true;
9134 return WERR_NOT_SUPPORTED;
9137 /****************************************************************
9138 _spoolss_WaitForPrinterChange
9139 ****************************************************************/
9141 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9142 struct spoolss_WaitForPrinterChange *r)
9144 p->rng_fault_state = true;
9145 return WERR_NOT_SUPPORTED;
9148 /****************************************************************
9149 _spoolss_ConfigurePort
9150 ****************************************************************/
9152 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9153 struct spoolss_ConfigurePort *r)
9155 p->rng_fault_state = true;
9156 return WERR_NOT_SUPPORTED;
9159 /****************************************************************
9161 ****************************************************************/
9163 WERROR _spoolss_DeletePort(pipes_struct *p,
9164 struct spoolss_DeletePort *r)
9166 p->rng_fault_state = true;
9167 return WERR_NOT_SUPPORTED;
9170 /****************************************************************
9171 _spoolss_CreatePrinterIC
9172 ****************************************************************/
9174 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9175 struct spoolss_CreatePrinterIC *r)
9177 p->rng_fault_state = true;
9178 return WERR_NOT_SUPPORTED;
9181 /****************************************************************
9182 _spoolss_PlayGDIScriptOnPrinterIC
9183 ****************************************************************/
9185 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9186 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9188 p->rng_fault_state = true;
9189 return WERR_NOT_SUPPORTED;
9192 /****************************************************************
9193 _spoolss_DeletePrinterIC
9194 ****************************************************************/
9196 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9197 struct spoolss_DeletePrinterIC *r)
9199 p->rng_fault_state = true;
9200 return WERR_NOT_SUPPORTED;
9203 /****************************************************************
9204 _spoolss_AddPrinterConnection
9205 ****************************************************************/
9207 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9208 struct spoolss_AddPrinterConnection *r)
9210 p->rng_fault_state = true;
9211 return WERR_NOT_SUPPORTED;
9214 /****************************************************************
9215 _spoolss_DeletePrinterConnection
9216 ****************************************************************/
9218 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9219 struct spoolss_DeletePrinterConnection *r)
9221 p->rng_fault_state = true;
9222 return WERR_NOT_SUPPORTED;
9225 /****************************************************************
9226 _spoolss_PrinterMessageBox
9227 ****************************************************************/
9229 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9230 struct spoolss_PrinterMessageBox *r)
9232 p->rng_fault_state = true;
9233 return WERR_NOT_SUPPORTED;
9236 /****************************************************************
9238 ****************************************************************/
9240 WERROR _spoolss_AddMonitor(pipes_struct *p,
9241 struct spoolss_AddMonitor *r)
9243 p->rng_fault_state = true;
9244 return WERR_NOT_SUPPORTED;
9247 /****************************************************************
9248 _spoolss_DeleteMonitor
9249 ****************************************************************/
9251 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9252 struct spoolss_DeleteMonitor *r)
9254 p->rng_fault_state = true;
9255 return WERR_NOT_SUPPORTED;
9258 /****************************************************************
9259 _spoolss_DeletePrintProcessor
9260 ****************************************************************/
9262 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9263 struct spoolss_DeletePrintProcessor *r)
9265 p->rng_fault_state = true;
9266 return WERR_NOT_SUPPORTED;
9269 /****************************************************************
9270 _spoolss_AddPrintProvidor
9271 ****************************************************************/
9273 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9274 struct spoolss_AddPrintProvidor *r)
9276 p->rng_fault_state = true;
9277 return WERR_NOT_SUPPORTED;
9280 /****************************************************************
9281 _spoolss_DeletePrintProvidor
9282 ****************************************************************/
9284 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9285 struct spoolss_DeletePrintProvidor *r)
9287 p->rng_fault_state = true;
9288 return WERR_NOT_SUPPORTED;
9291 /****************************************************************
9292 _spoolss_FindFirstPrinterChangeNotification
9293 ****************************************************************/
9295 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9296 struct spoolss_FindFirstPrinterChangeNotification *r)
9298 p->rng_fault_state = true;
9299 return WERR_NOT_SUPPORTED;
9302 /****************************************************************
9303 _spoolss_FindNextPrinterChangeNotification
9304 ****************************************************************/
9306 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9307 struct spoolss_FindNextPrinterChangeNotification *r)
9309 p->rng_fault_state = true;
9310 return WERR_NOT_SUPPORTED;
9313 /****************************************************************
9314 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9315 ****************************************************************/
9317 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9318 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9320 p->rng_fault_state = true;
9321 return WERR_NOT_SUPPORTED;
9324 /****************************************************************
9325 _spoolss_ReplyOpenPrinter
9326 ****************************************************************/
9328 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9329 struct spoolss_ReplyOpenPrinter *r)
9331 p->rng_fault_state = true;
9332 return WERR_NOT_SUPPORTED;
9335 /****************************************************************
9336 _spoolss_RouterReplyPrinter
9337 ****************************************************************/
9339 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9340 struct spoolss_RouterReplyPrinter *r)
9342 p->rng_fault_state = true;
9343 return WERR_NOT_SUPPORTED;
9346 /****************************************************************
9347 _spoolss_ReplyClosePrinter
9348 ****************************************************************/
9350 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9351 struct spoolss_ReplyClosePrinter *r)
9353 p->rng_fault_state = true;
9354 return WERR_NOT_SUPPORTED;
9357 /****************************************************************
9359 ****************************************************************/
9361 WERROR _spoolss_AddPortEx(pipes_struct *p,
9362 struct spoolss_AddPortEx *r)
9364 p->rng_fault_state = true;
9365 return WERR_NOT_SUPPORTED;
9368 /****************************************************************
9369 _spoolss_RouterFindFirstPrinterChangeNotification
9370 ****************************************************************/
9372 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9373 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9375 p->rng_fault_state = true;
9376 return WERR_NOT_SUPPORTED;
9379 /****************************************************************
9380 _spoolss_SpoolerInit
9381 ****************************************************************/
9383 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9384 struct spoolss_SpoolerInit *r)
9386 p->rng_fault_state = true;
9387 return WERR_NOT_SUPPORTED;
9390 /****************************************************************
9391 _spoolss_ResetPrinterEx
9392 ****************************************************************/
9394 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9395 struct spoolss_ResetPrinterEx *r)
9397 p->rng_fault_state = true;
9398 return WERR_NOT_SUPPORTED;
9401 /****************************************************************
9402 _spoolss_RouterReplyPrinterEx
9403 ****************************************************************/
9405 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9406 struct spoolss_RouterReplyPrinterEx *r)
9408 p->rng_fault_state = true;
9409 return WERR_NOT_SUPPORTED;
9412 /****************************************************************
9414 ****************************************************************/
9416 WERROR _spoolss_44(pipes_struct *p,
9417 struct spoolss_44 *r)
9419 p->rng_fault_state = true;
9420 return WERR_NOT_SUPPORTED;
9423 /****************************************************************
9425 ****************************************************************/
9427 WERROR _spoolss_47(pipes_struct *p,
9428 struct spoolss_47 *r)
9430 p->rng_fault_state = true;
9431 return WERR_NOT_SUPPORTED;
9434 /****************************************************************
9436 ****************************************************************/
9438 WERROR _spoolss_4a(pipes_struct *p,
9439 struct spoolss_4a *r)
9441 p->rng_fault_state = true;
9442 return WERR_NOT_SUPPORTED;
9445 /****************************************************************
9447 ****************************************************************/
9449 WERROR _spoolss_4b(pipes_struct *p,
9450 struct spoolss_4b *r)
9452 p->rng_fault_state = true;
9453 return WERR_NOT_SUPPORTED;
9456 /****************************************************************
9458 ****************************************************************/
9460 WERROR _spoolss_4c(pipes_struct *p,
9461 struct spoolss_4c *r)
9463 p->rng_fault_state = true;
9464 return WERR_NOT_SUPPORTED;
9467 /****************************************************************
9469 ****************************************************************/
9471 WERROR _spoolss_53(pipes_struct *p,
9472 struct spoolss_53 *r)
9474 p->rng_fault_state = true;
9475 return WERR_NOT_SUPPORTED;
9478 /****************************************************************
9480 ****************************************************************/
9482 WERROR _spoolss_55(pipes_struct *p,
9483 struct spoolss_55 *r)
9485 p->rng_fault_state = true;
9486 return WERR_NOT_SUPPORTED;
9489 /****************************************************************
9491 ****************************************************************/
9493 WERROR _spoolss_56(pipes_struct *p,
9494 struct spoolss_56 *r)
9496 p->rng_fault_state = true;
9497 return WERR_NOT_SUPPORTED;
9500 /****************************************************************
9502 ****************************************************************/
9504 WERROR _spoolss_57(pipes_struct *p,
9505 struct spoolss_57 *r)
9507 p->rng_fault_state = true;
9508 return WERR_NOT_SUPPORTED;
9511 /****************************************************************
9513 ****************************************************************/
9515 WERROR _spoolss_5a(pipes_struct *p,
9516 struct spoolss_5a *r)
9518 p->rng_fault_state = true;
9519 return WERR_NOT_SUPPORTED;
9522 /****************************************************************
9524 ****************************************************************/
9526 WERROR _spoolss_5b(pipes_struct *p,
9527 struct spoolss_5b *r)
9529 p->rng_fault_state = true;
9530 return WERR_NOT_SUPPORTED;
9533 /****************************************************************
9535 ****************************************************************/
9537 WERROR _spoolss_5c(pipes_struct *p,
9538 struct spoolss_5c *r)
9540 p->rng_fault_state = true;
9541 return WERR_NOT_SUPPORTED;
9544 /****************************************************************
9546 ****************************************************************/
9548 WERROR _spoolss_5d(pipes_struct *p,
9549 struct spoolss_5d *r)
9551 p->rng_fault_state = true;
9552 return WERR_NOT_SUPPORTED;
9555 /****************************************************************
9557 ****************************************************************/
9559 WERROR _spoolss_5e(pipes_struct *p,
9560 struct spoolss_5e *r)
9562 p->rng_fault_state = true;
9563 return WERR_NOT_SUPPORTED;
9566 /****************************************************************
9568 ****************************************************************/
9570 WERROR _spoolss_5f(pipes_struct *p,
9571 struct spoolss_5f *r)
9573 p->rng_fault_state = true;
9574 return WERR_NOT_SUPPORTED;
9577 /****************************************************************
9579 ****************************************************************/
9581 WERROR _spoolss_60(pipes_struct *p,
9582 struct spoolss_60 *r)
9584 p->rng_fault_state = true;
9585 return WERR_NOT_SUPPORTED;
9588 /****************************************************************
9590 ****************************************************************/
9592 WERROR _spoolss_61(pipes_struct *p,
9593 struct spoolss_61 *r)
9595 p->rng_fault_state = true;
9596 return WERR_NOT_SUPPORTED;
9599 /****************************************************************
9601 ****************************************************************/
9603 WERROR _spoolss_62(pipes_struct *p,
9604 struct spoolss_62 *r)
9606 p->rng_fault_state = true;
9607 return WERR_NOT_SUPPORTED;
9610 /****************************************************************
9612 ****************************************************************/
9614 WERROR _spoolss_63(pipes_struct *p,
9615 struct spoolss_63 *r)
9617 p->rng_fault_state = true;
9618 return WERR_NOT_SUPPORTED;
9621 /****************************************************************
9623 ****************************************************************/
9625 WERROR _spoolss_64(pipes_struct *p,
9626 struct spoolss_64 *r)
9628 p->rng_fault_state = true;
9629 return WERR_NOT_SUPPORTED;
9632 /****************************************************************
9634 ****************************************************************/
9636 WERROR _spoolss_65(pipes_struct *p,
9637 struct spoolss_65 *r)
9639 p->rng_fault_state = true;
9640 return WERR_NOT_SUPPORTED;
9643 /****************************************************************
9644 _spoolss_GetCorePrinterDrivers
9645 ****************************************************************/
9647 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9648 struct spoolss_GetCorePrinterDrivers *r)
9650 p->rng_fault_state = true;
9651 return WERR_NOT_SUPPORTED;
9654 /****************************************************************
9656 ****************************************************************/
9658 WERROR _spoolss_67(pipes_struct *p,
9659 struct spoolss_67 *r)
9661 p->rng_fault_state = true;
9662 return WERR_NOT_SUPPORTED;
9665 /****************************************************************
9666 _spoolss_GetPrinterDriverPackagePath
9667 ****************************************************************/
9669 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9670 struct spoolss_GetPrinterDriverPackagePath *r)
9672 p->rng_fault_state = true;
9673 return WERR_NOT_SUPPORTED;
9676 /****************************************************************
9678 ****************************************************************/
9680 WERROR _spoolss_69(pipes_struct *p,
9681 struct spoolss_69 *r)
9683 p->rng_fault_state = true;
9684 return WERR_NOT_SUPPORTED;
9687 /****************************************************************
9689 ****************************************************************/
9691 WERROR _spoolss_6a(pipes_struct *p,
9692 struct spoolss_6a *r)
9694 p->rng_fault_state = true;
9695 return WERR_NOT_SUPPORTED;
9698 /****************************************************************
9700 ****************************************************************/
9702 WERROR _spoolss_6b(pipes_struct *p,
9703 struct spoolss_6b *r)
9705 p->rng_fault_state = true;
9706 return WERR_NOT_SUPPORTED;
9709 /****************************************************************
9711 ****************************************************************/
9713 WERROR _spoolss_6c(pipes_struct *p,
9714 struct spoolss_6c *r)
9716 p->rng_fault_state = true;
9717 return WERR_NOT_SUPPORTED;
9720 /****************************************************************
9722 ****************************************************************/
9724 WERROR _spoolss_6d(pipes_struct *p,
9725 struct spoolss_6d *r)
9727 p->rng_fault_state = true;
9728 return WERR_NOT_SUPPORTED;