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.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/init_spoolss.h"
33 #include "librpc/gen_ndr/messaging.h"
35 #include "registry/reg_objects.h"
37 /* macros stolen from s4 spoolss server */
38 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
39 ((info)?ndr_size_##fn(info, level, 0):0)
41 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
42 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
44 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
45 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
47 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
50 extern userdom_struct current_user_info;
53 #define DBGC_CLASS DBGC_RPC_SRV
55 #ifndef MAX_OPEN_PRINTER_EXS
56 #define MAX_OPEN_PRINTER_EXS 50
59 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
61 static Printer_entry *printers_list;
63 typedef struct _counter_printer_0 {
64 struct _counter_printer_0 *next;
65 struct _counter_printer_0 *prev;
71 static counter_printer_0 *counter_list;
73 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
74 static uint32_t smb_connections = 0;
77 /* in printing/nt_printing.c */
79 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
81 /* API table for Xcv Monitor functions */
83 struct xcv_api_table {
85 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
88 /********************************************************************
89 * Canonicalize servername.
90 ********************************************************************/
92 static const char *canon_servername(const char *servername)
94 const char *pservername = servername;
95 while (*pservername == '\\') {
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v)
108 return JOB_STATUS_PAUSED;
110 return JOB_STATUS_SPOOLING;
112 return JOB_STATUS_PRINTING;
114 return JOB_STATUS_ERROR;
116 return JOB_STATUS_DELETING;
118 return JOB_STATUS_OFFLINE;
120 return JOB_STATUS_PAPEROUT;
122 return JOB_STATUS_PRINTED;
124 return JOB_STATUS_DELETED;
126 return JOB_STATUS_BLOCKED_DEVQ;
127 case LPQ_USER_INTERVENTION:
128 return JOB_STATUS_USER_INTERVENTION;
133 static int nt_printq_status(int v)
137 return PRINTER_STATUS_PAUSED;
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
172 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 win_errstr(result)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2, NULL);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 serverid_register_msg_flags(
189 messaging_server_id(smbd_messaging_context()),
190 false, FLAG_MSG_PRINT_NOTIFY);
196 /****************************************************************************
197 Functions to free a printer entry datastruct.
198 ****************************************************************************/
200 static int printer_entry_destructor(Printer_entry *Printer)
202 if (Printer->notify.client_connected == true) {
205 if ( Printer->printer_type == SPLHND_SERVER) {
207 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
208 } else if (Printer->printer_type == SPLHND_PRINTER) {
209 snum = print_queue_snum(Printer->sharename);
211 srv_spoolss_replycloseprinter(snum,
212 &Printer->notify.client_hnd);
216 Printer->notify.flags=0;
217 Printer->notify.options=0;
218 Printer->notify.localmachine[0]='\0';
219 Printer->notify.printerlocal=0;
220 TALLOC_FREE(Printer->notify.option);
221 Printer->notify.client_connected = false;
223 free_nt_devicemode( &Printer->nt_devmode );
224 free_a_printer( &Printer->printer_info, 2 );
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list, Printer);
231 /****************************************************************************
232 find printer index by handle
233 ****************************************************************************/
235 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
236 struct policy_handle *hnd)
238 Printer_entry *find_printer = NULL;
240 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
241 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
248 /****************************************************************************
249 Close printer index by handle.
250 ****************************************************************************/
252 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
254 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
257 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
262 close_policy_hnd(p, hnd);
267 /****************************************************************************
268 Delete a printer given a handle.
269 ****************************************************************************/
271 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
273 char *cmd = lp_deleteprinter_cmd();
274 char *command = NULL;
276 SE_PRIV se_printop = SE_PRINT_OPERATOR;
277 bool is_print_op = false;
279 /* can't fail if we don't try */
284 command = talloc_asprintf(ctx,
291 is_print_op = user_has_privileges( token, &se_printop );
293 DEBUG(10,("Running [%s]\n", command));
295 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
300 if ( (ret = smbrun(command, NULL)) == 0 ) {
301 /* Tell everyone we updated smb.conf. */
302 message_send_all(smbd_messaging_context(),
303 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
309 /********** END SePrintOperatorPrivlege BLOCK **********/
311 DEBUGADD(10,("returned [%d]\n", ret));
313 TALLOC_FREE(command);
316 return WERR_BADFID; /* What to return here? */
318 /* go ahead and re-read the services immediately */
320 reload_services(false);
323 if ( lp_servicenumber( sharename ) > 0 )
324 return WERR_ACCESS_DENIED;
329 /****************************************************************************
330 Delete a printer given a handle.
331 ****************************************************************************/
333 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
335 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
338 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
344 * It turns out that Windows allows delete printer on a handle
345 * opened by an admin user, then used on a pipe handle created
346 * by an anonymous user..... but they're working on security.... riiight !
350 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
351 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
352 return WERR_ACCESS_DENIED;
355 /* this does not need a become root since the access check has been
356 done on the handle already */
358 if (del_a_printer( Printer->sharename ) != 0) {
359 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
363 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
364 Printer->sharename );
367 /****************************************************************************
368 Return the snum of a printer corresponding to an handle.
369 ****************************************************************************/
371 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
372 int *number, struct share_params **params)
374 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
377 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
382 switch (Printer->printer_type) {
384 DEBUG(4,("short name:%s\n", Printer->sharename));
385 *number = print_queue_snum(Printer->sharename);
386 return (*number != -1);
394 /****************************************************************************
395 Set printer handle type.
396 Check if it's \\server or \\server\printer
397 ****************************************************************************/
399 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
401 DEBUG(3,("Setting printer type=%s\n", handlename));
403 if ( strlen(handlename) < 3 ) {
404 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
408 /* it's a print server */
409 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
410 DEBUGADD(4,("Printer is a print server\n"));
411 Printer->printer_type = SPLHND_SERVER;
413 /* it's a printer (set_printer_hnd_name() will handle port monitors */
415 DEBUGADD(4,("Printer is a printer\n"));
416 Printer->printer_type = SPLHND_PRINTER;
422 /****************************************************************************
423 Set printer handle name.. Accept names like \\server, \\server\printer,
424 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
425 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
426 XcvDataPort() interface.
427 ****************************************************************************/
429 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
432 int n_services=lp_numservices();
433 char *aprinter, *printername;
434 const char *servername;
437 NT_PRINTER_INFO_LEVEL *printer = NULL;
440 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
441 (unsigned long)strlen(handlename)));
443 aprinter = CONST_DISCARD(char *, handlename);
444 if ( *handlename == '\\' ) {
445 servername = canon_servername(handlename);
446 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
451 servername = global_myname();
454 /* save the servername to fill in replies on this handle */
456 if ( !is_myname_or_ipaddr( servername ) )
459 fstrcpy( Printer->servername, servername );
461 if ( Printer->printer_type == SPLHND_SERVER )
464 if ( Printer->printer_type != SPLHND_PRINTER )
467 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
469 /* check for the Port Monitor Interface */
471 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
472 Printer->printer_type = SPLHND_PORTMON_TCP;
473 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
476 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
477 Printer->printer_type = SPLHND_PORTMON_LOCAL;
478 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
482 /* Search all sharenames first as this is easier than pulling
483 the printer_info_2 off of disk. Don't use find_service() since
484 that calls out to map_username() */
486 /* do another loop to look for printernames */
488 for (snum=0; !found && snum<n_services; snum++) {
490 /* no point going on if this is not a printer */
492 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
495 fstrcpy(sname, lp_servicename(snum));
496 if ( strequal( aprinter, sname ) ) {
501 /* no point looking up the printer object if
502 we aren't allowing printername != sharename */
504 if ( lp_force_printername(snum) )
507 fstrcpy(sname, lp_servicename(snum));
511 /* This call doesn't fill in the location or comment from
512 * a CUPS server for efficiency with large numbers of printers.
516 result = get_a_printer_search( NULL, &printer, 2, sname );
517 if ( !W_ERROR_IS_OK(result) ) {
518 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
519 sname, win_errstr(result)));
523 /* printername is always returned as \\server\printername */
524 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
525 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
526 printer->info_2->printername));
527 free_a_printer( &printer, 2);
533 if ( strequal(printername, aprinter) ) {
534 free_a_printer( &printer, 2);
539 DEBUGADD(10, ("printername: %s\n", printername));
541 free_a_printer( &printer, 2);
544 free_a_printer( &printer, 2);
547 DEBUGADD(4,("Printer not found\n"));
551 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
553 fstrcpy(Printer->sharename, sname);
558 /****************************************************************************
559 Find first available printer slot. creates a printer handle for you.
560 ****************************************************************************/
562 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
563 const char *name, uint32_t access_granted)
565 Printer_entry *new_printer;
567 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
569 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
570 if (new_printer == NULL) {
573 talloc_set_destructor(new_printer, printer_entry_destructor);
575 if (!create_policy_hnd(p, hnd, new_printer)) {
576 TALLOC_FREE(new_printer);
580 /* Add to the internal list. */
581 DLIST_ADD(printers_list, new_printer);
583 new_printer->notify.option=NULL;
585 if (!set_printer_hnd_printertype(new_printer, name)) {
586 close_printer_handle(p, hnd);
590 if (!set_printer_hnd_name(new_printer, name)) {
591 close_printer_handle(p, hnd);
595 new_printer->access_granted = access_granted;
597 DEBUG(5, ("%d printer handles active\n",
598 (int)num_pipe_handles(p)));
603 /***************************************************************************
604 check to see if the client motify handle is monitoring the notification
605 given by (notify_type, notify_field).
606 **************************************************************************/
608 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
609 uint16_t notify_field)
614 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
615 uint16_t notify_field)
617 struct spoolss_NotifyOption *option = p->notify.option;
621 * Flags should always be zero when the change notify
622 * is registered by the client's spooler. A user Win32 app
623 * might use the flags though instead of the NOTIFY_OPTION_INFO
632 return is_monitoring_event_flags(
633 p->notify.flags, notify_type, notify_field);
635 for (i = 0; i < option->count; i++) {
637 /* Check match for notify_type */
639 if (option->types[i].type != notify_type)
642 /* Check match for field */
644 for (j = 0; j < option->types[i].count; j++) {
645 if (option->types[i].fields[j].field == notify_field) {
651 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
652 p->servername, p->sharename, notify_type, notify_field));
657 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
658 _data->data.integer[0] = _integer; \
659 _data->data.integer[1] = 0;
662 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
663 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
664 if (!_data->data.string.string) {\
665 _data->data.string.size = 0; \
667 _data->data.string.size = strlen_m_term(_p) * 2;
669 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
670 _data->data.devmode.devmode = _devmode;
672 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
673 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
674 if (!_data->data.sd.sd) { \
675 _data->data.sd.sd_size = 0; \
677 _data->data.sd.sd_size = _size;
679 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
684 struct spoolss_Time st;
688 if (!init_systemtime(&st, t)) {
692 p = talloc_array(mem_ctx, char, len);
698 * Systemtime must be linearized as a set of UINT16's.
699 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
702 SSVAL(p, 0, st.year);
703 SSVAL(p, 2, st.month);
704 SSVAL(p, 4, st.day_of_week);
706 SSVAL(p, 8, st.hour);
707 SSVAL(p, 10, st.minute);
708 SSVAL(p, 12, st.second);
709 SSVAL(p, 14, st.millisecond);
715 /* Convert a notification message to a struct spoolss_Notify */
717 static void notify_one_value(struct spoolss_notify_msg *msg,
718 struct spoolss_Notify *data,
721 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
724 static void notify_string(struct spoolss_notify_msg *msg,
725 struct spoolss_Notify *data,
728 /* The length of the message includes the trailing \0 */
730 data->data.string.size = msg->len * 2;
731 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
732 if (!data->data.string.string) {
733 data->data.string.size = 0;
738 static void notify_system_time(struct spoolss_notify_msg *msg,
739 struct spoolss_Notify *data,
742 data->data.string.string = NULL;
743 data->data.string.size = 0;
745 if (msg->len != sizeof(time_t)) {
746 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
751 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
752 &data->data.string.string,
753 &data->data.string.size);
756 struct notify2_message_table {
758 void (*fn)(struct spoolss_notify_msg *msg,
759 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
762 static struct notify2_message_table printer_notify_table[] = {
763 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
764 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
765 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
766 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
767 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
768 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
769 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
770 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
771 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
772 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
773 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
774 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
775 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
776 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
777 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
778 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
779 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
780 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
781 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
784 static struct notify2_message_table job_notify_table[] = {
785 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
786 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
787 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
788 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
789 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
790 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
791 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
792 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
793 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
794 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
795 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
796 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
797 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
798 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
799 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
800 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
801 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
802 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
803 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
804 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
805 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
806 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
807 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
808 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
812 /***********************************************************************
813 Allocate talloc context for container object
814 **********************************************************************/
816 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
821 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
826 /***********************************************************************
827 release all allocated memory and zero out structure
828 **********************************************************************/
830 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 talloc_destroy(ctr->ctx);
843 /***********************************************************************
844 **********************************************************************/
846 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
854 /***********************************************************************
855 **********************************************************************/
857 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
859 if ( !ctr || !ctr->msg_groups )
862 if ( idx >= ctr->num_groups )
865 return &ctr->msg_groups[idx];
869 /***********************************************************************
870 How many groups of change messages do we have ?
871 **********************************************************************/
873 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
878 return ctr->num_groups;
881 /***********************************************************************
882 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
883 **********************************************************************/
885 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
887 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
888 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
889 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
895 /* loop over all groups looking for a matching printer name */
897 for ( i=0; i<ctr->num_groups; i++ ) {
898 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
902 /* add a new group? */
904 if ( i == ctr->num_groups ) {
907 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
911 ctr->msg_groups = groups;
913 /* clear the new entry and set the printer name */
915 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
916 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
919 /* add the change messages; 'i' is the correct index now regardless */
921 msg_grp = &ctr->msg_groups[i];
925 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
926 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
929 msg_grp->msgs = msg_list;
931 new_slot = msg_grp->num_msgs-1;
932 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
934 /* need to allocate own copy of data */
937 msg_grp->msgs[new_slot].notify.data = (char *)
938 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
940 return ctr->num_groups;
943 void construct_info_data(struct spoolss_Notify *info_data,
944 enum spoolss_NotifyType type,
948 /***********************************************************************
949 Send a change notication message on all handles which have a call
951 **********************************************************************/
953 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
956 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
957 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
958 SPOOLSS_NOTIFY_MSG *messages;
959 int sending_msg_count;
962 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
966 messages = msg_group->msgs;
969 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
973 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
975 /* loop over all printers */
977 for (p = printers_list; p; p = p->next) {
978 struct spoolss_Notify *notifies;
983 /* Is there notification on this handle? */
985 if ( !p->notify.client_connected )
988 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
990 /* For this printer? Print servers always receive
993 if ( ( p->printer_type == SPLHND_PRINTER ) &&
994 ( !strequal(msg_group->printername, p->sharename) ) )
997 DEBUG(10,("Our printer\n"));
999 /* allocate the max entries possible */
1001 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1006 /* build the array of change notifications */
1008 sending_msg_count = 0;
1010 for ( i=0; i<msg_group->num_msgs; i++ ) {
1011 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1013 /* Are we monitoring this event? */
1015 if (!is_monitoring_event(p, msg->type, msg->field))
1018 sending_msg_count++;
1021 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1022 msg->type, msg->field, p->sharename));
1025 * if the is a printer notification handle and not a job notification
1026 * type, then set the id to 0. Other wise just use what was specified
1029 * When registering change notification on a print server handle
1030 * we always need to send back the id (snum) matching the printer
1031 * for which the change took place. For change notify registered
1032 * on a printer handle, this does not matter and the id should be 0.
1037 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1043 /* Convert unix jobid to smb jobid */
1045 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1046 id = sysjob_to_jobid(msg->id);
1049 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1054 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1057 case PRINTER_NOTIFY_TYPE:
1058 if ( printer_notify_table[msg->field].fn )
1059 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1062 case JOB_NOTIFY_TYPE:
1063 if ( job_notify_table[msg->field].fn )
1064 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1068 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1075 if ( sending_msg_count ) {
1078 union spoolss_ReplyPrinterInfo info;
1079 struct spoolss_NotifyInfo info0;
1080 uint32_t reply_result;
1082 info0.version = 0x2;
1083 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1084 info0.count = count;
1085 info0.notifies = notifies;
1087 info.info0 = &info0;
1089 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1090 &p->notify.client_hnd,
1091 p->notify.change, /* color */
1094 0, /* reply_type, must be 0 */
1097 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1098 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1099 notify_cli_pipe->srv_name_slash,
1102 switch (reply_result) {
1105 case PRINTER_NOTIFY_INFO_DISCARDED:
1106 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1107 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1116 DEBUG(8,("send_notify2_changes: Exit...\n"));
1120 /***********************************************************************
1121 **********************************************************************/
1123 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1126 uint32_t tv_sec, tv_usec;
1129 /* Unpack message */
1131 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1134 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1136 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1139 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1140 &msg->notify.value[0], &msg->notify.value[1]);
1142 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1143 &msg->len, &msg->notify.data);
1145 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1146 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1148 tv->tv_sec = tv_sec;
1149 tv->tv_usec = tv_usec;
1152 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1153 msg->notify.value[1]));
1155 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1160 /********************************************************************
1161 Receive a notify2 message list
1162 ********************************************************************/
1164 static void receive_notify2_message_list(struct messaging_context *msg,
1167 struct server_id server_id,
1170 size_t msg_count, i;
1171 char *buf = (char *)data->data;
1174 SPOOLSS_NOTIFY_MSG notify;
1175 SPOOLSS_NOTIFY_MSG_CTR messages;
1178 if (data->length < 4) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1183 msg_count = IVAL(buf, 0);
1186 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1188 if (msg_count == 0) {
1189 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1193 /* initialize the container */
1195 ZERO_STRUCT( messages );
1196 notify_msg_ctr_init( &messages );
1199 * build message groups for each printer identified
1200 * in a change_notify msg. Remember that a PCN message
1201 * includes the handle returned for the srv_spoolss_replyopenprinter()
1202 * call. Therefore messages are grouped according to printer handle.
1205 for ( i=0; i<msg_count; i++ ) {
1206 struct timeval msg_tv;
1208 if (msg_ptr + 4 - buf > data->length) {
1209 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1213 msg_len = IVAL(msg_ptr,0);
1216 if (msg_ptr + msg_len - buf > data->length) {
1217 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1221 /* unpack messages */
1223 ZERO_STRUCT( notify );
1224 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1227 /* add to correct list in container */
1229 notify_msg_ctr_addmsg( &messages, ¬ify );
1231 /* free memory that might have been allocated by notify2_unpack_msg() */
1233 if ( notify.len != 0 )
1234 SAFE_FREE( notify.notify.data );
1237 /* process each group of messages */
1239 num_groups = notify_msg_ctr_numgroups( &messages );
1240 for ( i=0; i<num_groups; i++ )
1241 send_notify2_changes( &messages, i );
1246 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1247 (uint32_t)msg_count ));
1249 notify_msg_ctr_destroy( &messages );
1254 /********************************************************************
1255 Send a message to ourself about new driver being installed
1256 so we can upgrade the information for each printer bound to this
1258 ********************************************************************/
1260 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1262 int len = strlen(drivername);
1267 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1270 messaging_send_buf(smbd_messaging_context(),
1271 messaging_server_id(smbd_messaging_context()),
1272 MSG_PRINTER_DRVUPGRADE,
1273 (uint8_t *)drivername, len+1);
1278 /**********************************************************************
1279 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1280 over all printers, upgrading ones as necessary
1281 **********************************************************************/
1283 void do_drv_upgrade_printer(struct messaging_context *msg,
1286 struct server_id server_id,
1291 int n_services = lp_numservices();
1294 len = MIN(data->length,sizeof(drivername)-1);
1295 strncpy(drivername, (const char *)data->data, len);
1297 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1299 /* Iterate the printer list */
1301 for (snum=0; snum<n_services; snum++)
1303 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1306 NT_PRINTER_INFO_LEVEL *printer = NULL;
1308 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1309 if (!W_ERROR_IS_OK(result))
1312 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1314 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1316 /* all we care about currently is the change_id */
1318 result = mod_a_printer(printer, 2);
1319 if (!W_ERROR_IS_OK(result)) {
1320 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1321 win_errstr(result)));
1325 free_a_printer(&printer, 2);
1332 /********************************************************************
1333 Update the cache for all printq's with a registered client
1335 ********************************************************************/
1337 void update_monitored_printq_cache( void )
1339 Printer_entry *printer = printers_list;
1342 /* loop through all printers and update the cache where
1343 client_connected == true */
1346 if ( (printer->printer_type == SPLHND_PRINTER)
1347 && printer->notify.client_connected )
1349 snum = print_queue_snum(printer->sharename);
1350 print_queue_status( snum, NULL, NULL );
1353 printer = printer->next;
1359 /****************************************************************
1360 _spoolss_OpenPrinter
1361 ****************************************************************/
1363 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1364 struct spoolss_OpenPrinter *r)
1366 struct spoolss_OpenPrinterEx e;
1369 ZERO_STRUCT(e.in.userlevel);
1371 e.in.printername = r->in.printername;
1372 e.in.datatype = r->in.datatype;
1373 e.in.devmode_ctr = r->in.devmode_ctr;
1374 e.in.access_mask = r->in.access_mask;
1377 e.out.handle = r->out.handle;
1379 werr = _spoolss_OpenPrinterEx(p, &e);
1381 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1382 /* OpenPrinterEx returns this for a bad
1383 * printer name. We must return WERR_INVALID_PRINTER_NAME
1386 werr = WERR_INVALID_PRINTER_NAME;
1392 /********************************************************************
1393 ********************************************************************/
1395 bool convert_devicemode(const char *printername,
1396 const struct spoolss_DeviceMode *devmode,
1397 NT_DEVICEMODE **pp_nt_devmode)
1399 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1402 * Ensure nt_devmode is a valid pointer
1403 * as we will be overwriting it.
1406 if (nt_devmode == NULL) {
1407 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1408 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1412 fstrcpy(nt_devmode->devicename, devmode->devicename);
1413 fstrcpy(nt_devmode->formname, devmode->formname);
1415 nt_devmode->devicename[31] = '\0';
1416 nt_devmode->formname[31] = '\0';
1418 nt_devmode->specversion = devmode->specversion;
1419 nt_devmode->driverversion = devmode->driverversion;
1420 nt_devmode->size = devmode->size;
1421 nt_devmode->fields = devmode->fields;
1422 nt_devmode->orientation = devmode->orientation;
1423 nt_devmode->papersize = devmode->papersize;
1424 nt_devmode->paperlength = devmode->paperlength;
1425 nt_devmode->paperwidth = devmode->paperwidth;
1426 nt_devmode->scale = devmode->scale;
1427 nt_devmode->copies = devmode->copies;
1428 nt_devmode->defaultsource = devmode->defaultsource;
1429 nt_devmode->printquality = devmode->printquality;
1430 nt_devmode->color = devmode->color;
1431 nt_devmode->duplex = devmode->duplex;
1432 nt_devmode->yresolution = devmode->yresolution;
1433 nt_devmode->ttoption = devmode->ttoption;
1434 nt_devmode->collate = devmode->collate;
1436 nt_devmode->logpixels = devmode->logpixels;
1437 nt_devmode->bitsperpel = devmode->bitsperpel;
1438 nt_devmode->pelswidth = devmode->pelswidth;
1439 nt_devmode->pelsheight = devmode->pelsheight;
1440 nt_devmode->displayflags = devmode->displayflags;
1441 nt_devmode->displayfrequency = devmode->displayfrequency;
1442 nt_devmode->icmmethod = devmode->icmmethod;
1443 nt_devmode->icmintent = devmode->icmintent;
1444 nt_devmode->mediatype = devmode->mediatype;
1445 nt_devmode->dithertype = devmode->dithertype;
1446 nt_devmode->reserved1 = devmode->reserved1;
1447 nt_devmode->reserved2 = devmode->reserved2;
1448 nt_devmode->panningwidth = devmode->panningwidth;
1449 nt_devmode->panningheight = devmode->panningheight;
1452 * Only change private and driverextra if the incoming devmode
1453 * has a new one. JRA.
1456 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1457 SAFE_FREE(nt_devmode->nt_dev_private);
1458 nt_devmode->driverextra = devmode->__driverextra_length;
1459 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1461 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1464 *pp_nt_devmode = nt_devmode;
1469 /****************************************************************
1470 _spoolss_OpenPrinterEx
1471 ****************************************************************/
1473 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1474 struct spoolss_OpenPrinterEx *r)
1477 Printer_entry *Printer=NULL;
1479 if (!r->in.printername) {
1480 return WERR_INVALID_PARAM;
1483 /* some sanity check because you can open a printer or a print server */
1484 /* aka: \\server\printer or \\server */
1486 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1488 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1489 ZERO_STRUCTP(r->out.handle);
1490 return WERR_INVALID_PARAM;
1493 Printer = find_printer_index_by_hnd(p, r->out.handle);
1495 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1496 "handle we created for printer %s\n", r->in.printername));
1497 close_printer_handle(p, r->out.handle);
1498 ZERO_STRUCTP(r->out.handle);
1499 return WERR_INVALID_PARAM;
1503 * First case: the user is opening the print server:
1505 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1506 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1508 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1509 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1510 * or if the user is listed in the smb.conf printer admin parameter.
1512 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1513 * client view printer folder, but does not show the MSAPW.
1515 * Note: this test needs code to check access rights here too. Jeremy
1516 * could you look at this?
1518 * Second case: the user is opening a printer:
1519 * NT doesn't let us connect to a printer if the connecting user
1520 * doesn't have print permission.
1522 * Third case: user is opening a Port Monitor
1523 * access checks same as opening a handle to the print server.
1526 switch (Printer->printer_type )
1529 case SPLHND_PORTMON_TCP:
1530 case SPLHND_PORTMON_LOCAL:
1531 /* Printserver handles use global struct... */
1535 /* Map standard access rights to object specific access rights */
1537 se_map_standard(&r->in.access_mask,
1538 &printserver_std_mapping);
1540 /* Deny any object specific bits that don't apply to print
1541 servers (i.e printer and job specific bits) */
1543 r->in.access_mask &= SEC_MASK_SPECIFIC;
1545 if (r->in.access_mask &
1546 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1547 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1548 close_printer_handle(p, r->out.handle);
1549 ZERO_STRUCTP(r->out.handle);
1550 return WERR_ACCESS_DENIED;
1553 /* Allow admin access */
1555 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1557 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1559 if (!lp_ms_add_printer_wizard()) {
1560 close_printer_handle(p, r->out.handle);
1561 ZERO_STRUCTP(r->out.handle);
1562 return WERR_ACCESS_DENIED;
1565 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1566 and not a printer admin, then fail */
1568 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1569 !user_has_privileges(p->server_info->ptok,
1571 !token_contains_name_in_list(
1572 uidtoname(p->server_info->utok.uid),
1573 p->server_info->info3->base.domain.string,
1575 p->server_info->ptok,
1576 lp_printer_admin(snum))) {
1577 close_printer_handle(p, r->out.handle);
1578 ZERO_STRUCTP(r->out.handle);
1579 return WERR_ACCESS_DENIED;
1582 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1586 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1589 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1590 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1592 /* We fall through to return WERR_OK */
1595 case SPLHND_PRINTER:
1596 /* NT doesn't let us connect to a printer if the connecting user
1597 doesn't have print permission. */
1599 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1600 close_printer_handle(p, r->out.handle);
1601 ZERO_STRUCTP(r->out.handle);
1605 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1606 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1609 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1611 /* map an empty access mask to the minimum access mask */
1612 if (r->in.access_mask == 0x0)
1613 r->in.access_mask = PRINTER_ACCESS_USE;
1616 * If we are not serving the printer driver for this printer,
1617 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1618 * will keep NT clients happy --jerry
1621 if (lp_use_client_driver(snum)
1622 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1624 r->in.access_mask = PRINTER_ACCESS_USE;
1627 /* check smb.conf parameters and the the sec_desc */
1629 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1630 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1631 ZERO_STRUCTP(r->out.handle);
1632 return WERR_ACCESS_DENIED;
1635 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1636 p->server_info->ptok, snum) ||
1637 !print_access_check(p->server_info, snum,
1638 r->in.access_mask)) {
1639 DEBUG(3, ("access DENIED for printer open\n"));
1640 close_printer_handle(p, r->out.handle);
1641 ZERO_STRUCTP(r->out.handle);
1642 return WERR_ACCESS_DENIED;
1645 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1646 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1647 close_printer_handle(p, r->out.handle);
1648 ZERO_STRUCTP(r->out.handle);
1649 return WERR_ACCESS_DENIED;
1652 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1653 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1655 r->in.access_mask = PRINTER_ACCESS_USE;
1657 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1658 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1663 /* sanity check to prevent programmer error */
1664 ZERO_STRUCTP(r->out.handle);
1668 Printer->access_granted = r->in.access_mask;
1671 * If the client sent a devmode in the OpenPrinter() call, then
1672 * save it here in case we get a job submission on this handle
1675 if ((Printer->printer_type != SPLHND_SERVER) &&
1676 r->in.devmode_ctr.devmode) {
1677 convert_devicemode(Printer->sharename,
1678 r->in.devmode_ctr.devmode,
1679 &Printer->nt_devmode);
1682 #if 0 /* JERRY -- I'm doubtful this is really effective */
1683 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1684 optimization in Windows 2000 clients --jerry */
1686 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1687 && (RA_WIN2K == get_remote_arch()) )
1689 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1690 sys_usleep( 500000 );
1697 /****************************************************************************
1698 ****************************************************************************/
1700 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1701 NT_PRINTER_INFO_LEVEL_2 *d)
1703 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1709 d->attributes = r->attributes;
1710 d->priority = r->priority;
1711 d->default_priority = r->defaultpriority;
1712 d->starttime = r->starttime;
1713 d->untiltime = r->untiltime;
1714 d->status = r->status;
1715 d->cjobs = r->cjobs;
1717 fstrcpy(d->servername, r->servername);
1718 fstrcpy(d->printername, r->printername);
1719 fstrcpy(d->sharename, r->sharename);
1720 fstrcpy(d->portname, r->portname);
1721 fstrcpy(d->drivername, r->drivername);
1722 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1723 fstrcpy(d->location, r->location);
1724 fstrcpy(d->sepfile, r->sepfile);
1725 fstrcpy(d->printprocessor, r->printprocessor);
1726 fstrcpy(d->datatype, r->datatype);
1727 fstrcpy(d->parameters, r->parameters);
1732 /****************************************************************************
1733 ****************************************************************************/
1735 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1736 NT_PRINTER_INFO_LEVEL *printer)
1740 switch (info_ctr->level) {
1742 /* allocate memory if needed. Messy because
1743 convert_printer_info is used to update an existing
1744 printer or build a new one */
1746 if (!printer->info_2) {
1747 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1748 if (!printer->info_2) {
1749 DEBUG(0,("convert_printer_info: "
1750 "talloc() failed!\n"));
1755 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1757 printer->info_2->setuptime = time(NULL);
1764 /****************************************************************
1765 _spoolss_ClosePrinter
1766 ****************************************************************/
1768 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1769 struct spoolss_ClosePrinter *r)
1771 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1773 if (Printer && Printer->document_started) {
1774 struct spoolss_EndDocPrinter e;
1776 e.in.handle = r->in.handle;
1778 _spoolss_EndDocPrinter(p, &e);
1781 if (!close_printer_handle(p, r->in.handle))
1784 /* clear the returned printer handle. Observed behavior
1785 from Win2k server. Don't think this really matters.
1786 Previous code just copied the value of the closed
1789 ZERO_STRUCTP(r->out.handle);
1794 /****************************************************************
1795 _spoolss_DeletePrinter
1796 ****************************************************************/
1798 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1799 struct spoolss_DeletePrinter *r)
1801 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1804 if (Printer && Printer->document_started) {
1805 struct spoolss_EndDocPrinter e;
1807 e.in.handle = r->in.handle;
1809 _spoolss_EndDocPrinter(p, &e);
1812 result = delete_printer_handle(p, r->in.handle);
1814 update_c_setprinter(false);
1819 /*******************************************************************
1820 * static function to lookup the version id corresponding to an
1821 * long architecture string
1822 ******************************************************************/
1824 static const struct print_architecture_table_node archi_table[]= {
1826 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1827 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1828 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1829 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1830 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1831 {"Windows IA64", SPL_ARCH_IA64, 3 },
1832 {"Windows x64", SPL_ARCH_X64, 3 },
1836 static int get_version_id(const char *arch)
1840 for (i=0; archi_table[i].long_archi != NULL; i++)
1842 if (strcmp(arch, archi_table[i].long_archi) == 0)
1843 return (archi_table[i].version);
1849 /****************************************************************
1850 _spoolss_DeletePrinterDriver
1851 ****************************************************************/
1853 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1854 struct spoolss_DeletePrinterDriver *r)
1857 struct spoolss_DriverInfo8 *info = NULL;
1858 struct spoolss_DriverInfo8 *info_win2k = NULL;
1861 WERROR status_win2k = WERR_ACCESS_DENIED;
1862 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1864 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1865 and not a printer admin, then fail */
1867 if ( (p->server_info->utok.uid != sec_initial_uid())
1868 && !user_has_privileges(p->server_info->ptok, &se_printop )
1869 && !token_contains_name_in_list(
1870 uidtoname(p->server_info->utok.uid),
1871 p->server_info->info3->base.domain.string,
1873 p->server_info->ptok,
1874 lp_printer_admin(-1)) )
1876 return WERR_ACCESS_DENIED;
1879 /* check that we have a valid driver name first */
1881 if ((version = get_version_id(r->in.architecture)) == -1)
1882 return WERR_INVALID_ENVIRONMENT;
1884 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1888 /* try for Win2k driver if "Windows NT x86" */
1890 if ( version == 2 ) {
1892 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1897 status = WERR_UNKNOWN_PRINTER_DRIVER;
1901 /* otherwise it was a failure */
1903 status = WERR_UNKNOWN_PRINTER_DRIVER;
1909 if (printer_driver_in_use(info)) {
1910 status = WERR_PRINTER_DRIVER_IN_USE;
1916 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1919 r->in.architecture, 3)))
1921 /* if we get to here, we now have 2 driver info structures to remove */
1922 /* remove the Win2k driver first*/
1924 status_win2k = delete_printer_driver(
1925 p, info_win2k, 3, false);
1926 free_a_printer_driver(info_win2k);
1928 /* this should not have failed---if it did, report to client */
1929 if ( !W_ERROR_IS_OK(status_win2k) )
1931 status = status_win2k;
1937 status = delete_printer_driver(p, info, version, false);
1939 /* if at least one of the deletes succeeded return OK */
1941 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1945 free_a_printer_driver(info);
1950 /****************************************************************
1951 _spoolss_DeletePrinterDriverEx
1952 ****************************************************************/
1954 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1955 struct spoolss_DeletePrinterDriverEx *r)
1957 struct spoolss_DriverInfo8 *info = NULL;
1958 struct spoolss_DriverInfo8 *info_win2k = NULL;
1962 WERROR status_win2k = WERR_ACCESS_DENIED;
1963 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1965 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1966 and not a printer admin, then fail */
1968 if ( (p->server_info->utok.uid != sec_initial_uid())
1969 && !user_has_privileges(p->server_info->ptok, &se_printop )
1970 && !token_contains_name_in_list(
1971 uidtoname(p->server_info->utok.uid),
1972 p->server_info->info3->base.domain.string,
1974 p->server_info->ptok, lp_printer_admin(-1)) )
1976 return WERR_ACCESS_DENIED;
1979 /* check that we have a valid driver name first */
1980 if ((version = get_version_id(r->in.architecture)) == -1) {
1981 /* this is what NT returns */
1982 return WERR_INVALID_ENVIRONMENT;
1985 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1986 version = r->in.version;
1988 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1989 r->in.architecture, version);
1991 if ( !W_ERROR_IS_OK(status) )
1994 * if the client asked for a specific version,
1995 * or this is something other than Windows NT x86,
1999 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2002 /* try for Win2k driver if "Windows NT x86" */
2005 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2008 status = WERR_UNKNOWN_PRINTER_DRIVER;
2013 if (printer_driver_in_use(info)) {
2014 status = WERR_PRINTER_DRIVER_IN_USE;
2019 * we have a couple of cases to consider.
2020 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2021 * then the delete should fail if **any** files overlap with
2023 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2024 * non-overlapping files
2025 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2026 * is set, the do not delete any files
2027 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2030 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2032 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2034 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2035 /* no idea of the correct error here */
2036 status = WERR_ACCESS_DENIED;
2041 /* also check for W32X86/3 if necessary; maybe we already have? */
2043 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2044 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2046 r->in.architecture, 3)))
2049 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2050 /* no idea of the correct error here */
2051 free_a_printer_driver(info_win2k);
2052 status = WERR_ACCESS_DENIED;
2056 /* if we get to here, we now have 2 driver info structures to remove */
2057 /* remove the Win2k driver first*/
2059 status_win2k = delete_printer_driver(
2060 p, info_win2k, 3, delete_files);
2061 free_a_printer_driver(info_win2k);
2063 /* this should not have failed---if it did, report to client */
2065 if ( !W_ERROR_IS_OK(status_win2k) )
2070 status = delete_printer_driver(p, info, version, delete_files);
2072 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2075 free_a_printer_driver(info);
2081 /****************************************************************************
2082 Internal routine for removing printerdata
2083 ***************************************************************************/
2085 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2087 return delete_printer_data( printer->info_2, key, value );
2090 /****************************************************************************
2091 Internal routine for storing printerdata
2092 ***************************************************************************/
2094 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2095 const char *key, const char *value,
2096 uint32_t type, uint8_t *data, int real_len)
2098 /* the registry objects enforce uniqueness based on value name */
2100 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2103 /********************************************************************
2104 GetPrinterData on a printer server Handle.
2105 ********************************************************************/
2107 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2109 enum winreg_Type *type,
2110 union spoolss_PrinterData *data)
2112 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2114 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2120 if (!StrCaseCmp(value, "BeepEnabled")) {
2126 if (!StrCaseCmp(value, "EventLog")) {
2128 /* formally was 0x1b */
2133 if (!StrCaseCmp(value, "NetPopup")) {
2139 if (!StrCaseCmp(value, "MajorVersion")) {
2142 /* Windows NT 4.0 seems to not allow uploading of drivers
2143 to a server that reports 0x3 as the MajorVersion.
2144 need to investigate more how Win2k gets around this .
2147 if (RA_WINNT == get_remote_arch()) {
2156 if (!StrCaseCmp(value, "MinorVersion")) {
2163 * uint32_t size = 0x114
2164 * uint32_t major = 5
2165 * uint32_t minor = [0|1]
2166 * uint32_t build = [2195|2600]
2167 * extra unicode string = e.g. "Service Pack 3"
2169 if (!StrCaseCmp(value, "OSVersion")) {
2171 enum ndr_err_code ndr_err;
2172 struct spoolss_OSVersion os;
2174 os.major = 5; /* Windows 2000 == 5.0 */
2176 os.build = 2195; /* build */
2177 os.extra_string = ""; /* leave extra string empty */
2179 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2180 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2181 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2182 return WERR_GENERAL_FAILURE;
2186 data->binary = blob;
2192 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2195 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2196 W_ERROR_HAVE_NO_MEMORY(data->string);
2201 if (!StrCaseCmp(value, "Architecture")) {
2203 data->string = talloc_strdup(mem_ctx,
2204 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2205 W_ERROR_HAVE_NO_MEMORY(data->string);
2210 if (!StrCaseCmp(value, "DsPresent")) {
2213 /* only show the publish check box if we are a
2214 member of a AD domain */
2216 if (lp_security() == SEC_ADS) {
2224 if (!StrCaseCmp(value, "DNSMachineName")) {
2225 const char *hostname = get_mydnsfullname();
2228 return WERR_BADFILE;
2232 data->string = talloc_strdup(mem_ctx, hostname);
2233 W_ERROR_HAVE_NO_MEMORY(data->string);
2240 return WERR_INVALID_PARAM;
2243 /****************************************************************
2244 _spoolss_GetPrinterData
2245 ****************************************************************/
2247 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2248 struct spoolss_GetPrinterData *r)
2250 struct spoolss_GetPrinterDataEx r2;
2252 r2.in.handle = r->in.handle;
2253 r2.in.key_name = "PrinterDriverData";
2254 r2.in.value_name = r->in.value_name;
2255 r2.in.offered = r->in.offered;
2256 r2.out.type = r->out.type;
2257 r2.out.data = r->out.data;
2258 r2.out.needed = r->out.needed;
2260 return _spoolss_GetPrinterDataEx(p, &r2);
2263 /*********************************************************
2264 Connect to the client machine.
2265 **********************************************************/
2267 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2268 struct sockaddr_storage *client_ss, const char *remote_machine)
2271 struct cli_state *the_cli;
2272 struct sockaddr_storage rm_addr;
2273 char addr[INET6_ADDRSTRLEN];
2275 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2276 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2278 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2279 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2282 print_sockaddr(addr, sizeof(addr), &rm_addr);
2284 rm_addr = *client_ss;
2285 print_sockaddr(addr, sizeof(addr), &rm_addr);
2286 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2290 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2291 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2296 /* setup the connection */
2297 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2298 &rm_addr, 0, "IPC$", "IPC",
2302 0, lp_client_signing(), NULL );
2304 if ( !NT_STATUS_IS_OK( ret ) ) {
2305 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2310 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2311 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2312 cli_shutdown(the_cli);
2317 * Ok - we have an anonymous connection to the IPC$ share.
2318 * Now start the NT Domain stuff :-).
2321 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2322 if (!NT_STATUS_IS_OK(ret)) {
2323 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2324 remote_machine, nt_errstr(ret)));
2325 cli_shutdown(the_cli);
2332 /***************************************************************************
2333 Connect to the client.
2334 ****************************************************************************/
2336 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2337 uint32_t localprinter, uint32_t type,
2338 struct policy_handle *handle,
2339 struct sockaddr_storage *client_ss)
2345 * If it's the first connection, contact the client
2346 * and connect to the IPC$ share anonymously
2348 if (smb_connections==0) {
2349 fstring unix_printer;
2351 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2353 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2356 messaging_register(smbd_messaging_context(), NULL,
2357 MSG_PRINTER_NOTIFY2,
2358 receive_notify2_message_list);
2359 /* Tell the connections db we're now interested in printer
2360 * notify messages. */
2361 serverid_register_msg_flags(
2362 messaging_server_id(smbd_messaging_context()),
2363 true, FLAG_MSG_PRINT_NOTIFY);
2367 * Tell the specific printing tdb we want messages for this printer
2368 * by registering our PID.
2371 if (!print_notify_register_pid(snum))
2372 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2376 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2384 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2385 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2386 win_errstr(result)));
2388 return (W_ERROR_IS_OK(result));
2391 /****************************************************************
2392 ****************************************************************/
2394 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2395 const struct spoolss_NotifyOption *r)
2397 struct spoolss_NotifyOption *option;
2404 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2411 if (!option->count) {
2415 option->types = talloc_zero_array(option,
2416 struct spoolss_NotifyOptionType, option->count);
2417 if (!option->types) {
2418 talloc_free(option);
2422 for (i=0; i < option->count; i++) {
2423 option->types[i] = r->types[i];
2425 if (option->types[i].count) {
2426 option->types[i].fields = talloc_zero_array(option,
2427 union spoolss_Field, option->types[i].count);
2428 if (!option->types[i].fields) {
2429 talloc_free(option);
2432 for (k=0; k<option->types[i].count; k++) {
2433 option->types[i].fields[k] =
2434 r->types[i].fields[k];
2442 /****************************************************************
2443 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2445 * before replying OK: status=0 a rpc call is made to the workstation
2446 * asking ReplyOpenPrinter
2448 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2449 * called from api_spoolss_rffpcnex
2450 ****************************************************************/
2452 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2453 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2456 struct spoolss_NotifyOption *option = r->in.notify_options;
2457 struct sockaddr_storage client_ss;
2459 /* store the notify value in the printer struct */
2461 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2464 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2465 "Invalid handle (%s:%u:%u).\n",
2466 OUR_HANDLE(r->in.handle)));
2470 Printer->notify.flags = r->in.flags;
2471 Printer->notify.options = r->in.options;
2472 Printer->notify.printerlocal = r->in.printer_local;
2474 TALLOC_FREE(Printer->notify.option);
2475 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2477 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2479 /* Connect to the client machine and send a ReplyOpenPrinter */
2481 if ( Printer->printer_type == SPLHND_SERVER)
2483 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2484 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2487 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2488 "client_address is %s\n", p->client_address));
2490 if (!interpret_string_addr(&client_ss, p->client_address,
2492 return WERR_SERVER_UNAVAILABLE;
2495 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2496 Printer->notify.printerlocal, 1,
2497 &Printer->notify.client_hnd, &client_ss))
2498 return WERR_SERVER_UNAVAILABLE;
2500 Printer->notify.client_connected = true;
2505 /*******************************************************************
2506 * fill a notify_info_data with the servername
2507 ********************************************************************/
2509 static void spoolss_notify_server_name(int snum,
2510 struct spoolss_Notify *data,
2511 print_queue_struct *queue,
2512 NT_PRINTER_INFO_LEVEL *printer,
2513 TALLOC_CTX *mem_ctx)
2515 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2518 /*******************************************************************
2519 * fill a notify_info_data with the printername (not including the servername).
2520 ********************************************************************/
2522 static void spoolss_notify_printer_name(int snum,
2523 struct spoolss_Notify *data,
2524 print_queue_struct *queue,
2525 NT_PRINTER_INFO_LEVEL *printer,
2526 TALLOC_CTX *mem_ctx)
2528 /* the notify name should not contain the \\server\ part */
2529 char *p = strrchr(printer->info_2->printername, '\\');
2532 p = printer->info_2->printername;
2537 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2540 /*******************************************************************
2541 * fill a notify_info_data with the servicename
2542 ********************************************************************/
2544 static void spoolss_notify_share_name(int snum,
2545 struct spoolss_Notify *data,
2546 print_queue_struct *queue,
2547 NT_PRINTER_INFO_LEVEL *printer,
2548 TALLOC_CTX *mem_ctx)
2550 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2553 /*******************************************************************
2554 * fill a notify_info_data with the port name
2555 ********************************************************************/
2557 static void spoolss_notify_port_name(int snum,
2558 struct spoolss_Notify *data,
2559 print_queue_struct *queue,
2560 NT_PRINTER_INFO_LEVEL *printer,
2561 TALLOC_CTX *mem_ctx)
2563 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2566 /*******************************************************************
2567 * fill a notify_info_data with the printername
2568 * but it doesn't exist, have to see what to do
2569 ********************************************************************/
2571 static void spoolss_notify_driver_name(int snum,
2572 struct spoolss_Notify *data,
2573 print_queue_struct *queue,
2574 NT_PRINTER_INFO_LEVEL *printer,
2575 TALLOC_CTX *mem_ctx)
2577 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2580 /*******************************************************************
2581 * fill a notify_info_data with the comment
2582 ********************************************************************/
2584 static void spoolss_notify_comment(int snum,
2585 struct spoolss_Notify *data,
2586 print_queue_struct *queue,
2587 NT_PRINTER_INFO_LEVEL *printer,
2588 TALLOC_CTX *mem_ctx)
2592 if (*printer->info_2->comment == '\0') {
2593 p = lp_comment(snum);
2595 p = printer->info_2->comment;
2598 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2601 /*******************************************************************
2602 * fill a notify_info_data with the comment
2603 * location = "Room 1, floor 2, building 3"
2604 ********************************************************************/
2606 static void spoolss_notify_location(int snum,
2607 struct spoolss_Notify *data,
2608 print_queue_struct *queue,
2609 NT_PRINTER_INFO_LEVEL *printer,
2610 TALLOC_CTX *mem_ctx)
2612 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2615 /*******************************************************************
2616 * fill a notify_info_data with the device mode
2617 * jfm:xxxx don't to it for know but that's a real problem !!!
2618 ********************************************************************/
2620 static void spoolss_notify_devmode(int snum,
2621 struct spoolss_Notify *data,
2622 print_queue_struct *queue,
2623 NT_PRINTER_INFO_LEVEL *printer,
2624 TALLOC_CTX *mem_ctx)
2626 /* for a dummy implementation we have to zero the fields */
2627 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2630 /*******************************************************************
2631 * fill a notify_info_data with the separator file name
2632 ********************************************************************/
2634 static void spoolss_notify_sepfile(int snum,
2635 struct spoolss_Notify *data,
2636 print_queue_struct *queue,
2637 NT_PRINTER_INFO_LEVEL *printer,
2638 TALLOC_CTX *mem_ctx)
2640 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2643 /*******************************************************************
2644 * fill a notify_info_data with the print processor
2645 * jfm:xxxx return always winprint to indicate we don't do anything to it
2646 ********************************************************************/
2648 static void spoolss_notify_print_processor(int snum,
2649 struct spoolss_Notify *data,
2650 print_queue_struct *queue,
2651 NT_PRINTER_INFO_LEVEL *printer,
2652 TALLOC_CTX *mem_ctx)
2654 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2657 /*******************************************************************
2658 * fill a notify_info_data with the print processor options
2659 * jfm:xxxx send an empty string
2660 ********************************************************************/
2662 static void spoolss_notify_parameters(int snum,
2663 struct spoolss_Notify *data,
2664 print_queue_struct *queue,
2665 NT_PRINTER_INFO_LEVEL *printer,
2666 TALLOC_CTX *mem_ctx)
2668 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2671 /*******************************************************************
2672 * fill a notify_info_data with the data type
2673 * jfm:xxxx always send RAW as data type
2674 ********************************************************************/
2676 static void spoolss_notify_datatype(int snum,
2677 struct spoolss_Notify *data,
2678 print_queue_struct *queue,
2679 NT_PRINTER_INFO_LEVEL *printer,
2680 TALLOC_CTX *mem_ctx)
2682 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2685 /*******************************************************************
2686 * fill a notify_info_data with the security descriptor
2687 * jfm:xxxx send an null pointer to say no security desc
2688 * have to implement security before !
2689 ********************************************************************/
2691 static void spoolss_notify_security_desc(int snum,
2692 struct spoolss_Notify *data,
2693 print_queue_struct *queue,
2694 NT_PRINTER_INFO_LEVEL *printer,
2695 TALLOC_CTX *mem_ctx)
2697 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2698 printer->info_2->secdesc_buf->sd_size,
2699 printer->info_2->secdesc_buf->sd);
2702 /*******************************************************************
2703 * fill a notify_info_data with the attributes
2704 * jfm:xxxx a samba printer is always shared
2705 ********************************************************************/
2707 static void spoolss_notify_attributes(int snum,
2708 struct spoolss_Notify *data,
2709 print_queue_struct *queue,
2710 NT_PRINTER_INFO_LEVEL *printer,
2711 TALLOC_CTX *mem_ctx)
2713 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2716 /*******************************************************************
2717 * fill a notify_info_data with the priority
2718 ********************************************************************/
2720 static void spoolss_notify_priority(int snum,
2721 struct spoolss_Notify *data,
2722 print_queue_struct *queue,
2723 NT_PRINTER_INFO_LEVEL *printer,
2724 TALLOC_CTX *mem_ctx)
2726 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2729 /*******************************************************************
2730 * fill a notify_info_data with the default priority
2731 ********************************************************************/
2733 static void spoolss_notify_default_priority(int snum,
2734 struct spoolss_Notify *data,
2735 print_queue_struct *queue,
2736 NT_PRINTER_INFO_LEVEL *printer,
2737 TALLOC_CTX *mem_ctx)
2739 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2742 /*******************************************************************
2743 * fill a notify_info_data with the start time
2744 ********************************************************************/
2746 static void spoolss_notify_start_time(int snum,
2747 struct spoolss_Notify *data,
2748 print_queue_struct *queue,
2749 NT_PRINTER_INFO_LEVEL *printer,
2750 TALLOC_CTX *mem_ctx)
2752 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2755 /*******************************************************************
2756 * fill a notify_info_data with the until time
2757 ********************************************************************/
2759 static void spoolss_notify_until_time(int snum,
2760 struct spoolss_Notify *data,
2761 print_queue_struct *queue,
2762 NT_PRINTER_INFO_LEVEL *printer,
2763 TALLOC_CTX *mem_ctx)
2765 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2768 /*******************************************************************
2769 * fill a notify_info_data with the status
2770 ********************************************************************/
2772 static void spoolss_notify_status(int snum,
2773 struct spoolss_Notify *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2778 print_status_struct status;
2780 print_queue_length(snum, &status);
2781 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2784 /*******************************************************************
2785 * fill a notify_info_data with the number of jobs queued
2786 ********************************************************************/
2788 static void spoolss_notify_cjobs(int snum,
2789 struct spoolss_Notify *data,
2790 print_queue_struct *queue,
2791 NT_PRINTER_INFO_LEVEL *printer,
2792 TALLOC_CTX *mem_ctx)
2794 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2797 /*******************************************************************
2798 * fill a notify_info_data with the average ppm
2799 ********************************************************************/
2801 static void spoolss_notify_average_ppm(int snum,
2802 struct spoolss_Notify *data,
2803 print_queue_struct *queue,
2804 NT_PRINTER_INFO_LEVEL *printer,
2805 TALLOC_CTX *mem_ctx)
2807 /* always respond 8 pages per minutes */
2808 /* a little hard ! */
2809 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2812 /*******************************************************************
2813 * fill a notify_info_data with username
2814 ********************************************************************/
2816 static void spoolss_notify_username(int snum,
2817 struct spoolss_Notify *data,
2818 print_queue_struct *queue,
2819 NT_PRINTER_INFO_LEVEL *printer,
2820 TALLOC_CTX *mem_ctx)
2822 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2825 /*******************************************************************
2826 * fill a notify_info_data with job status
2827 ********************************************************************/
2829 static void spoolss_notify_job_status(int snum,
2830 struct spoolss_Notify *data,
2831 print_queue_struct *queue,
2832 NT_PRINTER_INFO_LEVEL *printer,
2833 TALLOC_CTX *mem_ctx)
2835 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2838 /*******************************************************************
2839 * fill a notify_info_data with job name
2840 ********************************************************************/
2842 static void spoolss_notify_job_name(int snum,
2843 struct spoolss_Notify *data,
2844 print_queue_struct *queue,
2845 NT_PRINTER_INFO_LEVEL *printer,
2846 TALLOC_CTX *mem_ctx)
2848 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2851 /*******************************************************************
2852 * fill a notify_info_data with job status
2853 ********************************************************************/
2855 static void spoolss_notify_job_status_string(int snum,
2856 struct spoolss_Notify *data,
2857 print_queue_struct *queue,
2858 NT_PRINTER_INFO_LEVEL *printer,
2859 TALLOC_CTX *mem_ctx)
2862 * Now we're returning job status codes we just return a "" here. JRA.
2867 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2870 switch (queue->status) {
2875 p = ""; /* NT provides the paused string */
2884 #endif /* NO LONGER NEEDED. */
2886 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2889 /*******************************************************************
2890 * fill a notify_info_data with job time
2891 ********************************************************************/
2893 static void spoolss_notify_job_time(int snum,
2894 struct spoolss_Notify *data,
2895 print_queue_struct *queue,
2896 NT_PRINTER_INFO_LEVEL *printer,
2897 TALLOC_CTX *mem_ctx)
2899 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2902 /*******************************************************************
2903 * fill a notify_info_data with job size
2904 ********************************************************************/
2906 static void spoolss_notify_job_size(int snum,
2907 struct spoolss_Notify *data,
2908 print_queue_struct *queue,
2909 NT_PRINTER_INFO_LEVEL *printer,
2910 TALLOC_CTX *mem_ctx)
2912 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2915 /*******************************************************************
2916 * fill a notify_info_data with page info
2917 ********************************************************************/
2918 static void spoolss_notify_total_pages(int snum,
2919 struct spoolss_Notify *data,
2920 print_queue_struct *queue,
2921 NT_PRINTER_INFO_LEVEL *printer,
2922 TALLOC_CTX *mem_ctx)
2924 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2927 /*******************************************************************
2928 * fill a notify_info_data with pages printed info.
2929 ********************************************************************/
2930 static void spoolss_notify_pages_printed(int snum,
2931 struct spoolss_Notify *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2936 /* Add code when back-end tracks this */
2937 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2940 /*******************************************************************
2941 Fill a notify_info_data with job position.
2942 ********************************************************************/
2944 static void spoolss_notify_job_position(int snum,
2945 struct spoolss_Notify *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2950 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2953 /*******************************************************************
2954 Fill a notify_info_data with submitted time.
2955 ********************************************************************/
2957 static void spoolss_notify_submitted_time(int snum,
2958 struct spoolss_Notify *data,
2959 print_queue_struct *queue,
2960 NT_PRINTER_INFO_LEVEL *printer,
2961 TALLOC_CTX *mem_ctx)
2963 data->data.string.string = NULL;
2964 data->data.string.size = 0;
2966 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2967 &data->data.string.string,
2968 &data->data.string.size);
2972 struct s_notify_info_data_table
2974 enum spoolss_NotifyType type;
2977 enum spoolss_NotifyTable variable_type;
2978 void (*fn) (int snum, struct spoolss_Notify *data,
2979 print_queue_struct *queue,
2980 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2983 /* A table describing the various print notification constants and
2984 whether the notification data is a pointer to a variable sized
2985 buffer, a one value uint32_t or a two value uint32_t. */
2987 static const struct s_notify_info_data_table notify_info_data_table[] =
2989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3003 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3004 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3005 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3006 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3007 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3008 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3009 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3010 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3011 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3012 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3013 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3014 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3015 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3016 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3017 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3018 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3019 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3020 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3021 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3022 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3023 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3024 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3025 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3026 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3027 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3028 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3029 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3030 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3031 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3032 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3033 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3034 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3035 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3036 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3037 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3040 /*******************************************************************
3041 Return the variable_type of info_data structure.
3042 ********************************************************************/
3044 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3049 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3050 if ( (notify_info_data_table[i].type == type) &&
3051 (notify_info_data_table[i].field == field) ) {
3052 return notify_info_data_table[i].variable_type;
3056 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3061 /****************************************************************************
3062 ****************************************************************************/
3064 static bool search_notify(enum spoolss_NotifyType type,
3070 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3071 if (notify_info_data_table[i].type == type &&
3072 notify_info_data_table[i].field == field &&
3073 notify_info_data_table[i].fn != NULL) {
3082 /****************************************************************************
3083 ****************************************************************************/
3085 void construct_info_data(struct spoolss_Notify *info_data,
3086 enum spoolss_NotifyType type,
3090 info_data->type = type;
3091 info_data->field.field = field;
3092 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3093 info_data->job_id = id;
3096 /*******************************************************************
3098 * fill a notify_info struct with info asked
3100 ********************************************************************/
3102 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3103 struct spoolss_NotifyInfo *info,
3105 const struct spoolss_NotifyOptionType *option_type,
3107 TALLOC_CTX *mem_ctx)
3110 enum spoolss_NotifyType type;
3113 struct spoolss_Notify *current_data;
3114 NT_PRINTER_INFO_LEVEL *printer = NULL;
3115 print_queue_struct *queue=NULL;
3117 type = option_type->type;
3119 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3120 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3121 option_type->count, lp_servicename(snum)));
3123 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3126 for(field_num=0; field_num < option_type->count; field_num++) {
3127 field = option_type->fields[field_num].field;
3129 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3131 if (!search_notify(type, field, &j) )
3134 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3135 struct spoolss_Notify,
3137 if (info->notifies == NULL) {
3138 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3139 free_a_printer(&printer, 2);
3143 current_data = &info->notifies[info->count];
3145 construct_info_data(current_data, type, field, id);
3147 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3148 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3150 notify_info_data_table[j].fn(snum, current_data, queue,
3156 free_a_printer(&printer, 2);
3160 /*******************************************************************
3162 * fill a notify_info struct with info asked
3164 ********************************************************************/
3166 static bool construct_notify_jobs_info(print_queue_struct *queue,
3167 struct spoolss_NotifyInfo *info,
3168 NT_PRINTER_INFO_LEVEL *printer,
3170 const struct spoolss_NotifyOptionType *option_type,
3172 TALLOC_CTX *mem_ctx)
3175 enum spoolss_NotifyType type;
3177 struct spoolss_Notify *current_data;
3179 DEBUG(4,("construct_notify_jobs_info\n"));
3181 type = option_type->type;
3183 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3184 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3185 option_type->count));
3187 for(field_num=0; field_num<option_type->count; field_num++) {
3188 field = option_type->fields[field_num].field;
3190 if (!search_notify(type, field, &j) )
3193 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3194 struct spoolss_Notify,
3196 if (info->notifies == NULL) {
3197 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3201 current_data=&(info->notifies[info->count]);
3203 construct_info_data(current_data, type, field, id);
3204 notify_info_data_table[j].fn(snum, current_data, queue,
3213 * JFM: The enumeration is not that simple, it's even non obvious.
3215 * let's take an example: I want to monitor the PRINTER SERVER for
3216 * the printer's name and the number of jobs currently queued.
3217 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3218 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3220 * I have 3 printers on the back of my server.
3222 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3225 * 1 printer 1 name 1
3226 * 2 printer 1 cjob 1
3227 * 3 printer 2 name 2
3228 * 4 printer 2 cjob 2
3229 * 5 printer 3 name 3
3230 * 6 printer 3 name 3
3232 * that's the print server case, the printer case is even worse.
3235 /*******************************************************************
3237 * enumerate all printers on the printserver
3238 * fill a notify_info struct with info asked
3240 ********************************************************************/
3242 static WERROR printserver_notify_info(pipes_struct *p,
3243 struct policy_handle *hnd,
3244 struct spoolss_NotifyInfo *info,
3245 TALLOC_CTX *mem_ctx)
3248 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3249 int n_services=lp_numservices();
3251 struct spoolss_NotifyOption *option;
3252 struct spoolss_NotifyOptionType option_type;
3254 DEBUG(4,("printserver_notify_info\n"));
3259 option = Printer->notify.option;
3262 info->notifies = NULL;
3265 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3266 sending a ffpcn() request first */
3271 for (i=0; i<option->count; i++) {
3272 option_type = option->types[i];
3274 if (option_type.type != PRINTER_NOTIFY_TYPE)
3277 for (snum=0; snum<n_services; snum++)
3279 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3280 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3286 * Debugging information, don't delete.
3289 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3290 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3291 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3293 for (i=0; i<info->count; i++) {
3294 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3295 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3296 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3303 /*******************************************************************
3305 * fill a notify_info struct with info asked
3307 ********************************************************************/
3309 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3310 struct spoolss_NotifyInfo *info,
3311 TALLOC_CTX *mem_ctx)
3314 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3317 struct spoolss_NotifyOption *option;
3318 struct spoolss_NotifyOptionType option_type;
3320 print_queue_struct *queue=NULL;
3321 print_status_struct status;
3323 DEBUG(4,("printer_notify_info\n"));
3328 option = Printer->notify.option;
3332 info->notifies = NULL;
3335 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3336 sending a ffpcn() request first */
3341 get_printer_snum(p, hnd, &snum, NULL);
3343 for (i=0; i<option->count; i++) {
3344 option_type = option->types[i];
3346 switch (option_type.type) {
3347 case PRINTER_NOTIFY_TYPE:
3348 if(construct_notify_printer_info(Printer, info, snum,
3354 case JOB_NOTIFY_TYPE: {
3355 NT_PRINTER_INFO_LEVEL *printer = NULL;
3357 count = print_queue_status(snum, &queue, &status);
3359 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3362 for (j=0; j<count; j++) {
3363 construct_notify_jobs_info(&queue[j], info,
3370 free_a_printer(&printer, 2);
3380 * Debugging information, don't delete.
3383 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3384 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3385 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3387 for (i=0; i<info->count; i++) {
3388 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3389 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3390 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3396 /****************************************************************
3397 _spoolss_RouterRefreshPrinterChangeNotify
3398 ****************************************************************/
3400 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3401 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3403 struct spoolss_NotifyInfo *info;
3405 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3406 WERROR result = WERR_BADFID;
3408 /* we always have a spoolss_NotifyInfo struct */
3409 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3411 result = WERR_NOMEM;
3415 *r->out.info = info;
3418 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3419 "Invalid handle (%s:%u:%u).\n",
3420 OUR_HANDLE(r->in.handle)));
3424 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3427 * We are now using the change value, and
3428 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3429 * I don't have a global notification system, I'm sending back all the
3430 * informations even when _NOTHING_ has changed.
3433 /* We need to keep track of the change value to send back in
3434 RRPCN replies otherwise our updates are ignored. */
3436 Printer->notify.fnpcn = true;
3438 if (Printer->notify.client_connected) {
3439 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3440 "Saving change value in request [%x]\n",
3442 Printer->notify.change = r->in.change_low;
3445 /* just ignore the spoolss_NotifyOption */
3447 switch (Printer->printer_type) {
3449 result = printserver_notify_info(p, r->in.handle,
3453 case SPLHND_PRINTER:
3454 result = printer_notify_info(p, r->in.handle,
3459 Printer->notify.fnpcn = false;
3465 /********************************************************************
3466 * construct_printer_info_0
3467 * fill a printer_info_0 struct
3468 ********************************************************************/
3470 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3471 const NT_PRINTER_INFO_LEVEL *ntprinter,
3472 struct spoolss_PrinterInfo0 *r,
3476 counter_printer_0 *session_counter;
3478 print_status_struct status;
3480 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3481 W_ERROR_HAVE_NO_MEMORY(r->printername);
3483 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3484 W_ERROR_HAVE_NO_MEMORY(r->servername);
3486 count = print_queue_length(snum, &status);
3488 /* check if we already have a counter for this printer */
3489 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3490 if (session_counter->snum == snum)
3494 /* it's the first time, add it to the list */
3495 if (session_counter == NULL) {
3496 session_counter = SMB_MALLOC_P(counter_printer_0);
3497 W_ERROR_HAVE_NO_MEMORY(session_counter);
3498 ZERO_STRUCTP(session_counter);
3499 session_counter->snum = snum;
3500 session_counter->counter = 0;
3501 DLIST_ADD(counter_list, session_counter);
3505 session_counter->counter++;
3511 setuptime = (time_t)ntprinter->info_2->setuptime;
3513 init_systemtime(&r->time, gmtime(&setuptime));
3516 * the global_counter should be stored in a TDB as it's common to all the clients
3517 * and should be zeroed on samba startup
3519 r->global_counter = session_counter->counter;
3521 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3522 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3523 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3524 r->free_build = SPOOLSS_RELEASE_BUILD;
3526 r->max_spooling = 0;
3527 r->session_counter = session_counter->counter;
3528 r->num_error_out_of_paper = 0x0;
3529 r->num_error_not_ready = 0x0; /* number of print failure */
3531 r->number_of_processors = 0x1;
3532 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3533 r->high_part_total_bytes = 0x0;
3534 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3535 r->last_error = WERR_OK;
3536 r->status = nt_printq_status(status.status);
3537 r->enumerate_network_printers = 0x0;
3538 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3539 r->processor_architecture = 0x0;
3540 r->processor_level = 0x6; /* 6 ???*/
3548 /****************************************************************************
3549 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3550 should be valid upon entry
3551 ****************************************************************************/
3553 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3554 struct spoolss_DeviceMode *r,
3555 const NT_DEVICEMODE *ntdevmode)
3557 if (!r || !ntdevmode) {
3558 return WERR_INVALID_PARAM;
3561 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3562 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3564 r->specversion = ntdevmode->specversion;
3565 r->driverversion = ntdevmode->driverversion;
3566 r->size = ntdevmode->size;
3567 r->__driverextra_length = ntdevmode->driverextra;
3568 r->fields = ntdevmode->fields;
3570 r->orientation = ntdevmode->orientation;
3571 r->papersize = ntdevmode->papersize;
3572 r->paperlength = ntdevmode->paperlength;
3573 r->paperwidth = ntdevmode->paperwidth;
3574 r->scale = ntdevmode->scale;
3575 r->copies = ntdevmode->copies;
3576 r->defaultsource = ntdevmode->defaultsource;
3577 r->printquality = ntdevmode->printquality;
3578 r->color = ntdevmode->color;
3579 r->duplex = ntdevmode->duplex;
3580 r->yresolution = ntdevmode->yresolution;
3581 r->ttoption = ntdevmode->ttoption;
3582 r->collate = ntdevmode->collate;
3584 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3585 W_ERROR_HAVE_NO_MEMORY(r->formname);
3587 r->logpixels = ntdevmode->logpixels;
3588 r->bitsperpel = ntdevmode->bitsperpel;
3589 r->pelswidth = ntdevmode->pelswidth;
3590 r->pelsheight = ntdevmode->pelsheight;
3591 r->displayflags = ntdevmode->displayflags;
3592 r->displayfrequency = ntdevmode->displayfrequency;
3593 r->icmmethod = ntdevmode->icmmethod;
3594 r->icmintent = ntdevmode->icmintent;
3595 r->mediatype = ntdevmode->mediatype;
3596 r->dithertype = ntdevmode->dithertype;
3597 r->reserved1 = ntdevmode->reserved1;
3598 r->reserved2 = ntdevmode->reserved2;
3599 r->panningwidth = ntdevmode->panningwidth;
3600 r->panningheight = ntdevmode->panningheight;
3602 if (ntdevmode->nt_dev_private != NULL) {
3603 r->driverextra_data = data_blob_talloc(mem_ctx,
3604 ntdevmode->nt_dev_private,
3605 ntdevmode->driverextra);
3606 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3613 /****************************************************************************
3614 Create a spoolss_DeviceMode struct. Returns talloced memory.
3615 ****************************************************************************/
3617 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3618 const char *servicename)
3621 NT_PRINTER_INFO_LEVEL *printer = NULL;
3622 struct spoolss_DeviceMode *devmode = NULL;
3624 DEBUG(7,("construct_dev_mode\n"));
3626 DEBUGADD(8,("getting printer characteristics\n"));
3628 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3631 if (!printer->info_2->devmode) {
3632 DEBUG(5, ("BONG! There was no device mode!\n"));
3636 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3638 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3642 DEBUGADD(8,("loading DEVICEMODE\n"));
3644 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3645 if (!W_ERROR_IS_OK(result)) {
3646 TALLOC_FREE(devmode);
3650 free_a_printer(&printer,2);
3655 /********************************************************************
3656 * construct_printer_info1
3657 * fill a spoolss_PrinterInfo1 struct
3658 ********************************************************************/
3660 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3661 const NT_PRINTER_INFO_LEVEL *ntprinter,
3663 struct spoolss_PrinterInfo1 *r,
3668 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3669 ntprinter->info_2->printername,
3670 ntprinter->info_2->drivername,
3671 ntprinter->info_2->location);
3672 W_ERROR_HAVE_NO_MEMORY(r->description);
3674 if (*ntprinter->info_2->comment == '\0') {
3675 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3677 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3679 W_ERROR_HAVE_NO_MEMORY(r->comment);
3681 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3682 W_ERROR_HAVE_NO_MEMORY(r->name);
3687 /********************************************************************
3688 * construct_printer_info2
3689 * fill a spoolss_PrinterInfo2 struct
3690 ********************************************************************/
3692 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3693 const NT_PRINTER_INFO_LEVEL *ntprinter,
3694 struct spoolss_PrinterInfo2 *r,
3699 print_status_struct status;
3701 count = print_queue_length(snum, &status);
3703 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3704 W_ERROR_HAVE_NO_MEMORY(r->servername);
3705 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3706 W_ERROR_HAVE_NO_MEMORY(r->printername);
3707 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3708 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3709 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3710 W_ERROR_HAVE_NO_MEMORY(r->portname);
3711 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3712 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3714 if (*ntprinter->info_2->comment == '\0') {
3715 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3717 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3719 W_ERROR_HAVE_NO_MEMORY(r->comment);
3721 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3722 W_ERROR_HAVE_NO_MEMORY(r->location);
3723 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3724 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3725 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3726 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3727 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3728 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3729 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3730 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3732 r->attributes = ntprinter->info_2->attributes;
3734 r->priority = ntprinter->info_2->priority;
3735 r->defaultpriority = ntprinter->info_2->default_priority;
3736 r->starttime = ntprinter->info_2->starttime;
3737 r->untiltime = ntprinter->info_2->untiltime;
3738 r->status = nt_printq_status(status.status);
3740 r->averageppm = ntprinter->info_2->averageppm;
3742 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3744 DEBUG(8,("Returning NULL Devicemode!\n"));
3749 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3750 /* don't use talloc_steal() here unless you do a deep steal of all
3751 the SEC_DESC members */
3753 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3759 /********************************************************************
3760 * construct_printer_info3
3761 * fill a spoolss_PrinterInfo3 struct
3762 ********************************************************************/
3764 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3765 const NT_PRINTER_INFO_LEVEL *ntprinter,
3766 struct spoolss_PrinterInfo3 *r,
3769 /* These are the components of the SD we are returning. */
3771 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3772 /* don't use talloc_steal() here unless you do a deep steal of all
3773 the SEC_DESC members */
3775 r->secdesc = dup_sec_desc(mem_ctx,
3776 ntprinter->info_2->secdesc_buf->sd);
3777 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3783 /********************************************************************
3784 * construct_printer_info4
3785 * fill a spoolss_PrinterInfo4 struct
3786 ********************************************************************/
3788 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3789 const NT_PRINTER_INFO_LEVEL *ntprinter,
3790 struct spoolss_PrinterInfo4 *r,
3793 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3794 W_ERROR_HAVE_NO_MEMORY(r->printername);
3795 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3796 W_ERROR_HAVE_NO_MEMORY(r->servername);
3798 r->attributes = ntprinter->info_2->attributes;
3803 /********************************************************************
3804 * construct_printer_info5
3805 * fill a spoolss_PrinterInfo5 struct
3806 ********************************************************************/
3808 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3809 const NT_PRINTER_INFO_LEVEL *ntprinter,
3810 struct spoolss_PrinterInfo5 *r,
3813 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3814 W_ERROR_HAVE_NO_MEMORY(r->printername);
3815 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3816 W_ERROR_HAVE_NO_MEMORY(r->portname);
3818 r->attributes = ntprinter->info_2->attributes;
3820 /* these two are not used by NT+ according to MSDN */
3822 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3823 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3828 /********************************************************************
3829 * construct_printer_info_6
3830 * fill a spoolss_PrinterInfo6 struct
3831 ********************************************************************/
3833 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3834 const NT_PRINTER_INFO_LEVEL *ntprinter,
3835 struct spoolss_PrinterInfo6 *r,
3839 print_status_struct status;
3841 count = print_queue_length(snum, &status);
3843 r->status = nt_printq_status(status.status);
3848 /********************************************************************
3849 * construct_printer_info7
3850 * fill a spoolss_PrinterInfo7 struct
3851 ********************************************************************/
3853 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3854 Printer_entry *print_hnd,
3855 struct spoolss_PrinterInfo7 *r,
3860 if (is_printer_published(print_hnd, snum, &guid)) {
3861 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3862 r->action = DSPRINT_PUBLISH;
3864 r->guid = talloc_strdup(mem_ctx, "");
3865 r->action = DSPRINT_UNPUBLISH;
3867 W_ERROR_HAVE_NO_MEMORY(r->guid);
3872 /********************************************************************
3873 * construct_printer_info8
3874 * fill a spoolss_PrinterInfo8 struct
3875 ********************************************************************/
3877 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3878 const NT_PRINTER_INFO_LEVEL *ntprinter,
3879 struct spoolss_DeviceModeInfo *r,
3882 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3884 DEBUG(8,("Returning NULL Devicemode!\n"));
3891 /********************************************************************
3892 ********************************************************************/
3894 static bool snum_is_shared_printer(int snum)
3896 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3899 /********************************************************************
3900 Spoolss_enumprinters.
3901 ********************************************************************/
3903 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3906 union spoolss_PrinterInfo **info_p,
3910 int n_services = lp_numservices();
3911 union spoolss_PrinterInfo *info = NULL;
3913 WERROR result = WERR_OK;
3918 for (snum = 0; snum < n_services; snum++) {
3920 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3922 if (!snum_is_shared_printer(snum)) {
3926 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3927 lp_servicename(snum), snum));
3929 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3930 union spoolss_PrinterInfo,
3933 result = WERR_NOMEM;
3937 result = get_a_printer(NULL, &ntprinter, 2,
3938 lp_const_servicename(snum));
3939 if (!W_ERROR_IS_OK(result)) {
3945 result = construct_printer_info0(info, ntprinter,
3946 &info[count].info0, snum);
3949 result = construct_printer_info1(info, ntprinter, flags,
3950 &info[count].info1, snum);
3953 result = construct_printer_info2(info, ntprinter,
3954 &info[count].info2, snum);
3957 result = construct_printer_info4(info, ntprinter,
3958 &info[count].info4, snum);
3961 result = construct_printer_info5(info, ntprinter,
3962 &info[count].info5, snum);
3966 result = WERR_UNKNOWN_LEVEL;
3967 free_a_printer(&ntprinter, 2);
3971 free_a_printer(&ntprinter, 2);
3972 if (!W_ERROR_IS_OK(result)) {
3983 if (!W_ERROR_IS_OK(result)) {
3993 /********************************************************************
3994 * handle enumeration of printers at level 0
3995 ********************************************************************/
3997 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3999 const char *servername,
4000 union spoolss_PrinterInfo **info,
4003 DEBUG(4,("enum_all_printers_info_0\n"));
4005 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4009 /********************************************************************
4010 ********************************************************************/
4012 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4014 union spoolss_PrinterInfo **info,
4017 DEBUG(4,("enum_all_printers_info_1\n"));
4019 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4022 /********************************************************************
4023 enum_all_printers_info_1_local.
4024 *********************************************************************/
4026 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4027 union spoolss_PrinterInfo **info,
4030 DEBUG(4,("enum_all_printers_info_1_local\n"));
4032 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4035 /********************************************************************
4036 enum_all_printers_info_1_name.
4037 *********************************************************************/
4039 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4041 union spoolss_PrinterInfo **info,
4044 const char *s = name;
4046 DEBUG(4,("enum_all_printers_info_1_name\n"));
4048 if ((name[0] == '\\') && (name[1] == '\\')) {
4052 if (!is_myname_or_ipaddr(s)) {
4053 return WERR_INVALID_NAME;
4056 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4059 /********************************************************************
4060 enum_all_printers_info_1_network.
4061 *********************************************************************/
4063 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4065 union spoolss_PrinterInfo **info,
4068 const char *s = name;
4070 DEBUG(4,("enum_all_printers_info_1_network\n"));
4072 /* If we respond to a enum_printers level 1 on our name with flags
4073 set to PRINTER_ENUM_REMOTE with a list of printers then these
4074 printers incorrectly appear in the APW browse list.
4075 Specifically the printers for the server appear at the workgroup
4076 level where all the other servers in the domain are
4077 listed. Windows responds to this call with a
4078 WERR_CAN_NOT_COMPLETE so we should do the same. */
4080 if (name[0] == '\\' && name[1] == '\\') {
4084 if (is_myname_or_ipaddr(s)) {
4085 return WERR_CAN_NOT_COMPLETE;
4088 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4091 /********************************************************************
4092 * api_spoolss_enumprinters
4094 * called from api_spoolss_enumprinters (see this to understand)
4095 ********************************************************************/
4097 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4098 union spoolss_PrinterInfo **info,
4101 DEBUG(4,("enum_all_printers_info_2\n"));
4103 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4106 /********************************************************************
4107 * handle enumeration of printers at level 1
4108 ********************************************************************/
4110 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4113 union spoolss_PrinterInfo **info,
4116 /* Not all the flags are equals */
4118 if (flags & PRINTER_ENUM_LOCAL) {
4119 return enum_all_printers_info_1_local(mem_ctx, info, count);
4122 if (flags & PRINTER_ENUM_NAME) {
4123 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4126 if (flags & PRINTER_ENUM_NETWORK) {
4127 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4130 return WERR_OK; /* NT4sp5 does that */
4133 /********************************************************************
4134 * handle enumeration of printers at level 2
4135 ********************************************************************/
4137 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4139 const char *servername,
4140 union spoolss_PrinterInfo **info,
4143 if (flags & PRINTER_ENUM_LOCAL) {
4144 return enum_all_printers_info_2(mem_ctx, info, count);
4147 if (flags & PRINTER_ENUM_NAME) {
4148 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4149 return WERR_INVALID_NAME;
4152 return enum_all_printers_info_2(mem_ctx, info, count);
4155 if (flags & PRINTER_ENUM_REMOTE) {
4156 return WERR_UNKNOWN_LEVEL;
4162 /********************************************************************
4163 * handle enumeration of printers at level 4
4164 ********************************************************************/
4166 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4168 const char *servername,
4169 union spoolss_PrinterInfo **info,
4172 DEBUG(4,("enum_all_printers_info_4\n"));
4174 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4178 /********************************************************************
4179 * handle enumeration of printers at level 5
4180 ********************************************************************/
4182 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4184 const char *servername,
4185 union spoolss_PrinterInfo **info,
4188 DEBUG(4,("enum_all_printers_info_5\n"));
4190 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4193 /****************************************************************
4194 _spoolss_EnumPrinters
4195 ****************************************************************/
4197 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4198 struct spoolss_EnumPrinters *r)
4200 const char *name = NULL;
4203 /* that's an [in out] buffer */
4205 if (!r->in.buffer && (r->in.offered != 0)) {
4206 return WERR_INVALID_PARAM;
4209 DEBUG(4,("_spoolss_EnumPrinters\n"));
4213 *r->out.info = NULL;
4217 * flags==PRINTER_ENUM_NAME
4218 * if name=="" then enumerates all printers
4219 * if name!="" then enumerate the printer
4220 * flags==PRINTER_ENUM_REMOTE
4221 * name is NULL, enumerate printers
4222 * Level 2: name!="" enumerates printers, name can't be NULL
4223 * Level 3: doesn't exist
4224 * Level 4: does a local registry lookup
4225 * Level 5: same as Level 2
4229 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4230 W_ERROR_HAVE_NO_MEMORY(name);
4233 switch (r->in.level) {
4235 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4236 r->out.info, r->out.count);
4239 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4240 r->out.info, r->out.count);
4243 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4244 r->out.info, r->out.count);
4247 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4248 r->out.info, r->out.count);
4251 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4252 r->out.info, r->out.count);
4255 return WERR_UNKNOWN_LEVEL;
4258 if (!W_ERROR_IS_OK(result)) {
4262 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4263 spoolss_EnumPrinters,
4264 *r->out.info, r->in.level,
4266 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4267 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4269 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4272 /****************************************************************
4274 ****************************************************************/
4276 WERROR _spoolss_GetPrinter(pipes_struct *p,
4277 struct spoolss_GetPrinter *r)
4279 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4280 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4281 WERROR result = WERR_OK;
4285 /* that's an [in out] buffer */
4287 if (!r->in.buffer && (r->in.offered != 0)) {
4288 return WERR_INVALID_PARAM;
4293 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4297 result = get_a_printer(Printer, &ntprinter, 2,
4298 lp_const_servicename(snum));
4299 if (!W_ERROR_IS_OK(result)) {
4303 switch (r->in.level) {
4305 result = construct_printer_info0(p->mem_ctx, ntprinter,
4306 &r->out.info->info0, snum);
4309 result = construct_printer_info1(p->mem_ctx, ntprinter,
4311 &r->out.info->info1, snum);
4314 result = construct_printer_info2(p->mem_ctx, ntprinter,
4315 &r->out.info->info2, snum);
4318 result = construct_printer_info3(p->mem_ctx, ntprinter,
4319 &r->out.info->info3, snum);
4322 result = construct_printer_info4(p->mem_ctx, ntprinter,
4323 &r->out.info->info4, snum);
4326 result = construct_printer_info5(p->mem_ctx, ntprinter,
4327 &r->out.info->info5, snum);
4330 result = construct_printer_info6(p->mem_ctx, ntprinter,
4331 &r->out.info->info6, snum);
4334 result = construct_printer_info7(p->mem_ctx, Printer,
4335 &r->out.info->info7, snum);
4338 result = construct_printer_info8(p->mem_ctx, ntprinter,
4339 &r->out.info->info8, snum);
4342 result = WERR_UNKNOWN_LEVEL;
4346 free_a_printer(&ntprinter, 2);
4348 if (!W_ERROR_IS_OK(result)) {
4349 TALLOC_FREE(r->out.info);
4353 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4354 r->out.info, r->in.level);
4355 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4357 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4360 /********************************************************************
4361 ********************************************************************/
4363 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4364 const char **string_array,
4365 const char *cservername)
4367 int i, num_strings = 0;
4368 const char **array = NULL;
4370 if (!string_array) {
4374 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4376 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4377 cservername, string_array[i]);
4384 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4391 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4392 &array, &num_strings);
4398 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4400 if (in && strlen(in)) { \
4401 out = talloc_strdup(mem_ctx, in); \
4402 W_ERROR_HAVE_NO_MEMORY(out); \
4408 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4410 if (in && strlen(in)) { \
4411 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4413 out = talloc_strdup(mem_ctx, ""); \
4415 W_ERROR_HAVE_NO_MEMORY(out); \
4418 /********************************************************************
4419 * fill a spoolss_DriverInfo1 struct
4420 ********************************************************************/
4422 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4423 struct spoolss_DriverInfo1 *r,
4424 const struct spoolss_DriverInfo8 *driver,
4425 const char *servername)
4427 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4428 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4433 /********************************************************************
4434 * fill a spoolss_DriverInfo2 struct
4435 ********************************************************************/
4437 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4438 struct spoolss_DriverInfo2 *r,
4439 const struct spoolss_DriverInfo8 *driver,
4440 const char *servername)
4443 const char *cservername = canon_servername(servername);
4445 r->version = driver->version;
4447 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4448 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4449 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4450 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4452 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4453 driver->driver_path,
4456 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4460 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4461 driver->config_file,
4467 /********************************************************************
4468 * fill a spoolss_DriverInfo3 struct
4469 ********************************************************************/
4471 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4472 struct spoolss_DriverInfo3 *r,
4473 const struct spoolss_DriverInfo8 *driver,
4474 const char *servername)
4476 const char *cservername = canon_servername(servername);
4478 r->version = driver->version;
4480 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4481 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4482 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4483 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4485 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4486 driver->driver_path,
4489 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4493 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4494 driver->config_file,
4497 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4501 FILL_DRIVER_STRING(mem_ctx,
4502 driver->monitor_name,
4505 FILL_DRIVER_STRING(mem_ctx,
4506 driver->default_datatype,
4507 r->default_datatype);
4509 r->dependent_files = string_array_from_driver_info(mem_ctx,
4510 driver->dependent_files,
4515 /********************************************************************
4516 * fill a spoolss_DriverInfo4 struct
4517 ********************************************************************/
4519 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4520 struct spoolss_DriverInfo4 *r,
4521 const struct spoolss_DriverInfo8 *driver,
4522 const char *servername)
4524 const char *cservername = canon_servername(servername);
4526 r->version = driver->version;
4528 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4529 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4530 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4531 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4533 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4534 driver->driver_path,
4537 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4541 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4542 driver->config_file,
4545 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4549 r->dependent_files = string_array_from_driver_info(mem_ctx,
4550 driver->dependent_files,
4553 FILL_DRIVER_STRING(mem_ctx,
4554 driver->monitor_name,
4557 FILL_DRIVER_STRING(mem_ctx,
4558 driver->default_datatype,
4559 r->default_datatype);
4561 r->previous_names = string_array_from_driver_info(mem_ctx,
4562 driver->previous_names,
4568 /********************************************************************
4569 * fill a spoolss_DriverInfo5 struct
4570 ********************************************************************/
4572 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4573 struct spoolss_DriverInfo5 *r,
4574 const struct spoolss_DriverInfo8 *driver,
4575 const char *servername)
4577 const char *cservername = canon_servername(servername);
4579 r->version = driver->version;
4581 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4582 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4583 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4584 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4586 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4587 driver->driver_path,
4590 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4594 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4595 driver->config_file,
4598 r->driver_attributes = 0;
4599 r->config_version = 0;
4600 r->driver_version = 0;
4604 /********************************************************************
4605 * fill a spoolss_DriverInfo6 struct
4606 ********************************************************************/
4608 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4609 struct spoolss_DriverInfo6 *r,
4610 const struct spoolss_DriverInfo8 *driver,
4611 const char *servername)
4613 const char *cservername = canon_servername(servername);
4615 r->version = driver->version;
4617 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4618 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4619 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4620 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4622 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4623 driver->driver_path,
4626 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4630 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4631 driver->config_file,
4634 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4638 FILL_DRIVER_STRING(mem_ctx,
4639 driver->monitor_name,
4642 FILL_DRIVER_STRING(mem_ctx,
4643 driver->default_datatype,
4644 r->default_datatype);
4646 r->dependent_files = string_array_from_driver_info(mem_ctx,
4647 driver->dependent_files,
4649 r->previous_names = string_array_from_driver_info(mem_ctx,
4650 driver->previous_names,
4653 r->driver_date = driver->driver_date;
4654 r->driver_version = driver->driver_version;
4656 FILL_DRIVER_STRING(mem_ctx,
4657 driver->manufacturer_name,
4658 r->manufacturer_name);
4659 FILL_DRIVER_STRING(mem_ctx,
4660 driver->manufacturer_url,
4661 r->manufacturer_url);
4662 FILL_DRIVER_STRING(mem_ctx,
4663 driver->hardware_id,
4665 FILL_DRIVER_STRING(mem_ctx,
4672 /********************************************************************
4673 * fill a spoolss_DriverInfo8 struct
4674 ********************************************************************/
4676 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4677 struct spoolss_DriverInfo8 *r,
4678 const struct spoolss_DriverInfo8 *driver,
4679 const char *servername)
4681 const char *cservername = canon_servername(servername);
4683 r->version = driver->version;
4685 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4686 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4687 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4688 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4690 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4691 driver->driver_path,
4694 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4698 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4699 driver->config_file,
4702 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4706 FILL_DRIVER_STRING(mem_ctx,
4707 driver->monitor_name,
4710 FILL_DRIVER_STRING(mem_ctx,
4711 driver->default_datatype,
4712 r->default_datatype);
4714 r->dependent_files = string_array_from_driver_info(mem_ctx,
4715 driver->dependent_files,
4717 r->previous_names = string_array_from_driver_info(mem_ctx,
4718 driver->previous_names,
4721 r->driver_date = driver->driver_date;
4722 r->driver_version = driver->driver_version;
4724 FILL_DRIVER_STRING(mem_ctx,
4725 driver->manufacturer_name,
4726 r->manufacturer_name);
4727 FILL_DRIVER_STRING(mem_ctx,
4728 driver->manufacturer_url,
4729 r->manufacturer_url);
4730 FILL_DRIVER_STRING(mem_ctx,
4731 driver->hardware_id,
4733 FILL_DRIVER_STRING(mem_ctx,
4737 FILL_DRIVER_STRING(mem_ctx,
4738 driver->print_processor,
4739 r->print_processor);
4740 FILL_DRIVER_STRING(mem_ctx,
4741 driver->vendor_setup,
4744 r->color_profiles = string_array_from_driver_info(mem_ctx,
4745 driver->color_profiles,
4748 FILL_DRIVER_STRING(mem_ctx,
4752 r->printer_driver_attributes = driver->printer_driver_attributes;
4754 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4755 driver->core_driver_dependencies,
4758 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4759 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4764 #if 0 /* disabled until marshalling issues are resolved - gd */
4765 /********************************************************************
4766 ********************************************************************/
4768 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4769 struct spoolss_DriverFileInfo *r,
4770 const char *cservername,
4771 const char *file_name,
4772 enum spoolss_DriverFileType file_type,
4773 uint32_t file_version)
4775 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4776 cservername, file_name);
4777 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4778 r->file_type = file_type;
4779 r->file_version = file_version;
4784 /********************************************************************
4785 ********************************************************************/
4787 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4788 const struct spoolss_DriverInfo8 *driver,
4789 const char *cservername,
4790 struct spoolss_DriverFileInfo **info_p,
4793 struct spoolss_DriverFileInfo *info = NULL;
4801 if (strlen(driver->driver_path)) {
4802 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4803 struct spoolss_DriverFileInfo,
4805 W_ERROR_HAVE_NO_MEMORY(info);
4806 result = fill_spoolss_DriverFileInfo(info,
4809 driver->driver_path,
4810 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4812 W_ERROR_NOT_OK_RETURN(result);
4816 if (strlen(driver->config_file)) {
4817 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4818 struct spoolss_DriverFileInfo,
4820 W_ERROR_HAVE_NO_MEMORY(info);
4821 result = fill_spoolss_DriverFileInfo(info,
4824 driver->config_file,
4825 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4827 W_ERROR_NOT_OK_RETURN(result);
4831 if (strlen(driver->data_file)) {
4832 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4833 struct spoolss_DriverFileInfo,
4835 W_ERROR_HAVE_NO_MEMORY(info);
4836 result = fill_spoolss_DriverFileInfo(info,
4840 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4842 W_ERROR_NOT_OK_RETURN(result);
4846 if (strlen(driver->help_file)) {
4847 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4848 struct spoolss_DriverFileInfo,
4850 W_ERROR_HAVE_NO_MEMORY(info);
4851 result = fill_spoolss_DriverFileInfo(info,
4855 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4857 W_ERROR_NOT_OK_RETURN(result);
4861 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4862 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4863 struct spoolss_DriverFileInfo,
4865 W_ERROR_HAVE_NO_MEMORY(info);
4866 result = fill_spoolss_DriverFileInfo(info,
4869 driver->dependent_files[i],
4870 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4872 W_ERROR_NOT_OK_RETURN(result);
4882 /********************************************************************
4883 * fill a spoolss_DriverInfo101 struct
4884 ********************************************************************/
4886 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4887 struct spoolss_DriverInfo101 *r,
4888 const struct spoolss_DriverInfo8 *driver,
4889 const char *servername)
4891 const char *cservername = canon_servername(servername);
4894 r->version = driver->version;
4896 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4897 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4898 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4899 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4901 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4905 if (!W_ERROR_IS_OK(result)) {
4909 FILL_DRIVER_STRING(mem_ctx,
4910 driver->monitor_name,
4913 FILL_DRIVER_STRING(mem_ctx,
4914 driver->default_datatype,
4915 r->default_datatype);
4917 r->previous_names = string_array_from_driver_info(mem_ctx,
4918 driver->previous_names,
4920 r->driver_date = driver->driver_date;
4921 r->driver_version = driver->driver_version;
4923 FILL_DRIVER_STRING(mem_ctx,
4924 driver->manufacturer_name,
4925 r->manufacturer_name);
4926 FILL_DRIVER_STRING(mem_ctx,
4927 driver->manufacturer_url,
4928 r->manufacturer_url);
4929 FILL_DRIVER_STRING(mem_ctx,
4930 driver->hardware_id,
4932 FILL_DRIVER_STRING(mem_ctx,
4939 /********************************************************************
4940 ********************************************************************/
4942 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4944 union spoolss_DriverInfo *r,
4946 const char *servername,
4947 const char *architecture,
4950 NT_PRINTER_INFO_LEVEL *printer = NULL;
4951 struct spoolss_DriverInfo8 *driver;
4954 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4956 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4957 win_errstr(result)));
4959 if (!W_ERROR_IS_OK(result)) {
4960 return WERR_INVALID_PRINTER_NAME;
4963 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4964 architecture, version);
4966 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4967 win_errstr(result)));
4969 if (!W_ERROR_IS_OK(result)) {
4971 * Is this a W2k client ?
4975 free_a_printer(&printer, 2);
4976 return WERR_UNKNOWN_PRINTER_DRIVER;
4979 /* Yes - try again with a WinNT driver. */
4981 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4982 architecture, version);
4983 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4984 win_errstr(result)));
4985 if (!W_ERROR_IS_OK(result)) {
4986 free_a_printer(&printer, 2);
4987 return WERR_UNKNOWN_PRINTER_DRIVER;
4993 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4996 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4999 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5002 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5005 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5008 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5011 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5013 #if 0 /* disabled until marshalling issues are resolved - gd */
5015 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5019 result = WERR_UNKNOWN_LEVEL;
5023 free_a_printer(&printer, 2);
5024 free_a_printer_driver(driver);
5029 /****************************************************************
5030 _spoolss_GetPrinterDriver2
5031 ****************************************************************/
5033 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5034 struct spoolss_GetPrinterDriver2 *r)
5036 Printer_entry *printer;
5039 const char *servername;
5042 /* that's an [in out] buffer */
5044 if (!r->in.buffer && (r->in.offered != 0)) {
5045 return WERR_INVALID_PARAM;
5048 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5050 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5051 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5052 return WERR_INVALID_PRINTER_NAME;
5056 *r->out.server_major_version = 0;
5057 *r->out.server_minor_version = 0;
5059 servername = get_server_name(printer);
5061 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5065 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5069 r->in.client_major_version);
5070 if (!W_ERROR_IS_OK(result)) {
5071 TALLOC_FREE(r->out.info);
5075 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5076 r->out.info, r->in.level);
5077 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5079 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5083 /****************************************************************
5084 _spoolss_StartPagePrinter
5085 ****************************************************************/
5087 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5088 struct spoolss_StartPagePrinter *r)
5090 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5093 DEBUG(3,("_spoolss_StartPagePrinter: "
5094 "Error in startpageprinter printer handle\n"));
5098 Printer->page_started = true;
5102 /****************************************************************
5103 _spoolss_EndPagePrinter
5104 ****************************************************************/
5106 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5107 struct spoolss_EndPagePrinter *r)
5111 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5114 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5115 OUR_HANDLE(r->in.handle)));
5119 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5122 Printer->page_started = false;
5123 print_job_endpage(snum, Printer->jobid);
5128 /****************************************************************
5129 _spoolss_StartDocPrinter
5130 ****************************************************************/
5132 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5133 struct spoolss_StartDocPrinter *r)
5135 struct spoolss_DocumentInfo1 *info_1;
5137 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5140 DEBUG(2,("_spoolss_StartDocPrinter: "
5141 "Invalid handle (%s:%u:%u)\n",
5142 OUR_HANDLE(r->in.handle)));
5146 if (r->in.level != 1) {
5147 return WERR_UNKNOWN_LEVEL;
5150 info_1 = r->in.info.info1;
5153 * a nice thing with NT is it doesn't listen to what you tell it.
5154 * when asked to send _only_ RAW datas, it tries to send datas
5157 * So I add checks like in NT Server ...
5160 if (info_1->datatype) {
5161 if (strcmp(info_1->datatype, "RAW") != 0) {
5163 return WERR_INVALID_DATATYPE;
5167 /* get the share number of the printer */
5168 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5172 Printer->jobid = print_job_start(p->server_info, snum,
5173 info_1->document_name,
5174 Printer->nt_devmode);
5176 /* An error occured in print_job_start() so return an appropriate
5179 if (Printer->jobid == -1) {
5180 return map_werror_from_unix(errno);
5183 Printer->document_started = true;
5184 *r->out.job_id = Printer->jobid;
5189 /****************************************************************
5190 _spoolss_EndDocPrinter
5191 ****************************************************************/
5193 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5194 struct spoolss_EndDocPrinter *r)
5196 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5200 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5201 OUR_HANDLE(r->in.handle)));
5205 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5209 Printer->document_started = false;
5210 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5211 /* error codes unhandled so far ... */
5216 /****************************************************************
5217 _spoolss_WritePrinter
5218 ****************************************************************/
5220 WERROR _spoolss_WritePrinter(pipes_struct *p,
5221 struct spoolss_WritePrinter *r)
5223 ssize_t buffer_written;
5225 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5228 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5229 OUR_HANDLE(r->in.handle)));
5230 *r->out.num_written = r->in._data_size;
5234 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5237 buffer_written = print_job_write(snum, Printer->jobid,
5238 (const char *)r->in.data.data,
5240 (size_t)r->in._data_size);
5241 if (buffer_written == (ssize_t)-1) {
5242 *r->out.num_written = 0;
5243 if (errno == ENOSPC)
5244 return WERR_NO_SPOOL_SPACE;
5246 return WERR_ACCESS_DENIED;
5249 *r->out.num_written = r->in._data_size;
5254 /********************************************************************
5255 * api_spoolss_getprinter
5256 * called from the spoolss dispatcher
5258 ********************************************************************/
5260 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5264 WERROR errcode = WERR_BADFUNC;
5265 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5268 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5269 OUR_HANDLE(handle)));
5273 if (!get_printer_snum(p, handle, &snum, NULL))
5277 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5278 errcode = print_queue_pause(p->server_info, snum);
5280 case SPOOLSS_PRINTER_CONTROL_RESUME:
5281 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5282 errcode = print_queue_resume(p->server_info, snum);
5284 case SPOOLSS_PRINTER_CONTROL_PURGE:
5285 errcode = print_queue_purge(p->server_info, snum);
5288 return WERR_UNKNOWN_LEVEL;
5295 /****************************************************************
5296 _spoolss_AbortPrinter
5297 * From MSDN: "Deletes printer's spool file if printer is configured
5299 ****************************************************************/
5301 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5302 struct spoolss_AbortPrinter *r)
5304 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5306 WERROR errcode = WERR_OK;
5309 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5310 OUR_HANDLE(r->in.handle)));
5314 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5317 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5322 /********************************************************************
5323 * called by spoolss_api_setprinter
5324 * when updating a printer description
5325 ********************************************************************/
5327 static WERROR update_printer_sec(struct policy_handle *handle,
5328 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5330 struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5334 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5336 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5337 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5338 OUR_HANDLE(handle)));
5340 result = WERR_BADFID;
5345 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5346 result = WERR_INVALID_PARAM;
5350 /* Check the user has permissions to change the security
5351 descriptor. By experimentation with two NT machines, the user
5352 requires Full Access to the printer to change security
5355 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5356 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5357 result = WERR_ACCESS_DENIED;
5361 /* NT seems to like setting the security descriptor even though
5362 nothing may have actually changed. */
5364 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5365 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5366 result = WERR_BADFID;
5370 if (DEBUGLEVEL >= 10) {
5371 struct security_acl *the_acl;
5374 the_acl = old_secdesc_ctr->sd->dacl;
5375 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5376 lp_printername(snum), the_acl->num_aces));
5378 for (i = 0; i < the_acl->num_aces; i++) {
5379 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5380 &the_acl->aces[i].trustee),
5381 the_acl->aces[i].access_mask));
5384 the_acl = secdesc_ctr->sd->dacl;
5387 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5388 lp_printername(snum), the_acl->num_aces));
5390 for (i = 0; i < the_acl->num_aces; i++) {
5391 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5392 &the_acl->aces[i].trustee),
5393 the_acl->aces[i].access_mask));
5396 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5400 new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5401 if (!new_secdesc_ctr) {
5402 result = WERR_NOMEM;
5406 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5411 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5418 /********************************************************************
5419 Canonicalize printer info from a client
5421 ATTN: It does not matter what we set the servername to hear
5422 since we do the necessary work in get_a_printer() to set it to
5423 the correct value based on what the client sent in the
5424 _spoolss_open_printer_ex().
5425 ********************************************************************/
5427 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5429 fstring printername;
5432 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5433 "portname=%s drivername=%s comment=%s location=%s\n",
5434 info->servername, info->printername, info->sharename,
5435 info->portname, info->drivername, info->comment, info->location));
5437 /* we force some elements to "correct" values */
5438 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5439 fstrcpy(info->sharename, lp_servicename(snum));
5441 /* check to see if we allow printername != sharename */
5443 if ( lp_force_printername(snum) ) {
5444 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5445 global_myname(), info->sharename );
5448 /* make sure printername is in \\server\printername format */
5450 fstrcpy( printername, info->printername );
5452 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5453 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5457 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5458 global_myname(), p );
5461 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5462 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5469 /****************************************************************************
5470 ****************************************************************************/
5472 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5474 char *cmd = lp_addport_cmd();
5475 char *command = NULL;
5477 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5478 bool is_print_op = false;
5481 return WERR_ACCESS_DENIED;
5484 command = talloc_asprintf(ctx,
5485 "%s \"%s\" \"%s\"", cmd, portname, uri );
5491 is_print_op = user_has_privileges( token, &se_printop );
5493 DEBUG(10,("Running [%s]\n", command));
5495 /********* BEGIN SePrintOperatorPrivilege **********/
5500 ret = smbrun(command, NULL);
5505 /********* END SePrintOperatorPrivilege **********/
5507 DEBUGADD(10,("returned [%d]\n", ret));
5509 TALLOC_FREE(command);
5512 return WERR_ACCESS_DENIED;
5518 /****************************************************************************
5519 ****************************************************************************/
5521 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5523 char *cmd = lp_addprinter_cmd();
5525 char *command = NULL;
5529 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5530 bool is_print_op = false;
5531 char *remote_machine = talloc_strdup(ctx, "%m");
5533 if (!remote_machine) {
5536 remote_machine = talloc_sub_basic(ctx,
5537 current_user_info.smb_name,
5538 current_user_info.domain,
5540 if (!remote_machine) {
5544 command = talloc_asprintf(ctx,
5545 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5546 cmd, printer->info_2->printername, printer->info_2->sharename,
5547 printer->info_2->portname, printer->info_2->drivername,
5548 printer->info_2->location, printer->info_2->comment, remote_machine);
5554 is_print_op = user_has_privileges( token, &se_printop );
5556 DEBUG(10,("Running [%s]\n", command));
5558 /********* BEGIN SePrintOperatorPrivilege **********/
5563 if ( (ret = smbrun(command, &fd)) == 0 ) {
5564 /* Tell everyone we updated smb.conf. */
5565 message_send_all(smbd_messaging_context(),
5566 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5572 /********* END SePrintOperatorPrivilege **********/
5574 DEBUGADD(10,("returned [%d]\n", ret));
5576 TALLOC_FREE(command);
5577 TALLOC_FREE(remote_machine);
5585 /* reload our services immediately */
5587 reload_services(false);
5591 /* Get lines and convert them back to dos-codepage */
5592 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5593 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5596 /* Set the portname to what the script says the portname should be. */
5597 /* but don't require anything to be return from the script exit a good error code */
5600 /* Set the portname to what the script says the portname should be. */
5601 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5602 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5605 TALLOC_FREE(qlines);
5610 /********************************************************************
5611 * Called by spoolss_api_setprinter
5612 * when updating a printer description.
5613 ********************************************************************/
5615 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5616 struct spoolss_SetPrinterInfoCtr *info_ctr,
5617 struct spoolss_DeviceMode *devmode)
5620 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5621 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5626 DEBUG(8,("update_printer\n"));
5631 result = WERR_BADFID;
5635 if (!get_printer_snum(p, handle, &snum, NULL)) {
5636 result = WERR_BADFID;
5640 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5641 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5642 result = WERR_BADFID;
5646 DEBUGADD(8,("Converting info_2 struct\n"));
5649 * convert_printer_info converts the incoming
5650 * info from the client and overwrites the info
5651 * just read from the tdb in the pointer 'printer'.
5654 if (!convert_printer_info(info_ctr, printer)) {
5655 result = WERR_NOMEM;
5660 /* we have a valid devmode
5661 convert it and link it*/
5663 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5664 if (!convert_devicemode(printer->info_2->printername, devmode,
5665 &printer->info_2->devmode)) {
5666 result = WERR_NOMEM;
5671 /* Do sanity check on the requested changes for Samba */
5673 if (!check_printer_ok(printer->info_2, snum)) {
5674 result = WERR_INVALID_PARAM;
5678 /* FIXME!!! If the driver has changed we really should verify that
5679 it is installed before doing much else --jerry */
5681 /* Check calling user has permission to update printer description */
5683 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5684 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5685 result = WERR_ACCESS_DENIED;
5689 /* Call addprinter hook */
5690 /* Check changes to see if this is really needed */
5692 if ( *lp_addprinter_cmd()
5693 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5694 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5695 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5696 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5698 /* add_printer_hook() will call reload_services() */
5700 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5702 result = WERR_ACCESS_DENIED;
5708 * When a *new* driver is bound to a printer, the drivername is used to
5709 * lookup previously saved driver initialization info, which is then
5710 * bound to the printer, simulating what happens in the Windows arch.
5712 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5714 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5715 printer->info_2->drivername));
5717 notify_printer_driver(snum, printer->info_2->drivername);
5721 * flag which changes actually occured. This is a small subset of
5722 * all the possible changes. We also have to update things in the
5726 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5727 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5728 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5729 REG_SZ, buffer.data, buffer.length);
5731 notify_printer_comment(snum, printer->info_2->comment);
5734 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5735 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5736 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5737 REG_SZ, buffer.data, buffer.length);
5739 notify_printer_sharename(snum, printer->info_2->sharename);
5742 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5745 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5748 pname = printer->info_2->printername;
5751 push_reg_sz(talloc_tos(), &buffer, pname);
5752 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5753 REG_SZ, buffer.data, buffer.length);
5755 notify_printer_printername( snum, pname );
5758 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5759 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5760 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5761 REG_SZ, buffer.data, buffer.length);
5763 notify_printer_port(snum, printer->info_2->portname);
5766 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5767 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5768 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5769 REG_SZ, buffer.data, buffer.length);
5771 notify_printer_location(snum, printer->info_2->location);
5774 /* here we need to update some more DsSpooler keys */
5775 /* uNCName, serverName, shortServerName */
5777 push_reg_sz(talloc_tos(), &buffer, global_myname());
5778 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5779 REG_SZ, buffer.data, buffer.length);
5780 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5781 REG_SZ, buffer.data, buffer.length);
5783 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5784 global_myname(), printer->info_2->sharename );
5785 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5786 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5787 REG_SZ, buffer.data, buffer.length);
5789 /* Update printer info */
5790 result = mod_a_printer(printer, 2);
5793 free_a_printer(&printer, 2);
5794 free_a_printer(&old_printer, 2);
5800 /****************************************************************************
5801 ****************************************************************************/
5802 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5803 struct policy_handle *handle,
5804 struct spoolss_SetPrinterInfo7 *info7)
5808 Printer_entry *Printer;
5810 if ( lp_security() != SEC_ADS ) {
5811 return WERR_UNKNOWN_LEVEL;
5814 Printer = find_printer_index_by_hnd(p, handle);
5816 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5821 if (!get_printer_snum(p, handle, &snum, NULL))
5824 nt_printer_publish(Printer, snum, info7->action);
5828 return WERR_UNKNOWN_LEVEL;
5832 /********************************************************************
5833 ********************************************************************/
5835 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5836 struct spoolss_DeviceMode *devmode)
5839 NT_PRINTER_INFO_LEVEL *printer = NULL;
5840 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5843 DEBUG(8,("update_printer_devmode\n"));
5848 result = WERR_BADFID;
5852 if (!get_printer_snum(p, handle, &snum, NULL)) {
5853 result = WERR_BADFID;
5857 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5858 result = WERR_BADFID;
5863 /* we have a valid devmode
5864 convert it and link it*/
5866 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5867 if (!convert_devicemode(printer->info_2->printername, devmode,
5868 &printer->info_2->devmode)) {
5869 result = WERR_NOMEM;
5874 /* Check calling user has permission to update printer description */
5876 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5877 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5878 result = WERR_ACCESS_DENIED;
5883 /* Update printer info */
5884 result = mod_a_printer(printer, 2);
5887 free_a_printer(&printer, 2);
5893 /****************************************************************
5895 ****************************************************************/
5897 WERROR _spoolss_SetPrinter(pipes_struct *p,
5898 struct spoolss_SetPrinter *r)
5902 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5905 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5906 OUR_HANDLE(r->in.handle)));
5910 /* check the level */
5911 switch (r->in.info_ctr->level) {
5913 return control_printer(r->in.handle, r->in.command, p);
5915 result = update_printer(p, r->in.handle,
5917 r->in.devmode_ctr->devmode);
5918 if (!W_ERROR_IS_OK(result))
5920 if (r->in.secdesc_ctr->sd)
5921 result = update_printer_sec(r->in.handle, p,
5925 return update_printer_sec(r->in.handle, p,
5928 return publish_or_unpublish_printer(p, r->in.handle,
5929 r->in.info_ctr->info.info7);
5931 return update_printer_devmode(p, r->in.handle,
5932 r->in.devmode_ctr->devmode);
5934 return WERR_UNKNOWN_LEVEL;
5938 /****************************************************************
5939 _spoolss_FindClosePrinterNotify
5940 ****************************************************************/
5942 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5943 struct spoolss_FindClosePrinterNotify *r)
5945 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5948 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5949 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5953 if (Printer->notify.client_connected == true) {
5956 if ( Printer->printer_type == SPLHND_SERVER)
5958 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5959 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5962 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5965 Printer->notify.flags=0;
5966 Printer->notify.options=0;
5967 Printer->notify.localmachine[0]='\0';
5968 Printer->notify.printerlocal=0;
5969 TALLOC_FREE(Printer->notify.option);
5970 Printer->notify.client_connected = false;
5975 /****************************************************************
5977 ****************************************************************/
5979 WERROR _spoolss_AddJob(pipes_struct *p,
5980 struct spoolss_AddJob *r)
5982 if (!r->in.buffer && (r->in.offered != 0)) {
5983 return WERR_INVALID_PARAM;
5986 /* this is what a NT server returns for AddJob. AddJob must fail on
5987 * non-local printers */
5989 if (r->in.level != 1) {
5990 return WERR_UNKNOWN_LEVEL;
5993 return WERR_INVALID_PARAM;
5996 /****************************************************************************
5998 ****************************************************************************/
6000 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6001 struct spoolss_JobInfo1 *r,
6002 const print_queue_struct *queue,
6003 int position, int snum,
6004 const NT_PRINTER_INFO_LEVEL *ntprinter)
6008 t = gmtime(&queue->time);
6010 r->job_id = queue->job;
6012 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6013 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6014 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6015 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6016 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6017 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6018 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6019 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6020 r->data_type = talloc_strdup(mem_ctx, "RAW");
6021 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6022 r->text_status = talloc_strdup(mem_ctx, "");
6023 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6025 r->status = nt_printj_status(queue->status);
6026 r->priority = queue->priority;
6027 r->position = position;
6028 r->total_pages = queue->page_count;
6029 r->pages_printed = 0; /* ??? */
6031 init_systemtime(&r->submitted, t);
6036 /****************************************************************************
6038 ****************************************************************************/
6040 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6041 struct spoolss_JobInfo2 *r,
6042 const print_queue_struct *queue,
6043 int position, int snum,
6044 const NT_PRINTER_INFO_LEVEL *ntprinter,
6045 struct spoolss_DeviceMode *devmode)
6049 t = gmtime(&queue->time);
6051 r->job_id = queue->job;
6053 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6054 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6055 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6056 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6057 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6058 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6059 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6060 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6061 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6062 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6063 r->data_type = talloc_strdup(mem_ctx, "RAW");
6064 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6065 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6066 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6067 r->parameters = talloc_strdup(mem_ctx, "");
6068 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6069 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6070 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6072 r->devmode = devmode;
6074 r->text_status = talloc_strdup(mem_ctx, "");
6075 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6079 r->status = nt_printj_status(queue->status);
6080 r->priority = queue->priority;
6081 r->position = position;
6084 r->total_pages = queue->page_count;
6085 r->size = queue->size;
6086 init_systemtime(&r->submitted, t);
6088 r->pages_printed = 0; /* ??? */
6093 /****************************************************************************
6095 ****************************************************************************/
6097 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6098 struct spoolss_JobInfo3 *r,
6099 const print_queue_struct *queue,
6100 const print_queue_struct *next_queue,
6101 int position, int snum,
6102 const NT_PRINTER_INFO_LEVEL *ntprinter)
6104 r->job_id = queue->job;
6107 r->next_job_id = next_queue->job;
6114 /****************************************************************************
6115 Enumjobs at level 1.
6116 ****************************************************************************/
6118 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6119 const print_queue_struct *queue,
6120 uint32_t num_queues, int snum,
6121 const NT_PRINTER_INFO_LEVEL *ntprinter,
6122 union spoolss_JobInfo **info_p,
6125 union spoolss_JobInfo *info;
6127 WERROR result = WERR_OK;
6129 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6130 W_ERROR_HAVE_NO_MEMORY(info);
6132 *count = num_queues;
6134 for (i=0; i<*count; i++) {
6135 result = fill_job_info1(info,
6141 if (!W_ERROR_IS_OK(result)) {
6147 if (!W_ERROR_IS_OK(result)) {
6158 /****************************************************************************
6159 Enumjobs at level 2.
6160 ****************************************************************************/
6162 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6163 const print_queue_struct *queue,
6164 uint32_t num_queues, int snum,
6165 const NT_PRINTER_INFO_LEVEL *ntprinter,
6166 union spoolss_JobInfo **info_p,
6169 union spoolss_JobInfo *info;
6171 WERROR result = WERR_OK;
6173 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6174 W_ERROR_HAVE_NO_MEMORY(info);
6176 *count = num_queues;
6178 for (i=0; i<*count; i++) {
6180 struct spoolss_DeviceMode *devmode;
6182 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6184 result = WERR_NOMEM;
6188 result = fill_job_info2(info,
6195 if (!W_ERROR_IS_OK(result)) {
6201 if (!W_ERROR_IS_OK(result)) {
6212 /****************************************************************************
6213 Enumjobs at level 3.
6214 ****************************************************************************/
6216 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6217 const print_queue_struct *queue,
6218 uint32_t num_queues, int snum,
6219 const NT_PRINTER_INFO_LEVEL *ntprinter,
6220 union spoolss_JobInfo **info_p,
6223 union spoolss_JobInfo *info;
6225 WERROR result = WERR_OK;
6227 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6228 W_ERROR_HAVE_NO_MEMORY(info);
6230 *count = num_queues;
6232 for (i=0; i<*count; i++) {
6233 const print_queue_struct *next_queue = NULL;
6236 next_queue = &queue[i+1];
6239 result = fill_job_info3(info,
6246 if (!W_ERROR_IS_OK(result)) {
6252 if (!W_ERROR_IS_OK(result)) {
6263 /****************************************************************
6265 ****************************************************************/
6267 WERROR _spoolss_EnumJobs(pipes_struct *p,
6268 struct spoolss_EnumJobs *r)
6271 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6273 print_status_struct prt_status;
6274 print_queue_struct *queue = NULL;
6277 /* that's an [in out] buffer */
6279 if (!r->in.buffer && (r->in.offered != 0)) {
6280 return WERR_INVALID_PARAM;
6283 DEBUG(4,("_spoolss_EnumJobs\n"));
6287 *r->out.info = NULL;
6289 /* lookup the printer snum and tdb entry */
6291 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6295 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6296 if (!W_ERROR_IS_OK(result)) {
6300 count = print_queue_status(snum, &queue, &prt_status);
6301 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6302 count, prt_status.status, prt_status.message));
6306 free_a_printer(&ntprinter, 2);
6310 switch (r->in.level) {
6312 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6313 ntprinter, r->out.info, r->out.count);
6316 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6317 ntprinter, r->out.info, r->out.count);
6320 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6321 ntprinter, r->out.info, r->out.count);
6324 result = WERR_UNKNOWN_LEVEL;
6329 free_a_printer(&ntprinter, 2);
6331 if (!W_ERROR_IS_OK(result)) {
6335 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6337 *r->out.info, r->in.level,
6339 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6340 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6342 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6345 /****************************************************************
6346 _spoolss_ScheduleJob
6347 ****************************************************************/
6349 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6350 struct spoolss_ScheduleJob *r)
6355 /****************************************************************
6356 ****************************************************************/
6358 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6359 const char *printer_name,
6361 struct spoolss_SetJobInfo1 *r)
6365 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6369 if (strequal(old_doc_name, r->document_name)) {
6373 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6380 /****************************************************************
6382 ****************************************************************/
6384 WERROR _spoolss_SetJob(pipes_struct *p,
6385 struct spoolss_SetJob *r)
6388 WERROR errcode = WERR_BADFUNC;
6390 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6394 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6395 return WERR_INVALID_PRINTER_NAME;
6398 switch (r->in.command) {
6399 case SPOOLSS_JOB_CONTROL_CANCEL:
6400 case SPOOLSS_JOB_CONTROL_DELETE:
6401 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6405 case SPOOLSS_JOB_CONTROL_PAUSE:
6406 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6410 case SPOOLSS_JOB_CONTROL_RESTART:
6411 case SPOOLSS_JOB_CONTROL_RESUME:
6412 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6420 return WERR_UNKNOWN_LEVEL;
6423 if (!W_ERROR_IS_OK(errcode)) {
6427 if (r->in.ctr == NULL) {
6431 switch (r->in.ctr->level) {
6433 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6435 r->in.ctr->info.info1);
6441 return WERR_UNKNOWN_LEVEL;
6447 /****************************************************************************
6448 Enumerates all printer drivers by level and architecture.
6449 ****************************************************************************/
6451 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6452 const char *servername,
6453 const char *architecture,
6455 union spoolss_DriverInfo **info_p,
6461 fstring *list = NULL;
6462 struct spoolss_DriverInfo8 *driver;
6463 union spoolss_DriverInfo *info = NULL;
6465 WERROR result = WERR_OK;
6470 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6472 ndrivers = get_ntdrivers(&list, architecture, version);
6473 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6474 ndrivers, architecture, version));
6476 if (ndrivers == -1) {
6477 result = WERR_NOMEM;
6481 if (ndrivers != 0) {
6482 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6483 union spoolss_DriverInfo,
6486 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6487 "failed to enlarge driver info buffer!\n"));
6488 result = WERR_NOMEM;
6493 for (i=0; i<ndrivers; i++) {
6494 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6495 ZERO_STRUCT(driver);
6496 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6497 architecture, version);
6498 if (!W_ERROR_IS_OK(result)) {
6504 result = fill_printer_driver_info1(info, &info[count+i].info1,
6505 driver, servername);
6508 result = fill_printer_driver_info2(info, &info[count+i].info2,
6509 driver, servername);
6512 result = fill_printer_driver_info3(info, &info[count+i].info3,
6513 driver, servername);
6516 result = fill_printer_driver_info4(info, &info[count+i].info4,
6517 driver, servername);
6520 result = fill_printer_driver_info5(info, &info[count+i].info5,
6521 driver, servername);
6524 result = fill_printer_driver_info6(info, &info[count+i].info6,
6525 driver, servername);
6528 result = fill_printer_driver_info8(info, &info[count+i].info8,
6529 driver, servername);
6532 result = WERR_UNKNOWN_LEVEL;
6536 free_a_printer_driver(driver);
6538 if (!W_ERROR_IS_OK(result)) {
6550 if (!W_ERROR_IS_OK(result)) {
6561 /****************************************************************************
6562 Enumerates all printer drivers by level.
6563 ****************************************************************************/
6565 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6566 const char *servername,
6567 const char *architecture,
6569 union spoolss_DriverInfo **info_p,
6573 WERROR result = WERR_OK;
6575 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6577 for (a=0; archi_table[a].long_archi != NULL; a++) {
6579 union spoolss_DriverInfo *info = NULL;
6582 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6584 archi_table[a].long_archi,
6588 if (!W_ERROR_IS_OK(result)) {
6592 for (i=0; i < count; i++) {
6593 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6594 info[i], info_p, count_p);
6601 return enumprinterdrivers_level_by_architecture(mem_ctx,
6609 /****************************************************************
6610 _spoolss_EnumPrinterDrivers
6611 ****************************************************************/
6613 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6614 struct spoolss_EnumPrinterDrivers *r)
6616 const char *cservername;
6619 /* that's an [in out] buffer */
6621 if (!r->in.buffer && (r->in.offered != 0)) {
6622 return WERR_INVALID_PARAM;
6625 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6629 *r->out.info = NULL;
6631 cservername = canon_servername(r->in.server);
6633 if (!is_myname_or_ipaddr(cservername)) {
6634 return WERR_UNKNOWN_PRINTER_DRIVER;
6637 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6642 if (!W_ERROR_IS_OK(result)) {
6646 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6647 spoolss_EnumPrinterDrivers,
6648 *r->out.info, r->in.level,
6650 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6651 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6653 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6656 /****************************************************************************
6657 ****************************************************************************/
6659 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6660 struct spoolss_FormInfo1 *r,
6661 const nt_forms_struct *form)
6663 r->form_name = talloc_strdup(mem_ctx, form->name);
6664 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6666 r->flags = form->flag;
6667 r->size.width = form->width;
6668 r->size.height = form->length;
6669 r->area.left = form->left;
6670 r->area.top = form->top;
6671 r->area.right = form->right;
6672 r->area.bottom = form->bottom;
6677 /****************************************************************
6678 spoolss_enumforms_level1
6679 ****************************************************************/
6681 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6682 const nt_forms_struct *builtin_forms,
6683 uint32_t num_builtin_forms,
6684 const nt_forms_struct *user_forms,
6685 uint32_t num_user_forms,
6686 union spoolss_FormInfo **info_p,
6689 union spoolss_FormInfo *info;
6690 WERROR result = WERR_OK;
6693 *count = num_builtin_forms + num_user_forms;
6695 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6696 W_ERROR_HAVE_NO_MEMORY(info);
6698 /* construct the list of form structures */
6699 for (i=0; i<num_builtin_forms; i++) {
6700 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6701 result = fill_form_info_1(info, &info[i].info1,
6703 if (!W_ERROR_IS_OK(result)) {
6708 for (i=0; i<num_user_forms; i++) {
6709 DEBUGADD(6,("Filling user form number [%d]\n",i));
6710 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6712 if (!W_ERROR_IS_OK(result)) {
6718 if (!W_ERROR_IS_OK(result)) {
6729 /****************************************************************
6731 ****************************************************************/
6733 WERROR _spoolss_EnumForms(pipes_struct *p,
6734 struct spoolss_EnumForms *r)
6737 nt_forms_struct *user_forms = NULL;
6738 nt_forms_struct *builtin_forms = NULL;
6739 uint32_t num_user_forms;
6740 uint32_t num_builtin_forms;
6744 *r->out.info = NULL;
6746 /* that's an [in out] buffer */
6748 if (!r->in.buffer && (r->in.offered != 0) ) {
6749 return WERR_INVALID_PARAM;
6752 DEBUG(4,("_spoolss_EnumForms\n"));
6753 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6754 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6756 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6757 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6758 num_user_forms = get_ntforms(&user_forms);
6759 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6761 if (num_user_forms + num_builtin_forms == 0) {
6762 SAFE_FREE(builtin_forms);
6763 SAFE_FREE(user_forms);
6764 return WERR_NO_MORE_ITEMS;
6767 switch (r->in.level) {
6769 result = spoolss_enumforms_level1(p->mem_ctx,
6778 result = WERR_UNKNOWN_LEVEL;
6782 SAFE_FREE(user_forms);
6783 SAFE_FREE(builtin_forms);
6785 if (!W_ERROR_IS_OK(result)) {
6789 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6791 *r->out.info, r->in.level,
6793 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6794 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6796 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6799 /****************************************************************
6800 ****************************************************************/
6802 static WERROR find_form_byname(const char *name,
6803 nt_forms_struct *form)
6805 nt_forms_struct *list = NULL;
6806 int num_forms = 0, i = 0;
6808 if (get_a_builtin_ntform_by_string(name, form)) {
6812 num_forms = get_ntforms(&list);
6813 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6815 if (num_forms == 0) {
6819 /* Check if the requested name is in the list of form structures */
6820 for (i = 0; i < num_forms; i++) {
6822 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6824 if (strequal(name, list[i].name)) {
6825 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6837 /****************************************************************
6839 ****************************************************************/
6841 WERROR _spoolss_GetForm(pipes_struct *p,
6842 struct spoolss_GetForm *r)
6845 nt_forms_struct form;
6847 /* that's an [in out] buffer */
6849 if (!r->in.buffer && (r->in.offered != 0)) {
6850 return WERR_INVALID_PARAM;
6853 DEBUG(4,("_spoolss_GetForm\n"));
6854 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6855 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6857 result = find_form_byname(r->in.form_name, &form);
6858 if (!W_ERROR_IS_OK(result)) {
6859 TALLOC_FREE(r->out.info);
6863 switch (r->in.level) {
6865 result = fill_form_info_1(p->mem_ctx,
6866 &r->out.info->info1,
6871 result = WERR_UNKNOWN_LEVEL;
6875 if (!W_ERROR_IS_OK(result)) {
6876 TALLOC_FREE(r->out.info);
6880 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6881 r->out.info, r->in.level);
6882 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6884 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6887 /****************************************************************************
6888 ****************************************************************************/
6890 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6891 struct spoolss_PortInfo1 *r,
6894 r->port_name = talloc_strdup(mem_ctx, name);
6895 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6900 /****************************************************************************
6901 TODO: This probably needs distinguish between TCP/IP and Local ports
6903 ****************************************************************************/
6905 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6906 struct spoolss_PortInfo2 *r,
6909 r->port_name = talloc_strdup(mem_ctx, name);
6910 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6912 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6913 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6915 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6916 W_ERROR_HAVE_NO_MEMORY(r->description);
6918 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6925 /****************************************************************************
6926 wrapper around the enumer ports command
6927 ****************************************************************************/
6929 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6931 char *cmd = lp_enumports_cmd();
6932 char **qlines = NULL;
6933 char *command = NULL;
6941 /* if no hook then just fill in the default port */
6944 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6947 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6948 TALLOC_FREE(qlines);
6955 /* we have a valid enumport command */
6957 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6962 DEBUG(10,("Running [%s]\n", command));
6963 ret = smbrun(command, &fd);
6964 DEBUG(10,("Returned [%d]\n", ret));
6965 TALLOC_FREE(command);
6970 return WERR_ACCESS_DENIED;
6974 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6975 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6985 /****************************************************************************
6987 ****************************************************************************/
6989 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6990 union spoolss_PortInfo **info_p,
6993 union spoolss_PortInfo *info = NULL;
6995 WERROR result = WERR_OK;
6996 char **qlines = NULL;
6999 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7000 if (!W_ERROR_IS_OK(result)) {
7005 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7007 DEBUG(10,("Returning WERR_NOMEM\n"));
7008 result = WERR_NOMEM;
7012 for (i=0; i<numlines; i++) {
7013 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7014 result = fill_port_1(info, &info[i].info1, qlines[i]);
7015 if (!W_ERROR_IS_OK(result)) {
7020 TALLOC_FREE(qlines);
7023 if (!W_ERROR_IS_OK(result)) {
7025 TALLOC_FREE(qlines);
7037 /****************************************************************************
7039 ****************************************************************************/
7041 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7042 union spoolss_PortInfo **info_p,
7045 union spoolss_PortInfo *info = NULL;
7047 WERROR result = WERR_OK;
7048 char **qlines = NULL;
7051 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7052 if (!W_ERROR_IS_OK(result)) {
7057 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7059 DEBUG(10,("Returning WERR_NOMEM\n"));
7060 result = WERR_NOMEM;
7064 for (i=0; i<numlines; i++) {
7065 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7066 result = fill_port_2(info, &info[i].info2, qlines[i]);
7067 if (!W_ERROR_IS_OK(result)) {
7072 TALLOC_FREE(qlines);
7075 if (!W_ERROR_IS_OK(result)) {
7077 TALLOC_FREE(qlines);
7089 /****************************************************************
7091 ****************************************************************/
7093 WERROR _spoolss_EnumPorts(pipes_struct *p,
7094 struct spoolss_EnumPorts *r)
7098 /* that's an [in out] buffer */
7100 if (!r->in.buffer && (r->in.offered != 0)) {
7101 return WERR_INVALID_PARAM;
7104 DEBUG(4,("_spoolss_EnumPorts\n"));
7108 *r->out.info = NULL;
7110 switch (r->in.level) {
7112 result = enumports_level_1(p->mem_ctx, r->out.info,
7116 result = enumports_level_2(p->mem_ctx, r->out.info,
7120 return WERR_UNKNOWN_LEVEL;
7123 if (!W_ERROR_IS_OK(result)) {
7127 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7129 *r->out.info, r->in.level,
7131 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7132 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7134 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7137 /****************************************************************************
7138 ****************************************************************************/
7140 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7142 struct spoolss_SetPrinterInfoCtr *info_ctr,
7143 struct spoolss_DeviceMode *devmode,
7144 struct security_descriptor *sec_desc,
7145 struct spoolss_UserLevelCtr *user_ctr,
7146 struct policy_handle *handle)
7148 NT_PRINTER_INFO_LEVEL *printer = NULL;
7151 WERROR err = WERR_OK;
7153 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7154 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7158 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7159 if (!convert_printer_info(info_ctr, printer)) {
7160 free_a_printer(&printer, 2);
7164 /* samba does not have a concept of local, non-shared printers yet, so
7165 * make sure we always setup sharename - gd */
7166 if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7167 DEBUG(5, ("spoolss_addprinterex_level_2: "
7168 "no sharename has been set, setting printername %s as sharename\n",
7169 printer->info_2->printername));
7170 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7173 /* check to see if the printer already exists */
7175 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7176 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7177 printer->info_2->sharename));
7178 free_a_printer(&printer, 2);
7179 return WERR_PRINTER_ALREADY_EXISTS;
7182 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7183 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7184 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7185 printer->info_2->printername));
7186 free_a_printer(&printer, 2);
7187 return WERR_PRINTER_ALREADY_EXISTS;
7191 /* validate printer info struct */
7192 if (!info_ctr->info.info2->printername ||
7193 strlen(info_ctr->info.info2->printername) == 0) {
7194 free_a_printer(&printer,2);
7195 return WERR_INVALID_PRINTER_NAME;
7197 if (!info_ctr->info.info2->portname ||
7198 strlen(info_ctr->info.info2->portname) == 0) {
7199 free_a_printer(&printer,2);
7200 return WERR_UNKNOWN_PORT;
7202 if (!info_ctr->info.info2->drivername ||
7203 strlen(info_ctr->info.info2->drivername) == 0) {
7204 free_a_printer(&printer,2);
7205 return WERR_UNKNOWN_PRINTER_DRIVER;
7207 if (!info_ctr->info.info2->printprocessor ||
7208 strlen(info_ctr->info.info2->printprocessor) == 0) {
7209 free_a_printer(&printer,2);
7210 return WERR_UNKNOWN_PRINTPROCESSOR;
7213 /* FIXME!!! smbd should check to see if the driver is installed before
7214 trying to add a printer like this --jerry */
7216 if (*lp_addprinter_cmd() ) {
7217 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7219 free_a_printer(&printer,2);
7220 return WERR_ACCESS_DENIED;
7223 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7224 "smb.conf parameter \"addprinter command\" is defined. This"
7225 "parameter must exist for this call to succeed\n",
7226 printer->info_2->sharename ));
7229 /* use our primary netbios name since get_a_printer() will convert
7230 it to what the client expects on a case by case basis */
7232 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7233 printer->info_2->sharename);
7236 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7237 free_a_printer(&printer,2);
7238 return WERR_ACCESS_DENIED;
7241 /* you must be a printer admin to add a new printer */
7242 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7243 free_a_printer(&printer,2);
7244 return WERR_ACCESS_DENIED;
7248 * Do sanity check on the requested changes for Samba.
7251 if (!check_printer_ok(printer->info_2, snum)) {
7252 free_a_printer(&printer,2);
7253 return WERR_INVALID_PARAM;
7257 * When a printer is created, the drivername bound to the printer is used
7258 * to lookup previously saved driver initialization info, which is then
7259 * bound to the new printer, simulating what happens in the Windows arch.
7264 /* A valid devmode was included, convert and link it
7266 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7268 if (!convert_devicemode(printer->info_2->printername, devmode,
7269 &printer->info_2->devmode)) {
7274 /* write the ASCII on disk */
7275 err = mod_a_printer(printer, 2);
7276 if (!W_ERROR_IS_OK(err)) {
7277 free_a_printer(&printer,2);
7281 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7282 /* Handle open failed - remove addition. */
7283 del_a_printer(printer->info_2->sharename);
7284 free_a_printer(&printer,2);
7285 ZERO_STRUCTP(handle);
7286 return WERR_ACCESS_DENIED;
7289 update_c_setprinter(false);
7290 free_a_printer(&printer,2);
7295 /****************************************************************
7296 _spoolss_AddPrinterEx
7297 ****************************************************************/
7299 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7300 struct spoolss_AddPrinterEx *r)
7302 switch (r->in.info_ctr->level) {
7304 /* we don't handle yet */
7305 /* but I know what to do ... */
7306 return WERR_UNKNOWN_LEVEL;
7308 return spoolss_addprinterex_level_2(p, r->in.server,
7310 r->in.devmode_ctr->devmode,
7311 r->in.secdesc_ctr->sd,
7312 r->in.userlevel_ctr,
7315 return WERR_UNKNOWN_LEVEL;
7319 /****************************************************************
7321 ****************************************************************/
7323 WERROR _spoolss_AddPrinter(pipes_struct *p,
7324 struct spoolss_AddPrinter *r)
7326 struct spoolss_AddPrinterEx a;
7327 struct spoolss_UserLevelCtr userlevel_ctr;
7329 ZERO_STRUCT(userlevel_ctr);
7331 userlevel_ctr.level = 1;
7333 a.in.server = r->in.server;
7334 a.in.info_ctr = r->in.info_ctr;
7335 a.in.devmode_ctr = r->in.devmode_ctr;
7336 a.in.secdesc_ctr = r->in.secdesc_ctr;
7337 a.in.userlevel_ctr = &userlevel_ctr;
7338 a.out.handle = r->out.handle;
7340 return _spoolss_AddPrinterEx(p, &a);
7343 /****************************************************************
7344 _spoolss_AddPrinterDriverEx
7345 ****************************************************************/
7347 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7348 struct spoolss_AddPrinterDriverEx *r)
7350 WERROR err = WERR_OK;
7351 char *driver_name = NULL;
7356 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7357 fn = "_spoolss_AddPrinterDriver";
7359 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7360 fn = "_spoolss_AddPrinterDriverEx";
7363 return WERR_INVALID_PARAM;
7367 * we only support the semantics of AddPrinterDriver()
7368 * i.e. only copy files that are newer than existing ones
7371 if (r->in.flags == 0) {
7372 return WERR_INVALID_PARAM;
7375 if (r->in.flags != APD_COPY_NEW_FILES) {
7376 return WERR_ACCESS_DENIED;
7380 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7381 /* Clever hack from Martin Zielinski <mz@seh.de>
7382 * to allow downgrade from level 8 (Vista).
7384 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7385 r->in.info_ctr->level));
7386 return WERR_UNKNOWN_LEVEL;
7389 DEBUG(5,("Cleaning driver's information\n"));
7390 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7391 if (!W_ERROR_IS_OK(err))
7394 DEBUG(5,("Moving driver to final destination\n"));
7395 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7400 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7401 err = WERR_ACCESS_DENIED;
7406 * I think this is where he DrvUpgradePrinter() hook would be
7407 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7408 * server. Right now, we just need to send ourselves a message
7409 * to update each printer bound to this driver. --jerry
7412 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7413 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7421 /****************************************************************
7422 _spoolss_AddPrinterDriver
7423 ****************************************************************/
7425 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7426 struct spoolss_AddPrinterDriver *r)
7428 struct spoolss_AddPrinterDriverEx a;
7430 switch (r->in.info_ctr->level) {
7437 return WERR_UNKNOWN_LEVEL;
7440 a.in.servername = r->in.servername;
7441 a.in.info_ctr = r->in.info_ctr;
7442 a.in.flags = APD_COPY_NEW_FILES;
7444 return _spoolss_AddPrinterDriverEx(p, &a);
7447 /****************************************************************************
7448 ****************************************************************************/
7450 struct _spoolss_paths {
7456 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7458 static const struct _spoolss_paths spoolss_paths[]= {
7459 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7460 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7463 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7464 const char *servername,
7465 const char *environment,
7469 const char *pservername = NULL;
7470 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7471 const char *short_archi;
7475 /* environment may be empty */
7476 if (environment && strlen(environment)) {
7477 long_archi = environment;
7480 /* servername may be empty */
7481 if (servername && strlen(servername)) {
7482 pservername = canon_servername(servername);
7484 if (!is_myname_or_ipaddr(pservername)) {
7485 return WERR_INVALID_PARAM;
7489 if (!(short_archi = get_short_archi(long_archi))) {
7490 return WERR_INVALID_ENVIRONMENT;
7493 switch (component) {
7494 case SPOOLSS_PRTPROCS_PATH:
7495 case SPOOLSS_DRIVER_PATH:
7497 *path = talloc_asprintf(mem_ctx,
7500 spoolss_paths[component].share,
7503 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7504 SPOOLSS_DEFAULT_SERVER_PATH,
7505 spoolss_paths[component].dir,
7510 return WERR_INVALID_PARAM;
7520 /****************************************************************************
7521 ****************************************************************************/
7523 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7524 const char *servername,
7525 const char *environment,
7526 struct spoolss_DriverDirectoryInfo1 *r)
7531 werr = compose_spoolss_server_path(mem_ctx,
7534 SPOOLSS_DRIVER_PATH,
7536 if (!W_ERROR_IS_OK(werr)) {
7540 DEBUG(4,("printer driver directory: [%s]\n", path));
7542 r->directory_name = path;
7547 /****************************************************************
7548 _spoolss_GetPrinterDriverDirectory
7549 ****************************************************************/
7551 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7552 struct spoolss_GetPrinterDriverDirectory *r)
7556 /* that's an [in out] buffer */
7558 if (!r->in.buffer && (r->in.offered != 0)) {
7559 return WERR_INVALID_PARAM;
7562 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7567 /* r->in.level is ignored */
7569 werror = getprinterdriverdir_level_1(p->mem_ctx,
7572 &r->out.info->info1);
7573 if (!W_ERROR_IS_OK(werror)) {
7574 TALLOC_FREE(r->out.info);
7578 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7579 r->out.info, r->in.level);
7580 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7582 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7585 /****************************************************************
7586 _spoolss_EnumPrinterData
7587 ****************************************************************/
7589 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7590 struct spoolss_EnumPrinterData *r)
7593 struct spoolss_EnumPrinterDataEx r2;
7595 struct spoolss_PrinterEnumValues *info, *val = NULL;
7598 r2.in.handle = r->in.handle;
7599 r2.in.key_name = "PrinterDriverData";
7601 r2.out.count = &count;
7602 r2.out.info = &info;
7603 r2.out.needed = &needed;
7605 result = _spoolss_EnumPrinterDataEx(p, &r2);
7606 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7607 r2.in.offered = needed;
7608 result = _spoolss_EnumPrinterDataEx(p, &r2);
7610 if (!W_ERROR_IS_OK(result)) {
7615 * The NT machine wants to know the biggest size of value and data
7617 * cf: MSDN EnumPrinterData remark section
7620 if (!r->in.value_offered && !r->in.data_offered) {
7621 uint32_t biggest_valuesize = 0;
7622 uint32_t biggest_datasize = 0;
7625 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7627 for (i=0; i<count; i++) {
7629 name_length = strlen(info[i].value_name);
7630 if (strlen(info[i].value_name) > biggest_valuesize) {
7631 biggest_valuesize = name_length;
7634 if (info[i].data_length > biggest_datasize) {
7635 biggest_datasize = info[i].data_length;
7638 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7642 /* the value is an UNICODE string but real_value_size is the length
7643 in bytes including the trailing 0 */
7645 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7646 *r->out.data_needed = biggest_datasize;
7648 DEBUG(6,("final values: [%d], [%d]\n",
7649 *r->out.value_needed, *r->out.data_needed));
7654 if (r->in.enum_index < count) {
7655 val = &info[r->in.enum_index];
7659 /* out_value should default to "" or else NT4 has
7660 problems unmarshalling the response */
7662 if (r->in.value_offered) {
7663 *r->out.value_needed = 1;
7664 r->out.value_name = talloc_strdup(r, "");
7665 if (!r->out.value_name) {
7669 r->out.value_name = NULL;
7670 *r->out.value_needed = 0;
7673 /* the data is counted in bytes */
7675 *r->out.data_needed = r->in.data_offered;
7677 result = WERR_NO_MORE_ITEMS;
7681 * - counted in bytes in the request
7682 * - counted in UNICODE chars in the max reply
7683 * - counted in bytes in the real size
7685 * take a pause *before* coding not *during* coding
7689 if (r->in.value_offered) {
7690 r->out.value_name = talloc_strdup(r, val->value_name);
7691 if (!r->out.value_name) {
7694 *r->out.value_needed = val->value_name_len;
7696 r->out.value_name = NULL;
7697 *r->out.value_needed = 0;
7702 *r->out.type = val->type;
7704 /* data - counted in bytes */
7707 * See the section "Dynamically Typed Query Parameters"
7711 if (r->out.data && val->data && val->data->data &&
7712 val->data_length && r->in.data_offered) {
7713 memcpy(r->out.data, val->data->data,
7714 MIN(val->data_length,r->in.data_offered));
7717 *r->out.data_needed = val->data_length;
7725 /****************************************************************
7726 _spoolss_SetPrinterData
7727 ****************************************************************/
7729 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7730 struct spoolss_SetPrinterData *r)
7732 struct spoolss_SetPrinterDataEx r2;
7734 r2.in.handle = r->in.handle;
7735 r2.in.key_name = "PrinterDriverData";
7736 r2.in.value_name = r->in.value_name;
7737 r2.in.type = r->in.type;
7738 r2.in.data = r->in.data;
7739 r2.in.offered = r->in.offered;
7741 return _spoolss_SetPrinterDataEx(p, &r2);
7744 /****************************************************************
7745 _spoolss_ResetPrinter
7746 ****************************************************************/
7748 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7749 struct spoolss_ResetPrinter *r)
7751 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7754 DEBUG(5,("_spoolss_ResetPrinter\n"));
7757 * All we do is to check to see if the handle and queue is valid.
7758 * This call really doesn't mean anything to us because we only
7759 * support RAW printing. --jerry
7763 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7764 OUR_HANDLE(r->in.handle)));
7768 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7772 /* blindly return success */
7776 /****************************************************************
7777 _spoolss_DeletePrinterData
7778 ****************************************************************/
7780 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7781 struct spoolss_DeletePrinterData *r)
7783 struct spoolss_DeletePrinterDataEx r2;
7785 r2.in.handle = r->in.handle;
7786 r2.in.key_name = "PrinterDriverData";
7787 r2.in.value_name = r->in.value_name;
7789 return _spoolss_DeletePrinterDataEx(p, &r2);
7792 /****************************************************************
7794 ****************************************************************/
7796 WERROR _spoolss_AddForm(pipes_struct *p,
7797 struct spoolss_AddForm *r)
7799 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7800 nt_forms_struct tmpForm;
7802 WERROR status = WERR_OK;
7803 NT_PRINTER_INFO_LEVEL *printer = NULL;
7804 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7807 nt_forms_struct *list=NULL;
7808 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7811 DEBUG(5,("_spoolss_AddForm\n"));
7814 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7815 OUR_HANDLE(r->in.handle)));
7820 /* forms can be added on printer or on the print server handle */
7822 if ( Printer->printer_type == SPLHND_PRINTER )
7824 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7827 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7828 if (!W_ERROR_IS_OK(status))
7832 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7833 and not a printer admin, then fail */
7835 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7836 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7837 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7838 p->server_info->info3->base.domain.string,
7840 p->server_info->ptok,
7841 lp_printer_admin(snum))) {
7842 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7843 status = WERR_ACCESS_DENIED;
7847 switch (form->flags) {
7848 case SPOOLSS_FORM_USER:
7849 case SPOOLSS_FORM_BUILTIN:
7850 case SPOOLSS_FORM_PRINTER:
7853 status = WERR_INVALID_PARAM;
7857 /* can't add if builtin */
7859 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7860 status = WERR_FILE_EXISTS;
7864 count = get_ntforms(&list);
7866 for (i=0; i < count; i++) {
7867 if (strequal(form->form_name, list[i].name)) {
7868 status = WERR_FILE_EXISTS;
7873 if(!add_a_form(&list, form, &count)) {
7874 status = WERR_NOMEM;
7879 write_ntforms(&list, count);
7883 * ChangeID must always be set if this is a printer
7886 if ( Printer->printer_type == SPLHND_PRINTER )
7887 status = mod_a_printer(printer, 2);
7891 free_a_printer(&printer, 2);
7897 /****************************************************************
7899 ****************************************************************/
7901 WERROR _spoolss_DeleteForm(pipes_struct *p,
7902 struct spoolss_DeleteForm *r)
7904 const char *form_name = r->in.form_name;
7905 nt_forms_struct tmpForm;
7907 nt_forms_struct *list=NULL;
7908 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7910 WERROR status = WERR_OK;
7911 NT_PRINTER_INFO_LEVEL *printer = NULL;
7912 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7915 DEBUG(5,("_spoolss_DeleteForm\n"));
7918 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7919 OUR_HANDLE(r->in.handle)));
7923 /* forms can be deleted on printer of on the print server handle */
7925 if ( Printer->printer_type == SPLHND_PRINTER )
7927 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7930 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7931 if (!W_ERROR_IS_OK(status))
7935 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7936 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7937 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7938 p->server_info->info3->base.domain.string,
7940 p->server_info->ptok,
7941 lp_printer_admin(snum))) {
7942 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7943 return WERR_ACCESS_DENIED;
7947 /* can't delete if builtin */
7949 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7950 status = WERR_INVALID_PARAM;
7954 count = get_ntforms(&list);
7957 ret = delete_a_form(&list, form_name, &count, &status);
7964 * ChangeID must always be set if this is a printer
7967 if ( Printer->printer_type == SPLHND_PRINTER )
7968 status = mod_a_printer(printer, 2);
7972 free_a_printer(&printer, 2);
7978 /****************************************************************
7980 ****************************************************************/
7982 WERROR _spoolss_SetForm(pipes_struct *p,
7983 struct spoolss_SetForm *r)
7985 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7986 nt_forms_struct tmpForm;
7988 WERROR status = WERR_OK;
7989 NT_PRINTER_INFO_LEVEL *printer = NULL;
7990 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7993 nt_forms_struct *list=NULL;
7994 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7996 DEBUG(5,("_spoolss_SetForm\n"));
7999 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8000 OUR_HANDLE(r->in.handle)));
8004 /* forms can be modified on printer of on the print server handle */
8006 if ( Printer->printer_type == SPLHND_PRINTER )
8008 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8011 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8012 if (!W_ERROR_IS_OK(status))
8016 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8017 and not a printer admin, then fail */
8019 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8020 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8021 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8022 p->server_info->info3->base.domain.string,
8024 p->server_info->ptok,
8025 lp_printer_admin(snum))) {
8026 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8027 status = WERR_ACCESS_DENIED;
8031 /* can't set if builtin */
8032 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8033 status = WERR_INVALID_PARAM;
8037 count = get_ntforms(&list);
8038 update_a_form(&list, form, count);
8040 write_ntforms(&list, count);
8044 * ChangeID must always be set if this is a printer
8047 if ( Printer->printer_type == SPLHND_PRINTER )
8048 status = mod_a_printer(printer, 2);
8053 free_a_printer(&printer, 2);
8059 /****************************************************************************
8060 fill_print_processor1
8061 ****************************************************************************/
8063 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8064 struct spoolss_PrintProcessorInfo1 *r,
8065 const char *print_processor_name)
8067 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8068 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8073 /****************************************************************************
8074 enumprintprocessors level 1.
8075 ****************************************************************************/
8077 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8078 union spoolss_PrintProcessorInfo **info_p,
8081 union spoolss_PrintProcessorInfo *info;
8084 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8085 W_ERROR_HAVE_NO_MEMORY(info);
8089 result = fill_print_processor1(info, &info[0].info1, "winprint");
8090 if (!W_ERROR_IS_OK(result)) {
8095 if (!W_ERROR_IS_OK(result)) {
8106 /****************************************************************
8107 _spoolss_EnumPrintProcessors
8108 ****************************************************************/
8110 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8111 struct spoolss_EnumPrintProcessors *r)
8115 /* that's an [in out] buffer */
8117 if (!r->in.buffer && (r->in.offered != 0)) {
8118 return WERR_INVALID_PARAM;
8121 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8124 * Enumerate the print processors ...
8126 * Just reply with "winprint", to keep NT happy
8127 * and I can use my nice printer checker.
8132 *r->out.info = NULL;
8134 switch (r->in.level) {
8136 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8140 return WERR_UNKNOWN_LEVEL;
8143 if (!W_ERROR_IS_OK(result)) {
8147 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8148 spoolss_EnumPrintProcessors,
8149 *r->out.info, r->in.level,
8151 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8152 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8154 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8157 /****************************************************************************
8158 fill_printprocdatatype1
8159 ****************************************************************************/
8161 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8162 struct spoolss_PrintProcDataTypesInfo1 *r,
8163 const char *name_array)
8165 r->name_array = talloc_strdup(mem_ctx, name_array);
8166 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8171 /****************************************************************************
8172 enumprintprocdatatypes level 1.
8173 ****************************************************************************/
8175 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8176 union spoolss_PrintProcDataTypesInfo **info_p,
8180 union spoolss_PrintProcDataTypesInfo *info;
8182 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8183 W_ERROR_HAVE_NO_MEMORY(info);
8187 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8188 if (!W_ERROR_IS_OK(result)) {
8193 if (!W_ERROR_IS_OK(result)) {
8204 /****************************************************************
8205 _spoolss_EnumPrintProcDataTypes
8206 ****************************************************************/
8208 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8209 struct spoolss_EnumPrintProcDataTypes *r)
8213 /* that's an [in out] buffer */
8215 if (!r->in.buffer && (r->in.offered != 0)) {
8216 return WERR_INVALID_PARAM;
8219 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8223 *r->out.info = NULL;
8225 switch (r->in.level) {
8227 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8231 return WERR_UNKNOWN_LEVEL;
8234 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8235 spoolss_EnumPrintProcDataTypes,
8236 *r->out.info, r->in.level,
8238 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8239 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8241 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8244 /****************************************************************************
8246 ****************************************************************************/
8248 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8249 struct spoolss_MonitorInfo1 *r,
8250 const char *monitor_name)
8252 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8253 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8258 /****************************************************************************
8260 ****************************************************************************/
8262 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8263 struct spoolss_MonitorInfo2 *r,
8264 const char *monitor_name,
8265 const char *environment,
8266 const char *dll_name)
8268 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8269 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8270 r->environment = talloc_strdup(mem_ctx, environment);
8271 W_ERROR_HAVE_NO_MEMORY(r->environment);
8272 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8273 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8278 /****************************************************************************
8279 enumprintmonitors level 1.
8280 ****************************************************************************/
8282 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8283 union spoolss_MonitorInfo **info_p,
8286 union spoolss_MonitorInfo *info;
8287 WERROR result = WERR_OK;
8289 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8290 W_ERROR_HAVE_NO_MEMORY(info);
8294 result = fill_monitor_1(info, &info[0].info1,
8296 if (!W_ERROR_IS_OK(result)) {
8300 result = fill_monitor_1(info, &info[1].info1,
8302 if (!W_ERROR_IS_OK(result)) {
8307 if (!W_ERROR_IS_OK(result)) {
8318 /****************************************************************************
8319 enumprintmonitors level 2.
8320 ****************************************************************************/
8322 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8323 union spoolss_MonitorInfo **info_p,
8326 union spoolss_MonitorInfo *info;
8327 WERROR result = WERR_OK;
8329 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8330 W_ERROR_HAVE_NO_MEMORY(info);
8334 result = fill_monitor_2(info, &info[0].info2,
8336 "Windows NT X86", /* FIXME */
8338 if (!W_ERROR_IS_OK(result)) {
8342 result = fill_monitor_2(info, &info[1].info2,
8344 "Windows NT X86", /* FIXME */
8346 if (!W_ERROR_IS_OK(result)) {
8351 if (!W_ERROR_IS_OK(result)) {
8362 /****************************************************************
8363 _spoolss_EnumMonitors
8364 ****************************************************************/
8366 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8367 struct spoolss_EnumMonitors *r)
8371 /* that's an [in out] buffer */
8373 if (!r->in.buffer && (r->in.offered != 0)) {
8374 return WERR_INVALID_PARAM;
8377 DEBUG(5,("_spoolss_EnumMonitors\n"));
8380 * Enumerate the print monitors ...
8382 * Just reply with "Local Port", to keep NT happy
8383 * and I can use my nice printer checker.
8388 *r->out.info = NULL;
8390 switch (r->in.level) {
8392 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8396 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8400 return WERR_UNKNOWN_LEVEL;
8403 if (!W_ERROR_IS_OK(result)) {
8407 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8408 spoolss_EnumMonitors,
8409 *r->out.info, r->in.level,
8411 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8412 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8414 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8417 /****************************************************************************
8418 ****************************************************************************/
8420 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8421 const print_queue_struct *queue,
8422 int count, int snum,
8423 const NT_PRINTER_INFO_LEVEL *ntprinter,
8425 struct spoolss_JobInfo1 *r)
8430 for (i=0; i<count; i++) {
8431 if (queue[i].job == (int)jobid) {
8437 if (found == false) {
8438 /* NT treats not found as bad param... yet another bad choice */
8439 return WERR_INVALID_PARAM;
8442 return fill_job_info1(mem_ctx,
8450 /****************************************************************************
8451 ****************************************************************************/
8453 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8454 const print_queue_struct *queue,
8455 int count, int snum,
8456 const NT_PRINTER_INFO_LEVEL *ntprinter,
8458 struct spoolss_JobInfo2 *r)
8462 struct spoolss_DeviceMode *devmode;
8463 NT_DEVICEMODE *nt_devmode;
8466 for (i=0; i<count; i++) {
8467 if (queue[i].job == (int)jobid) {
8473 if (found == false) {
8474 /* NT treats not found as bad param... yet another bad
8476 return WERR_INVALID_PARAM;
8480 * if the print job does not have a DEVMODE associated with it,
8481 * just use the one for the printer. A NULL devicemode is not
8482 * a failure condition
8485 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8487 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8488 W_ERROR_HAVE_NO_MEMORY(devmode);
8489 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8490 if (!W_ERROR_IS_OK(result)) {
8494 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8495 W_ERROR_HAVE_NO_MEMORY(devmode);
8498 return fill_job_info2(mem_ctx,
8507 /****************************************************************
8509 ****************************************************************/
8511 WERROR _spoolss_GetJob(pipes_struct *p,
8512 struct spoolss_GetJob *r)
8514 WERROR result = WERR_OK;
8515 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8518 print_queue_struct *queue = NULL;
8519 print_status_struct prt_status;
8521 /* that's an [in out] buffer */
8523 if (!r->in.buffer && (r->in.offered != 0)) {
8524 return WERR_INVALID_PARAM;
8527 DEBUG(5,("_spoolss_GetJob\n"));
8531 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8535 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8536 if (!W_ERROR_IS_OK(result)) {
8540 count = print_queue_status(snum, &queue, &prt_status);
8542 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8543 count, prt_status.status, prt_status.message));
8545 switch (r->in.level) {
8547 result = getjob_level_1(p->mem_ctx,
8548 queue, count, snum, ntprinter,
8549 r->in.job_id, &r->out.info->info1);
8552 result = getjob_level_2(p->mem_ctx,
8553 queue, count, snum, ntprinter,
8554 r->in.job_id, &r->out.info->info2);
8557 result = WERR_UNKNOWN_LEVEL;
8562 free_a_printer(&ntprinter, 2);
8564 if (!W_ERROR_IS_OK(result)) {
8565 TALLOC_FREE(r->out.info);
8569 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8571 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8573 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8576 /****************************************************************
8577 _spoolss_GetPrinterDataEx
8578 ****************************************************************/
8580 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8581 struct spoolss_GetPrinterDataEx *r)
8584 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8585 struct regval_blob *val = NULL;
8586 NT_PRINTER_INFO_LEVEL *printer = NULL;
8588 WERROR result = WERR_OK;
8591 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8593 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8594 r->in.key_name, r->in.value_name));
8596 /* in case of problem, return some default values */
8599 *r->out.type = REG_NONE;
8602 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8603 OUR_HANDLE(r->in.handle)));
8604 result = WERR_BADFID;
8608 /* Is the handle to a printer or to the server? */
8610 if (Printer->printer_type == SPLHND_SERVER) {
8612 union spoolss_PrinterData data;
8614 result = getprinterdata_printer_server(p->mem_ctx,
8618 if (!W_ERROR_IS_OK(result)) {
8622 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8623 *r->out.type, &data);
8624 if (!W_ERROR_IS_OK(result)) {
8628 *r->out.needed = blob.length;
8630 if (r->in.offered >= *r->out.needed) {
8631 memcpy(r->out.data, blob.data, blob.length);
8634 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8637 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8638 result = WERR_BADFID;
8642 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8643 if (!W_ERROR_IS_OK(result)) {
8647 /* check to see if the keyname is valid */
8648 if (!strlen(r->in.key_name)) {
8649 result = WERR_INVALID_PARAM;
8653 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8655 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8656 strequal(r->in.value_name, "ChangeId")) {
8657 *r->out.type = REG_DWORD;
8659 if (r->in.offered >= *r->out.needed) {
8660 SIVAL(r->out.data, 0, printer->info_2->changeid);
8666 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8667 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8668 "Invalid keyname [%s]\n", r->in.key_name ));
8669 result = WERR_BADFILE;
8673 val = get_printer_data(printer->info_2,
8674 r->in.key_name, r->in.value_name);
8676 result = WERR_BADFILE;
8680 *r->out.needed = regval_size(val);
8681 *r->out.type = regval_type(val);
8683 if (r->in.offered >= *r->out.needed) {
8684 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8688 free_a_printer(&printer, 2);
8691 if (!W_ERROR_IS_OK(result)) {
8695 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8696 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8698 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8701 /****************************************************************
8702 _spoolss_SetPrinterDataEx
8703 ****************************************************************/
8705 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8706 struct spoolss_SetPrinterDataEx *r)
8708 NT_PRINTER_INFO_LEVEL *printer = NULL;
8710 WERROR result = WERR_OK;
8711 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8714 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8716 /* From MSDN documentation of SetPrinterDataEx: pass request to
8717 SetPrinterData if key is "PrinterDriverData" */
8720 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8721 OUR_HANDLE(r->in.handle)));
8725 if (Printer->printer_type == SPLHND_SERVER) {
8726 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8727 "Not implemented for server handles yet\n"));
8728 return WERR_INVALID_PARAM;
8731 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8736 * Access check : NT returns "access denied" if you make a
8737 * SetPrinterData call without the necessary privildge.
8738 * we were originally returning OK if nothing changed
8739 * which made Win2k issue **a lot** of SetPrinterData
8740 * when connecting to a printer --jerry
8743 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8744 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8745 "change denied by handle access permissions\n"));
8746 return WERR_ACCESS_DENIED;
8749 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8750 if (!W_ERROR_IS_OK(result)) {
8754 /* check for OID in valuename */
8756 oid_string = strchr(r->in.value_name, ',');
8762 /* save the registry data */
8764 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8765 r->in.type, r->in.data, r->in.offered);
8767 if (W_ERROR_IS_OK(result)) {
8768 /* save the OID if one was specified */
8770 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8771 r->in.key_name, SPOOL_OID_KEY);
8773 result = WERR_NOMEM;
8778 * I'm not checking the status here on purpose. Don't know
8779 * if this is right, but I'm returning the status from the
8780 * previous set_printer_dataex() call. I have no idea if
8781 * this is right. --jerry
8784 set_printer_dataex(printer, str, r->in.value_name,
8785 REG_SZ, (uint8_t *)oid_string,
8786 strlen(oid_string)+1);
8789 result = mod_a_printer(printer, 2);
8793 free_a_printer(&printer, 2);
8798 /****************************************************************
8799 _spoolss_DeletePrinterDataEx
8800 ****************************************************************/
8802 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8803 struct spoolss_DeletePrinterDataEx *r)
8805 NT_PRINTER_INFO_LEVEL *printer = NULL;
8807 WERROR status = WERR_OK;
8808 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8810 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8813 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8814 "Invalid handle (%s:%u:%u).\n",
8815 OUR_HANDLE(r->in.handle)));
8819 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8822 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8823 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8824 "printer properties change denied by handle\n"));
8825 return WERR_ACCESS_DENIED;
8828 if (!r->in.value_name || !r->in.key_name) {
8832 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8833 if (!W_ERROR_IS_OK(status))
8836 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8838 if ( W_ERROR_IS_OK(status) )
8839 mod_a_printer( printer, 2 );
8841 free_a_printer(&printer, 2);
8846 /****************************************************************
8847 _spoolss_EnumPrinterKey
8848 ****************************************************************/
8850 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8851 struct spoolss_EnumPrinterKey *r)
8853 fstring *keynames = NULL;
8855 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8856 NT_PRINTER_DATA *data;
8857 NT_PRINTER_INFO_LEVEL *printer = NULL;
8859 WERROR result = WERR_BADFILE;
8861 const char **array = NULL;
8864 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8867 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8868 OUR_HANDLE(r->in.handle)));
8872 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8876 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8877 if (!W_ERROR_IS_OK(result)) {
8881 /* get the list of subkey names */
8883 data = printer->info_2->data;
8885 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8886 if (num_keys == -1) {
8887 result = WERR_BADFILE;
8891 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8893 result = WERR_NOMEM;
8898 array[0] = talloc_strdup(array, "");
8900 result = WERR_NOMEM;
8905 for (i=0; i < num_keys; i++) {
8907 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8910 array[i] = talloc_strdup(array, keynames[i]);
8912 result = WERR_NOMEM;
8917 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8918 result = WERR_NOMEM;
8922 *r->out._ndr_size = r->in.offered / 2;
8923 *r->out.needed = blob.length;
8925 if (r->in.offered < *r->out.needed) {
8926 result = WERR_MORE_DATA;
8929 r->out.key_buffer->string_array = array;
8933 if (!W_ERROR_IS_OK(result)) {
8935 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8940 free_a_printer(&printer, 2);
8941 SAFE_FREE(keynames);
8946 /****************************************************************
8947 _spoolss_DeletePrinterKey
8948 ****************************************************************/
8950 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8951 struct spoolss_DeletePrinterKey *r)
8953 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8954 NT_PRINTER_INFO_LEVEL *printer = NULL;
8958 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8961 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8962 OUR_HANDLE(r->in.handle)));
8966 /* if keyname == NULL, return error */
8968 if ( !r->in.key_name )
8969 return WERR_INVALID_PARAM;
8971 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8974 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8975 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8976 "printer properties change denied by handle\n"));
8977 return WERR_ACCESS_DENIED;
8980 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8981 if (!W_ERROR_IS_OK(status))
8984 /* delete the key and all subneys */
8986 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8988 if ( W_ERROR_IS_OK(status) )
8989 status = mod_a_printer(printer, 2);
8991 free_a_printer( &printer, 2 );
8996 /****************************************************************
8997 ****************************************************************/
8999 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9000 struct regval_blob *v,
9001 struct spoolss_PrinterEnumValues *r)
9003 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9004 W_ERROR_HAVE_NO_MEMORY(r->data);
9006 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9007 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9009 r->value_name_len = strlen_m_term(regval_name(v)) * 2;
9011 r->type = regval_type(v);
9012 r->data_length = regval_size(v);
9014 if (r->data_length) {
9015 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9021 /****************************************************************
9022 _spoolss_EnumPrinterDataEx
9023 ****************************************************************/
9025 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9026 struct spoolss_EnumPrinterDataEx *r)
9029 NT_PRINTER_INFO_LEVEL *printer = NULL;
9030 struct spoolss_PrinterEnumValues *info = NULL;
9031 NT_PRINTER_DATA *p_data;
9032 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9038 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9042 *r->out.info = NULL;
9045 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9046 OUR_HANDLE(r->in.handle)));
9051 * first check for a keyname of NULL or "". Win2k seems to send
9052 * this a lot and we should send back WERR_INVALID_PARAM
9053 * no need to spend time looking up the printer in this case.
9057 if (!strlen(r->in.key_name)) {
9058 result = WERR_INVALID_PARAM;
9062 /* get the printer off of disk */
9064 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9068 ZERO_STRUCT(printer);
9069 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9070 if (!W_ERROR_IS_OK(result)) {
9074 /* now look for a match on the key name */
9076 p_data = printer->info_2->data;
9078 key_index = lookup_printerkey(p_data, r->in.key_name);
9079 if (key_index == -1) {
9080 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9082 result = WERR_INVALID_PARAM;
9086 /* allocate the memory for the array of pointers -- if necessary */
9088 count = regval_ctr_numvals(p_data->keys[key_index].values);
9090 result = WERR_OK; /* ??? */
9094 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9095 struct spoolss_PrinterEnumValues,
9098 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9099 result = WERR_NOMEM;
9104 * loop through all params and build the array to pass
9105 * back to the client
9108 for (i=0; i < count; i++) {
9110 struct regval_blob *val;
9112 /* lookup the registry value */
9114 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9116 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9120 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9121 if (!W_ERROR_IS_OK(result)) {
9126 #if 0 /* FIXME - gd */
9127 /* housekeeping information in the reply */
9129 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9130 * the hand marshalled container size is a multiple
9131 * of 4 bytes for RPC alignment.
9135 needed += 4-(needed % 4);
9138 *r->out.count = count;
9139 *r->out.info = info;
9144 free_a_printer(&printer, 2);
9147 if (!W_ERROR_IS_OK(result)) {
9151 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9152 spoolss_EnumPrinterDataEx,
9155 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9156 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9158 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9161 /****************************************************************************
9162 ****************************************************************************/
9164 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9165 const char *servername,
9166 const char *environment,
9167 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9172 werr = compose_spoolss_server_path(mem_ctx,
9175 SPOOLSS_PRTPROCS_PATH,
9177 if (!W_ERROR_IS_OK(werr)) {
9181 DEBUG(4,("print processor directory: [%s]\n", path));
9183 r->directory_name = path;
9188 /****************************************************************
9189 _spoolss_GetPrintProcessorDirectory
9190 ****************************************************************/
9192 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9193 struct spoolss_GetPrintProcessorDirectory *r)
9197 /* that's an [in out] buffer */
9199 if (!r->in.buffer && (r->in.offered != 0)) {
9200 return WERR_INVALID_PARAM;
9203 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9208 /* r->in.level is ignored */
9210 /* We always should reply with a local print processor directory so that
9211 * users are not forced to have a [prnproc$] share on the Samba spoolss
9212 * server - Guenther */
9214 result = getprintprocessordirectory_level_1(p->mem_ctx,
9215 NULL, /* r->in.server */
9217 &r->out.info->info1);
9218 if (!W_ERROR_IS_OK(result)) {
9219 TALLOC_FREE(r->out.info);
9223 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9224 r->out.info, r->in.level);
9225 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9227 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9230 /*******************************************************************
9231 ********************************************************************/
9233 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9234 const char *dllname)
9236 enum ndr_err_code ndr_err;
9237 struct spoolss_MonitorUi ui;
9239 ui.dll_name = dllname;
9241 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9242 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9243 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9244 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9246 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9249 /*******************************************************************
9250 Streams the monitor UI DLL name in UNICODE
9251 *******************************************************************/
9253 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9254 NT_USER_TOKEN *token, DATA_BLOB *in,
9255 DATA_BLOB *out, uint32_t *needed)
9257 const char *dllname = "tcpmonui.dll";
9259 *needed = (strlen(dllname)+1) * 2;
9261 if (out->length < *needed) {
9262 return WERR_INSUFFICIENT_BUFFER;
9265 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9272 /*******************************************************************
9273 ********************************************************************/
9275 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9276 struct spoolss_PortData1 *port1,
9277 const DATA_BLOB *buf)
9279 enum ndr_err_code ndr_err;
9280 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9281 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9282 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9283 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9285 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9288 /*******************************************************************
9289 ********************************************************************/
9291 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9292 struct spoolss_PortData2 *port2,
9293 const DATA_BLOB *buf)
9295 enum ndr_err_code ndr_err;
9296 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9297 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9298 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9299 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9301 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9304 /*******************************************************************
9305 Create a new TCP/IP port
9306 *******************************************************************/
9308 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9309 NT_USER_TOKEN *token, DATA_BLOB *in,
9310 DATA_BLOB *out, uint32_t *needed)
9312 struct spoolss_PortData1 port1;
9313 struct spoolss_PortData2 port2;
9314 char *device_uri = NULL;
9317 const char *portname;
9318 const char *hostaddress;
9320 uint32_t port_number;
9323 /* peek for spoolss_PortData version */
9325 if (!in || (in->length < (128 + 4))) {
9326 return WERR_GENERAL_FAILURE;
9329 version = IVAL(in->data, 128);
9335 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9339 portname = port1.portname;
9340 hostaddress = port1.hostaddress;
9341 queue = port1.queue;
9342 protocol = port1.protocol;
9343 port_number = port1.port_number;
9349 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9353 portname = port2.portname;
9354 hostaddress = port2.hostaddress;
9355 queue = port2.queue;
9356 protocol = port2.protocol;
9357 port_number = port2.port_number;
9361 DEBUG(1,("xcvtcp_addport: "
9362 "unknown version of port_data: %d\n", version));
9363 return WERR_UNKNOWN_PORT;
9366 /* create the device URI and call the add_port_hook() */
9369 case PROTOCOL_RAWTCP_TYPE:
9370 device_uri = talloc_asprintf(mem_ctx,
9371 "socket://%s:%d/", hostaddress,
9375 case PROTOCOL_LPR_TYPE:
9376 device_uri = talloc_asprintf(mem_ctx,
9377 "lpr://%s/%s", hostaddress, queue );
9381 return WERR_UNKNOWN_PORT;
9388 return add_port_hook(mem_ctx, token, portname, device_uri);
9391 /*******************************************************************
9392 *******************************************************************/
9394 struct xcv_api_table xcvtcp_cmds[] = {
9395 { "MonitorUI", xcvtcp_monitorui },
9396 { "AddPort", xcvtcp_addport},
9400 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9401 NT_USER_TOKEN *token, const char *command,
9408 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9410 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9411 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9412 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9415 return WERR_BADFUNC;
9418 /*******************************************************************
9419 *******************************************************************/
9420 #if 0 /* don't support management using the "Local Port" monitor */
9422 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9423 NT_USER_TOKEN *token, DATA_BLOB *in,
9424 DATA_BLOB *out, uint32_t *needed)
9426 const char *dllname = "localui.dll";
9428 *needed = (strlen(dllname)+1) * 2;
9430 if (out->length < *needed) {
9431 return WERR_INSUFFICIENT_BUFFER;
9434 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9441 /*******************************************************************
9442 *******************************************************************/
9444 struct xcv_api_table xcvlocal_cmds[] = {
9445 { "MonitorUI", xcvlocal_monitorui },
9449 struct xcv_api_table xcvlocal_cmds[] = {
9456 /*******************************************************************
9457 *******************************************************************/
9459 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9460 NT_USER_TOKEN *token, const char *command,
9461 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9466 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9468 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9469 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9470 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9472 return WERR_BADFUNC;
9475 /****************************************************************
9477 ****************************************************************/
9479 WERROR _spoolss_XcvData(pipes_struct *p,
9480 struct spoolss_XcvData *r)
9482 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9483 DATA_BLOB out_data = data_blob_null;
9487 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9488 OUR_HANDLE(r->in.handle)));
9492 /* Has to be a handle to the TCP/IP port monitor */
9494 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9495 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9499 /* requires administrative access to the server */
9501 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9502 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9503 return WERR_ACCESS_DENIED;
9506 /* Allocate the outgoing buffer */
9508 if (r->in.out_data_size) {
9509 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9510 if (out_data.data == NULL) {
9515 switch ( Printer->printer_type ) {
9516 case SPLHND_PORTMON_TCP:
9517 werror = process_xcvtcp_command(p->mem_ctx,
9518 p->server_info->ptok,
9519 r->in.function_name,
9520 &r->in.in_data, &out_data,
9523 case SPLHND_PORTMON_LOCAL:
9524 werror = process_xcvlocal_command(p->mem_ctx,
9525 p->server_info->ptok,
9526 r->in.function_name,
9527 &r->in.in_data, &out_data,
9531 werror = WERR_INVALID_PRINT_MONITOR;
9534 if (!W_ERROR_IS_OK(werror)) {
9538 *r->out.status_code = 0;
9540 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9541 memcpy(r->out.out_data, out_data.data,
9542 MIN(r->in.out_data_size, out_data.length));
9548 /****************************************************************
9549 _spoolss_AddPrintProcessor
9550 ****************************************************************/
9552 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9553 struct spoolss_AddPrintProcessor *r)
9555 /* for now, just indicate success and ignore the add. We'll
9556 automatically set the winprint processor for printer
9557 entries later. Used to debug the LexMark Optra S 1855 PCL
9563 /****************************************************************
9565 ****************************************************************/
9567 WERROR _spoolss_AddPort(pipes_struct *p,
9568 struct spoolss_AddPort *r)
9570 /* do what w2k3 does */
9572 return WERR_NOT_SUPPORTED;
9575 /****************************************************************
9576 _spoolss_GetPrinterDriver
9577 ****************************************************************/
9579 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9580 struct spoolss_GetPrinterDriver *r)
9582 p->rng_fault_state = true;
9583 return WERR_NOT_SUPPORTED;
9586 /****************************************************************
9587 _spoolss_ReadPrinter
9588 ****************************************************************/
9590 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9591 struct spoolss_ReadPrinter *r)
9593 p->rng_fault_state = true;
9594 return WERR_NOT_SUPPORTED;
9597 /****************************************************************
9598 _spoolss_WaitForPrinterChange
9599 ****************************************************************/
9601 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9602 struct spoolss_WaitForPrinterChange *r)
9604 p->rng_fault_state = true;
9605 return WERR_NOT_SUPPORTED;
9608 /****************************************************************
9609 _spoolss_ConfigurePort
9610 ****************************************************************/
9612 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9613 struct spoolss_ConfigurePort *r)
9615 p->rng_fault_state = true;
9616 return WERR_NOT_SUPPORTED;
9619 /****************************************************************
9621 ****************************************************************/
9623 WERROR _spoolss_DeletePort(pipes_struct *p,
9624 struct spoolss_DeletePort *r)
9626 p->rng_fault_state = true;
9627 return WERR_NOT_SUPPORTED;
9630 /****************************************************************
9631 _spoolss_CreatePrinterIC
9632 ****************************************************************/
9634 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9635 struct spoolss_CreatePrinterIC *r)
9637 p->rng_fault_state = true;
9638 return WERR_NOT_SUPPORTED;
9641 /****************************************************************
9642 _spoolss_PlayGDIScriptOnPrinterIC
9643 ****************************************************************/
9645 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9646 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9648 p->rng_fault_state = true;
9649 return WERR_NOT_SUPPORTED;
9652 /****************************************************************
9653 _spoolss_DeletePrinterIC
9654 ****************************************************************/
9656 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9657 struct spoolss_DeletePrinterIC *r)
9659 p->rng_fault_state = true;
9660 return WERR_NOT_SUPPORTED;
9663 /****************************************************************
9664 _spoolss_AddPrinterConnection
9665 ****************************************************************/
9667 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9668 struct spoolss_AddPrinterConnection *r)
9670 p->rng_fault_state = true;
9671 return WERR_NOT_SUPPORTED;
9674 /****************************************************************
9675 _spoolss_DeletePrinterConnection
9676 ****************************************************************/
9678 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9679 struct spoolss_DeletePrinterConnection *r)
9681 p->rng_fault_state = true;
9682 return WERR_NOT_SUPPORTED;
9685 /****************************************************************
9686 _spoolss_PrinterMessageBox
9687 ****************************************************************/
9689 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9690 struct spoolss_PrinterMessageBox *r)
9692 p->rng_fault_state = true;
9693 return WERR_NOT_SUPPORTED;
9696 /****************************************************************
9698 ****************************************************************/
9700 WERROR _spoolss_AddMonitor(pipes_struct *p,
9701 struct spoolss_AddMonitor *r)
9703 p->rng_fault_state = true;
9704 return WERR_NOT_SUPPORTED;
9707 /****************************************************************
9708 _spoolss_DeleteMonitor
9709 ****************************************************************/
9711 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9712 struct spoolss_DeleteMonitor *r)
9714 p->rng_fault_state = true;
9715 return WERR_NOT_SUPPORTED;
9718 /****************************************************************
9719 _spoolss_DeletePrintProcessor
9720 ****************************************************************/
9722 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9723 struct spoolss_DeletePrintProcessor *r)
9725 p->rng_fault_state = true;
9726 return WERR_NOT_SUPPORTED;
9729 /****************************************************************
9730 _spoolss_AddPrintProvidor
9731 ****************************************************************/
9733 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9734 struct spoolss_AddPrintProvidor *r)
9736 p->rng_fault_state = true;
9737 return WERR_NOT_SUPPORTED;
9740 /****************************************************************
9741 _spoolss_DeletePrintProvidor
9742 ****************************************************************/
9744 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9745 struct spoolss_DeletePrintProvidor *r)
9747 p->rng_fault_state = true;
9748 return WERR_NOT_SUPPORTED;
9751 /****************************************************************
9752 _spoolss_FindFirstPrinterChangeNotification
9753 ****************************************************************/
9755 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9756 struct spoolss_FindFirstPrinterChangeNotification *r)
9758 p->rng_fault_state = true;
9759 return WERR_NOT_SUPPORTED;
9762 /****************************************************************
9763 _spoolss_FindNextPrinterChangeNotification
9764 ****************************************************************/
9766 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9767 struct spoolss_FindNextPrinterChangeNotification *r)
9769 p->rng_fault_state = true;
9770 return WERR_NOT_SUPPORTED;
9773 /****************************************************************
9774 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9775 ****************************************************************/
9777 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9778 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9780 p->rng_fault_state = true;
9781 return WERR_NOT_SUPPORTED;
9784 /****************************************************************
9785 _spoolss_ReplyOpenPrinter
9786 ****************************************************************/
9788 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9789 struct spoolss_ReplyOpenPrinter *r)
9791 p->rng_fault_state = true;
9792 return WERR_NOT_SUPPORTED;
9795 /****************************************************************
9796 _spoolss_RouterReplyPrinter
9797 ****************************************************************/
9799 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9800 struct spoolss_RouterReplyPrinter *r)
9802 p->rng_fault_state = true;
9803 return WERR_NOT_SUPPORTED;
9806 /****************************************************************
9807 _spoolss_ReplyClosePrinter
9808 ****************************************************************/
9810 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9811 struct spoolss_ReplyClosePrinter *r)
9813 p->rng_fault_state = true;
9814 return WERR_NOT_SUPPORTED;
9817 /****************************************************************
9819 ****************************************************************/
9821 WERROR _spoolss_AddPortEx(pipes_struct *p,
9822 struct spoolss_AddPortEx *r)
9824 p->rng_fault_state = true;
9825 return WERR_NOT_SUPPORTED;
9828 /****************************************************************
9829 _spoolss_RouterFindFirstPrinterChangeNotification
9830 ****************************************************************/
9832 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9833 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9835 p->rng_fault_state = true;
9836 return WERR_NOT_SUPPORTED;
9839 /****************************************************************
9840 _spoolss_SpoolerInit
9841 ****************************************************************/
9843 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9844 struct spoolss_SpoolerInit *r)
9846 p->rng_fault_state = true;
9847 return WERR_NOT_SUPPORTED;
9850 /****************************************************************
9851 _spoolss_ResetPrinterEx
9852 ****************************************************************/
9854 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9855 struct spoolss_ResetPrinterEx *r)
9857 p->rng_fault_state = true;
9858 return WERR_NOT_SUPPORTED;
9861 /****************************************************************
9862 _spoolss_RouterReplyPrinterEx
9863 ****************************************************************/
9865 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9866 struct spoolss_RouterReplyPrinterEx *r)
9868 p->rng_fault_state = true;
9869 return WERR_NOT_SUPPORTED;
9872 /****************************************************************
9874 ****************************************************************/
9876 WERROR _spoolss_44(pipes_struct *p,
9877 struct spoolss_44 *r)
9879 p->rng_fault_state = true;
9880 return WERR_NOT_SUPPORTED;
9883 /****************************************************************
9885 ****************************************************************/
9887 WERROR _spoolss_47(pipes_struct *p,
9888 struct spoolss_47 *r)
9890 p->rng_fault_state = true;
9891 return WERR_NOT_SUPPORTED;
9894 /****************************************************************
9896 ****************************************************************/
9898 WERROR _spoolss_4a(pipes_struct *p,
9899 struct spoolss_4a *r)
9901 p->rng_fault_state = true;
9902 return WERR_NOT_SUPPORTED;
9905 /****************************************************************
9907 ****************************************************************/
9909 WERROR _spoolss_4b(pipes_struct *p,
9910 struct spoolss_4b *r)
9912 p->rng_fault_state = true;
9913 return WERR_NOT_SUPPORTED;
9916 /****************************************************************
9918 ****************************************************************/
9920 WERROR _spoolss_4c(pipes_struct *p,
9921 struct spoolss_4c *r)
9923 p->rng_fault_state = true;
9924 return WERR_NOT_SUPPORTED;
9927 /****************************************************************
9929 ****************************************************************/
9931 WERROR _spoolss_53(pipes_struct *p,
9932 struct spoolss_53 *r)
9934 p->rng_fault_state = true;
9935 return WERR_NOT_SUPPORTED;
9938 /****************************************************************
9940 ****************************************************************/
9942 WERROR _spoolss_55(pipes_struct *p,
9943 struct spoolss_55 *r)
9945 p->rng_fault_state = true;
9946 return WERR_NOT_SUPPORTED;
9949 /****************************************************************
9951 ****************************************************************/
9953 WERROR _spoolss_56(pipes_struct *p,
9954 struct spoolss_56 *r)
9956 p->rng_fault_state = true;
9957 return WERR_NOT_SUPPORTED;
9960 /****************************************************************
9962 ****************************************************************/
9964 WERROR _spoolss_57(pipes_struct *p,
9965 struct spoolss_57 *r)
9967 p->rng_fault_state = true;
9968 return WERR_NOT_SUPPORTED;
9971 /****************************************************************
9973 ****************************************************************/
9975 WERROR _spoolss_5a(pipes_struct *p,
9976 struct spoolss_5a *r)
9978 p->rng_fault_state = true;
9979 return WERR_NOT_SUPPORTED;
9982 /****************************************************************
9984 ****************************************************************/
9986 WERROR _spoolss_5b(pipes_struct *p,
9987 struct spoolss_5b *r)
9989 p->rng_fault_state = true;
9990 return WERR_NOT_SUPPORTED;
9993 /****************************************************************
9995 ****************************************************************/
9997 WERROR _spoolss_5c(pipes_struct *p,
9998 struct spoolss_5c *r)
10000 p->rng_fault_state = true;
10001 return WERR_NOT_SUPPORTED;
10004 /****************************************************************
10006 ****************************************************************/
10008 WERROR _spoolss_5d(pipes_struct *p,
10009 struct spoolss_5d *r)
10011 p->rng_fault_state = true;
10012 return WERR_NOT_SUPPORTED;
10015 /****************************************************************
10017 ****************************************************************/
10019 WERROR _spoolss_5e(pipes_struct *p,
10020 struct spoolss_5e *r)
10022 p->rng_fault_state = true;
10023 return WERR_NOT_SUPPORTED;
10026 /****************************************************************
10028 ****************************************************************/
10030 WERROR _spoolss_5f(pipes_struct *p,
10031 struct spoolss_5f *r)
10033 p->rng_fault_state = true;
10034 return WERR_NOT_SUPPORTED;
10037 /****************************************************************
10039 ****************************************************************/
10041 WERROR _spoolss_60(pipes_struct *p,
10042 struct spoolss_60 *r)
10044 p->rng_fault_state = true;
10045 return WERR_NOT_SUPPORTED;
10048 /****************************************************************
10050 ****************************************************************/
10052 WERROR _spoolss_61(pipes_struct *p,
10053 struct spoolss_61 *r)
10055 p->rng_fault_state = true;
10056 return WERR_NOT_SUPPORTED;
10059 /****************************************************************
10061 ****************************************************************/
10063 WERROR _spoolss_62(pipes_struct *p,
10064 struct spoolss_62 *r)
10066 p->rng_fault_state = true;
10067 return WERR_NOT_SUPPORTED;
10070 /****************************************************************
10072 ****************************************************************/
10074 WERROR _spoolss_63(pipes_struct *p,
10075 struct spoolss_63 *r)
10077 p->rng_fault_state = true;
10078 return WERR_NOT_SUPPORTED;
10081 /****************************************************************
10083 ****************************************************************/
10085 WERROR _spoolss_64(pipes_struct *p,
10086 struct spoolss_64 *r)
10088 p->rng_fault_state = true;
10089 return WERR_NOT_SUPPORTED;
10092 /****************************************************************
10094 ****************************************************************/
10096 WERROR _spoolss_65(pipes_struct *p,
10097 struct spoolss_65 *r)
10099 p->rng_fault_state = true;
10100 return WERR_NOT_SUPPORTED;
10103 /****************************************************************
10104 _spoolss_GetCorePrinterDrivers
10105 ****************************************************************/
10107 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10108 struct spoolss_GetCorePrinterDrivers *r)
10110 p->rng_fault_state = true;
10111 return WERR_NOT_SUPPORTED;
10114 /****************************************************************
10116 ****************************************************************/
10118 WERROR _spoolss_67(pipes_struct *p,
10119 struct spoolss_67 *r)
10121 p->rng_fault_state = true;
10122 return WERR_NOT_SUPPORTED;
10125 /****************************************************************
10126 _spoolss_GetPrinterDriverPackagePath
10127 ****************************************************************/
10129 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10130 struct spoolss_GetPrinterDriverPackagePath *r)
10132 p->rng_fault_state = true;
10133 return WERR_NOT_SUPPORTED;
10136 /****************************************************************
10138 ****************************************************************/
10140 WERROR _spoolss_69(pipes_struct *p,
10141 struct spoolss_69 *r)
10143 p->rng_fault_state = true;
10144 return WERR_NOT_SUPPORTED;
10147 /****************************************************************
10149 ****************************************************************/
10151 WERROR _spoolss_6a(pipes_struct *p,
10152 struct spoolss_6a *r)
10154 p->rng_fault_state = true;
10155 return WERR_NOT_SUPPORTED;
10158 /****************************************************************
10160 ****************************************************************/
10162 WERROR _spoolss_6b(pipes_struct *p,
10163 struct spoolss_6b *r)
10165 p->rng_fault_state = true;
10166 return WERR_NOT_SUPPORTED;
10169 /****************************************************************
10171 ****************************************************************/
10173 WERROR _spoolss_6c(pipes_struct *p,
10174 struct spoolss_6c *r)
10176 p->rng_fault_state = true;
10177 return WERR_NOT_SUPPORTED;
10180 /****************************************************************
10182 ****************************************************************/
10184 WERROR _spoolss_6d(pipes_struct *p,
10185 struct spoolss_6d *r)
10187 p->rng_fault_state = true;
10188 return WERR_NOT_SUPPORTED;