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"
36 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry/reg_objects.h"
40 /* macros stolen from s4 spoolss server */
41 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
42 ((info)?ndr_size_##fn(info, level, 0):0)
44 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
45 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
47 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
48 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
50 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
53 extern userdom_struct current_user_info;
56 #define DBGC_CLASS DBGC_RPC_SRV
58 #ifndef MAX_OPEN_PRINTER_EXS
59 #define MAX_OPEN_PRINTER_EXS 50
62 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 struct _counter_printer_0 *next;
68 struct _counter_printer_0 *prev;
74 static counter_printer_0 *counter_list;
76 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
77 static uint32_t smb_connections = 0;
80 /* in printing/nt_printing.c */
82 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
84 /* API table for Xcv Monitor functions */
86 struct xcv_api_table {
88 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
91 /********************************************************************
92 * Canonicalize servername.
93 ********************************************************************/
95 static const char *canon_servername(const char *servername)
97 const char *pservername = servername;
98 while (*pservername == '\\') {
104 /* translate between internal status numbers and NT status numbers */
105 static int nt_printj_status(int v)
111 return JOB_STATUS_PAUSED;
113 return JOB_STATUS_SPOOLING;
115 return JOB_STATUS_PRINTING;
117 return JOB_STATUS_ERROR;
119 return JOB_STATUS_DELETING;
121 return JOB_STATUS_OFFLINE;
123 return JOB_STATUS_PAPEROUT;
125 return JOB_STATUS_PRINTED;
127 return JOB_STATUS_DELETED;
129 return JOB_STATUS_BLOCKED_DEVQ;
130 case LPQ_USER_INTERVENTION:
131 return JOB_STATUS_USER_INTERVENTION;
136 static int nt_printq_status(int v)
140 return PRINTER_STATUS_PAUSED;
149 /***************************************************************************
150 Disconnect from the client
151 ****************************************************************************/
153 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
159 * Tell the specific printing tdb we no longer want messages for this printer
160 * by deregistering our PID.
163 if (!print_notify_deregister_pid(snum))
164 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
166 /* weird if the test succeds !!! */
167 if (smb_connections==0) {
168 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
172 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
175 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
176 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
177 win_errstr(result)));
179 /* if it's the last connection, deconnect the IPC$ share */
180 if (smb_connections==1) {
182 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
183 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
185 messaging_deregister(smbd_messaging_context(),
186 MSG_PRINTER_NOTIFY2, NULL);
188 /* Tell the connections db we're no longer interested in
189 * printer notify messages. */
191 serverid_register_msg_flags(
192 messaging_server_id(smbd_messaging_context()),
193 false, FLAG_MSG_PRINT_NOTIFY);
199 /****************************************************************************
200 Functions to free a printer entry datastruct.
201 ****************************************************************************/
203 static int printer_entry_destructor(Printer_entry *Printer)
205 if (Printer->notify.client_connected == true) {
208 if ( Printer->printer_type == SPLHND_SERVER) {
210 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
211 } else if (Printer->printer_type == SPLHND_PRINTER) {
212 snum = print_queue_snum(Printer->sharename);
214 srv_spoolss_replycloseprinter(snum,
215 &Printer->notify.client_hnd);
219 Printer->notify.flags=0;
220 Printer->notify.options=0;
221 Printer->notify.localmachine[0]='\0';
222 Printer->notify.printerlocal=0;
223 TALLOC_FREE(Printer->notify.option);
224 Printer->notify.client_connected = false;
226 TALLOC_FREE(Printer->devmode);
227 free_a_printer( &Printer->printer_info, 2 );
229 /* Remove from the internal list. */
230 DLIST_REMOVE(printers_list, Printer);
234 /****************************************************************************
235 find printer index by handle
236 ****************************************************************************/
238 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
239 struct policy_handle *hnd)
241 Printer_entry *find_printer = NULL;
243 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
244 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
251 /****************************************************************************
252 Close printer index by handle.
253 ****************************************************************************/
255 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
257 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
260 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
265 close_policy_hnd(p, hnd);
270 /****************************************************************************
271 Delete a printer given a handle.
272 ****************************************************************************/
274 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
276 char *cmd = lp_deleteprinter_cmd();
277 char *command = NULL;
279 SE_PRIV se_printop = SE_PRINT_OPERATOR;
280 bool is_print_op = false;
282 /* can't fail if we don't try */
287 command = talloc_asprintf(ctx,
294 is_print_op = user_has_privileges( token, &se_printop );
296 DEBUG(10,("Running [%s]\n", command));
298 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
303 if ( (ret = smbrun(command, NULL)) == 0 ) {
304 /* Tell everyone we updated smb.conf. */
305 message_send_all(smbd_messaging_context(),
306 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
312 /********** END SePrintOperatorPrivlege BLOCK **********/
314 DEBUGADD(10,("returned [%d]\n", ret));
316 TALLOC_FREE(command);
319 return WERR_BADFID; /* What to return here? */
321 /* go ahead and re-read the services immediately */
323 reload_services(false);
326 if ( lp_servicenumber( sharename ) > 0 )
327 return WERR_ACCESS_DENIED;
332 /****************************************************************************
333 Delete a printer given a handle.
334 ****************************************************************************/
336 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
338 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
341 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
347 * It turns out that Windows allows delete printer on a handle
348 * opened by an admin user, then used on a pipe handle created
349 * by an anonymous user..... but they're working on security.... riiight !
353 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
354 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
355 return WERR_ACCESS_DENIED;
358 /* this does not need a become root since the access check has been
359 done on the handle already */
361 if (del_a_printer( Printer->sharename ) != 0) {
362 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
366 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
367 Printer->sharename );
370 /****************************************************************************
371 Return the snum of a printer corresponding to an handle.
372 ****************************************************************************/
374 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
375 int *number, struct share_params **params)
377 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
380 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
385 switch (Printer->printer_type) {
387 DEBUG(4,("short name:%s\n", Printer->sharename));
388 *number = print_queue_snum(Printer->sharename);
389 return (*number != -1);
397 /****************************************************************************
398 Set printer handle type.
399 Check if it's \\server or \\server\printer
400 ****************************************************************************/
402 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
404 DEBUG(3,("Setting printer type=%s\n", handlename));
406 if ( strlen(handlename) < 3 ) {
407 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
411 /* it's a print server */
412 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
413 DEBUGADD(4,("Printer is a print server\n"));
414 Printer->printer_type = SPLHND_SERVER;
416 /* it's a printer (set_printer_hnd_name() will handle port monitors */
418 DEBUGADD(4,("Printer is a printer\n"));
419 Printer->printer_type = SPLHND_PRINTER;
425 /****************************************************************************
426 Set printer handle name.. Accept names like \\server, \\server\printer,
427 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
428 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
429 XcvDataPort() interface.
430 ****************************************************************************/
432 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
433 struct auth_serversupplied_info *server_info,
434 Printer_entry *Printer,
435 const char *handlename)
438 int n_services=lp_numservices();
440 const char *printername;
441 const char *servername;
444 struct spoolss_PrinterInfo2 *info2 = NULL;
447 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
448 (unsigned long)strlen(handlename)));
450 aprinter = CONST_DISCARD(char *, handlename);
451 if ( *handlename == '\\' ) {
452 servername = canon_servername(handlename);
453 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
457 if (!is_myname_or_ipaddr(servername)) {
461 fstrcpy(Printer->servername, servername);
464 if (Printer->printer_type == SPLHND_SERVER) {
468 if (Printer->printer_type != SPLHND_PRINTER) {
472 DEBUGADD(5, ("searching for [%s]\n", aprinter));
474 /* check for the Port Monitor Interface */
475 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
476 Printer->printer_type = SPLHND_PORTMON_TCP;
477 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
480 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
481 Printer->printer_type = SPLHND_PORTMON_LOCAL;
482 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
486 /* Search all sharenames first as this is easier than pulling
487 the printer_info_2 off of disk. Don't use find_service() since
488 that calls out to map_username() */
490 /* do another loop to look for printernames */
491 for (snum = 0; !found && snum < n_services; snum++) {
492 const char *printer = lp_const_servicename(snum);
494 /* no point going on if this is not a printer */
495 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
499 /* ignore [printers] share */
500 if (strequal(printer, "printers")) {
504 fstrcpy(sname, printer);
505 if (strequal(aprinter, printer)) {
510 /* no point looking up the printer object if
511 we aren't allowing printername != sharename */
512 if (lp_force_printername(snum)) {
516 result = winreg_get_printer(mem_ctx,
521 if ( !W_ERROR_IS_OK(result) ) {
522 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
523 sname, win_errstr(result)));
527 printername = strrchr(info2->printername, '\\');
528 if (printername == NULL) {
529 printername = info2->printername;
534 if (strequal(printername, aprinter)) {
539 DEBUGADD(10, ("printername: %s\n", printername));
545 DEBUGADD(4,("Printer not found\n"));
549 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
551 fstrcpy(Printer->sharename, sname);
556 /****************************************************************************
557 Find first available printer slot. creates a printer handle for you.
558 ****************************************************************************/
560 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
561 const char *name, uint32_t access_granted)
563 Printer_entry *new_printer;
565 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
567 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
568 if (new_printer == NULL) {
571 talloc_set_destructor(new_printer, printer_entry_destructor);
573 if (!create_policy_hnd(p, hnd, new_printer)) {
574 TALLOC_FREE(new_printer);
578 /* Add to the internal list. */
579 DLIST_ADD(printers_list, new_printer);
581 new_printer->notify.option=NULL;
583 if (!set_printer_hnd_printertype(new_printer, name)) {
584 close_printer_handle(p, hnd);
588 if (!set_printer_hnd_name(p->mem_ctx, p->server_info, new_printer, name)) {
589 close_printer_handle(p, hnd);
593 new_printer->access_granted = access_granted;
595 DEBUG(5, ("%d printer handles active\n",
596 (int)num_pipe_handles(p)));
601 /***************************************************************************
602 check to see if the client motify handle is monitoring the notification
603 given by (notify_type, notify_field).
604 **************************************************************************/
606 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
607 uint16_t notify_field)
612 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
613 uint16_t notify_field)
615 struct spoolss_NotifyOption *option = p->notify.option;
619 * Flags should always be zero when the change notify
620 * is registered by the client's spooler. A user Win32 app
621 * might use the flags though instead of the NOTIFY_OPTION_INFO
630 return is_monitoring_event_flags(
631 p->notify.flags, notify_type, notify_field);
633 for (i = 0; i < option->count; i++) {
635 /* Check match for notify_type */
637 if (option->types[i].type != notify_type)
640 /* Check match for field */
642 for (j = 0; j < option->types[i].count; j++) {
643 if (option->types[i].fields[j].field == notify_field) {
649 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
650 p->servername, p->sharename, notify_type, notify_field));
655 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
656 _data->data.integer[0] = _integer; \
657 _data->data.integer[1] = 0;
660 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
661 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
662 if (!_data->data.string.string) {\
663 _data->data.string.size = 0; \
665 _data->data.string.size = strlen_m_term(_p) * 2;
667 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
668 _data->data.devmode.devmode = _devmode;
670 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
671 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
672 if (!_data->data.sd.sd) { \
673 _data->data.sd.sd_size = 0; \
675 _data->data.sd.sd_size = \
676 ndr_size_security_descriptor(_data->data.sd.sd, 0);
678 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
683 struct spoolss_Time st;
687 if (!init_systemtime(&st, t)) {
691 p = talloc_array(mem_ctx, char, len);
697 * Systemtime must be linearized as a set of UINT16's.
698 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
701 SSVAL(p, 0, st.year);
702 SSVAL(p, 2, st.month);
703 SSVAL(p, 4, st.day_of_week);
705 SSVAL(p, 8, st.hour);
706 SSVAL(p, 10, st.minute);
707 SSVAL(p, 12, st.second);
708 SSVAL(p, 14, st.millisecond);
714 /* Convert a notification message to a struct spoolss_Notify */
716 static void notify_one_value(struct spoolss_notify_msg *msg,
717 struct spoolss_Notify *data,
720 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
723 static void notify_string(struct spoolss_notify_msg *msg,
724 struct spoolss_Notify *data,
727 /* The length of the message includes the trailing \0 */
729 data->data.string.size = msg->len * 2;
730 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
731 if (!data->data.string.string) {
732 data->data.string.size = 0;
737 static void notify_system_time(struct spoolss_notify_msg *msg,
738 struct spoolss_Notify *data,
741 data->data.string.string = NULL;
742 data->data.string.size = 0;
744 if (msg->len != sizeof(time_t)) {
745 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
750 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
751 &data->data.string.string,
752 &data->data.string.size);
755 struct notify2_message_table {
757 void (*fn)(struct spoolss_notify_msg *msg,
758 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
761 static struct notify2_message_table printer_notify_table[] = {
762 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
763 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
764 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
765 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
766 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
767 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
768 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
769 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
770 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
771 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
772 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
773 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
774 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
775 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
776 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
777 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
778 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
779 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
780 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
783 static struct notify2_message_table job_notify_table[] = {
784 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
785 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
786 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
787 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
788 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
789 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
790 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
791 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
792 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
793 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
794 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
795 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
796 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
797 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
798 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
799 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
800 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
801 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
802 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
803 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
804 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
805 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
806 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
807 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
811 /***********************************************************************
812 Allocate talloc context for container object
813 **********************************************************************/
815 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
820 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
825 /***********************************************************************
826 release all allocated memory and zero out structure
827 **********************************************************************/
829 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
835 talloc_destroy(ctr->ctx);
842 /***********************************************************************
843 **********************************************************************/
845 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
853 /***********************************************************************
854 **********************************************************************/
856 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
858 if ( !ctr || !ctr->msg_groups )
861 if ( idx >= ctr->num_groups )
864 return &ctr->msg_groups[idx];
868 /***********************************************************************
869 How many groups of change messages do we have ?
870 **********************************************************************/
872 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
877 return ctr->num_groups;
880 /***********************************************************************
881 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
882 **********************************************************************/
884 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
886 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
887 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
888 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
894 /* loop over all groups looking for a matching printer name */
896 for ( i=0; i<ctr->num_groups; i++ ) {
897 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
901 /* add a new group? */
903 if ( i == ctr->num_groups ) {
906 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
907 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
910 ctr->msg_groups = groups;
912 /* clear the new entry and set the printer name */
914 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
915 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
918 /* add the change messages; 'i' is the correct index now regardless */
920 msg_grp = &ctr->msg_groups[i];
924 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
925 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
928 msg_grp->msgs = msg_list;
930 new_slot = msg_grp->num_msgs-1;
931 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
933 /* need to allocate own copy of data */
936 msg_grp->msgs[new_slot].notify.data = (char *)
937 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
939 return ctr->num_groups;
942 static void construct_info_data(struct spoolss_Notify *info_data,
943 enum spoolss_NotifyType type,
944 uint16_t field, int id);
946 /***********************************************************************
947 Send a change notication message on all handles which have a call
949 **********************************************************************/
951 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
954 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
955 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
956 SPOOLSS_NOTIFY_MSG *messages;
957 int sending_msg_count;
960 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
964 messages = msg_group->msgs;
967 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
971 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
973 /* loop over all printers */
975 for (p = printers_list; p; p = p->next) {
976 struct spoolss_Notify *notifies;
981 /* Is there notification on this handle? */
983 if ( !p->notify.client_connected )
986 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
988 /* For this printer? Print servers always receive
991 if ( ( p->printer_type == SPLHND_PRINTER ) &&
992 ( !strequal(msg_group->printername, p->sharename) ) )
995 DEBUG(10,("Our printer\n"));
997 /* allocate the max entries possible */
999 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1004 /* build the array of change notifications */
1006 sending_msg_count = 0;
1008 for ( i=0; i<msg_group->num_msgs; i++ ) {
1009 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1011 /* Are we monitoring this event? */
1013 if (!is_monitoring_event(p, msg->type, msg->field))
1016 sending_msg_count++;
1019 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1020 msg->type, msg->field, p->sharename));
1023 * if the is a printer notification handle and not a job notification
1024 * type, then set the id to 0. Other wise just use what was specified
1027 * When registering change notification on a print server handle
1028 * we always need to send back the id (snum) matching the printer
1029 * for which the change took place. For change notify registered
1030 * on a printer handle, this does not matter and the id should be 0.
1035 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1041 /* Convert unix jobid to smb jobid */
1043 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1044 id = sysjob_to_jobid(msg->id);
1047 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1052 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1055 case PRINTER_NOTIFY_TYPE:
1056 if ( printer_notify_table[msg->field].fn )
1057 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1060 case JOB_NOTIFY_TYPE:
1061 if ( job_notify_table[msg->field].fn )
1062 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1066 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1073 if ( sending_msg_count ) {
1076 union spoolss_ReplyPrinterInfo info;
1077 struct spoolss_NotifyInfo info0;
1078 uint32_t reply_result;
1080 info0.version = 0x2;
1081 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1082 info0.count = count;
1083 info0.notifies = notifies;
1085 info.info0 = &info0;
1087 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1088 &p->notify.client_hnd,
1089 p->notify.change, /* color */
1092 0, /* reply_type, must be 0 */
1095 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1096 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1097 notify_cli_pipe->srv_name_slash,
1100 switch (reply_result) {
1103 case PRINTER_NOTIFY_INFO_DISCARDED:
1104 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1105 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1114 DEBUG(8,("send_notify2_changes: Exit...\n"));
1118 /***********************************************************************
1119 **********************************************************************/
1121 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1124 uint32_t tv_sec, tv_usec;
1127 /* Unpack message */
1129 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1132 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1134 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1137 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1138 &msg->notify.value[0], &msg->notify.value[1]);
1140 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1141 &msg->len, &msg->notify.data);
1143 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1144 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1146 tv->tv_sec = tv_sec;
1147 tv->tv_usec = tv_usec;
1150 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1151 msg->notify.value[1]));
1153 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1158 /********************************************************************
1159 Receive a notify2 message list
1160 ********************************************************************/
1162 static void receive_notify2_message_list(struct messaging_context *msg,
1165 struct server_id server_id,
1168 size_t msg_count, i;
1169 char *buf = (char *)data->data;
1172 SPOOLSS_NOTIFY_MSG notify;
1173 SPOOLSS_NOTIFY_MSG_CTR messages;
1176 if (data->length < 4) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1181 msg_count = IVAL(buf, 0);
1184 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1186 if (msg_count == 0) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1191 /* initialize the container */
1193 ZERO_STRUCT( messages );
1194 notify_msg_ctr_init( &messages );
1197 * build message groups for each printer identified
1198 * in a change_notify msg. Remember that a PCN message
1199 * includes the handle returned for the srv_spoolss_replyopenprinter()
1200 * call. Therefore messages are grouped according to printer handle.
1203 for ( i=0; i<msg_count; i++ ) {
1204 struct timeval msg_tv;
1206 if (msg_ptr + 4 - buf > data->length) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1211 msg_len = IVAL(msg_ptr,0);
1214 if (msg_ptr + msg_len - buf > data->length) {
1215 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1219 /* unpack messages */
1221 ZERO_STRUCT( notify );
1222 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1225 /* add to correct list in container */
1227 notify_msg_ctr_addmsg( &messages, ¬ify );
1229 /* free memory that might have been allocated by notify2_unpack_msg() */
1231 if ( notify.len != 0 )
1232 SAFE_FREE( notify.notify.data );
1235 /* process each group of messages */
1237 num_groups = notify_msg_ctr_numgroups( &messages );
1238 for ( i=0; i<num_groups; i++ )
1239 send_notify2_changes( &messages, i );
1244 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1245 (uint32_t)msg_count ));
1247 notify_msg_ctr_destroy( &messages );
1252 /********************************************************************
1253 Send a message to ourself about new driver being installed
1254 so we can upgrade the information for each printer bound to this
1256 ********************************************************************/
1258 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1260 int len = strlen(drivername);
1265 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1268 messaging_send_buf(smbd_messaging_context(),
1269 messaging_server_id(smbd_messaging_context()),
1270 MSG_PRINTER_DRVUPGRADE,
1271 (uint8_t *)drivername, len+1);
1276 /**********************************************************************
1277 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1278 over all printers, upgrading ones as necessary
1279 **********************************************************************/
1281 void do_drv_upgrade_printer(struct messaging_context *msg,
1284 struct server_id server_id,
1287 TALLOC_CTX *tmp_ctx;
1288 struct auth_serversupplied_info *server_info = NULL;
1289 struct spoolss_PrinterInfo2 *pinfo2;
1292 const char *drivername;
1294 int n_services = lp_numservices();
1297 tmp_ctx = talloc_new(NULL);
1298 if (!tmp_ctx) return;
1300 status = make_server_info_system(tmp_ctx, &server_info);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 DEBUG(0, ("do_drv_upgrade_printer: "
1303 "Could not create system server_info\n"));
1307 len = MIN(data->length,sizeof(drivername)-1);
1308 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1310 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1314 DEBUG(10, ("do_drv_upgrade_printer: "
1315 "Got message for new driver [%s]\n", drivername));
1317 /* Iterate the printer list */
1319 for (snum = 0; snum < n_services; snum++) {
1320 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1324 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1325 lp_const_servicename(snum),
1328 if (!W_ERROR_IS_OK(result)) {
1332 if (strcmp(drivername, pinfo2->drivername) != 0) {
1336 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1338 /* all we care about currently is the change_id */
1339 result = winreg_printer_update_changeid(tmp_ctx,
1341 pinfo2->printername);
1343 if (!W_ERROR_IS_OK(result)) {
1344 DEBUG(3, ("do_drv_upgrade_printer: "
1345 "Failed to update changeid [%s]\n",
1346 win_errstr(result)));
1352 talloc_free(tmp_ctx);
1355 /********************************************************************
1356 Update the cache for all printq's with a registered client
1358 ********************************************************************/
1360 void update_monitored_printq_cache( void )
1362 Printer_entry *printer = printers_list;
1365 /* loop through all printers and update the cache where
1366 client_connected == true */
1369 if ( (printer->printer_type == SPLHND_PRINTER)
1370 && printer->notify.client_connected )
1372 snum = print_queue_snum(printer->sharename);
1373 print_queue_status( snum, NULL, NULL );
1376 printer = printer->next;
1382 /****************************************************************
1383 _spoolss_OpenPrinter
1384 ****************************************************************/
1386 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1387 struct spoolss_OpenPrinter *r)
1389 struct spoolss_OpenPrinterEx e;
1392 ZERO_STRUCT(e.in.userlevel);
1394 e.in.printername = r->in.printername;
1395 e.in.datatype = r->in.datatype;
1396 e.in.devmode_ctr = r->in.devmode_ctr;
1397 e.in.access_mask = r->in.access_mask;
1400 e.out.handle = r->out.handle;
1402 werr = _spoolss_OpenPrinterEx(p, &e);
1404 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1405 /* OpenPrinterEx returns this for a bad
1406 * printer name. We must return WERR_INVALID_PRINTER_NAME
1409 werr = WERR_INVALID_PRINTER_NAME;
1415 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1416 struct spoolss_DeviceMode *orig,
1417 struct spoolss_DeviceMode **dest)
1419 struct spoolss_DeviceMode *dm;
1421 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1426 /* copy all values, then duplicate strings and structs */
1429 dm->devicename = talloc_strdup(dm, orig->devicename);
1430 if (!dm->devicename) {
1433 dm->formname = talloc_strdup(dm, orig->formname);
1434 if (!dm->formname) {
1437 if (orig->driverextra_data.data) {
1438 dm->driverextra_data.data =
1439 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1440 orig->driverextra_data.length);
1441 if (!dm->driverextra_data.data) {
1450 /****************************************************************
1451 _spoolss_OpenPrinterEx
1452 ****************************************************************/
1454 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1455 struct spoolss_OpenPrinterEx *r)
1458 Printer_entry *Printer=NULL;
1460 if (!r->in.printername) {
1461 return WERR_INVALID_PARAM;
1464 /* some sanity check because you can open a printer or a print server */
1465 /* aka: \\server\printer or \\server */
1467 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1469 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1470 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1471 " for printer %s\n", r->in.printername));
1472 ZERO_STRUCTP(r->out.handle);
1473 return WERR_INVALID_PARAM;
1476 Printer = find_printer_index_by_hnd(p, r->out.handle);
1478 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1479 "handle we created for printer %s\n", r->in.printername));
1480 close_printer_handle(p, r->out.handle);
1481 ZERO_STRUCTP(r->out.handle);
1482 return WERR_INVALID_PARAM;
1486 * First case: the user is opening the print server:
1488 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1489 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1491 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1492 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1493 * or if the user is listed in the smb.conf printer admin parameter.
1495 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1496 * client view printer folder, but does not show the MSAPW.
1498 * Note: this test needs code to check access rights here too. Jeremy
1499 * could you look at this?
1501 * Second case: the user is opening a printer:
1502 * NT doesn't let us connect to a printer if the connecting user
1503 * doesn't have print permission.
1505 * Third case: user is opening a Port Monitor
1506 * access checks same as opening a handle to the print server.
1509 switch (Printer->printer_type )
1512 case SPLHND_PORTMON_TCP:
1513 case SPLHND_PORTMON_LOCAL:
1514 /* Printserver handles use global struct... */
1518 /* Map standard access rights to object specific access rights */
1520 se_map_standard(&r->in.access_mask,
1521 &printserver_std_mapping);
1523 /* Deny any object specific bits that don't apply to print
1524 servers (i.e printer and job specific bits) */
1526 r->in.access_mask &= SEC_MASK_SPECIFIC;
1528 if (r->in.access_mask &
1529 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1530 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1531 close_printer_handle(p, r->out.handle);
1532 ZERO_STRUCTP(r->out.handle);
1533 return WERR_ACCESS_DENIED;
1536 /* Allow admin access */
1538 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1540 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1542 if (!lp_ms_add_printer_wizard()) {
1543 close_printer_handle(p, r->out.handle);
1544 ZERO_STRUCTP(r->out.handle);
1545 return WERR_ACCESS_DENIED;
1548 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1549 and not a printer admin, then fail */
1551 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1552 !user_has_privileges(p->server_info->ptok,
1554 !token_contains_name_in_list(
1555 uidtoname(p->server_info->utok.uid),
1556 p->server_info->info3->base.domain.string,
1558 p->server_info->ptok,
1559 lp_printer_admin(snum))) {
1560 close_printer_handle(p, r->out.handle);
1561 ZERO_STRUCTP(r->out.handle);
1562 return WERR_ACCESS_DENIED;
1565 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1569 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1572 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1573 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1575 /* We fall through to return WERR_OK */
1578 case SPLHND_PRINTER:
1579 /* NT doesn't let us connect to a printer if the connecting user
1580 doesn't have print permission. */
1582 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1583 close_printer_handle(p, r->out.handle);
1584 ZERO_STRUCTP(r->out.handle);
1588 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1589 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1592 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1594 /* map an empty access mask to the minimum access mask */
1595 if (r->in.access_mask == 0x0)
1596 r->in.access_mask = PRINTER_ACCESS_USE;
1599 * If we are not serving the printer driver for this printer,
1600 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1601 * will keep NT clients happy --jerry
1604 if (lp_use_client_driver(snum)
1605 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1607 r->in.access_mask = PRINTER_ACCESS_USE;
1610 /* check smb.conf parameters and the the sec_desc */
1612 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1613 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1614 ZERO_STRUCTP(r->out.handle);
1615 return WERR_ACCESS_DENIED;
1618 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1619 p->server_info->ptok, snum) ||
1620 !print_access_check(p->server_info, snum,
1621 r->in.access_mask)) {
1622 DEBUG(3, ("access DENIED for printer open\n"));
1623 close_printer_handle(p, r->out.handle);
1624 ZERO_STRUCTP(r->out.handle);
1625 return WERR_ACCESS_DENIED;
1628 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1629 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1630 close_printer_handle(p, r->out.handle);
1631 ZERO_STRUCTP(r->out.handle);
1632 return WERR_ACCESS_DENIED;
1635 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1636 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1638 r->in.access_mask = PRINTER_ACCESS_USE;
1640 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1641 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1643 winreg_create_printer(p->mem_ctx,
1645 Printer->servername,
1646 lp_const_servicename(snum));
1651 /* sanity check to prevent programmer error */
1652 ZERO_STRUCTP(r->out.handle);
1656 Printer->access_granted = r->in.access_mask;
1659 * If the client sent a devmode in the OpenPrinter() call, then
1660 * save it here in case we get a job submission on this handle
1663 if ((Printer->printer_type != SPLHND_SERVER) &&
1664 r->in.devmode_ctr.devmode) {
1665 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1669 #if 0 /* JERRY -- I'm doubtful this is really effective */
1670 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1671 optimization in Windows 2000 clients --jerry */
1673 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1674 && (RA_WIN2K == get_remote_arch()) )
1676 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1677 sys_usleep( 500000 );
1684 /****************************************************************
1685 _spoolss_ClosePrinter
1686 ****************************************************************/
1688 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1689 struct spoolss_ClosePrinter *r)
1691 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1693 if (Printer && Printer->document_started) {
1694 struct spoolss_EndDocPrinter e;
1696 e.in.handle = r->in.handle;
1698 _spoolss_EndDocPrinter(p, &e);
1701 if (!close_printer_handle(p, r->in.handle))
1704 /* clear the returned printer handle. Observed behavior
1705 from Win2k server. Don't think this really matters.
1706 Previous code just copied the value of the closed
1709 ZERO_STRUCTP(r->out.handle);
1714 /****************************************************************
1715 _spoolss_DeletePrinter
1716 ****************************************************************/
1718 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1719 struct spoolss_DeletePrinter *r)
1721 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1725 if (Printer && Printer->document_started) {
1726 struct spoolss_EndDocPrinter e;
1728 e.in.handle = r->in.handle;
1730 _spoolss_EndDocPrinter(p, &e);
1733 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1734 winreg_delete_printer_key(p->mem_ctx,
1736 lp_const_servicename(snum),
1740 result = delete_printer_handle(p, r->in.handle);
1745 /*******************************************************************
1746 * static function to lookup the version id corresponding to an
1747 * long architecture string
1748 ******************************************************************/
1750 static const struct print_architecture_table_node archi_table[]= {
1752 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1753 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1754 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1755 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1756 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1757 {"Windows IA64", SPL_ARCH_IA64, 3 },
1758 {"Windows x64", SPL_ARCH_X64, 3 },
1762 static int get_version_id(const char *arch)
1766 for (i=0; archi_table[i].long_archi != NULL; i++)
1768 if (strcmp(arch, archi_table[i].long_archi) == 0)
1769 return (archi_table[i].version);
1775 /****************************************************************
1776 _spoolss_DeletePrinterDriver
1777 ****************************************************************/
1779 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1780 struct spoolss_DeletePrinterDriver *r)
1783 struct spoolss_DriverInfo8 *info = NULL;
1784 struct spoolss_DriverInfo8 *info_win2k = NULL;
1787 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1789 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1790 and not a printer admin, then fail */
1792 if ( (p->server_info->utok.uid != sec_initial_uid())
1793 && !user_has_privileges(p->server_info->ptok, &se_printop )
1794 && !token_contains_name_in_list(
1795 uidtoname(p->server_info->utok.uid),
1796 p->server_info->info3->base.domain.string,
1798 p->server_info->ptok,
1799 lp_printer_admin(-1)) )
1801 return WERR_ACCESS_DENIED;
1804 /* check that we have a valid driver name first */
1806 if ((version = get_version_id(r->in.architecture)) == -1)
1807 return WERR_INVALID_ENVIRONMENT;
1809 status = winreg_get_driver(p->mem_ctx, p->server_info,
1810 r->in.architecture, r->in.driver,
1812 if (!W_ERROR_IS_OK(status)) {
1813 /* try for Win2k driver if "Windows NT x86" */
1815 if ( version == 2 ) {
1818 status = winreg_get_driver(p->mem_ctx, p->server_info,
1822 if (!W_ERROR_IS_OK(status)) {
1823 status = WERR_UNKNOWN_PRINTER_DRIVER;
1827 /* otherwise it was a failure */
1829 status = WERR_UNKNOWN_PRINTER_DRIVER;
1835 if (printer_driver_in_use(p->mem_ctx, p->server_info, info)) {
1836 status = WERR_PRINTER_DRIVER_IN_USE;
1841 status = winreg_get_driver(p->mem_ctx, p->server_info,
1843 r->in.driver, 3, &info_win2k);
1844 if (W_ERROR_IS_OK(status)) {
1845 /* if we get to here, we now have 2 driver info structures to remove */
1846 /* remove the Win2k driver first*/
1848 status = winreg_del_driver(p->mem_ctx,
1851 talloc_free(info_win2k);
1853 /* this should not have failed---if it did, report to client */
1854 if (!W_ERROR_IS_OK(status)) {
1860 status = winreg_del_driver(p->mem_ctx, p->server_info, info, version);
1868 /****************************************************************
1869 _spoolss_DeletePrinterDriverEx
1870 ****************************************************************/
1872 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1873 struct spoolss_DeletePrinterDriverEx *r)
1875 struct spoolss_DriverInfo8 *info = NULL;
1876 struct spoolss_DriverInfo8 *info_win2k = NULL;
1880 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1882 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1883 and not a printer admin, then fail */
1885 if ( (p->server_info->utok.uid != sec_initial_uid())
1886 && !user_has_privileges(p->server_info->ptok, &se_printop )
1887 && !token_contains_name_in_list(
1888 uidtoname(p->server_info->utok.uid),
1889 p->server_info->info3->base.domain.string,
1891 p->server_info->ptok, lp_printer_admin(-1)) )
1893 return WERR_ACCESS_DENIED;
1896 /* check that we have a valid driver name first */
1897 if ((version = get_version_id(r->in.architecture)) == -1) {
1898 /* this is what NT returns */
1899 return WERR_INVALID_ENVIRONMENT;
1902 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1903 version = r->in.version;
1905 status = winreg_get_driver(p->mem_ctx, p->server_info,
1906 r->in.architecture, r->in.driver,
1908 if (!W_ERROR_IS_OK(status)) {
1909 status = WERR_UNKNOWN_PRINTER_DRIVER;
1912 * if the client asked for a specific version,
1913 * or this is something other than Windows NT x86,
1917 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1920 /* try for Win2k driver if "Windows NT x86" */
1923 status = winreg_get_driver(info, p->server_info,
1927 if (!W_ERROR_IS_OK(status)) {
1928 status = WERR_UNKNOWN_PRINTER_DRIVER;
1933 if (printer_driver_in_use(info, p->server_info, info)) {
1934 status = WERR_PRINTER_DRIVER_IN_USE;
1939 * we have a couple of cases to consider.
1940 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1941 * then the delete should fail if **any** files overlap with
1943 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1944 * non-overlapping files
1945 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1946 * is set, the do not delete any files
1947 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1950 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1952 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1955 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1956 printer_driver_files_in_use(info, p->server_info, info)) {
1957 /* no idea of the correct error here */
1958 status = WERR_ACCESS_DENIED;
1963 /* also check for W32X86/3 if necessary; maybe we already have? */
1965 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
1966 status = winreg_get_driver(info, p->server_info,
1968 r->in.driver, 3, &info_win2k);
1969 if (W_ERROR_IS_OK(status)) {
1972 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1973 printer_driver_files_in_use(info, p->server_info,
1975 /* no idea of the correct error here */
1976 talloc_free(info_win2k);
1977 status = WERR_ACCESS_DENIED;
1981 /* if we get to here, we now have 2 driver info structures to remove */
1982 /* remove the Win2k driver first*/
1984 status = winreg_del_driver(info, p->server_info,
1987 /* this should not have failed---if it did, report to client */
1989 if (!W_ERROR_IS_OK(status)) {
1994 * now delete any associated files if delete_files is
1995 * true. Even if this part failes, we return succes
1996 * because the driver doesn not exist any more
1999 delete_driver_files(p->server_info,
2005 status = winreg_del_driver(info, p->server_info, info, version);
2006 if (!W_ERROR_IS_OK(status)) {
2011 * now delete any associated files if delete_files is
2012 * true. Even if this part failes, we return succes
2013 * because the driver doesn not exist any more
2016 delete_driver_files(p->server_info, info);
2025 /****************************************************************************
2026 Internal routine for storing printerdata
2027 ***************************************************************************/
2029 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2030 const char *key, const char *value,
2031 uint32_t type, uint8_t *data, int real_len)
2033 /* the registry objects enforce uniqueness based on value name */
2035 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2038 /********************************************************************
2039 GetPrinterData on a printer server Handle.
2040 ********************************************************************/
2042 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2044 enum winreg_Type *type,
2045 union spoolss_PrinterData *data)
2047 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2049 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2055 if (!StrCaseCmp(value, "BeepEnabled")) {
2061 if (!StrCaseCmp(value, "EventLog")) {
2063 /* formally was 0x1b */
2068 if (!StrCaseCmp(value, "NetPopup")) {
2074 if (!StrCaseCmp(value, "MajorVersion")) {
2077 /* Windows NT 4.0 seems to not allow uploading of drivers
2078 to a server that reports 0x3 as the MajorVersion.
2079 need to investigate more how Win2k gets around this .
2082 if (RA_WINNT == get_remote_arch()) {
2091 if (!StrCaseCmp(value, "MinorVersion")) {
2098 * uint32_t size = 0x114
2099 * uint32_t major = 5
2100 * uint32_t minor = [0|1]
2101 * uint32_t build = [2195|2600]
2102 * extra unicode string = e.g. "Service Pack 3"
2104 if (!StrCaseCmp(value, "OSVersion")) {
2106 enum ndr_err_code ndr_err;
2107 struct spoolss_OSVersion os;
2109 os.major = 5; /* Windows 2000 == 5.0 */
2111 os.build = 2195; /* build */
2112 os.extra_string = ""; /* leave extra string empty */
2114 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2115 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2116 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2117 return WERR_GENERAL_FAILURE;
2121 data->binary = blob;
2127 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2130 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2131 W_ERROR_HAVE_NO_MEMORY(data->string);
2136 if (!StrCaseCmp(value, "Architecture")) {
2138 data->string = talloc_strdup(mem_ctx,
2139 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2140 W_ERROR_HAVE_NO_MEMORY(data->string);
2145 if (!StrCaseCmp(value, "DsPresent")) {
2148 /* only show the publish check box if we are a
2149 member of a AD domain */
2151 if (lp_security() == SEC_ADS) {
2159 if (!StrCaseCmp(value, "DNSMachineName")) {
2160 const char *hostname = get_mydnsfullname();
2163 return WERR_BADFILE;
2167 data->string = talloc_strdup(mem_ctx, hostname);
2168 W_ERROR_HAVE_NO_MEMORY(data->string);
2175 return WERR_INVALID_PARAM;
2178 /****************************************************************
2179 _spoolss_GetPrinterData
2180 ****************************************************************/
2182 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2183 struct spoolss_GetPrinterData *r)
2185 struct spoolss_GetPrinterDataEx r2;
2187 r2.in.handle = r->in.handle;
2188 r2.in.key_name = "PrinterDriverData";
2189 r2.in.value_name = r->in.value_name;
2190 r2.in.offered = r->in.offered;
2191 r2.out.type = r->out.type;
2192 r2.out.data = r->out.data;
2193 r2.out.needed = r->out.needed;
2195 return _spoolss_GetPrinterDataEx(p, &r2);
2198 /*********************************************************
2199 Connect to the client machine.
2200 **********************************************************/
2202 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2203 struct sockaddr_storage *client_ss, const char *remote_machine)
2206 struct cli_state *the_cli;
2207 struct sockaddr_storage rm_addr;
2208 char addr[INET6_ADDRSTRLEN];
2210 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2211 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2213 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2214 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2217 print_sockaddr(addr, sizeof(addr), &rm_addr);
2219 rm_addr = *client_ss;
2220 print_sockaddr(addr, sizeof(addr), &rm_addr);
2221 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2225 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2226 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2231 /* setup the connection */
2232 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2233 &rm_addr, 0, "IPC$", "IPC",
2237 0, lp_client_signing(), NULL );
2239 if ( !NT_STATUS_IS_OK( ret ) ) {
2240 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2245 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2246 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2247 cli_shutdown(the_cli);
2252 * Ok - we have an anonymous connection to the IPC$ share.
2253 * Now start the NT Domain stuff :-).
2256 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2257 if (!NT_STATUS_IS_OK(ret)) {
2258 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2259 remote_machine, nt_errstr(ret)));
2260 cli_shutdown(the_cli);
2267 /***************************************************************************
2268 Connect to the client.
2269 ****************************************************************************/
2271 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2272 uint32_t localprinter, uint32_t type,
2273 struct policy_handle *handle,
2274 struct sockaddr_storage *client_ss)
2280 * If it's the first connection, contact the client
2281 * and connect to the IPC$ share anonymously
2283 if (smb_connections==0) {
2284 fstring unix_printer;
2286 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2288 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2291 messaging_register(smbd_messaging_context(), NULL,
2292 MSG_PRINTER_NOTIFY2,
2293 receive_notify2_message_list);
2294 /* Tell the connections db we're now interested in printer
2295 * notify messages. */
2296 serverid_register_msg_flags(
2297 messaging_server_id(smbd_messaging_context()),
2298 true, FLAG_MSG_PRINT_NOTIFY);
2302 * Tell the specific printing tdb we want messages for this printer
2303 * by registering our PID.
2306 if (!print_notify_register_pid(snum))
2307 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2311 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2319 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2320 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2321 win_errstr(result)));
2323 return (W_ERROR_IS_OK(result));
2326 /****************************************************************
2327 ****************************************************************/
2329 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2330 const struct spoolss_NotifyOption *r)
2332 struct spoolss_NotifyOption *option;
2339 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2346 if (!option->count) {
2350 option->types = talloc_zero_array(option,
2351 struct spoolss_NotifyOptionType, option->count);
2352 if (!option->types) {
2353 talloc_free(option);
2357 for (i=0; i < option->count; i++) {
2358 option->types[i] = r->types[i];
2360 if (option->types[i].count) {
2361 option->types[i].fields = talloc_zero_array(option,
2362 union spoolss_Field, option->types[i].count);
2363 if (!option->types[i].fields) {
2364 talloc_free(option);
2367 for (k=0; k<option->types[i].count; k++) {
2368 option->types[i].fields[k] =
2369 r->types[i].fields[k];
2377 /****************************************************************
2378 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2380 * before replying OK: status=0 a rpc call is made to the workstation
2381 * asking ReplyOpenPrinter
2383 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2384 * called from api_spoolss_rffpcnex
2385 ****************************************************************/
2387 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2388 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2391 struct spoolss_NotifyOption *option = r->in.notify_options;
2392 struct sockaddr_storage client_ss;
2394 /* store the notify value in the printer struct */
2396 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2399 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2400 "Invalid handle (%s:%u:%u).\n",
2401 OUR_HANDLE(r->in.handle)));
2405 Printer->notify.flags = r->in.flags;
2406 Printer->notify.options = r->in.options;
2407 Printer->notify.printerlocal = r->in.printer_local;
2409 TALLOC_FREE(Printer->notify.option);
2410 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2412 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2414 /* Connect to the client machine and send a ReplyOpenPrinter */
2416 if ( Printer->printer_type == SPLHND_SERVER)
2418 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2419 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2422 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2423 "client_address is %s\n", p->client_address));
2425 if (!interpret_string_addr(&client_ss, p->client_address,
2427 return WERR_SERVER_UNAVAILABLE;
2430 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2431 Printer->notify.printerlocal, 1,
2432 &Printer->notify.client_hnd, &client_ss))
2433 return WERR_SERVER_UNAVAILABLE;
2435 Printer->notify.client_connected = true;
2440 /*******************************************************************
2441 * fill a notify_info_data with the servername
2442 ********************************************************************/
2444 static void spoolss_notify_server_name(int snum,
2445 struct spoolss_Notify *data,
2446 print_queue_struct *queue,
2447 struct spoolss_PrinterInfo2 *pinfo2,
2448 TALLOC_CTX *mem_ctx)
2450 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2453 /*******************************************************************
2454 * fill a notify_info_data with the printername (not including the servername).
2455 ********************************************************************/
2457 static void spoolss_notify_printer_name(int snum,
2458 struct spoolss_Notify *data,
2459 print_queue_struct *queue,
2460 struct spoolss_PrinterInfo2 *pinfo2,
2461 TALLOC_CTX *mem_ctx)
2463 /* the notify name should not contain the \\server\ part */
2464 const char *p = strrchr(pinfo2->printername, '\\');
2467 p = pinfo2->printername;
2472 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2475 /*******************************************************************
2476 * fill a notify_info_data with the servicename
2477 ********************************************************************/
2479 static void spoolss_notify_share_name(int snum,
2480 struct spoolss_Notify *data,
2481 print_queue_struct *queue,
2482 struct spoolss_PrinterInfo2 *pinfo2,
2483 TALLOC_CTX *mem_ctx)
2485 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2488 /*******************************************************************
2489 * fill a notify_info_data with the port name
2490 ********************************************************************/
2492 static void spoolss_notify_port_name(int snum,
2493 struct spoolss_Notify *data,
2494 print_queue_struct *queue,
2495 struct spoolss_PrinterInfo2 *pinfo2,
2496 TALLOC_CTX *mem_ctx)
2498 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2501 /*******************************************************************
2502 * fill a notify_info_data with the printername
2503 * but it doesn't exist, have to see what to do
2504 ********************************************************************/
2506 static void spoolss_notify_driver_name(int snum,
2507 struct spoolss_Notify *data,
2508 print_queue_struct *queue,
2509 struct spoolss_PrinterInfo2 *pinfo2,
2510 TALLOC_CTX *mem_ctx)
2512 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2515 /*******************************************************************
2516 * fill a notify_info_data with the comment
2517 ********************************************************************/
2519 static void spoolss_notify_comment(int snum,
2520 struct spoolss_Notify *data,
2521 print_queue_struct *queue,
2522 struct spoolss_PrinterInfo2 *pinfo2,
2523 TALLOC_CTX *mem_ctx)
2527 if (*pinfo2->comment == '\0') {
2528 p = lp_comment(snum);
2530 p = pinfo2->comment;
2533 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2536 /*******************************************************************
2537 * fill a notify_info_data with the comment
2538 * location = "Room 1, floor 2, building 3"
2539 ********************************************************************/
2541 static void spoolss_notify_location(int snum,
2542 struct spoolss_Notify *data,
2543 print_queue_struct *queue,
2544 struct spoolss_PrinterInfo2 *pinfo2,
2545 TALLOC_CTX *mem_ctx)
2547 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2550 /*******************************************************************
2551 * fill a notify_info_data with the device mode
2552 * jfm:xxxx don't to it for know but that's a real problem !!!
2553 ********************************************************************/
2555 static void spoolss_notify_devmode(int snum,
2556 struct spoolss_Notify *data,
2557 print_queue_struct *queue,
2558 struct spoolss_PrinterInfo2 *pinfo2,
2559 TALLOC_CTX *mem_ctx)
2561 /* for a dummy implementation we have to zero the fields */
2562 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2565 /*******************************************************************
2566 * fill a notify_info_data with the separator file name
2567 ********************************************************************/
2569 static void spoolss_notify_sepfile(int snum,
2570 struct spoolss_Notify *data,
2571 print_queue_struct *queue,
2572 struct spoolss_PrinterInfo2 *pinfo2,
2573 TALLOC_CTX *mem_ctx)
2575 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2578 /*******************************************************************
2579 * fill a notify_info_data with the print processor
2580 * jfm:xxxx return always winprint to indicate we don't do anything to it
2581 ********************************************************************/
2583 static void spoolss_notify_print_processor(int snum,
2584 struct spoolss_Notify *data,
2585 print_queue_struct *queue,
2586 struct spoolss_PrinterInfo2 *pinfo2,
2587 TALLOC_CTX *mem_ctx)
2589 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2592 /*******************************************************************
2593 * fill a notify_info_data with the print processor options
2594 * jfm:xxxx send an empty string
2595 ********************************************************************/
2597 static void spoolss_notify_parameters(int snum,
2598 struct spoolss_Notify *data,
2599 print_queue_struct *queue,
2600 struct spoolss_PrinterInfo2 *pinfo2,
2601 TALLOC_CTX *mem_ctx)
2603 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2606 /*******************************************************************
2607 * fill a notify_info_data with the data type
2608 * jfm:xxxx always send RAW as data type
2609 ********************************************************************/
2611 static void spoolss_notify_datatype(int snum,
2612 struct spoolss_Notify *data,
2613 print_queue_struct *queue,
2614 struct spoolss_PrinterInfo2 *pinfo2,
2615 TALLOC_CTX *mem_ctx)
2617 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2620 /*******************************************************************
2621 * fill a notify_info_data with the security descriptor
2622 * jfm:xxxx send an null pointer to say no security desc
2623 * have to implement security before !
2624 ********************************************************************/
2626 static void spoolss_notify_security_desc(int snum,
2627 struct spoolss_Notify *data,
2628 print_queue_struct *queue,
2629 struct spoolss_PrinterInfo2 *pinfo2,
2630 TALLOC_CTX *mem_ctx)
2632 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2635 /*******************************************************************
2636 * fill a notify_info_data with the attributes
2637 * jfm:xxxx a samba printer is always shared
2638 ********************************************************************/
2640 static void spoolss_notify_attributes(int snum,
2641 struct spoolss_Notify *data,
2642 print_queue_struct *queue,
2643 struct spoolss_PrinterInfo2 *pinfo2,
2644 TALLOC_CTX *mem_ctx)
2646 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2649 /*******************************************************************
2650 * fill a notify_info_data with the priority
2651 ********************************************************************/
2653 static void spoolss_notify_priority(int snum,
2654 struct spoolss_Notify *data,
2655 print_queue_struct *queue,
2656 struct spoolss_PrinterInfo2 *pinfo2,
2657 TALLOC_CTX *mem_ctx)
2659 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2662 /*******************************************************************
2663 * fill a notify_info_data with the default priority
2664 ********************************************************************/
2666 static void spoolss_notify_default_priority(int snum,
2667 struct spoolss_Notify *data,
2668 print_queue_struct *queue,
2669 struct spoolss_PrinterInfo2 *pinfo2,
2670 TALLOC_CTX *mem_ctx)
2672 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2675 /*******************************************************************
2676 * fill a notify_info_data with the start time
2677 ********************************************************************/
2679 static void spoolss_notify_start_time(int snum,
2680 struct spoolss_Notify *data,
2681 print_queue_struct *queue,
2682 struct spoolss_PrinterInfo2 *pinfo2,
2683 TALLOC_CTX *mem_ctx)
2685 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2688 /*******************************************************************
2689 * fill a notify_info_data with the until time
2690 ********************************************************************/
2692 static void spoolss_notify_until_time(int snum,
2693 struct spoolss_Notify *data,
2694 print_queue_struct *queue,
2695 struct spoolss_PrinterInfo2 *pinfo2,
2696 TALLOC_CTX *mem_ctx)
2698 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2701 /*******************************************************************
2702 * fill a notify_info_data with the status
2703 ********************************************************************/
2705 static void spoolss_notify_status(int snum,
2706 struct spoolss_Notify *data,
2707 print_queue_struct *queue,
2708 struct spoolss_PrinterInfo2 *pinfo2,
2709 TALLOC_CTX *mem_ctx)
2711 print_status_struct status;
2713 print_queue_length(snum, &status);
2714 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2717 /*******************************************************************
2718 * fill a notify_info_data with the number of jobs queued
2719 ********************************************************************/
2721 static void spoolss_notify_cjobs(int snum,
2722 struct spoolss_Notify *data,
2723 print_queue_struct *queue,
2724 struct spoolss_PrinterInfo2 *pinfo2,
2725 TALLOC_CTX *mem_ctx)
2727 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2730 /*******************************************************************
2731 * fill a notify_info_data with the average ppm
2732 ********************************************************************/
2734 static void spoolss_notify_average_ppm(int snum,
2735 struct spoolss_Notify *data,
2736 print_queue_struct *queue,
2737 struct spoolss_PrinterInfo2 *pinfo2,
2738 TALLOC_CTX *mem_ctx)
2740 /* always respond 8 pages per minutes */
2741 /* a little hard ! */
2742 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2745 /*******************************************************************
2746 * fill a notify_info_data with username
2747 ********************************************************************/
2749 static void spoolss_notify_username(int snum,
2750 struct spoolss_Notify *data,
2751 print_queue_struct *queue,
2752 struct spoolss_PrinterInfo2 *pinfo2,
2753 TALLOC_CTX *mem_ctx)
2755 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2758 /*******************************************************************
2759 * fill a notify_info_data with job status
2760 ********************************************************************/
2762 static void spoolss_notify_job_status(int snum,
2763 struct spoolss_Notify *data,
2764 print_queue_struct *queue,
2765 struct spoolss_PrinterInfo2 *pinfo2,
2766 TALLOC_CTX *mem_ctx)
2768 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2771 /*******************************************************************
2772 * fill a notify_info_data with job name
2773 ********************************************************************/
2775 static void spoolss_notify_job_name(int snum,
2776 struct spoolss_Notify *data,
2777 print_queue_struct *queue,
2778 struct spoolss_PrinterInfo2 *pinfo2,
2779 TALLOC_CTX *mem_ctx)
2781 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2784 /*******************************************************************
2785 * fill a notify_info_data with job status
2786 ********************************************************************/
2788 static void spoolss_notify_job_status_string(int snum,
2789 struct spoolss_Notify *data,
2790 print_queue_struct *queue,
2791 struct spoolss_PrinterInfo2 *pinfo2,
2792 TALLOC_CTX *mem_ctx)
2795 * Now we're returning job status codes we just return a "" here. JRA.
2800 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2803 switch (queue->status) {
2808 p = ""; /* NT provides the paused string */
2817 #endif /* NO LONGER NEEDED. */
2819 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2822 /*******************************************************************
2823 * fill a notify_info_data with job time
2824 ********************************************************************/
2826 static void spoolss_notify_job_time(int snum,
2827 struct spoolss_Notify *data,
2828 print_queue_struct *queue,
2829 struct spoolss_PrinterInfo2 *pinfo2,
2830 TALLOC_CTX *mem_ctx)
2832 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2835 /*******************************************************************
2836 * fill a notify_info_data with job size
2837 ********************************************************************/
2839 static void spoolss_notify_job_size(int snum,
2840 struct spoolss_Notify *data,
2841 print_queue_struct *queue,
2842 struct spoolss_PrinterInfo2 *pinfo2,
2843 TALLOC_CTX *mem_ctx)
2845 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2848 /*******************************************************************
2849 * fill a notify_info_data with page info
2850 ********************************************************************/
2851 static void spoolss_notify_total_pages(int snum,
2852 struct spoolss_Notify *data,
2853 print_queue_struct *queue,
2854 struct spoolss_PrinterInfo2 *pinfo2,
2855 TALLOC_CTX *mem_ctx)
2857 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2860 /*******************************************************************
2861 * fill a notify_info_data with pages printed info.
2862 ********************************************************************/
2863 static void spoolss_notify_pages_printed(int snum,
2864 struct spoolss_Notify *data,
2865 print_queue_struct *queue,
2866 struct spoolss_PrinterInfo2 *pinfo2,
2867 TALLOC_CTX *mem_ctx)
2869 /* Add code when back-end tracks this */
2870 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2873 /*******************************************************************
2874 Fill a notify_info_data with job position.
2875 ********************************************************************/
2877 static void spoolss_notify_job_position(int snum,
2878 struct spoolss_Notify *data,
2879 print_queue_struct *queue,
2880 struct spoolss_PrinterInfo2 *pinfo2,
2881 TALLOC_CTX *mem_ctx)
2883 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2886 /*******************************************************************
2887 Fill a notify_info_data with submitted time.
2888 ********************************************************************/
2890 static void spoolss_notify_submitted_time(int snum,
2891 struct spoolss_Notify *data,
2892 print_queue_struct *queue,
2893 struct spoolss_PrinterInfo2 *pinfo2,
2894 TALLOC_CTX *mem_ctx)
2896 data->data.string.string = NULL;
2897 data->data.string.size = 0;
2899 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2900 &data->data.string.string,
2901 &data->data.string.size);
2905 struct s_notify_info_data_table
2907 enum spoolss_NotifyType type;
2910 enum spoolss_NotifyTable variable_type;
2911 void (*fn) (int snum, struct spoolss_Notify *data,
2912 print_queue_struct *queue,
2913 struct spoolss_PrinterInfo2 *pinfo2,
2914 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 static void construct_info_data(struct spoolss_Notify *info_data,
3020 enum spoolss_NotifyType type,
3021 uint16_t field, int id)
3023 info_data->type = type;
3024 info_data->field.field = field;
3025 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3026 info_data->job_id = id;
3029 /*******************************************************************
3031 * fill a notify_info struct with info asked
3033 ********************************************************************/
3035 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3036 struct spoolss_NotifyInfo *info,
3037 struct spoolss_PrinterInfo2 *pinfo2,
3039 const struct spoolss_NotifyOptionType *option_type,
3041 TALLOC_CTX *mem_ctx)
3044 enum spoolss_NotifyType type;
3047 struct spoolss_Notify *current_data;
3048 print_queue_struct *queue=NULL;
3050 type = option_type->type;
3052 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3053 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3054 option_type->count, lp_servicename(snum)));
3056 for(field_num=0; field_num < option_type->count; field_num++) {
3057 field = option_type->fields[field_num].field;
3059 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3061 if (!search_notify(type, field, &j) )
3064 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3065 struct spoolss_Notify,
3067 if (info->notifies == NULL) {
3068 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3072 current_data = &info->notifies[info->count];
3074 construct_info_data(current_data, type, field, id);
3076 DEBUG(10, ("construct_notify_printer_info: "
3077 "calling [%s] snum=%d printername=[%s])\n",
3078 notify_info_data_table[j].name, snum,
3079 pinfo2->printername));
3081 notify_info_data_table[j].fn(snum, current_data, queue,
3090 /*******************************************************************
3092 * fill a notify_info struct with info asked
3094 ********************************************************************/
3096 static bool construct_notify_jobs_info(print_queue_struct *queue,
3097 struct spoolss_NotifyInfo *info,
3098 struct spoolss_PrinterInfo2 *pinfo2,
3100 const struct spoolss_NotifyOptionType *option_type,
3102 TALLOC_CTX *mem_ctx)
3105 enum spoolss_NotifyType type;
3107 struct spoolss_Notify *current_data;
3109 DEBUG(4,("construct_notify_jobs_info\n"));
3111 type = option_type->type;
3113 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3114 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3115 option_type->count));
3117 for(field_num=0; field_num<option_type->count; field_num++) {
3118 field = option_type->fields[field_num].field;
3120 if (!search_notify(type, field, &j) )
3123 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3124 struct spoolss_Notify,
3126 if (info->notifies == NULL) {
3127 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3131 current_data=&(info->notifies[info->count]);
3133 construct_info_data(current_data, type, field, id);
3134 notify_info_data_table[j].fn(snum, current_data, queue,
3143 * JFM: The enumeration is not that simple, it's even non obvious.
3145 * let's take an example: I want to monitor the PRINTER SERVER for
3146 * the printer's name and the number of jobs currently queued.
3147 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3148 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3150 * I have 3 printers on the back of my server.
3152 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3155 * 1 printer 1 name 1
3156 * 2 printer 1 cjob 1
3157 * 3 printer 2 name 2
3158 * 4 printer 2 cjob 2
3159 * 5 printer 3 name 3
3160 * 6 printer 3 name 3
3162 * that's the print server case, the printer case is even worse.
3165 /*******************************************************************
3167 * enumerate all printers on the printserver
3168 * fill a notify_info struct with info asked
3170 ********************************************************************/
3172 static WERROR printserver_notify_info(pipes_struct *p,
3173 struct policy_handle *hnd,
3174 struct spoolss_NotifyInfo *info,
3175 TALLOC_CTX *mem_ctx)
3178 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3179 int n_services=lp_numservices();
3181 struct spoolss_NotifyOption *option;
3182 struct spoolss_NotifyOptionType option_type;
3183 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3186 DEBUG(4,("printserver_notify_info\n"));
3191 option = Printer->notify.option;
3194 info->notifies = NULL;
3197 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3198 sending a ffpcn() request first */
3203 for (i=0; i<option->count; i++) {
3204 option_type = option->types[i];
3206 if (option_type.type != PRINTER_NOTIFY_TYPE)
3209 for (snum = 0; snum < n_services; snum++) {
3210 if (!lp_browseable(snum) ||
3211 !lp_snum_ok(snum) ||
3212 !lp_print_ok(snum)) {
3213 continue; /* skip */
3216 /* FIXME: should we use a SYSTEM server_info here? */
3217 result = winreg_get_printer(mem_ctx, p->server_info,
3218 Printer->servername,
3219 lp_servicename(snum),
3221 if (!W_ERROR_IS_OK(result)) {
3222 DEBUG(4, ("printserver_notify_info: "
3223 "Failed to get printer [%s]\n",
3224 lp_servicename(snum)));
3229 construct_notify_printer_info(Printer, info,
3234 TALLOC_FREE(pinfo2);
3240 * Debugging information, don't delete.
3243 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3244 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3245 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3247 for (i=0; i<info->count; i++) {
3248 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3249 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3250 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3257 /*******************************************************************
3259 * fill a notify_info struct with info asked
3261 ********************************************************************/
3263 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3264 struct spoolss_NotifyInfo *info,
3265 TALLOC_CTX *mem_ctx)
3268 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3271 struct spoolss_NotifyOption *option;
3272 struct spoolss_NotifyOptionType option_type;
3274 print_queue_struct *queue=NULL;
3275 print_status_struct status;
3276 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3279 DEBUG(4,("printer_notify_info\n"));
3284 option = Printer->notify.option;
3288 info->notifies = NULL;
3291 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3292 sending a ffpcn() request first */
3297 get_printer_snum(p, hnd, &snum, NULL);
3299 /* FIXME: should we use a SYSTEM server_info here ? */
3300 result = winreg_get_printer(mem_ctx, p->server_info,
3301 Printer->servername,
3302 lp_servicename(snum), &pinfo2);
3303 if (!W_ERROR_IS_OK(result)) {
3307 for (i=0; i<option->count; i++) {
3308 option_type = option->types[i];
3310 switch (option_type.type) {
3311 case PRINTER_NOTIFY_TYPE:
3312 if (construct_notify_printer_info(Printer, info,
3320 case JOB_NOTIFY_TYPE:
3322 count = print_queue_status(snum, &queue, &status);
3324 for (j=0; j<count; j++) {
3325 construct_notify_jobs_info(&queue[j], info,
3338 * Debugging information, don't delete.
3341 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3342 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3343 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3345 for (i=0; i<info->count; i++) {
3346 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3347 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3348 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3352 talloc_free(pinfo2);
3356 /****************************************************************
3357 _spoolss_RouterRefreshPrinterChangeNotify
3358 ****************************************************************/
3360 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3361 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3363 struct spoolss_NotifyInfo *info;
3365 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3366 WERROR result = WERR_BADFID;
3368 /* we always have a spoolss_NotifyInfo struct */
3369 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3371 result = WERR_NOMEM;
3375 *r->out.info = info;
3378 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3379 "Invalid handle (%s:%u:%u).\n",
3380 OUR_HANDLE(r->in.handle)));
3384 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3387 * We are now using the change value, and
3388 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3389 * I don't have a global notification system, I'm sending back all the
3390 * informations even when _NOTHING_ has changed.
3393 /* We need to keep track of the change value to send back in
3394 RRPCN replies otherwise our updates are ignored. */
3396 Printer->notify.fnpcn = true;
3398 if (Printer->notify.client_connected) {
3399 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3400 "Saving change value in request [%x]\n",
3402 Printer->notify.change = r->in.change_low;
3405 /* just ignore the spoolss_NotifyOption */
3407 switch (Printer->printer_type) {
3409 result = printserver_notify_info(p, r->in.handle,
3413 case SPLHND_PRINTER:
3414 result = printer_notify_info(p, r->in.handle,
3419 Printer->notify.fnpcn = false;
3425 /********************************************************************
3426 * construct_printer_info_0
3427 * fill a printer_info_0 struct
3428 ********************************************************************/
3430 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3431 struct auth_serversupplied_info *server_info,
3432 struct spoolss_PrinterInfo2 *info2,
3433 struct spoolss_PrinterInfo0 *r,
3437 counter_printer_0 *session_counter;
3438 struct timeval setuptime;
3439 print_status_struct status;
3441 r->printername = talloc_strdup(mem_ctx, info2->printername);
3442 W_ERROR_HAVE_NO_MEMORY(r->printername);
3444 r->servername = talloc_strdup(mem_ctx, info2->servername);
3445 W_ERROR_HAVE_NO_MEMORY(r->servername);
3447 count = print_queue_length(snum, &status);
3449 /* check if we already have a counter for this printer */
3450 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3451 if (session_counter->snum == snum)
3455 /* it's the first time, add it to the list */
3456 if (session_counter == NULL) {
3457 session_counter = SMB_MALLOC_P(counter_printer_0);
3458 W_ERROR_HAVE_NO_MEMORY(session_counter);
3459 ZERO_STRUCTP(session_counter);
3460 session_counter->snum = snum;
3461 session_counter->counter = 0;
3462 DLIST_ADD(counter_list, session_counter);
3466 session_counter->counter++;
3472 get_startup_time(&setuptime);
3473 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3476 * the global_counter should be stored in a TDB as it's common to all the clients
3477 * and should be zeroed on samba startup
3479 r->global_counter = session_counter->counter;
3481 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3482 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3483 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3484 r->free_build = SPOOLSS_RELEASE_BUILD;
3486 r->max_spooling = 0;
3487 r->session_counter = session_counter->counter;
3488 r->num_error_out_of_paper = 0x0;
3489 r->num_error_not_ready = 0x0; /* number of print failure */
3491 r->number_of_processors = 0x1;
3492 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3493 r->high_part_total_bytes = 0x0;
3494 winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3495 r->last_error = WERR_OK;
3496 r->status = nt_printq_status(status.status);
3497 r->enumerate_network_printers = 0x0;
3498 r->c_setprinter = 0x0;
3499 r->processor_architecture = 0x0;
3500 r->processor_level = 0x6; /* 6 ???*/
3509 /********************************************************************
3510 * construct_printer_info1
3511 * fill a spoolss_PrinterInfo1 struct
3512 ********************************************************************/
3514 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3515 const struct spoolss_PrinterInfo2 *info2,
3517 struct spoolss_PrinterInfo1 *r,
3522 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3526 W_ERROR_HAVE_NO_MEMORY(r->description);
3528 if (info2->comment == NULL || info2->comment[0] == '\0') {
3529 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3531 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3533 W_ERROR_HAVE_NO_MEMORY(r->comment);
3535 r->name = talloc_strdup(mem_ctx, info2->printername);
3536 W_ERROR_HAVE_NO_MEMORY(r->name);
3541 /********************************************************************
3542 * construct_printer_info2
3543 * fill a spoolss_PrinterInfo2 struct
3544 ********************************************************************/
3546 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3547 const struct spoolss_PrinterInfo2 *info2,
3548 struct spoolss_PrinterInfo2 *r,
3552 print_status_struct status;
3554 count = print_queue_length(snum, &status);
3556 r->servername = talloc_strdup(mem_ctx, info2->servername);
3557 W_ERROR_HAVE_NO_MEMORY(r->servername);
3558 r->printername = talloc_strdup(mem_ctx, info2->printername);
3559 W_ERROR_HAVE_NO_MEMORY(r->printername);
3560 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3561 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3562 r->portname = talloc_strdup(mem_ctx, info2->portname);
3563 W_ERROR_HAVE_NO_MEMORY(r->portname);
3564 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3565 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3567 if (info2->comment[0] == '\0') {
3568 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3570 r->comment = talloc_strdup(mem_ctx, info2->comment);
3572 W_ERROR_HAVE_NO_MEMORY(r->comment);
3574 r->location = talloc_strdup(mem_ctx, info2->location);
3575 W_ERROR_HAVE_NO_MEMORY(r->location);
3576 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
3577 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3578 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
3579 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3580 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
3581 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3582 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
3583 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3585 r->attributes = info2->attributes;
3587 r->priority = info2->priority;
3588 r->defaultpriority = info2->defaultpriority;
3589 r->starttime = info2->starttime;
3590 r->untiltime = info2->untiltime;
3591 r->status = nt_printq_status(status.status);
3593 r->averageppm = info2->averageppm;
3595 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3597 DEBUG(8,("Returning NULL Devicemode!\n"));
3602 if (info2->secdesc != NULL) {
3603 /* don't use talloc_steal() here unless you do a deep steal of all
3604 the SEC_DESC members */
3606 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3612 /********************************************************************
3613 * construct_printer_info3
3614 * fill a spoolss_PrinterInfo3 struct
3615 ********************************************************************/
3617 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3618 const struct spoolss_PrinterInfo2 *info2,
3619 struct spoolss_PrinterInfo3 *r,
3622 /* These are the components of the SD we are returning. */
3624 if (info2->secdesc != NULL) {
3625 /* don't use talloc_steal() here unless you do a deep steal of all
3626 the SEC_DESC members */
3628 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3629 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3635 /********************************************************************
3636 * construct_printer_info4
3637 * fill a spoolss_PrinterInfo4 struct
3638 ********************************************************************/
3640 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3641 const struct spoolss_PrinterInfo2 *info2,
3642 struct spoolss_PrinterInfo4 *r,
3645 r->printername = talloc_strdup(mem_ctx, info2->printername);
3646 W_ERROR_HAVE_NO_MEMORY(r->printername);
3647 r->servername = talloc_strdup(mem_ctx, info2->servername);
3648 W_ERROR_HAVE_NO_MEMORY(r->servername);
3650 r->attributes = info2->attributes;
3655 /********************************************************************
3656 * construct_printer_info5
3657 * fill a spoolss_PrinterInfo5 struct
3658 ********************************************************************/
3660 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3661 const struct spoolss_PrinterInfo2 *info2,
3662 struct spoolss_PrinterInfo5 *r,
3665 r->printername = talloc_strdup(mem_ctx, info2->printername);
3666 W_ERROR_HAVE_NO_MEMORY(r->printername);
3667 r->portname = talloc_strdup(mem_ctx, info2->portname);
3668 W_ERROR_HAVE_NO_MEMORY(r->portname);
3670 r->attributes = info2->attributes;
3672 /* these two are not used by NT+ according to MSDN */
3673 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3674 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3679 /********************************************************************
3680 * construct_printer_info_6
3681 * fill a spoolss_PrinterInfo6 struct
3682 ********************************************************************/
3684 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3685 const struct spoolss_PrinterInfo2 *info2,
3686 struct spoolss_PrinterInfo6 *r,
3690 print_status_struct status;
3692 count = print_queue_length(snum, &status);
3694 r->status = nt_printq_status(status.status);
3699 /********************************************************************
3700 * construct_printer_info7
3701 * fill a spoolss_PrinterInfo7 struct
3702 ********************************************************************/
3704 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3705 Printer_entry *print_hnd,
3706 struct spoolss_PrinterInfo7 *r,
3711 if (is_printer_published(print_hnd, snum, &guid)) {
3712 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3713 r->action = DSPRINT_PUBLISH;
3715 r->guid = talloc_strdup(mem_ctx, "");
3716 r->action = DSPRINT_UNPUBLISH;
3718 W_ERROR_HAVE_NO_MEMORY(r->guid);
3723 /********************************************************************
3724 * construct_printer_info8
3725 * fill a spoolss_PrinterInfo8 struct
3726 ********************************************************************/
3728 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3729 const struct spoolss_PrinterInfo2 *info2,
3730 struct spoolss_DeviceModeInfo *r,
3733 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3735 DEBUG(8,("Returning NULL Devicemode!\n"));
3742 /********************************************************************
3743 ********************************************************************/
3745 static bool snum_is_shared_printer(int snum)
3747 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3750 /********************************************************************
3751 Spoolss_enumprinters.
3752 ********************************************************************/
3754 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3755 struct auth_serversupplied_info *server_info,
3758 union spoolss_PrinterInfo **info_p,
3762 int n_services = lp_numservices();
3763 union spoolss_PrinterInfo *info = NULL;
3765 WERROR result = WERR_OK;
3770 for (snum = 0; snum < n_services; snum++) {
3772 const char *printer;
3773 struct spoolss_PrinterInfo2 *info2;
3775 if (!snum_is_shared_printer(snum)) {
3779 printer = lp_const_servicename(snum);
3781 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3784 result = winreg_create_printer(mem_ctx,
3788 if (!W_ERROR_IS_OK(result)) {
3792 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3793 union spoolss_PrinterInfo,
3796 result = WERR_NOMEM;
3800 result = winreg_get_printer(mem_ctx, server_info,
3801 NULL, printer, &info2);
3802 if (!W_ERROR_IS_OK(result)) {
3808 result = construct_printer_info0(info, server_info, info2,
3809 &info[count].info0, snum);
3812 result = construct_printer_info1(info, info2, flags,
3813 &info[count].info1, snum);
3816 result = construct_printer_info2(info, info2,
3817 &info[count].info2, snum);
3820 result = construct_printer_info4(info, info2,
3821 &info[count].info4, snum);
3824 result = construct_printer_info5(info, info2,
3825 &info[count].info5, snum);
3829 result = WERR_UNKNOWN_LEVEL;
3833 if (!W_ERROR_IS_OK(result)) {
3844 if (!W_ERROR_IS_OK(result)) {
3854 /********************************************************************
3855 * handle enumeration of printers at level 0
3856 ********************************************************************/
3858 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3859 struct auth_serversupplied_info *server_info,
3861 const char *servername,
3862 union spoolss_PrinterInfo **info,
3865 DEBUG(4,("enum_all_printers_info_0\n"));
3867 return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3871 /********************************************************************
3872 ********************************************************************/
3874 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3875 struct auth_serversupplied_info *server_info,
3877 union spoolss_PrinterInfo **info,
3880 DEBUG(4,("enum_all_printers_info_1\n"));
3882 return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3885 /********************************************************************
3886 enum_all_printers_info_1_local.
3887 *********************************************************************/
3889 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3890 struct auth_serversupplied_info *server_info,
3891 union spoolss_PrinterInfo **info,
3894 DEBUG(4,("enum_all_printers_info_1_local\n"));
3896 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3899 /********************************************************************
3900 enum_all_printers_info_1_name.
3901 *********************************************************************/
3903 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3904 struct auth_serversupplied_info *server_info,
3906 union spoolss_PrinterInfo **info,
3909 const char *s = name;
3911 DEBUG(4,("enum_all_printers_info_1_name\n"));
3913 if ((name[0] == '\\') && (name[1] == '\\')) {
3917 if (!is_myname_or_ipaddr(s)) {
3918 return WERR_INVALID_NAME;
3921 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3924 /********************************************************************
3925 enum_all_printers_info_1_network.
3926 *********************************************************************/
3928 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3929 struct auth_serversupplied_info *server_info,
3931 union spoolss_PrinterInfo **info,
3934 const char *s = name;
3936 DEBUG(4,("enum_all_printers_info_1_network\n"));
3938 /* If we respond to a enum_printers level 1 on our name with flags
3939 set to PRINTER_ENUM_REMOTE with a list of printers then these
3940 printers incorrectly appear in the APW browse list.
3941 Specifically the printers for the server appear at the workgroup
3942 level where all the other servers in the domain are
3943 listed. Windows responds to this call with a
3944 WERR_CAN_NOT_COMPLETE so we should do the same. */
3946 if (name[0] == '\\' && name[1] == '\\') {
3950 if (is_myname_or_ipaddr(s)) {
3951 return WERR_CAN_NOT_COMPLETE;
3954 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
3957 /********************************************************************
3958 * api_spoolss_enumprinters
3960 * called from api_spoolss_enumprinters (see this to understand)
3961 ********************************************************************/
3963 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3964 struct auth_serversupplied_info *server_info,
3965 union spoolss_PrinterInfo **info,
3968 DEBUG(4,("enum_all_printers_info_2\n"));
3970 return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
3973 /********************************************************************
3974 * handle enumeration of printers at level 1
3975 ********************************************************************/
3977 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3978 struct auth_serversupplied_info *server_info,
3981 union spoolss_PrinterInfo **info,
3984 /* Not all the flags are equals */
3986 if (flags & PRINTER_ENUM_LOCAL) {
3987 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
3990 if (flags & PRINTER_ENUM_NAME) {
3991 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
3994 if (flags & PRINTER_ENUM_NETWORK) {
3995 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
3998 return WERR_OK; /* NT4sp5 does that */
4001 /********************************************************************
4002 * handle enumeration of printers at level 2
4003 ********************************************************************/
4005 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4006 struct auth_serversupplied_info *server_info,
4008 const char *servername,
4009 union spoolss_PrinterInfo **info,
4012 if (flags & PRINTER_ENUM_LOCAL) {
4013 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4016 if (flags & PRINTER_ENUM_NAME) {
4017 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4018 return WERR_INVALID_NAME;
4021 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4024 if (flags & PRINTER_ENUM_REMOTE) {
4025 return WERR_UNKNOWN_LEVEL;
4031 /********************************************************************
4032 * handle enumeration of printers at level 4
4033 ********************************************************************/
4035 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4036 struct auth_serversupplied_info *server_info,
4038 const char *servername,
4039 union spoolss_PrinterInfo **info,
4042 DEBUG(4,("enum_all_printers_info_4\n"));
4044 return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4048 /********************************************************************
4049 * handle enumeration of printers at level 5
4050 ********************************************************************/
4052 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4053 struct auth_serversupplied_info *server_info,
4055 const char *servername,
4056 union spoolss_PrinterInfo **info,
4059 DEBUG(4,("enum_all_printers_info_5\n"));
4061 return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4064 /****************************************************************
4065 _spoolss_EnumPrinters
4066 ****************************************************************/
4068 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4069 struct spoolss_EnumPrinters *r)
4071 const char *name = NULL;
4074 /* that's an [in out] buffer */
4076 if (!r->in.buffer && (r->in.offered != 0)) {
4077 return WERR_INVALID_PARAM;
4080 DEBUG(4,("_spoolss_EnumPrinters\n"));
4084 *r->out.info = NULL;
4088 * flags==PRINTER_ENUM_NAME
4089 * if name=="" then enumerates all printers
4090 * if name!="" then enumerate the printer
4091 * flags==PRINTER_ENUM_REMOTE
4092 * name is NULL, enumerate printers
4093 * Level 2: name!="" enumerates printers, name can't be NULL
4094 * Level 3: doesn't exist
4095 * Level 4: does a local registry lookup
4096 * Level 5: same as Level 2
4100 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4101 W_ERROR_HAVE_NO_MEMORY(name);
4104 switch (r->in.level) {
4106 result = enumprinters_level0(p->mem_ctx, p->server_info,
4108 r->out.info, r->out.count);
4111 result = enumprinters_level1(p->mem_ctx, p->server_info,
4113 r->out.info, r->out.count);
4116 result = enumprinters_level2(p->mem_ctx, p->server_info,
4118 r->out.info, r->out.count);
4121 result = enumprinters_level4(p->mem_ctx, p->server_info,
4123 r->out.info, r->out.count);
4126 result = enumprinters_level5(p->mem_ctx, p->server_info,
4128 r->out.info, r->out.count);
4131 return WERR_UNKNOWN_LEVEL;
4134 if (!W_ERROR_IS_OK(result)) {
4138 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4139 spoolss_EnumPrinters,
4140 *r->out.info, r->in.level,
4142 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4143 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4145 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4148 /****************************************************************
4150 ****************************************************************/
4152 WERROR _spoolss_GetPrinter(pipes_struct *p,
4153 struct spoolss_GetPrinter *r)
4155 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4156 struct spoolss_PrinterInfo2 *info2 = NULL;
4157 WERROR result = WERR_OK;
4158 const char *servername = NULL;
4161 /* that's an [in out] buffer */
4163 if (!r->in.buffer && (r->in.offered != 0)) {
4164 return WERR_INVALID_PARAM;
4169 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4173 if (Printer != NULL || Printer->servername != NULL) {
4174 servername = Printer->servername;
4177 result = winreg_get_printer(p->mem_ctx,
4180 lp_const_servicename(snum),
4182 if (!W_ERROR_IS_OK(result)) {
4186 switch (r->in.level) {
4188 result = construct_printer_info0(p->mem_ctx, p->server_info,
4190 &r->out.info->info0, snum);
4193 result = construct_printer_info1(p->mem_ctx, info2,
4195 &r->out.info->info1, snum);
4198 result = construct_printer_info2(p->mem_ctx, info2,
4199 &r->out.info->info2, snum);
4202 result = construct_printer_info3(p->mem_ctx, info2,
4203 &r->out.info->info3, snum);
4206 result = construct_printer_info4(p->mem_ctx, info2,
4207 &r->out.info->info4, snum);
4210 result = construct_printer_info5(p->mem_ctx, info2,
4211 &r->out.info->info5, snum);
4214 result = construct_printer_info6(p->mem_ctx, info2,
4215 &r->out.info->info6, snum);
4218 result = construct_printer_info7(p->mem_ctx, Printer,
4219 &r->out.info->info7, snum);
4222 result = construct_printer_info8(p->mem_ctx, info2,
4223 &r->out.info->info8, snum);
4226 result = WERR_UNKNOWN_LEVEL;
4230 if (!W_ERROR_IS_OK(result)) {
4231 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4232 r->in.level, win_errstr(result)));
4233 TALLOC_FREE(r->out.info);
4237 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4238 r->out.info, r->in.level);
4239 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4241 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4244 /********************************************************************
4245 ********************************************************************/
4247 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4248 const char **string_array,
4249 const char *cservername)
4251 int i, num_strings = 0;
4252 const char **array = NULL;
4254 if (!string_array) {
4258 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4260 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4261 cservername, string_array[i]);
4268 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4275 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4276 &array, &num_strings);
4282 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4284 if (in && strlen(in)) { \
4285 out = talloc_strdup(mem_ctx, in); \
4286 W_ERROR_HAVE_NO_MEMORY(out); \
4292 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4294 if (in && strlen(in)) { \
4295 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4297 out = talloc_strdup(mem_ctx, ""); \
4299 W_ERROR_HAVE_NO_MEMORY(out); \
4302 /********************************************************************
4303 * fill a spoolss_DriverInfo1 struct
4304 ********************************************************************/
4306 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4307 struct spoolss_DriverInfo1 *r,
4308 const struct spoolss_DriverInfo8 *driver,
4309 const char *servername)
4311 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4312 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4317 /********************************************************************
4318 * fill a spoolss_DriverInfo2 struct
4319 ********************************************************************/
4321 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4322 struct spoolss_DriverInfo2 *r,
4323 const struct spoolss_DriverInfo8 *driver,
4324 const char *servername)
4327 const char *cservername = canon_servername(servername);
4329 r->version = driver->version;
4331 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4332 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4333 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4334 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4336 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4337 driver->driver_path,
4340 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4344 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4345 driver->config_file,
4351 /********************************************************************
4352 * fill a spoolss_DriverInfo3 struct
4353 ********************************************************************/
4355 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4356 struct spoolss_DriverInfo3 *r,
4357 const struct spoolss_DriverInfo8 *driver,
4358 const char *servername)
4360 const char *cservername = canon_servername(servername);
4362 r->version = driver->version;
4364 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4365 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4366 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4367 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4369 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4370 driver->driver_path,
4373 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4377 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4378 driver->config_file,
4381 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4385 FILL_DRIVER_STRING(mem_ctx,
4386 driver->monitor_name,
4389 FILL_DRIVER_STRING(mem_ctx,
4390 driver->default_datatype,
4391 r->default_datatype);
4393 r->dependent_files = string_array_from_driver_info(mem_ctx,
4394 driver->dependent_files,
4399 /********************************************************************
4400 * fill a spoolss_DriverInfo4 struct
4401 ********************************************************************/
4403 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4404 struct spoolss_DriverInfo4 *r,
4405 const struct spoolss_DriverInfo8 *driver,
4406 const char *servername)
4408 const char *cservername = canon_servername(servername);
4410 r->version = driver->version;
4412 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4413 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4414 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4415 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4417 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4418 driver->driver_path,
4421 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4425 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4426 driver->config_file,
4429 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4433 r->dependent_files = string_array_from_driver_info(mem_ctx,
4434 driver->dependent_files,
4437 FILL_DRIVER_STRING(mem_ctx,
4438 driver->monitor_name,
4441 FILL_DRIVER_STRING(mem_ctx,
4442 driver->default_datatype,
4443 r->default_datatype);
4445 r->previous_names = string_array_from_driver_info(mem_ctx,
4446 driver->previous_names,
4452 /********************************************************************
4453 * fill a spoolss_DriverInfo5 struct
4454 ********************************************************************/
4456 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4457 struct spoolss_DriverInfo5 *r,
4458 const struct spoolss_DriverInfo8 *driver,
4459 const char *servername)
4461 const char *cservername = canon_servername(servername);
4463 r->version = driver->version;
4465 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4466 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4467 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4468 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4470 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4471 driver->driver_path,
4474 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4478 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4479 driver->config_file,
4482 r->driver_attributes = 0;
4483 r->config_version = 0;
4484 r->driver_version = 0;
4488 /********************************************************************
4489 * fill a spoolss_DriverInfo6 struct
4490 ********************************************************************/
4492 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4493 struct spoolss_DriverInfo6 *r,
4494 const struct spoolss_DriverInfo8 *driver,
4495 const char *servername)
4497 const char *cservername = canon_servername(servername);
4499 r->version = driver->version;
4501 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4502 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4503 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4504 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4506 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4507 driver->driver_path,
4510 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4514 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4515 driver->config_file,
4518 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4522 FILL_DRIVER_STRING(mem_ctx,
4523 driver->monitor_name,
4526 FILL_DRIVER_STRING(mem_ctx,
4527 driver->default_datatype,
4528 r->default_datatype);
4530 r->dependent_files = string_array_from_driver_info(mem_ctx,
4531 driver->dependent_files,
4533 r->previous_names = string_array_from_driver_info(mem_ctx,
4534 driver->previous_names,
4537 r->driver_date = driver->driver_date;
4538 r->driver_version = driver->driver_version;
4540 FILL_DRIVER_STRING(mem_ctx,
4541 driver->manufacturer_name,
4542 r->manufacturer_name);
4543 FILL_DRIVER_STRING(mem_ctx,
4544 driver->manufacturer_url,
4545 r->manufacturer_url);
4546 FILL_DRIVER_STRING(mem_ctx,
4547 driver->hardware_id,
4549 FILL_DRIVER_STRING(mem_ctx,
4556 /********************************************************************
4557 * fill a spoolss_DriverInfo8 struct
4558 ********************************************************************/
4560 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4561 struct spoolss_DriverInfo8 *r,
4562 const struct spoolss_DriverInfo8 *driver,
4563 const char *servername)
4565 const char *cservername = canon_servername(servername);
4567 r->version = driver->version;
4569 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4570 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4571 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4572 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4574 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4575 driver->driver_path,
4578 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4582 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4583 driver->config_file,
4586 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4590 FILL_DRIVER_STRING(mem_ctx,
4591 driver->monitor_name,
4594 FILL_DRIVER_STRING(mem_ctx,
4595 driver->default_datatype,
4596 r->default_datatype);
4598 r->dependent_files = string_array_from_driver_info(mem_ctx,
4599 driver->dependent_files,
4601 r->previous_names = string_array_from_driver_info(mem_ctx,
4602 driver->previous_names,
4605 r->driver_date = driver->driver_date;
4606 r->driver_version = driver->driver_version;
4608 FILL_DRIVER_STRING(mem_ctx,
4609 driver->manufacturer_name,
4610 r->manufacturer_name);
4611 FILL_DRIVER_STRING(mem_ctx,
4612 driver->manufacturer_url,
4613 r->manufacturer_url);
4614 FILL_DRIVER_STRING(mem_ctx,
4615 driver->hardware_id,
4617 FILL_DRIVER_STRING(mem_ctx,
4621 FILL_DRIVER_STRING(mem_ctx,
4622 driver->print_processor,
4623 r->print_processor);
4624 FILL_DRIVER_STRING(mem_ctx,
4625 driver->vendor_setup,
4628 r->color_profiles = string_array_from_driver_info(mem_ctx,
4629 driver->color_profiles,
4632 FILL_DRIVER_STRING(mem_ctx,
4636 r->printer_driver_attributes = driver->printer_driver_attributes;
4638 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4639 driver->core_driver_dependencies,
4642 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4643 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4648 #if 0 /* disabled until marshalling issues are resolved - gd */
4649 /********************************************************************
4650 ********************************************************************/
4652 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4653 struct spoolss_DriverFileInfo *r,
4654 const char *cservername,
4655 const char *file_name,
4656 enum spoolss_DriverFileType file_type,
4657 uint32_t file_version)
4659 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4660 cservername, file_name);
4661 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4662 r->file_type = file_type;
4663 r->file_version = file_version;
4668 /********************************************************************
4669 ********************************************************************/
4671 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4672 const struct spoolss_DriverInfo8 *driver,
4673 const char *cservername,
4674 struct spoolss_DriverFileInfo **info_p,
4677 struct spoolss_DriverFileInfo *info = NULL;
4685 if (strlen(driver->driver_path)) {
4686 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4687 struct spoolss_DriverFileInfo,
4689 W_ERROR_HAVE_NO_MEMORY(info);
4690 result = fill_spoolss_DriverFileInfo(info,
4693 driver->driver_path,
4694 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4696 W_ERROR_NOT_OK_RETURN(result);
4700 if (strlen(driver->config_file)) {
4701 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4702 struct spoolss_DriverFileInfo,
4704 W_ERROR_HAVE_NO_MEMORY(info);
4705 result = fill_spoolss_DriverFileInfo(info,
4708 driver->config_file,
4709 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4711 W_ERROR_NOT_OK_RETURN(result);
4715 if (strlen(driver->data_file)) {
4716 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4717 struct spoolss_DriverFileInfo,
4719 W_ERROR_HAVE_NO_MEMORY(info);
4720 result = fill_spoolss_DriverFileInfo(info,
4724 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4726 W_ERROR_NOT_OK_RETURN(result);
4730 if (strlen(driver->help_file)) {
4731 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4732 struct spoolss_DriverFileInfo,
4734 W_ERROR_HAVE_NO_MEMORY(info);
4735 result = fill_spoolss_DriverFileInfo(info,
4739 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4741 W_ERROR_NOT_OK_RETURN(result);
4745 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4746 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4747 struct spoolss_DriverFileInfo,
4749 W_ERROR_HAVE_NO_MEMORY(info);
4750 result = fill_spoolss_DriverFileInfo(info,
4753 driver->dependent_files[i],
4754 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4756 W_ERROR_NOT_OK_RETURN(result);
4766 /********************************************************************
4767 * fill a spoolss_DriverInfo101 struct
4768 ********************************************************************/
4770 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4771 struct spoolss_DriverInfo101 *r,
4772 const struct spoolss_DriverInfo8 *driver,
4773 const char *servername)
4775 const char *cservername = canon_servername(servername);
4778 r->version = driver->version;
4780 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4781 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4782 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4783 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4785 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4789 if (!W_ERROR_IS_OK(result)) {
4793 FILL_DRIVER_STRING(mem_ctx,
4794 driver->monitor_name,
4797 FILL_DRIVER_STRING(mem_ctx,
4798 driver->default_datatype,
4799 r->default_datatype);
4801 r->previous_names = string_array_from_driver_info(mem_ctx,
4802 driver->previous_names,
4804 r->driver_date = driver->driver_date;
4805 r->driver_version = driver->driver_version;
4807 FILL_DRIVER_STRING(mem_ctx,
4808 driver->manufacturer_name,
4809 r->manufacturer_name);
4810 FILL_DRIVER_STRING(mem_ctx,
4811 driver->manufacturer_url,
4812 r->manufacturer_url);
4813 FILL_DRIVER_STRING(mem_ctx,
4814 driver->hardware_id,
4816 FILL_DRIVER_STRING(mem_ctx,
4823 /********************************************************************
4824 ********************************************************************/
4826 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4827 struct auth_serversupplied_info *server_info,
4829 union spoolss_DriverInfo *r,
4831 const char *servername,
4832 const char *architecture,
4835 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4836 struct spoolss_DriverInfo8 *driver;
4839 result = winreg_get_printer(mem_ctx,
4842 lp_const_servicename(snum),
4845 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4846 win_errstr(result)));
4848 if (!W_ERROR_IS_OK(result)) {
4849 return WERR_INVALID_PRINTER_NAME;
4852 result = winreg_get_driver(mem_ctx, server_info, architecture,
4853 pinfo2->drivername, version, &driver);
4855 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4856 win_errstr(result)));
4858 if (!W_ERROR_IS_OK(result)) {
4860 * Is this a W2k client ?
4864 talloc_free(pinfo2);
4865 return WERR_UNKNOWN_PRINTER_DRIVER;
4868 /* Yes - try again with a WinNT driver. */
4870 result = winreg_get_driver(mem_ctx, server_info, architecture,
4873 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4874 win_errstr(result)));
4875 if (!W_ERROR_IS_OK(result)) {
4876 talloc_free(pinfo2);
4877 return WERR_UNKNOWN_PRINTER_DRIVER;
4883 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4886 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4889 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4892 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4895 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4898 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4901 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
4903 #if 0 /* disabled until marshalling issues are resolved - gd */
4905 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
4909 result = WERR_UNKNOWN_LEVEL;
4913 talloc_free(pinfo2);
4914 talloc_free(driver);
4919 /****************************************************************
4920 _spoolss_GetPrinterDriver2
4921 ****************************************************************/
4923 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
4924 struct spoolss_GetPrinterDriver2 *r)
4926 Printer_entry *printer;
4929 const char *servername;
4932 /* that's an [in out] buffer */
4934 if (!r->in.buffer && (r->in.offered != 0)) {
4935 return WERR_INVALID_PARAM;
4938 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
4940 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
4941 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
4942 return WERR_INVALID_PRINTER_NAME;
4946 *r->out.server_major_version = 0;
4947 *r->out.server_minor_version = 0;
4949 servername = get_server_name(printer);
4951 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4955 result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
4956 r->in.level, r->out.info,
4959 r->in.client_major_version);
4960 if (!W_ERROR_IS_OK(result)) {
4961 TALLOC_FREE(r->out.info);
4965 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
4966 r->out.info, r->in.level);
4967 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4969 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4973 /****************************************************************
4974 _spoolss_StartPagePrinter
4975 ****************************************************************/
4977 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
4978 struct spoolss_StartPagePrinter *r)
4980 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4983 DEBUG(3,("_spoolss_StartPagePrinter: "
4984 "Error in startpageprinter printer handle\n"));
4988 Printer->page_started = true;
4992 /****************************************************************
4993 _spoolss_EndPagePrinter
4994 ****************************************************************/
4996 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
4997 struct spoolss_EndPagePrinter *r)
5001 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5004 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5005 OUR_HANDLE(r->in.handle)));
5009 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5012 Printer->page_started = false;
5013 print_job_endpage(snum, Printer->jobid);
5018 /****************************************************************
5019 _spoolss_StartDocPrinter
5020 ****************************************************************/
5022 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5023 struct spoolss_StartDocPrinter *r)
5025 struct spoolss_DocumentInfo1 *info_1;
5027 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5030 DEBUG(2,("_spoolss_StartDocPrinter: "
5031 "Invalid handle (%s:%u:%u)\n",
5032 OUR_HANDLE(r->in.handle)));
5036 if (r->in.level != 1) {
5037 return WERR_UNKNOWN_LEVEL;
5040 info_1 = r->in.info.info1;
5043 * a nice thing with NT is it doesn't listen to what you tell it.
5044 * when asked to send _only_ RAW datas, it tries to send datas
5047 * So I add checks like in NT Server ...
5050 if (info_1->datatype) {
5051 if (strcmp(info_1->datatype, "RAW") != 0) {
5053 return WERR_INVALID_DATATYPE;
5057 /* get the share number of the printer */
5058 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5062 Printer->jobid = print_job_start(p->server_info, snum,
5063 info_1->document_name,
5066 /* An error occured in print_job_start() so return an appropriate
5069 if (Printer->jobid == -1) {
5070 return map_werror_from_unix(errno);
5073 Printer->document_started = true;
5074 *r->out.job_id = Printer->jobid;
5079 /****************************************************************
5080 _spoolss_EndDocPrinter
5081 ****************************************************************/
5083 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5084 struct spoolss_EndDocPrinter *r)
5086 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5090 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5091 OUR_HANDLE(r->in.handle)));
5095 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5099 Printer->document_started = false;
5100 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5101 /* error codes unhandled so far ... */
5106 /****************************************************************
5107 _spoolss_WritePrinter
5108 ****************************************************************/
5110 WERROR _spoolss_WritePrinter(pipes_struct *p,
5111 struct spoolss_WritePrinter *r)
5113 ssize_t buffer_written;
5115 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5118 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5119 OUR_HANDLE(r->in.handle)));
5120 *r->out.num_written = r->in._data_size;
5124 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5127 buffer_written = print_job_write(snum, Printer->jobid,
5128 (const char *)r->in.data.data,
5130 (size_t)r->in._data_size);
5131 if (buffer_written == (ssize_t)-1) {
5132 *r->out.num_written = 0;
5133 if (errno == ENOSPC)
5134 return WERR_NO_SPOOL_SPACE;
5136 return WERR_ACCESS_DENIED;
5139 *r->out.num_written = r->in._data_size;
5144 /********************************************************************
5145 * api_spoolss_getprinter
5146 * called from the spoolss dispatcher
5148 ********************************************************************/
5150 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5154 WERROR errcode = WERR_BADFUNC;
5155 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5158 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5159 OUR_HANDLE(handle)));
5163 if (!get_printer_snum(p, handle, &snum, NULL))
5167 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5168 errcode = print_queue_pause(p->server_info, snum);
5170 case SPOOLSS_PRINTER_CONTROL_RESUME:
5171 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5172 errcode = print_queue_resume(p->server_info, snum);
5174 case SPOOLSS_PRINTER_CONTROL_PURGE:
5175 errcode = print_queue_purge(p->server_info, snum);
5178 return WERR_UNKNOWN_LEVEL;
5185 /****************************************************************
5186 _spoolss_AbortPrinter
5187 * From MSDN: "Deletes printer's spool file if printer is configured
5189 ****************************************************************/
5191 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5192 struct spoolss_AbortPrinter *r)
5194 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5196 WERROR errcode = WERR_OK;
5199 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5200 OUR_HANDLE(r->in.handle)));
5204 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5207 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5212 /********************************************************************
5213 * called by spoolss_api_setprinter
5214 * when updating a printer description
5215 ********************************************************************/
5217 static WERROR update_printer_sec(struct policy_handle *handle,
5218 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5220 struct spoolss_security_descriptor *new_secdesc = NULL;
5221 struct spoolss_security_descriptor *old_secdesc = NULL;
5222 const char *printer;
5226 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5228 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5229 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5230 OUR_HANDLE(handle)));
5232 result = WERR_BADFID;
5236 if (secdesc_ctr == NULL) {
5237 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5238 result = WERR_INVALID_PARAM;
5241 printer = lp_const_servicename(snum);
5243 /* Check the user has permissions to change the security
5244 descriptor. By experimentation with two NT machines, the user
5245 requires Full Access to the printer to change security
5248 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5249 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5250 result = WERR_ACCESS_DENIED;
5254 /* NT seems to like setting the security descriptor even though
5255 nothing may have actually changed. */
5256 result = winreg_get_printer_secdesc(p->mem_ctx,
5260 if (!W_ERROR_IS_OK(result)) {
5261 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5262 result = WERR_BADFID;
5266 if (DEBUGLEVEL >= 10) {
5267 struct security_acl *the_acl;
5270 the_acl = secdesc_ctr->sd->dacl;
5271 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5272 printer, the_acl->num_aces));
5274 for (i = 0; i < the_acl->num_aces; i++) {
5275 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5276 &the_acl->aces[i].trustee),
5277 the_acl->aces[i].access_mask));
5280 the_acl = secdesc_ctr->sd->dacl;
5283 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5284 printer, the_acl->num_aces));
5286 for (i = 0; i < the_acl->num_aces; i++) {
5287 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5288 &the_acl->aces[i].trustee),
5289 the_acl->aces[i].access_mask));
5292 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5296 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5297 if (new_secdesc == NULL) {
5298 result = WERR_NOMEM;
5302 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5307 result = winreg_set_printer_secdesc(p->mem_ctx,
5316 /********************************************************************
5317 Canonicalize printer info from a client
5319 ATTN: It does not matter what we set the servername to hear
5320 since we do the necessary work in get_a_printer() to set it to
5321 the correct value based on what the client sent in the
5322 _spoolss_open_printer_ex().
5323 ********************************************************************/
5325 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5326 struct spoolss_SetPrinterInfo2 *info2,
5329 fstring printername;
5332 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5333 "portname=%s drivername=%s comment=%s location=%s\n",
5334 info2->servername, info2->printername, info2->sharename,
5335 info2->portname, info2->drivername, info2->comment,
5338 /* we force some elements to "correct" values */
5339 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5340 if (info2->servername == NULL) {
5343 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5344 if (info2->sharename == NULL) {
5348 /* check to see if we allow printername != sharename */
5349 if (lp_force_printername(snum)) {
5350 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5351 global_myname(), info2->sharename);
5353 /* make sure printername is in \\server\printername format */
5354 fstrcpy(printername, info2->printername);
5356 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5357 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5361 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5362 global_myname(), p);
5364 if (info2->printername == NULL) {
5368 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5369 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5374 /****************************************************************************
5375 ****************************************************************************/
5377 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5379 char *cmd = lp_addport_cmd();
5380 char *command = NULL;
5382 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5383 bool is_print_op = false;
5386 return WERR_ACCESS_DENIED;
5389 command = talloc_asprintf(ctx,
5390 "%s \"%s\" \"%s\"", cmd, portname, uri );
5396 is_print_op = user_has_privileges( token, &se_printop );
5398 DEBUG(10,("Running [%s]\n", command));
5400 /********* BEGIN SePrintOperatorPrivilege **********/
5405 ret = smbrun(command, NULL);
5410 /********* END SePrintOperatorPrivilege **********/
5412 DEBUGADD(10,("returned [%d]\n", ret));
5414 TALLOC_FREE(command);
5417 return WERR_ACCESS_DENIED;
5423 /****************************************************************************
5424 ****************************************************************************/
5426 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5427 struct spoolss_SetPrinterInfo2 *info2)
5429 char *cmd = lp_addprinter_cmd();
5431 char *command = NULL;
5435 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5436 bool is_print_op = false;
5437 char *remote_machine = talloc_strdup(ctx, "%m");
5439 if (!remote_machine) {
5442 remote_machine = talloc_sub_basic(ctx,
5443 current_user_info.smb_name,
5444 current_user_info.domain,
5446 if (!remote_machine) {
5450 command = talloc_asprintf(ctx,
5451 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5452 cmd, info2->printername, info2->sharename,
5453 info2->portname, info2->drivername,
5454 info2->location, info2->comment, remote_machine);
5460 is_print_op = user_has_privileges( token, &se_printop );
5462 DEBUG(10,("Running [%s]\n", command));
5464 /********* BEGIN SePrintOperatorPrivilege **********/
5469 if ( (ret = smbrun(command, &fd)) == 0 ) {
5470 /* Tell everyone we updated smb.conf. */
5471 message_send_all(smbd_messaging_context(),
5472 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5478 /********* END SePrintOperatorPrivilege **********/
5480 DEBUGADD(10,("returned [%d]\n", ret));
5482 TALLOC_FREE(command);
5483 TALLOC_FREE(remote_machine);
5491 /* reload our services immediately */
5493 reload_services(false);
5497 /* Get lines and convert them back to dos-codepage */
5498 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5499 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5502 /* Set the portname to what the script says the portname should be. */
5503 /* but don't require anything to be return from the script exit a good error code */
5506 /* Set the portname to what the script says the portname should be. */
5507 info2->portname = talloc_strdup(ctx, qlines[0]);
5508 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5511 TALLOC_FREE(qlines);
5516 /********************************************************************
5517 * Called by spoolss_api_setprinter
5518 * when updating a printer description.
5519 ********************************************************************/
5521 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5522 struct spoolss_SetPrinterInfoCtr *info_ctr,
5523 struct spoolss_DeviceMode *devmode)
5525 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5526 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5527 struct spoolss_PrinterInfo2 *old_printer;
5528 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5529 const char *servername = NULL;
5535 DEBUG(8,("update_printer\n"));
5540 result = WERR_BADFID;
5544 if (!get_printer_snum(p, handle, &snum, NULL)) {
5545 result = WERR_BADFID;
5549 if (Printer != NULL || Printer->servername != NULL) {
5550 servername = Printer->servername;
5553 result = winreg_get_printer(p->mem_ctx,
5556 lp_const_servicename(snum),
5558 if (!W_ERROR_IS_OK(result)) {
5559 result = WERR_BADFID;
5563 /* Do sanity check on the requested changes for Samba */
5564 if (!check_printer_ok(p->mem_ctx, printer, snum)) {
5565 result = WERR_INVALID_PARAM;
5569 /* FIXME!!! If the driver has changed we really should verify that
5570 it is installed before doing much else --jerry */
5572 /* Check calling user has permission to update printer description */
5573 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5574 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5575 result = WERR_ACCESS_DENIED;
5579 /* Call addprinter hook */
5580 /* Check changes to see if this is really needed */
5582 if (*lp_addprinter_cmd() &&
5583 (!strequal(printer->drivername, old_printer->drivername) ||
5584 !strequal(printer->comment, old_printer->comment) ||
5585 !strequal(printer->portname, old_printer->portname) ||
5586 !strequal(printer->location, old_printer->location)) )
5588 /* add_printer_hook() will call reload_services() */
5589 if (!add_printer_hook(p->mem_ctx, p->server_info->ptok,
5591 result = WERR_ACCESS_DENIED;
5597 * When a *new* driver is bound to a printer, the drivername is used to
5598 * lookup previously saved driver initialization info, which is then
5599 * bound to the printer, simulating what happens in the Windows arch.
5601 if (!strequal(printer->drivername, old_printer->drivername)) {
5602 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5603 printer->drivername));
5605 notify_printer_driver(snum, printer->drivername);
5609 * flag which changes actually occured. This is a small subset of
5610 * all the possible changes. We also have to update things in the
5613 if (!strequal(printer->comment, old_printer->comment)) {
5614 push_reg_sz(talloc_tos(), &buffer, printer->comment);
5615 winreg_set_printer_dataex(p->mem_ctx,
5618 SPOOL_DSSPOOLER_KEY,
5624 notify_printer_comment(snum, printer->comment);
5627 if (!strequal(printer->sharename, old_printer->sharename)) {
5628 push_reg_sz(talloc_tos(), &buffer, printer->sharename);
5629 winreg_set_printer_dataex(p->mem_ctx,
5632 SPOOL_DSSPOOLER_KEY,
5638 notify_printer_sharename(snum, printer->sharename);
5641 if (!strequal(printer->printername, old_printer->printername)) {
5644 if ( (pname = strchr_m( printer->printername+2, '\\' )) != NULL )
5647 pname = printer->printername;
5649 push_reg_sz(talloc_tos(), &buffer, pname);
5650 winreg_set_printer_dataex(p->mem_ctx,
5653 SPOOL_DSSPOOLER_KEY,
5659 notify_printer_printername( snum, pname );
5662 if (!strequal(printer->portname, old_printer->portname)) {
5663 push_reg_sz(talloc_tos(), &buffer, printer->portname);
5664 winreg_set_printer_dataex(p->mem_ctx,
5667 SPOOL_DSSPOOLER_KEY,
5673 notify_printer_port(snum, printer->portname);
5676 if (!strequal(printer->location, old_printer->location)) {
5677 push_reg_sz(talloc_tos(), &buffer, printer->location);
5678 winreg_set_printer_dataex(p->mem_ctx,
5681 SPOOL_DSSPOOLER_KEY,
5687 notify_printer_location(snum, printer->location);
5690 /* here we need to update some more DsSpooler keys */
5691 /* uNCName, serverName, shortServerName */
5693 push_reg_sz(talloc_tos(), &buffer, global_myname());
5694 winreg_set_printer_dataex(p->mem_ctx,
5697 SPOOL_DSSPOOLER_KEY,
5702 winreg_set_printer_dataex(p->mem_ctx,
5705 SPOOL_DSSPOOLER_KEY,
5711 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5712 global_myname(), printer->sharename );
5713 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5714 winreg_set_printer_dataex(p->mem_ctx,
5717 SPOOL_DSSPOOLER_KEY,
5723 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5725 if (devmode == NULL) {
5726 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5728 result = winreg_update_printer(p->mem_ctx,
5737 talloc_free(old_printer);
5742 /****************************************************************************
5743 ****************************************************************************/
5744 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5745 struct policy_handle *handle,
5746 struct spoolss_SetPrinterInfo7 *info7)
5750 Printer_entry *Printer;
5752 if ( lp_security() != SEC_ADS ) {
5753 return WERR_UNKNOWN_LEVEL;
5756 Printer = find_printer_index_by_hnd(p, handle);
5758 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5763 if (!get_printer_snum(p, handle, &snum, NULL))
5766 nt_printer_publish(Printer, snum, info7->action);
5770 return WERR_UNKNOWN_LEVEL;
5774 /********************************************************************
5775 ********************************************************************/
5777 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5778 struct spoolss_DeviceMode *devmode)
5781 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5782 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
5784 DEBUG(8,("update_printer_devmode\n"));
5790 if (!get_printer_snum(p, handle, &snum, NULL)) {
5794 /* Check calling user has permission to update printer description */
5795 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5796 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5797 return WERR_ACCESS_DENIED;
5800 return winreg_update_printer(p->mem_ctx,
5802 lp_const_servicename(snum),
5810 /****************************************************************
5812 ****************************************************************/
5814 WERROR _spoolss_SetPrinter(pipes_struct *p,
5815 struct spoolss_SetPrinter *r)
5819 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5822 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5823 OUR_HANDLE(r->in.handle)));
5827 /* check the level */
5828 switch (r->in.info_ctr->level) {
5830 return control_printer(r->in.handle, r->in.command, p);
5832 result = update_printer(p, r->in.handle,
5834 r->in.devmode_ctr->devmode);
5835 if (!W_ERROR_IS_OK(result))
5837 if (r->in.secdesc_ctr->sd)
5838 result = update_printer_sec(r->in.handle, p,
5842 return update_printer_sec(r->in.handle, p,
5845 return publish_or_unpublish_printer(p, r->in.handle,
5846 r->in.info_ctr->info.info7);
5848 return update_printer_devmode(p, r->in.handle,
5849 r->in.devmode_ctr->devmode);
5851 return WERR_UNKNOWN_LEVEL;
5855 /****************************************************************
5856 _spoolss_FindClosePrinterNotify
5857 ****************************************************************/
5859 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5860 struct spoolss_FindClosePrinterNotify *r)
5862 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5865 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5866 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5870 if (Printer->notify.client_connected == true) {
5873 if ( Printer->printer_type == SPLHND_SERVER)
5875 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5876 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5879 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5882 Printer->notify.flags=0;
5883 Printer->notify.options=0;
5884 Printer->notify.localmachine[0]='\0';
5885 Printer->notify.printerlocal=0;
5886 TALLOC_FREE(Printer->notify.option);
5887 Printer->notify.client_connected = false;
5892 /****************************************************************
5894 ****************************************************************/
5896 WERROR _spoolss_AddJob(pipes_struct *p,
5897 struct spoolss_AddJob *r)
5899 if (!r->in.buffer && (r->in.offered != 0)) {
5900 return WERR_INVALID_PARAM;
5903 /* this is what a NT server returns for AddJob. AddJob must fail on
5904 * non-local printers */
5906 if (r->in.level != 1) {
5907 return WERR_UNKNOWN_LEVEL;
5910 return WERR_INVALID_PARAM;
5913 /****************************************************************************
5915 ****************************************************************************/
5917 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5918 struct spoolss_JobInfo1 *r,
5919 const print_queue_struct *queue,
5920 int position, int snum,
5921 struct spoolss_PrinterInfo2 *pinfo2)
5925 t = gmtime(&queue->time);
5927 r->job_id = queue->job;
5929 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5930 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5931 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
5932 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5933 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5934 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5935 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5936 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5937 r->data_type = talloc_strdup(mem_ctx, "RAW");
5938 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5939 r->text_status = talloc_strdup(mem_ctx, "");
5940 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5942 r->status = nt_printj_status(queue->status);
5943 r->priority = queue->priority;
5944 r->position = position;
5945 r->total_pages = queue->page_count;
5946 r->pages_printed = 0; /* ??? */
5948 init_systemtime(&r->submitted, t);
5953 /****************************************************************************
5955 ****************************************************************************/
5957 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
5958 struct spoolss_JobInfo2 *r,
5959 const print_queue_struct *queue,
5960 int position, int snum,
5961 struct spoolss_PrinterInfo2 *pinfo2,
5962 struct spoolss_DeviceMode *devmode)
5966 t = gmtime(&queue->time);
5968 r->job_id = queue->job;
5970 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5971 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5972 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
5973 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5974 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5975 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5976 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5977 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5978 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
5979 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
5980 r->data_type = talloc_strdup(mem_ctx, "RAW");
5981 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5982 r->print_processor = talloc_strdup(mem_ctx, "winprint");
5983 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
5984 r->parameters = talloc_strdup(mem_ctx, "");
5985 W_ERROR_HAVE_NO_MEMORY(r->parameters);
5986 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
5987 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5989 r->devmode = devmode;
5991 r->text_status = talloc_strdup(mem_ctx, "");
5992 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5996 r->status = nt_printj_status(queue->status);
5997 r->priority = queue->priority;
5998 r->position = position;
6001 r->total_pages = queue->page_count;
6002 r->size = queue->size;
6003 init_systemtime(&r->submitted, t);
6005 r->pages_printed = 0; /* ??? */
6010 /****************************************************************************
6012 ****************************************************************************/
6014 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6015 struct spoolss_JobInfo3 *r,
6016 const print_queue_struct *queue,
6017 const print_queue_struct *next_queue,
6018 int position, int snum,
6019 struct spoolss_PrinterInfo2 *pinfo2)
6021 r->job_id = queue->job;
6024 r->next_job_id = next_queue->job;
6031 /****************************************************************************
6032 Enumjobs at level 1.
6033 ****************************************************************************/
6035 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6036 const print_queue_struct *queue,
6037 uint32_t num_queues, int snum,
6038 struct spoolss_PrinterInfo2 *pinfo2,
6039 union spoolss_JobInfo **info_p,
6042 union spoolss_JobInfo *info;
6044 WERROR result = WERR_OK;
6046 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6047 W_ERROR_HAVE_NO_MEMORY(info);
6049 *count = num_queues;
6051 for (i=0; i<*count; i++) {
6052 result = fill_job_info1(info,
6058 if (!W_ERROR_IS_OK(result)) {
6064 if (!W_ERROR_IS_OK(result)) {
6075 /****************************************************************************
6076 Enumjobs at level 2.
6077 ****************************************************************************/
6079 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6080 const print_queue_struct *queue,
6081 uint32_t num_queues, int snum,
6082 struct spoolss_PrinterInfo2 *pinfo2,
6083 union spoolss_JobInfo **info_p,
6086 struct spoolss_DeviceMode *devmode;
6087 union spoolss_JobInfo *info;
6089 WERROR result = WERR_OK;
6091 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6092 W_ERROR_HAVE_NO_MEMORY(info);
6094 *count = num_queues;
6096 for (i=0; i<*count; i++) {
6098 if (!pinfo2->devmode) {
6099 result = spoolss_create_default_devmode(info,
6100 pinfo2->printername,
6103 result = copy_devicemode(info,
6107 if (!W_ERROR_IS_OK(result)) {
6108 DEBUG(3, ("Can't proceed w/o a devmode!"));
6112 result = fill_job_info2(info,
6119 if (!W_ERROR_IS_OK(result)) {
6125 if (!W_ERROR_IS_OK(result)) {
6136 /****************************************************************************
6137 Enumjobs at level 3.
6138 ****************************************************************************/
6140 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6141 const print_queue_struct *queue,
6142 uint32_t num_queues, int snum,
6143 struct spoolss_PrinterInfo2 *pinfo2,
6144 union spoolss_JobInfo **info_p,
6147 union spoolss_JobInfo *info;
6149 WERROR result = WERR_OK;
6151 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6152 W_ERROR_HAVE_NO_MEMORY(info);
6154 *count = num_queues;
6156 for (i=0; i<*count; i++) {
6157 const print_queue_struct *next_queue = NULL;
6160 next_queue = &queue[i+1];
6163 result = fill_job_info3(info,
6170 if (!W_ERROR_IS_OK(result)) {
6176 if (!W_ERROR_IS_OK(result)) {
6187 /****************************************************************
6189 ****************************************************************/
6191 WERROR _spoolss_EnumJobs(pipes_struct *p,
6192 struct spoolss_EnumJobs *r)
6195 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6197 print_status_struct prt_status;
6198 print_queue_struct *queue = NULL;
6201 /* that's an [in out] buffer */
6203 if (!r->in.buffer && (r->in.offered != 0)) {
6204 return WERR_INVALID_PARAM;
6207 DEBUG(4,("_spoolss_EnumJobs\n"));
6211 *r->out.info = NULL;
6213 /* lookup the printer snum and tdb entry */
6215 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6219 result = winreg_get_printer(talloc_tos(), p->server_info, NULL,
6220 lp_servicename(snum), &pinfo2);
6221 if (!W_ERROR_IS_OK(result)) {
6225 count = print_queue_status(snum, &queue, &prt_status);
6226 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6227 count, prt_status.status, prt_status.message));
6231 TALLOC_FREE(pinfo2);
6235 switch (r->in.level) {
6237 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6238 pinfo2, r->out.info, r->out.count);
6241 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6242 pinfo2, r->out.info, r->out.count);
6245 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6246 pinfo2, r->out.info, r->out.count);
6249 result = WERR_UNKNOWN_LEVEL;
6254 TALLOC_FREE(pinfo2);
6256 if (!W_ERROR_IS_OK(result)) {
6260 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6262 *r->out.info, r->in.level,
6264 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6265 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6267 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6270 /****************************************************************
6271 _spoolss_ScheduleJob
6272 ****************************************************************/
6274 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6275 struct spoolss_ScheduleJob *r)
6280 /****************************************************************
6281 ****************************************************************/
6283 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6284 const char *printer_name,
6286 struct spoolss_SetJobInfo1 *r)
6290 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6294 if (strequal(old_doc_name, r->document_name)) {
6298 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6305 /****************************************************************
6307 ****************************************************************/
6309 WERROR _spoolss_SetJob(pipes_struct *p,
6310 struct spoolss_SetJob *r)
6313 WERROR errcode = WERR_BADFUNC;
6315 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6319 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6320 return WERR_INVALID_PRINTER_NAME;
6323 switch (r->in.command) {
6324 case SPOOLSS_JOB_CONTROL_CANCEL:
6325 case SPOOLSS_JOB_CONTROL_DELETE:
6326 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6330 case SPOOLSS_JOB_CONTROL_PAUSE:
6331 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6335 case SPOOLSS_JOB_CONTROL_RESTART:
6336 case SPOOLSS_JOB_CONTROL_RESUME:
6337 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6345 return WERR_UNKNOWN_LEVEL;
6348 if (!W_ERROR_IS_OK(errcode)) {
6352 if (r->in.ctr == NULL) {
6356 switch (r->in.ctr->level) {
6358 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6360 r->in.ctr->info.info1);
6366 return WERR_UNKNOWN_LEVEL;
6372 /****************************************************************************
6373 Enumerates all printer drivers by level and architecture.
6374 ****************************************************************************/
6376 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6377 struct auth_serversupplied_info *server_info,
6378 const char *servername,
6379 const char *architecture,
6381 union spoolss_DriverInfo **info_p,
6386 struct spoolss_DriverInfo8 *driver;
6387 union spoolss_DriverInfo *info = NULL;
6389 WERROR result = WERR_OK;
6390 uint32_t num_drivers;
6391 const char **drivers;
6396 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6397 result = winreg_get_driver_list(mem_ctx, server_info,
6398 architecture, version,
6399 &num_drivers, &drivers);
6400 if (!W_ERROR_IS_OK(result)) {
6403 DEBUG(4, ("we have:[%d] drivers in environment"
6404 " [%s] and version [%d]\n",
6405 num_drivers, architecture, version));
6407 if (num_drivers != 0) {
6408 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6409 union spoolss_DriverInfo,
6410 count + num_drivers);
6412 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6413 "failed to enlarge driver info buffer!\n"));
6414 result = WERR_NOMEM;
6419 for (i = 0; i < num_drivers; i++) {
6420 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6422 result = winreg_get_driver(mem_ctx, server_info,
6423 architecture, drivers[i],
6425 if (!W_ERROR_IS_OK(result)) {
6431 result = fill_printer_driver_info1(info, &info[count+i].info1,
6432 driver, servername);
6435 result = fill_printer_driver_info2(info, &info[count+i].info2,
6436 driver, servername);
6439 result = fill_printer_driver_info3(info, &info[count+i].info3,
6440 driver, servername);
6443 result = fill_printer_driver_info4(info, &info[count+i].info4,
6444 driver, servername);
6447 result = fill_printer_driver_info5(info, &info[count+i].info5,
6448 driver, servername);
6451 result = fill_printer_driver_info6(info, &info[count+i].info6,
6452 driver, servername);
6455 result = fill_printer_driver_info8(info, &info[count+i].info8,
6456 driver, servername);
6459 result = WERR_UNKNOWN_LEVEL;
6463 TALLOC_FREE(driver);
6465 if (!W_ERROR_IS_OK(result)) {
6470 count += num_drivers;
6471 TALLOC_FREE(drivers);
6475 TALLOC_FREE(drivers);
6477 if (!W_ERROR_IS_OK(result)) {
6488 /****************************************************************************
6489 Enumerates all printer drivers by level.
6490 ****************************************************************************/
6492 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6493 struct auth_serversupplied_info *server_info,
6494 const char *servername,
6495 const char *architecture,
6497 union spoolss_DriverInfo **info_p,
6501 WERROR result = WERR_OK;
6503 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6505 for (a=0; archi_table[a].long_archi != NULL; a++) {
6507 union spoolss_DriverInfo *info = NULL;
6510 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6513 archi_table[a].long_archi,
6517 if (!W_ERROR_IS_OK(result)) {
6521 for (i=0; i < count; i++) {
6522 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6523 info[i], info_p, count_p);
6530 return enumprinterdrivers_level_by_architecture(mem_ctx,
6539 /****************************************************************
6540 _spoolss_EnumPrinterDrivers
6541 ****************************************************************/
6543 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6544 struct spoolss_EnumPrinterDrivers *r)
6546 const char *cservername;
6549 /* that's an [in out] buffer */
6551 if (!r->in.buffer && (r->in.offered != 0)) {
6552 return WERR_INVALID_PARAM;
6555 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6559 *r->out.info = NULL;
6561 cservername = canon_servername(r->in.server);
6563 if (!is_myname_or_ipaddr(cservername)) {
6564 return WERR_UNKNOWN_PRINTER_DRIVER;
6567 result = enumprinterdrivers_level(p->mem_ctx,
6574 if (!W_ERROR_IS_OK(result)) {
6578 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6579 spoolss_EnumPrinterDrivers,
6580 *r->out.info, r->in.level,
6582 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6583 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6585 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6588 /****************************************************************
6590 ****************************************************************/
6592 WERROR _spoolss_EnumForms(pipes_struct *p,
6593 struct spoolss_EnumForms *r)
6599 *r->out.info = NULL;
6601 /* that's an [in out] buffer */
6603 if (!r->in.buffer && (r->in.offered != 0) ) {
6604 return WERR_INVALID_PARAM;
6607 DEBUG(4,("_spoolss_EnumForms\n"));
6608 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6609 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6611 switch (r->in.level) {
6613 result = winreg_printer_enumforms1(p->mem_ctx,
6619 result = WERR_UNKNOWN_LEVEL;
6623 if (!W_ERROR_IS_OK(result)) {
6627 if (*r->out.count == 0) {
6628 return WERR_NO_MORE_ITEMS;
6631 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6633 *r->out.info, r->in.level,
6635 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6636 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6638 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6641 /****************************************************************
6643 ****************************************************************/
6645 WERROR _spoolss_GetForm(pipes_struct *p,
6646 struct spoolss_GetForm *r)
6650 /* that's an [in out] buffer */
6652 if (!r->in.buffer && (r->in.offered != 0)) {
6653 return WERR_INVALID_PARAM;
6656 DEBUG(4,("_spoolss_GetForm\n"));
6657 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6658 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6660 switch (r->in.level) {
6662 result = winreg_printer_getform1(p->mem_ctx,
6665 &r->out.info->info1);
6668 result = WERR_UNKNOWN_LEVEL;
6672 if (!W_ERROR_IS_OK(result)) {
6673 TALLOC_FREE(r->out.info);
6677 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6678 r->out.info, r->in.level);
6679 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6681 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6684 /****************************************************************************
6685 ****************************************************************************/
6687 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6688 struct spoolss_PortInfo1 *r,
6691 r->port_name = talloc_strdup(mem_ctx, name);
6692 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6697 /****************************************************************************
6698 TODO: This probably needs distinguish between TCP/IP and Local ports
6700 ****************************************************************************/
6702 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6703 struct spoolss_PortInfo2 *r,
6706 r->port_name = talloc_strdup(mem_ctx, name);
6707 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6709 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6710 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6712 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6713 W_ERROR_HAVE_NO_MEMORY(r->description);
6715 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6722 /****************************************************************************
6723 wrapper around the enumer ports command
6724 ****************************************************************************/
6726 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6728 char *cmd = lp_enumports_cmd();
6729 char **qlines = NULL;
6730 char *command = NULL;
6738 /* if no hook then just fill in the default port */
6741 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6744 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6745 TALLOC_FREE(qlines);
6752 /* we have a valid enumport command */
6754 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6759 DEBUG(10,("Running [%s]\n", command));
6760 ret = smbrun(command, &fd);
6761 DEBUG(10,("Returned [%d]\n", ret));
6762 TALLOC_FREE(command);
6767 return WERR_ACCESS_DENIED;
6771 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6772 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6782 /****************************************************************************
6784 ****************************************************************************/
6786 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6787 union spoolss_PortInfo **info_p,
6790 union spoolss_PortInfo *info = NULL;
6792 WERROR result = WERR_OK;
6793 char **qlines = NULL;
6796 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6797 if (!W_ERROR_IS_OK(result)) {
6802 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6804 DEBUG(10,("Returning WERR_NOMEM\n"));
6805 result = WERR_NOMEM;
6809 for (i=0; i<numlines; i++) {
6810 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6811 result = fill_port_1(info, &info[i].info1, qlines[i]);
6812 if (!W_ERROR_IS_OK(result)) {
6817 TALLOC_FREE(qlines);
6820 if (!W_ERROR_IS_OK(result)) {
6822 TALLOC_FREE(qlines);
6834 /****************************************************************************
6836 ****************************************************************************/
6838 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6839 union spoolss_PortInfo **info_p,
6842 union spoolss_PortInfo *info = NULL;
6844 WERROR result = WERR_OK;
6845 char **qlines = NULL;
6848 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6849 if (!W_ERROR_IS_OK(result)) {
6854 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6856 DEBUG(10,("Returning WERR_NOMEM\n"));
6857 result = WERR_NOMEM;
6861 for (i=0; i<numlines; i++) {
6862 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6863 result = fill_port_2(info, &info[i].info2, qlines[i]);
6864 if (!W_ERROR_IS_OK(result)) {
6869 TALLOC_FREE(qlines);
6872 if (!W_ERROR_IS_OK(result)) {
6874 TALLOC_FREE(qlines);
6886 /****************************************************************
6888 ****************************************************************/
6890 WERROR _spoolss_EnumPorts(pipes_struct *p,
6891 struct spoolss_EnumPorts *r)
6895 /* that's an [in out] buffer */
6897 if (!r->in.buffer && (r->in.offered != 0)) {
6898 return WERR_INVALID_PARAM;
6901 DEBUG(4,("_spoolss_EnumPorts\n"));
6905 *r->out.info = NULL;
6907 switch (r->in.level) {
6909 result = enumports_level_1(p->mem_ctx, r->out.info,
6913 result = enumports_level_2(p->mem_ctx, r->out.info,
6917 return WERR_UNKNOWN_LEVEL;
6920 if (!W_ERROR_IS_OK(result)) {
6924 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6926 *r->out.info, r->in.level,
6928 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6929 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6931 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6934 /****************************************************************************
6935 ****************************************************************************/
6937 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
6939 struct spoolss_SetPrinterInfoCtr *info_ctr,
6940 struct spoolss_DeviceMode *devmode,
6941 struct security_descriptor *secdesc,
6942 struct spoolss_UserLevelCtr *user_ctr,
6943 struct policy_handle *handle)
6945 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
6946 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
6948 WERROR err = WERR_OK;
6950 /* samba does not have a concept of local, non-shared printers yet, so
6951 * make sure we always setup sharename - gd */
6952 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
6953 (info2->printername != NULL && info2->printername[0] != '\0')) {
6954 DEBUG(5, ("spoolss_addprinterex_level_2: "
6955 "no sharename has been set, setting printername %s as sharename\n",
6956 info2->printername));
6957 info2->sharename = info2->printername;
6960 /* check to see if the printer already exists */
6961 if ((snum = print_queue_snum(info2->sharename)) != -1) {
6962 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6964 return WERR_PRINTER_ALREADY_EXISTS;
6967 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
6968 if ((snum = print_queue_snum(info2->printername)) != -1) {
6969 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6970 info2->printername));
6971 return WERR_PRINTER_ALREADY_EXISTS;
6975 /* validate printer info struct */
6976 if (!info2->printername || strlen(info2->printername) == 0) {
6977 return WERR_INVALID_PRINTER_NAME;
6979 if (!info2->portname || strlen(info2->portname) == 0) {
6980 return WERR_UNKNOWN_PORT;
6982 if (!info2->drivername || strlen(info2->drivername) == 0) {
6983 return WERR_UNKNOWN_PRINTER_DRIVER;
6985 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
6986 return WERR_UNKNOWN_PRINTPROCESSOR;
6989 /* FIXME!!! smbd should check to see if the driver is installed before
6990 trying to add a printer like this --jerry */
6992 if (*lp_addprinter_cmd() ) {
6993 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6995 return WERR_ACCESS_DENIED;
6998 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
6999 "smb.conf parameter \"addprinter command\" is defined. This"
7000 "parameter must exist for this call to succeed\n",
7001 info2->sharename ));
7004 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7005 return WERR_ACCESS_DENIED;
7008 /* you must be a printer admin to add a new printer */
7009 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7010 return WERR_ACCESS_DENIED;
7014 * Do sanity check on the requested changes for Samba.
7017 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7018 return WERR_INVALID_PARAM;
7021 if (devmode == NULL) {
7022 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7025 err = winreg_update_printer(p->mem_ctx,
7032 if (!W_ERROR_IS_OK(err)) {
7036 if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7037 /* Handle open failed - remove addition. */
7038 ZERO_STRUCTP(handle);
7039 return WERR_ACCESS_DENIED;
7045 /****************************************************************
7046 _spoolss_AddPrinterEx
7047 ****************************************************************/
7049 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7050 struct spoolss_AddPrinterEx *r)
7052 switch (r->in.info_ctr->level) {
7054 /* we don't handle yet */
7055 /* but I know what to do ... */
7056 return WERR_UNKNOWN_LEVEL;
7058 return spoolss_addprinterex_level_2(p, r->in.server,
7060 r->in.devmode_ctr->devmode,
7061 r->in.secdesc_ctr->sd,
7062 r->in.userlevel_ctr,
7065 return WERR_UNKNOWN_LEVEL;
7069 /****************************************************************
7071 ****************************************************************/
7073 WERROR _spoolss_AddPrinter(pipes_struct *p,
7074 struct spoolss_AddPrinter *r)
7076 struct spoolss_AddPrinterEx a;
7077 struct spoolss_UserLevelCtr userlevel_ctr;
7079 ZERO_STRUCT(userlevel_ctr);
7081 userlevel_ctr.level = 1;
7083 a.in.server = r->in.server;
7084 a.in.info_ctr = r->in.info_ctr;
7085 a.in.devmode_ctr = r->in.devmode_ctr;
7086 a.in.secdesc_ctr = r->in.secdesc_ctr;
7087 a.in.userlevel_ctr = &userlevel_ctr;
7088 a.out.handle = r->out.handle;
7090 return _spoolss_AddPrinterEx(p, &a);
7093 /****************************************************************
7094 _spoolss_AddPrinterDriverEx
7095 ****************************************************************/
7097 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7098 struct spoolss_AddPrinterDriverEx *r)
7100 WERROR err = WERR_OK;
7101 const char *driver_name = NULL;
7106 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7107 fn = "_spoolss_AddPrinterDriver";
7109 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7110 fn = "_spoolss_AddPrinterDriverEx";
7113 return WERR_INVALID_PARAM;
7117 * we only support the semantics of AddPrinterDriver()
7118 * i.e. only copy files that are newer than existing ones
7121 if (r->in.flags == 0) {
7122 return WERR_INVALID_PARAM;
7125 if (r->in.flags != APD_COPY_NEW_FILES) {
7126 return WERR_ACCESS_DENIED;
7130 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7131 /* Clever hack from Martin Zielinski <mz@seh.de>
7132 * to allow downgrade from level 8 (Vista).
7134 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7135 r->in.info_ctr->level));
7136 return WERR_UNKNOWN_LEVEL;
7139 DEBUG(5,("Cleaning driver's information\n"));
7140 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7141 if (!W_ERROR_IS_OK(err))
7144 DEBUG(5,("Moving driver to final destination\n"));
7145 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7150 err = winreg_add_driver(p->mem_ctx, p->server_info,
7151 r->in.info_ctr, &driver_name, &version);
7152 if (!W_ERROR_IS_OK(err)) {
7157 * I think this is where he DrvUpgradePrinter() hook would be
7158 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7159 * server. Right now, we just need to send ourselves a message
7160 * to update each printer bound to this driver. --jerry
7163 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7164 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7172 /****************************************************************
7173 _spoolss_AddPrinterDriver
7174 ****************************************************************/
7176 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7177 struct spoolss_AddPrinterDriver *r)
7179 struct spoolss_AddPrinterDriverEx a;
7181 switch (r->in.info_ctr->level) {
7188 return WERR_UNKNOWN_LEVEL;
7191 a.in.servername = r->in.servername;
7192 a.in.info_ctr = r->in.info_ctr;
7193 a.in.flags = APD_COPY_NEW_FILES;
7195 return _spoolss_AddPrinterDriverEx(p, &a);
7198 /****************************************************************************
7199 ****************************************************************************/
7201 struct _spoolss_paths {
7207 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7209 static const struct _spoolss_paths spoolss_paths[]= {
7210 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7211 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7214 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7215 const char *servername,
7216 const char *environment,
7220 const char *pservername = NULL;
7221 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7222 const char *short_archi;
7226 /* environment may be empty */
7227 if (environment && strlen(environment)) {
7228 long_archi = environment;
7231 /* servername may be empty */
7232 if (servername && strlen(servername)) {
7233 pservername = canon_servername(servername);
7235 if (!is_myname_or_ipaddr(pservername)) {
7236 return WERR_INVALID_PARAM;
7240 if (!(short_archi = get_short_archi(long_archi))) {
7241 return WERR_INVALID_ENVIRONMENT;
7244 switch (component) {
7245 case SPOOLSS_PRTPROCS_PATH:
7246 case SPOOLSS_DRIVER_PATH:
7248 *path = talloc_asprintf(mem_ctx,
7251 spoolss_paths[component].share,
7254 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7255 SPOOLSS_DEFAULT_SERVER_PATH,
7256 spoolss_paths[component].dir,
7261 return WERR_INVALID_PARAM;
7271 /****************************************************************************
7272 ****************************************************************************/
7274 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7275 const char *servername,
7276 const char *environment,
7277 struct spoolss_DriverDirectoryInfo1 *r)
7282 werr = compose_spoolss_server_path(mem_ctx,
7285 SPOOLSS_DRIVER_PATH,
7287 if (!W_ERROR_IS_OK(werr)) {
7291 DEBUG(4,("printer driver directory: [%s]\n", path));
7293 r->directory_name = path;
7298 /****************************************************************
7299 _spoolss_GetPrinterDriverDirectory
7300 ****************************************************************/
7302 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7303 struct spoolss_GetPrinterDriverDirectory *r)
7307 /* that's an [in out] buffer */
7309 if (!r->in.buffer && (r->in.offered != 0)) {
7310 return WERR_INVALID_PARAM;
7313 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7318 /* r->in.level is ignored */
7320 werror = getprinterdriverdir_level_1(p->mem_ctx,
7323 &r->out.info->info1);
7324 if (!W_ERROR_IS_OK(werror)) {
7325 TALLOC_FREE(r->out.info);
7329 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7330 r->out.info, r->in.level);
7331 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7333 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7336 /****************************************************************
7337 _spoolss_EnumPrinterData
7338 ****************************************************************/
7340 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7341 struct spoolss_EnumPrinterData *r)
7344 struct spoolss_EnumPrinterDataEx r2;
7346 struct spoolss_PrinterEnumValues *info, *val = NULL;
7349 r2.in.handle = r->in.handle;
7350 r2.in.key_name = "PrinterDriverData";
7352 r2.out.count = &count;
7353 r2.out.info = &info;
7354 r2.out.needed = &needed;
7356 result = _spoolss_EnumPrinterDataEx(p, &r2);
7357 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7358 r2.in.offered = needed;
7359 result = _spoolss_EnumPrinterDataEx(p, &r2);
7361 if (!W_ERROR_IS_OK(result)) {
7366 * The NT machine wants to know the biggest size of value and data
7368 * cf: MSDN EnumPrinterData remark section
7371 if (!r->in.value_offered && !r->in.data_offered) {
7372 uint32_t biggest_valuesize = 0;
7373 uint32_t biggest_datasize = 0;
7376 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7378 for (i=0; i<count; i++) {
7380 name_length = strlen(info[i].value_name);
7381 if (strlen(info[i].value_name) > biggest_valuesize) {
7382 biggest_valuesize = name_length;
7385 if (info[i].data_length > biggest_datasize) {
7386 biggest_datasize = info[i].data_length;
7389 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7393 /* the value is an UNICODE string but real_value_size is the length
7394 in bytes including the trailing 0 */
7396 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7397 *r->out.data_needed = biggest_datasize;
7399 DEBUG(6,("final values: [%d], [%d]\n",
7400 *r->out.value_needed, *r->out.data_needed));
7405 if (r->in.enum_index < count) {
7406 val = &info[r->in.enum_index];
7410 /* out_value should default to "" or else NT4 has
7411 problems unmarshalling the response */
7413 if (r->in.value_offered) {
7414 *r->out.value_needed = 1;
7415 r->out.value_name = talloc_strdup(r, "");
7416 if (!r->out.value_name) {
7420 r->out.value_name = NULL;
7421 *r->out.value_needed = 0;
7424 /* the data is counted in bytes */
7426 *r->out.data_needed = r->in.data_offered;
7428 result = WERR_NO_MORE_ITEMS;
7432 * - counted in bytes in the request
7433 * - counted in UNICODE chars in the max reply
7434 * - counted in bytes in the real size
7436 * take a pause *before* coding not *during* coding
7440 if (r->in.value_offered) {
7441 r->out.value_name = talloc_strdup(r, val->value_name);
7442 if (!r->out.value_name) {
7445 *r->out.value_needed = val->value_name_len;
7447 r->out.value_name = NULL;
7448 *r->out.value_needed = 0;
7453 *r->out.type = val->type;
7455 /* data - counted in bytes */
7458 * See the section "Dynamically Typed Query Parameters"
7462 if (r->out.data && val->data && val->data->data &&
7463 val->data_length && r->in.data_offered) {
7464 memcpy(r->out.data, val->data->data,
7465 MIN(val->data_length,r->in.data_offered));
7468 *r->out.data_needed = val->data_length;
7476 /****************************************************************
7477 _spoolss_SetPrinterData
7478 ****************************************************************/
7480 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7481 struct spoolss_SetPrinterData *r)
7483 struct spoolss_SetPrinterDataEx r2;
7485 r2.in.handle = r->in.handle;
7486 r2.in.key_name = "PrinterDriverData";
7487 r2.in.value_name = r->in.value_name;
7488 r2.in.type = r->in.type;
7489 r2.in.data = r->in.data;
7490 r2.in.offered = r->in.offered;
7492 return _spoolss_SetPrinterDataEx(p, &r2);
7495 /****************************************************************
7496 _spoolss_ResetPrinter
7497 ****************************************************************/
7499 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7500 struct spoolss_ResetPrinter *r)
7502 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7505 DEBUG(5,("_spoolss_ResetPrinter\n"));
7508 * All we do is to check to see if the handle and queue is valid.
7509 * This call really doesn't mean anything to us because we only
7510 * support RAW printing. --jerry
7514 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7515 OUR_HANDLE(r->in.handle)));
7519 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7523 /* blindly return success */
7527 /****************************************************************
7528 _spoolss_DeletePrinterData
7529 ****************************************************************/
7531 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7532 struct spoolss_DeletePrinterData *r)
7534 struct spoolss_DeletePrinterDataEx r2;
7536 r2.in.handle = r->in.handle;
7537 r2.in.key_name = "PrinterDriverData";
7538 r2.in.value_name = r->in.value_name;
7540 return _spoolss_DeletePrinterDataEx(p, &r2);
7543 /****************************************************************
7545 ****************************************************************/
7547 WERROR _spoolss_AddForm(pipes_struct *p,
7548 struct spoolss_AddForm *r)
7550 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7552 WERROR status = WERR_OK;
7553 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7555 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7557 DEBUG(5,("_spoolss_AddForm\n"));
7560 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7561 OUR_HANDLE(r->in.handle)));
7565 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7566 and not a printer admin, then fail */
7568 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7569 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7570 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7571 p->server_info->info3->base.domain.string,
7573 p->server_info->ptok,
7574 lp_printer_admin(snum))) {
7575 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7576 return WERR_ACCESS_DENIED;
7579 switch (form->flags) {
7580 case SPOOLSS_FORM_USER:
7581 case SPOOLSS_FORM_BUILTIN:
7582 case SPOOLSS_FORM_PRINTER:
7585 return WERR_INVALID_PARAM;
7588 status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7589 if (!W_ERROR_IS_OK(status)) {
7594 * ChangeID must always be set if this is a printer
7596 if (Printer->printer_type == SPLHND_PRINTER) {
7597 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7601 status = winreg_printer_update_changeid(p->mem_ctx,
7603 lp_const_servicename(snum));
7604 if (!W_ERROR_IS_OK(status)) {
7612 /****************************************************************
7614 ****************************************************************/
7616 WERROR _spoolss_DeleteForm(pipes_struct *p,
7617 struct spoolss_DeleteForm *r)
7619 const char *form_name = r->in.form_name;
7620 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7622 WERROR status = WERR_OK;
7623 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7625 DEBUG(5,("_spoolss_DeleteForm\n"));
7628 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7629 OUR_HANDLE(r->in.handle)));
7633 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7634 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7635 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7636 p->server_info->info3->base.domain.string,
7638 p->server_info->ptok,
7639 lp_printer_admin(snum))) {
7640 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7641 return WERR_ACCESS_DENIED;
7644 status = winreg_printer_deleteform1(p->mem_ctx,
7647 if (!W_ERROR_IS_OK(status)) {
7652 * ChangeID must always be set if this is a printer
7654 if (Printer->printer_type == SPLHND_PRINTER) {
7655 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7659 status = winreg_printer_update_changeid(p->mem_ctx,
7661 lp_const_servicename(snum));
7662 if (!W_ERROR_IS_OK(status)) {
7670 /****************************************************************
7672 ****************************************************************/
7674 WERROR _spoolss_SetForm(pipes_struct *p,
7675 struct spoolss_SetForm *r)
7677 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7678 const char *form_name = r->in.form_name;
7680 WERROR status = WERR_OK;
7681 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7683 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7685 DEBUG(5,("_spoolss_SetForm\n"));
7688 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7689 OUR_HANDLE(r->in.handle)));
7693 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7694 and not a printer admin, then fail */
7696 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7697 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7698 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7699 p->server_info->info3->base.domain.string,
7701 p->server_info->ptok,
7702 lp_printer_admin(snum))) {
7703 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7704 return WERR_ACCESS_DENIED;
7707 status = winreg_printer_setform1(p->mem_ctx,
7711 if (!W_ERROR_IS_OK(status)) {
7716 * ChangeID must always be set if this is a printer
7718 if (Printer->printer_type == SPLHND_PRINTER) {
7719 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7723 status = winreg_printer_update_changeid(p->mem_ctx,
7725 lp_const_servicename(snum));
7726 if (!W_ERROR_IS_OK(status)) {
7734 /****************************************************************************
7735 fill_print_processor1
7736 ****************************************************************************/
7738 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7739 struct spoolss_PrintProcessorInfo1 *r,
7740 const char *print_processor_name)
7742 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7743 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7748 /****************************************************************************
7749 enumprintprocessors level 1.
7750 ****************************************************************************/
7752 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7753 union spoolss_PrintProcessorInfo **info_p,
7756 union spoolss_PrintProcessorInfo *info;
7759 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7760 W_ERROR_HAVE_NO_MEMORY(info);
7764 result = fill_print_processor1(info, &info[0].info1, "winprint");
7765 if (!W_ERROR_IS_OK(result)) {
7770 if (!W_ERROR_IS_OK(result)) {
7781 /****************************************************************
7782 _spoolss_EnumPrintProcessors
7783 ****************************************************************/
7785 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7786 struct spoolss_EnumPrintProcessors *r)
7790 /* that's an [in out] buffer */
7792 if (!r->in.buffer && (r->in.offered != 0)) {
7793 return WERR_INVALID_PARAM;
7796 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7799 * Enumerate the print processors ...
7801 * Just reply with "winprint", to keep NT happy
7802 * and I can use my nice printer checker.
7807 *r->out.info = NULL;
7809 switch (r->in.level) {
7811 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7815 return WERR_UNKNOWN_LEVEL;
7818 if (!W_ERROR_IS_OK(result)) {
7822 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7823 spoolss_EnumPrintProcessors,
7824 *r->out.info, r->in.level,
7826 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7827 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7829 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7832 /****************************************************************************
7833 fill_printprocdatatype1
7834 ****************************************************************************/
7836 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
7837 struct spoolss_PrintProcDataTypesInfo1 *r,
7838 const char *name_array)
7840 r->name_array = talloc_strdup(mem_ctx, name_array);
7841 W_ERROR_HAVE_NO_MEMORY(r->name_array);
7846 /****************************************************************************
7847 enumprintprocdatatypes level 1.
7848 ****************************************************************************/
7850 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
7851 union spoolss_PrintProcDataTypesInfo **info_p,
7855 union spoolss_PrintProcDataTypesInfo *info;
7857 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
7858 W_ERROR_HAVE_NO_MEMORY(info);
7862 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
7863 if (!W_ERROR_IS_OK(result)) {
7868 if (!W_ERROR_IS_OK(result)) {
7879 /****************************************************************
7880 _spoolss_EnumPrintProcDataTypes
7881 ****************************************************************/
7883 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
7884 struct spoolss_EnumPrintProcDataTypes *r)
7888 /* that's an [in out] buffer */
7890 if (!r->in.buffer && (r->in.offered != 0)) {
7891 return WERR_INVALID_PARAM;
7894 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
7898 *r->out.info = NULL;
7900 switch (r->in.level) {
7902 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
7906 return WERR_UNKNOWN_LEVEL;
7909 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7910 spoolss_EnumPrintProcDataTypes,
7911 *r->out.info, r->in.level,
7913 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7914 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7916 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7919 /****************************************************************************
7921 ****************************************************************************/
7923 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
7924 struct spoolss_MonitorInfo1 *r,
7925 const char *monitor_name)
7927 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
7928 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7933 /****************************************************************************
7935 ****************************************************************************/
7937 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
7938 struct spoolss_MonitorInfo2 *r,
7939 const char *monitor_name,
7940 const char *environment,
7941 const char *dll_name)
7943 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
7944 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7945 r->environment = talloc_strdup(mem_ctx, environment);
7946 W_ERROR_HAVE_NO_MEMORY(r->environment);
7947 r->dll_name = talloc_strdup(mem_ctx, dll_name);
7948 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
7953 /****************************************************************************
7954 enumprintmonitors level 1.
7955 ****************************************************************************/
7957 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
7958 union spoolss_MonitorInfo **info_p,
7961 union spoolss_MonitorInfo *info;
7962 WERROR result = WERR_OK;
7964 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
7965 W_ERROR_HAVE_NO_MEMORY(info);
7969 result = fill_monitor_1(info, &info[0].info1,
7971 if (!W_ERROR_IS_OK(result)) {
7975 result = fill_monitor_1(info, &info[1].info1,
7977 if (!W_ERROR_IS_OK(result)) {
7982 if (!W_ERROR_IS_OK(result)) {
7993 /****************************************************************************
7994 enumprintmonitors level 2.
7995 ****************************************************************************/
7997 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
7998 union spoolss_MonitorInfo **info_p,
8001 union spoolss_MonitorInfo *info;
8002 WERROR result = WERR_OK;
8004 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8005 W_ERROR_HAVE_NO_MEMORY(info);
8009 result = fill_monitor_2(info, &info[0].info2,
8011 "Windows NT X86", /* FIXME */
8013 if (!W_ERROR_IS_OK(result)) {
8017 result = fill_monitor_2(info, &info[1].info2,
8019 "Windows NT X86", /* FIXME */
8021 if (!W_ERROR_IS_OK(result)) {
8026 if (!W_ERROR_IS_OK(result)) {
8037 /****************************************************************
8038 _spoolss_EnumMonitors
8039 ****************************************************************/
8041 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8042 struct spoolss_EnumMonitors *r)
8046 /* that's an [in out] buffer */
8048 if (!r->in.buffer && (r->in.offered != 0)) {
8049 return WERR_INVALID_PARAM;
8052 DEBUG(5,("_spoolss_EnumMonitors\n"));
8055 * Enumerate the print monitors ...
8057 * Just reply with "Local Port", to keep NT happy
8058 * and I can use my nice printer checker.
8063 *r->out.info = NULL;
8065 switch (r->in.level) {
8067 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8071 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8075 return WERR_UNKNOWN_LEVEL;
8078 if (!W_ERROR_IS_OK(result)) {
8082 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8083 spoolss_EnumMonitors,
8084 *r->out.info, r->in.level,
8086 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8087 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8089 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8092 /****************************************************************************
8093 ****************************************************************************/
8095 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8096 const print_queue_struct *queue,
8097 int count, int snum,
8098 struct spoolss_PrinterInfo2 *pinfo2,
8100 struct spoolss_JobInfo1 *r)
8105 for (i=0; i<count; i++) {
8106 if (queue[i].job == (int)jobid) {
8112 if (found == false) {
8113 /* NT treats not found as bad param... yet another bad choice */
8114 return WERR_INVALID_PARAM;
8117 return fill_job_info1(mem_ctx,
8125 /****************************************************************************
8126 ****************************************************************************/
8128 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8129 const print_queue_struct *queue,
8130 int count, int snum,
8131 struct spoolss_PrinterInfo2 *pinfo2,
8133 struct spoolss_JobInfo2 *r)
8137 struct spoolss_DeviceMode *devmode;
8140 for (i=0; i<count; i++) {
8141 if (queue[i].job == (int)jobid) {
8147 if (found == false) {
8148 /* NT treats not found as bad param... yet another bad
8150 return WERR_INVALID_PARAM;
8154 * if the print job does not have a DEVMODE associated with it,
8155 * just use the one for the printer. A NULL devicemode is not
8156 * a failure condition
8159 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8161 result = spoolss_create_default_devmode(mem_ctx,
8162 pinfo2->printername,
8164 if (!W_ERROR_IS_OK(result)) {
8165 DEBUG(3, ("Can't proceed w/o a devmode!"));
8170 return fill_job_info2(mem_ctx,
8179 /****************************************************************
8181 ****************************************************************/
8183 WERROR _spoolss_GetJob(pipes_struct *p,
8184 struct spoolss_GetJob *r)
8186 WERROR result = WERR_OK;
8187 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8190 print_queue_struct *queue = NULL;
8191 print_status_struct prt_status;
8193 /* that's an [in out] buffer */
8195 if (!r->in.buffer && (r->in.offered != 0)) {
8196 return WERR_INVALID_PARAM;
8199 DEBUG(5,("_spoolss_GetJob\n"));
8203 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8207 result = winreg_get_printer(talloc_tos(), p->server_info, NULL,
8208 lp_servicename(snum), &pinfo2);
8209 if (!W_ERROR_IS_OK(result)) {
8213 count = print_queue_status(snum, &queue, &prt_status);
8215 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8216 count, prt_status.status, prt_status.message));
8218 switch (r->in.level) {
8220 result = getjob_level_1(p->mem_ctx,
8221 queue, count, snum, pinfo2,
8222 r->in.job_id, &r->out.info->info1);
8225 result = getjob_level_2(p->mem_ctx,
8226 queue, count, snum, pinfo2,
8227 r->in.job_id, &r->out.info->info2);
8230 result = WERR_UNKNOWN_LEVEL;
8235 TALLOC_FREE(pinfo2);
8237 if (!W_ERROR_IS_OK(result)) {
8238 TALLOC_FREE(r->out.info);
8242 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8244 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8246 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8249 /****************************************************************
8250 _spoolss_GetPrinterDataEx
8251 ****************************************************************/
8253 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8254 struct spoolss_GetPrinterDataEx *r)
8257 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8258 const char *printer;
8260 WERROR result = WERR_OK;
8262 enum winreg_Type val_type;
8267 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8269 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8270 r->in.key_name, r->in.value_name));
8272 /* in case of problem, return some default values */
8275 *r->out.type = REG_NONE;
8278 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8279 OUR_HANDLE(r->in.handle)));
8280 result = WERR_BADFID;
8284 /* Is the handle to a printer or to the server? */
8286 if (Printer->printer_type == SPLHND_SERVER) {
8288 union spoolss_PrinterData data;
8290 result = getprinterdata_printer_server(p->mem_ctx,
8294 if (!W_ERROR_IS_OK(result)) {
8298 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8299 *r->out.type, &data);
8300 if (!W_ERROR_IS_OK(result)) {
8304 *r->out.needed = blob.length;
8306 if (r->in.offered >= *r->out.needed) {
8307 memcpy(r->out.data, blob.data, blob.length);
8310 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8313 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8316 printer = lp_const_servicename(snum);
8318 /* check to see if the keyname is valid */
8319 if (!strlen(r->in.key_name)) {
8320 return WERR_INVALID_PARAM;
8323 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8324 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8325 strequal(r->in.value_name, "ChangeId")) {
8326 *r->out.type = REG_DWORD;
8328 if (r->in.offered >= *r->out.needed) {
8329 uint32_t changeid = 0;
8331 result = winreg_printer_get_changeid(p->mem_ctx,
8335 if (!W_ERROR_IS_OK(result)) {
8339 SIVAL(r->out.data, 0, changeid);
8345 result = winreg_get_printer_dataex(p->mem_ctx,
8353 if (!W_ERROR_IS_OK(result)) {
8357 *r->out.needed = val_size;
8358 *r->out.type = val_type;
8360 if (r->in.offered >= *r->out.needed) {
8361 memcpy(r->out.data, val_data, val_size);
8365 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8366 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8368 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8371 /****************************************************************
8372 _spoolss_SetPrinterDataEx
8373 ****************************************************************/
8375 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8376 struct spoolss_SetPrinterDataEx *r)
8378 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8380 WERROR result = WERR_OK;
8381 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8384 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8386 /* From MSDN documentation of SetPrinterDataEx: pass request to
8387 SetPrinterData if key is "PrinterDriverData" */
8390 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8391 OUR_HANDLE(r->in.handle)));
8395 if (Printer->printer_type == SPLHND_SERVER) {
8396 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8397 "Not implemented for server handles yet\n"));
8398 return WERR_INVALID_PARAM;
8401 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8406 * Access check : NT returns "access denied" if you make a
8407 * SetPrinterData call without the necessary privildge.
8408 * we were originally returning OK if nothing changed
8409 * which made Win2k issue **a lot** of SetPrinterData
8410 * when connecting to a printer --jerry
8413 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8414 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8415 "change denied by handle access permissions\n"));
8416 return WERR_ACCESS_DENIED;
8419 result = winreg_get_printer(Printer, p->server_info,
8420 Printer->servername,
8421 lp_servicename(snum),
8423 if (!W_ERROR_IS_OK(result)) {
8427 /* check for OID in valuename */
8429 oid_string = strchr(r->in.value_name, ',');
8435 /* save the registry data */
8437 result = winreg_set_printer_dataex(p->mem_ctx,
8446 if (W_ERROR_IS_OK(result)) {
8447 /* save the OID if one was specified */
8449 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8450 r->in.key_name, SPOOL_OID_KEY);
8452 result = WERR_NOMEM;
8457 * I'm not checking the status here on purpose. Don't know
8458 * if this is right, but I'm returning the status from the
8459 * previous set_printer_dataex() call. I have no idea if
8460 * this is right. --jerry
8462 winreg_set_printer_dataex(p->mem_ctx,
8468 (uint8_t *) oid_string,
8469 strlen(oid_string) + 1);
8472 result = winreg_printer_update_changeid(p->mem_ctx,
8474 lp_const_servicename(snum));
8479 talloc_free(pinfo2);
8483 /****************************************************************
8484 _spoolss_DeletePrinterDataEx
8485 ****************************************************************/
8487 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8488 struct spoolss_DeletePrinterDataEx *r)
8490 const char *printer;
8492 WERROR status = WERR_OK;
8493 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8495 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8498 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8499 "Invalid handle (%s:%u:%u).\n",
8500 OUR_HANDLE(r->in.handle)));
8504 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8505 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8506 "printer properties change denied by handle\n"));
8507 return WERR_ACCESS_DENIED;
8510 if (!r->in.value_name || !r->in.key_name) {
8514 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8517 printer = lp_const_servicename(snum);
8519 status = winreg_delete_printer_dataex(p->mem_ctx,
8524 if (W_ERROR_IS_OK(status)) {
8525 status = winreg_printer_update_changeid(p->mem_ctx,
8533 /****************************************************************
8534 _spoolss_EnumPrinterKey
8535 ****************************************************************/
8537 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8538 struct spoolss_EnumPrinterKey *r)
8541 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8543 WERROR result = WERR_BADFILE;
8544 const char **array = NULL;
8547 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8550 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8551 OUR_HANDLE(r->in.handle)));
8555 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8559 result = winreg_enum_printer_key(p->mem_ctx,
8561 lp_const_servicename(snum),
8565 if (!W_ERROR_IS_OK(result)) {
8569 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8570 result = WERR_NOMEM;
8574 *r->out._ndr_size = r->in.offered / 2;
8575 *r->out.needed = blob.length;
8577 if (r->in.offered < *r->out.needed) {
8578 result = WERR_MORE_DATA;
8581 r->out.key_buffer->string_array = array;
8585 if (!W_ERROR_IS_OK(result)) {
8587 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8595 /****************************************************************
8596 _spoolss_DeletePrinterKey
8597 ****************************************************************/
8599 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8600 struct spoolss_DeletePrinterKey *r)
8602 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8605 const char *printer;
8607 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8610 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8611 OUR_HANDLE(r->in.handle)));
8615 /* if keyname == NULL, return error */
8616 if ( !r->in.key_name )
8617 return WERR_INVALID_PARAM;
8619 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8623 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8624 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8625 "printer properties change denied by handle\n"));
8626 return WERR_ACCESS_DENIED;
8629 printer = lp_const_servicename(snum);
8631 /* delete the key and all subkeys */
8632 status = winreg_delete_printer_key(p->mem_ctx,
8636 if (W_ERROR_IS_OK(status)) {
8637 status = winreg_printer_update_changeid(p->mem_ctx,
8645 /****************************************************************
8646 _spoolss_EnumPrinterDataEx
8647 ****************************************************************/
8649 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8650 struct spoolss_EnumPrinterDataEx *r)
8653 struct spoolss_PrinterEnumValues *info = NULL;
8654 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8658 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8662 *r->out.info = NULL;
8665 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8666 OUR_HANDLE(r->in.handle)));
8671 * first check for a keyname of NULL or "". Win2k seems to send
8672 * this a lot and we should send back WERR_INVALID_PARAM
8673 * no need to spend time looking up the printer in this case.
8677 if (!strlen(r->in.key_name)) {
8678 result = WERR_INVALID_PARAM;
8682 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8686 /* now look for a match on the key name */
8687 result = winreg_enum_printer_dataex(p->mem_ctx,
8689 lp_const_servicename(snum),
8693 if (!W_ERROR_IS_OK(result)) {
8697 #if 0 /* FIXME - gd */
8698 /* housekeeping information in the reply */
8700 /* Fix from Martin Zielinski <mz@seh.de> - ensure
8701 * the hand marshalled container size is a multiple
8702 * of 4 bytes for RPC alignment.
8706 needed += 4-(needed % 4);
8709 *r->out.count = count;
8710 *r->out.info = info;
8713 if (!W_ERROR_IS_OK(result)) {
8717 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8718 spoolss_EnumPrinterDataEx,
8721 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8722 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8724 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8727 /****************************************************************************
8728 ****************************************************************************/
8730 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8731 const char *servername,
8732 const char *environment,
8733 struct spoolss_PrintProcessorDirectoryInfo1 *r)
8738 werr = compose_spoolss_server_path(mem_ctx,
8741 SPOOLSS_PRTPROCS_PATH,
8743 if (!W_ERROR_IS_OK(werr)) {
8747 DEBUG(4,("print processor directory: [%s]\n", path));
8749 r->directory_name = path;
8754 /****************************************************************
8755 _spoolss_GetPrintProcessorDirectory
8756 ****************************************************************/
8758 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8759 struct spoolss_GetPrintProcessorDirectory *r)
8763 /* that's an [in out] buffer */
8765 if (!r->in.buffer && (r->in.offered != 0)) {
8766 return WERR_INVALID_PARAM;
8769 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8774 /* r->in.level is ignored */
8776 /* We always should reply with a local print processor directory so that
8777 * users are not forced to have a [prnproc$] share on the Samba spoolss
8778 * server - Guenther */
8780 result = getprintprocessordirectory_level_1(p->mem_ctx,
8781 NULL, /* r->in.server */
8783 &r->out.info->info1);
8784 if (!W_ERROR_IS_OK(result)) {
8785 TALLOC_FREE(r->out.info);
8789 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8790 r->out.info, r->in.level);
8791 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8793 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8796 /*******************************************************************
8797 ********************************************************************/
8799 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8800 const char *dllname)
8802 enum ndr_err_code ndr_err;
8803 struct spoolss_MonitorUi ui;
8805 ui.dll_name = dllname;
8807 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8808 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8809 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8810 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8812 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8815 /*******************************************************************
8816 Streams the monitor UI DLL name in UNICODE
8817 *******************************************************************/
8819 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8820 NT_USER_TOKEN *token, DATA_BLOB *in,
8821 DATA_BLOB *out, uint32_t *needed)
8823 const char *dllname = "tcpmonui.dll";
8825 *needed = (strlen(dllname)+1) * 2;
8827 if (out->length < *needed) {
8828 return WERR_INSUFFICIENT_BUFFER;
8831 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8838 /*******************************************************************
8839 ********************************************************************/
8841 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
8842 struct spoolss_PortData1 *port1,
8843 const DATA_BLOB *buf)
8845 enum ndr_err_code ndr_err;
8846 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
8847 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
8848 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8849 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
8851 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8854 /*******************************************************************
8855 ********************************************************************/
8857 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
8858 struct spoolss_PortData2 *port2,
8859 const DATA_BLOB *buf)
8861 enum ndr_err_code ndr_err;
8862 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
8863 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
8864 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8865 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
8867 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8870 /*******************************************************************
8871 Create a new TCP/IP port
8872 *******************************************************************/
8874 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
8875 NT_USER_TOKEN *token, DATA_BLOB *in,
8876 DATA_BLOB *out, uint32_t *needed)
8878 struct spoolss_PortData1 port1;
8879 struct spoolss_PortData2 port2;
8880 char *device_uri = NULL;
8883 const char *portname;
8884 const char *hostaddress;
8886 uint32_t port_number;
8889 /* peek for spoolss_PortData version */
8891 if (!in || (in->length < (128 + 4))) {
8892 return WERR_GENERAL_FAILURE;
8895 version = IVAL(in->data, 128);
8901 if (!pull_port_data_1(mem_ctx, &port1, in)) {
8905 portname = port1.portname;
8906 hostaddress = port1.hostaddress;
8907 queue = port1.queue;
8908 protocol = port1.protocol;
8909 port_number = port1.port_number;
8915 if (!pull_port_data_2(mem_ctx, &port2, in)) {
8919 portname = port2.portname;
8920 hostaddress = port2.hostaddress;
8921 queue = port2.queue;
8922 protocol = port2.protocol;
8923 port_number = port2.port_number;
8927 DEBUG(1,("xcvtcp_addport: "
8928 "unknown version of port_data: %d\n", version));
8929 return WERR_UNKNOWN_PORT;
8932 /* create the device URI and call the add_port_hook() */
8935 case PROTOCOL_RAWTCP_TYPE:
8936 device_uri = talloc_asprintf(mem_ctx,
8937 "socket://%s:%d/", hostaddress,
8941 case PROTOCOL_LPR_TYPE:
8942 device_uri = talloc_asprintf(mem_ctx,
8943 "lpr://%s/%s", hostaddress, queue );
8947 return WERR_UNKNOWN_PORT;
8954 return add_port_hook(mem_ctx, token, portname, device_uri);
8957 /*******************************************************************
8958 *******************************************************************/
8960 struct xcv_api_table xcvtcp_cmds[] = {
8961 { "MonitorUI", xcvtcp_monitorui },
8962 { "AddPort", xcvtcp_addport},
8966 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
8967 NT_USER_TOKEN *token, const char *command,
8974 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
8976 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
8977 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
8978 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
8981 return WERR_BADFUNC;
8984 /*******************************************************************
8985 *******************************************************************/
8986 #if 0 /* don't support management using the "Local Port" monitor */
8988 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
8989 NT_USER_TOKEN *token, DATA_BLOB *in,
8990 DATA_BLOB *out, uint32_t *needed)
8992 const char *dllname = "localui.dll";
8994 *needed = (strlen(dllname)+1) * 2;
8996 if (out->length < *needed) {
8997 return WERR_INSUFFICIENT_BUFFER;
9000 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9007 /*******************************************************************
9008 *******************************************************************/
9010 struct xcv_api_table xcvlocal_cmds[] = {
9011 { "MonitorUI", xcvlocal_monitorui },
9015 struct xcv_api_table xcvlocal_cmds[] = {
9022 /*******************************************************************
9023 *******************************************************************/
9025 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9026 NT_USER_TOKEN *token, const char *command,
9027 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9032 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9034 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9035 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9036 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9038 return WERR_BADFUNC;
9041 /****************************************************************
9043 ****************************************************************/
9045 WERROR _spoolss_XcvData(pipes_struct *p,
9046 struct spoolss_XcvData *r)
9048 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9049 DATA_BLOB out_data = data_blob_null;
9053 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9054 OUR_HANDLE(r->in.handle)));
9058 /* Has to be a handle to the TCP/IP port monitor */
9060 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9061 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9065 /* requires administrative access to the server */
9067 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9068 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9069 return WERR_ACCESS_DENIED;
9072 /* Allocate the outgoing buffer */
9074 if (r->in.out_data_size) {
9075 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9076 if (out_data.data == NULL) {
9081 switch ( Printer->printer_type ) {
9082 case SPLHND_PORTMON_TCP:
9083 werror = process_xcvtcp_command(p->mem_ctx,
9084 p->server_info->ptok,
9085 r->in.function_name,
9086 &r->in.in_data, &out_data,
9089 case SPLHND_PORTMON_LOCAL:
9090 werror = process_xcvlocal_command(p->mem_ctx,
9091 p->server_info->ptok,
9092 r->in.function_name,
9093 &r->in.in_data, &out_data,
9097 werror = WERR_INVALID_PRINT_MONITOR;
9100 if (!W_ERROR_IS_OK(werror)) {
9104 *r->out.status_code = 0;
9106 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9107 memcpy(r->out.out_data, out_data.data,
9108 MIN(r->in.out_data_size, out_data.length));
9114 /****************************************************************
9115 _spoolss_AddPrintProcessor
9116 ****************************************************************/
9118 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9119 struct spoolss_AddPrintProcessor *r)
9121 /* for now, just indicate success and ignore the add. We'll
9122 automatically set the winprint processor for printer
9123 entries later. Used to debug the LexMark Optra S 1855 PCL
9129 /****************************************************************
9131 ****************************************************************/
9133 WERROR _spoolss_AddPort(pipes_struct *p,
9134 struct spoolss_AddPort *r)
9136 /* do what w2k3 does */
9138 return WERR_NOT_SUPPORTED;
9141 /****************************************************************
9142 _spoolss_GetPrinterDriver
9143 ****************************************************************/
9145 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9146 struct spoolss_GetPrinterDriver *r)
9148 p->rng_fault_state = true;
9149 return WERR_NOT_SUPPORTED;
9152 /****************************************************************
9153 _spoolss_ReadPrinter
9154 ****************************************************************/
9156 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9157 struct spoolss_ReadPrinter *r)
9159 p->rng_fault_state = true;
9160 return WERR_NOT_SUPPORTED;
9163 /****************************************************************
9164 _spoolss_WaitForPrinterChange
9165 ****************************************************************/
9167 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9168 struct spoolss_WaitForPrinterChange *r)
9170 p->rng_fault_state = true;
9171 return WERR_NOT_SUPPORTED;
9174 /****************************************************************
9175 _spoolss_ConfigurePort
9176 ****************************************************************/
9178 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9179 struct spoolss_ConfigurePort *r)
9181 p->rng_fault_state = true;
9182 return WERR_NOT_SUPPORTED;
9185 /****************************************************************
9187 ****************************************************************/
9189 WERROR _spoolss_DeletePort(pipes_struct *p,
9190 struct spoolss_DeletePort *r)
9192 p->rng_fault_state = true;
9193 return WERR_NOT_SUPPORTED;
9196 /****************************************************************
9197 _spoolss_CreatePrinterIC
9198 ****************************************************************/
9200 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9201 struct spoolss_CreatePrinterIC *r)
9203 p->rng_fault_state = true;
9204 return WERR_NOT_SUPPORTED;
9207 /****************************************************************
9208 _spoolss_PlayGDIScriptOnPrinterIC
9209 ****************************************************************/
9211 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9212 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9214 p->rng_fault_state = true;
9215 return WERR_NOT_SUPPORTED;
9218 /****************************************************************
9219 _spoolss_DeletePrinterIC
9220 ****************************************************************/
9222 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9223 struct spoolss_DeletePrinterIC *r)
9225 p->rng_fault_state = true;
9226 return WERR_NOT_SUPPORTED;
9229 /****************************************************************
9230 _spoolss_AddPrinterConnection
9231 ****************************************************************/
9233 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9234 struct spoolss_AddPrinterConnection *r)
9236 p->rng_fault_state = true;
9237 return WERR_NOT_SUPPORTED;
9240 /****************************************************************
9241 _spoolss_DeletePrinterConnection
9242 ****************************************************************/
9244 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9245 struct spoolss_DeletePrinterConnection *r)
9247 p->rng_fault_state = true;
9248 return WERR_NOT_SUPPORTED;
9251 /****************************************************************
9252 _spoolss_PrinterMessageBox
9253 ****************************************************************/
9255 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9256 struct spoolss_PrinterMessageBox *r)
9258 p->rng_fault_state = true;
9259 return WERR_NOT_SUPPORTED;
9262 /****************************************************************
9264 ****************************************************************/
9266 WERROR _spoolss_AddMonitor(pipes_struct *p,
9267 struct spoolss_AddMonitor *r)
9269 p->rng_fault_state = true;
9270 return WERR_NOT_SUPPORTED;
9273 /****************************************************************
9274 _spoolss_DeleteMonitor
9275 ****************************************************************/
9277 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9278 struct spoolss_DeleteMonitor *r)
9280 p->rng_fault_state = true;
9281 return WERR_NOT_SUPPORTED;
9284 /****************************************************************
9285 _spoolss_DeletePrintProcessor
9286 ****************************************************************/
9288 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9289 struct spoolss_DeletePrintProcessor *r)
9291 p->rng_fault_state = true;
9292 return WERR_NOT_SUPPORTED;
9295 /****************************************************************
9296 _spoolss_AddPrintProvidor
9297 ****************************************************************/
9299 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9300 struct spoolss_AddPrintProvidor *r)
9302 p->rng_fault_state = true;
9303 return WERR_NOT_SUPPORTED;
9306 /****************************************************************
9307 _spoolss_DeletePrintProvidor
9308 ****************************************************************/
9310 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9311 struct spoolss_DeletePrintProvidor *r)
9313 p->rng_fault_state = true;
9314 return WERR_NOT_SUPPORTED;
9317 /****************************************************************
9318 _spoolss_FindFirstPrinterChangeNotification
9319 ****************************************************************/
9321 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9322 struct spoolss_FindFirstPrinterChangeNotification *r)
9324 p->rng_fault_state = true;
9325 return WERR_NOT_SUPPORTED;
9328 /****************************************************************
9329 _spoolss_FindNextPrinterChangeNotification
9330 ****************************************************************/
9332 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9333 struct spoolss_FindNextPrinterChangeNotification *r)
9335 p->rng_fault_state = true;
9336 return WERR_NOT_SUPPORTED;
9339 /****************************************************************
9340 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9341 ****************************************************************/
9343 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9344 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9346 p->rng_fault_state = true;
9347 return WERR_NOT_SUPPORTED;
9350 /****************************************************************
9351 _spoolss_ReplyOpenPrinter
9352 ****************************************************************/
9354 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9355 struct spoolss_ReplyOpenPrinter *r)
9357 p->rng_fault_state = true;
9358 return WERR_NOT_SUPPORTED;
9361 /****************************************************************
9362 _spoolss_RouterReplyPrinter
9363 ****************************************************************/
9365 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9366 struct spoolss_RouterReplyPrinter *r)
9368 p->rng_fault_state = true;
9369 return WERR_NOT_SUPPORTED;
9372 /****************************************************************
9373 _spoolss_ReplyClosePrinter
9374 ****************************************************************/
9376 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9377 struct spoolss_ReplyClosePrinter *r)
9379 p->rng_fault_state = true;
9380 return WERR_NOT_SUPPORTED;
9383 /****************************************************************
9385 ****************************************************************/
9387 WERROR _spoolss_AddPortEx(pipes_struct *p,
9388 struct spoolss_AddPortEx *r)
9390 p->rng_fault_state = true;
9391 return WERR_NOT_SUPPORTED;
9394 /****************************************************************
9395 _spoolss_RouterFindFirstPrinterChangeNotification
9396 ****************************************************************/
9398 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9399 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9401 p->rng_fault_state = true;
9402 return WERR_NOT_SUPPORTED;
9405 /****************************************************************
9406 _spoolss_SpoolerInit
9407 ****************************************************************/
9409 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9410 struct spoolss_SpoolerInit *r)
9412 p->rng_fault_state = true;
9413 return WERR_NOT_SUPPORTED;
9416 /****************************************************************
9417 _spoolss_ResetPrinterEx
9418 ****************************************************************/
9420 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9421 struct spoolss_ResetPrinterEx *r)
9423 p->rng_fault_state = true;
9424 return WERR_NOT_SUPPORTED;
9427 /****************************************************************
9428 _spoolss_RouterReplyPrinterEx
9429 ****************************************************************/
9431 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9432 struct spoolss_RouterReplyPrinterEx *r)
9434 p->rng_fault_state = true;
9435 return WERR_NOT_SUPPORTED;
9438 /****************************************************************
9440 ****************************************************************/
9442 WERROR _spoolss_44(pipes_struct *p,
9443 struct spoolss_44 *r)
9445 p->rng_fault_state = true;
9446 return WERR_NOT_SUPPORTED;
9449 /****************************************************************
9451 ****************************************************************/
9453 WERROR _spoolss_47(pipes_struct *p,
9454 struct spoolss_47 *r)
9456 p->rng_fault_state = true;
9457 return WERR_NOT_SUPPORTED;
9460 /****************************************************************
9462 ****************************************************************/
9464 WERROR _spoolss_4a(pipes_struct *p,
9465 struct spoolss_4a *r)
9467 p->rng_fault_state = true;
9468 return WERR_NOT_SUPPORTED;
9471 /****************************************************************
9473 ****************************************************************/
9475 WERROR _spoolss_4b(pipes_struct *p,
9476 struct spoolss_4b *r)
9478 p->rng_fault_state = true;
9479 return WERR_NOT_SUPPORTED;
9482 /****************************************************************
9484 ****************************************************************/
9486 WERROR _spoolss_4c(pipes_struct *p,
9487 struct spoolss_4c *r)
9489 p->rng_fault_state = true;
9490 return WERR_NOT_SUPPORTED;
9493 /****************************************************************
9495 ****************************************************************/
9497 WERROR _spoolss_53(pipes_struct *p,
9498 struct spoolss_53 *r)
9500 p->rng_fault_state = true;
9501 return WERR_NOT_SUPPORTED;
9504 /****************************************************************
9506 ****************************************************************/
9508 WERROR _spoolss_55(pipes_struct *p,
9509 struct spoolss_55 *r)
9511 p->rng_fault_state = true;
9512 return WERR_NOT_SUPPORTED;
9515 /****************************************************************
9517 ****************************************************************/
9519 WERROR _spoolss_56(pipes_struct *p,
9520 struct spoolss_56 *r)
9522 p->rng_fault_state = true;
9523 return WERR_NOT_SUPPORTED;
9526 /****************************************************************
9528 ****************************************************************/
9530 WERROR _spoolss_57(pipes_struct *p,
9531 struct spoolss_57 *r)
9533 p->rng_fault_state = true;
9534 return WERR_NOT_SUPPORTED;
9537 /****************************************************************
9539 ****************************************************************/
9541 WERROR _spoolss_5a(pipes_struct *p,
9542 struct spoolss_5a *r)
9544 p->rng_fault_state = true;
9545 return WERR_NOT_SUPPORTED;
9548 /****************************************************************
9550 ****************************************************************/
9552 WERROR _spoolss_5b(pipes_struct *p,
9553 struct spoolss_5b *r)
9555 p->rng_fault_state = true;
9556 return WERR_NOT_SUPPORTED;
9559 /****************************************************************
9561 ****************************************************************/
9563 WERROR _spoolss_5c(pipes_struct *p,
9564 struct spoolss_5c *r)
9566 p->rng_fault_state = true;
9567 return WERR_NOT_SUPPORTED;
9570 /****************************************************************
9572 ****************************************************************/
9574 WERROR _spoolss_5d(pipes_struct *p,
9575 struct spoolss_5d *r)
9577 p->rng_fault_state = true;
9578 return WERR_NOT_SUPPORTED;
9581 /****************************************************************
9583 ****************************************************************/
9585 WERROR _spoolss_5e(pipes_struct *p,
9586 struct spoolss_5e *r)
9588 p->rng_fault_state = true;
9589 return WERR_NOT_SUPPORTED;
9592 /****************************************************************
9594 ****************************************************************/
9596 WERROR _spoolss_5f(pipes_struct *p,
9597 struct spoolss_5f *r)
9599 p->rng_fault_state = true;
9600 return WERR_NOT_SUPPORTED;
9603 /****************************************************************
9605 ****************************************************************/
9607 WERROR _spoolss_60(pipes_struct *p,
9608 struct spoolss_60 *r)
9610 p->rng_fault_state = true;
9611 return WERR_NOT_SUPPORTED;
9614 /****************************************************************
9616 ****************************************************************/
9618 WERROR _spoolss_61(pipes_struct *p,
9619 struct spoolss_61 *r)
9621 p->rng_fault_state = true;
9622 return WERR_NOT_SUPPORTED;
9625 /****************************************************************
9627 ****************************************************************/
9629 WERROR _spoolss_62(pipes_struct *p,
9630 struct spoolss_62 *r)
9632 p->rng_fault_state = true;
9633 return WERR_NOT_SUPPORTED;
9636 /****************************************************************
9638 ****************************************************************/
9640 WERROR _spoolss_63(pipes_struct *p,
9641 struct spoolss_63 *r)
9643 p->rng_fault_state = true;
9644 return WERR_NOT_SUPPORTED;
9647 /****************************************************************
9649 ****************************************************************/
9651 WERROR _spoolss_64(pipes_struct *p,
9652 struct spoolss_64 *r)
9654 p->rng_fault_state = true;
9655 return WERR_NOT_SUPPORTED;
9658 /****************************************************************
9660 ****************************************************************/
9662 WERROR _spoolss_65(pipes_struct *p,
9663 struct spoolss_65 *r)
9665 p->rng_fault_state = true;
9666 return WERR_NOT_SUPPORTED;
9669 /****************************************************************
9670 _spoolss_GetCorePrinterDrivers
9671 ****************************************************************/
9673 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9674 struct spoolss_GetCorePrinterDrivers *r)
9676 p->rng_fault_state = true;
9677 return WERR_NOT_SUPPORTED;
9680 /****************************************************************
9682 ****************************************************************/
9684 WERROR _spoolss_67(pipes_struct *p,
9685 struct spoolss_67 *r)
9687 p->rng_fault_state = true;
9688 return WERR_NOT_SUPPORTED;
9691 /****************************************************************
9692 _spoolss_GetPrinterDriverPackagePath
9693 ****************************************************************/
9695 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9696 struct spoolss_GetPrinterDriverPackagePath *r)
9698 p->rng_fault_state = true;
9699 return WERR_NOT_SUPPORTED;
9702 /****************************************************************
9704 ****************************************************************/
9706 WERROR _spoolss_69(pipes_struct *p,
9707 struct spoolss_69 *r)
9709 p->rng_fault_state = true;
9710 return WERR_NOT_SUPPORTED;
9713 /****************************************************************
9715 ****************************************************************/
9717 WERROR _spoolss_6a(pipes_struct *p,
9718 struct spoolss_6a *r)
9720 p->rng_fault_state = true;
9721 return WERR_NOT_SUPPORTED;
9724 /****************************************************************
9726 ****************************************************************/
9728 WERROR _spoolss_6b(pipes_struct *p,
9729 struct spoolss_6b *r)
9731 p->rng_fault_state = true;
9732 return WERR_NOT_SUPPORTED;
9735 /****************************************************************
9737 ****************************************************************/
9739 WERROR _spoolss_6c(pipes_struct *p,
9740 struct spoolss_6c *r)
9742 p->rng_fault_state = true;
9743 return WERR_NOT_SUPPORTED;
9746 /****************************************************************
9748 ****************************************************************/
9750 WERROR _spoolss_6d(pipes_struct *p,
9751 struct spoolss_6d *r)
9753 p->rng_fault_state = true;
9754 return WERR_NOT_SUPPORTED;