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.
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. */
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33 ((info)?ndr_size_##fn(info, level, ic, 0):0)
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44 extern userdom_struct current_user_info;
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57 const char *long_archi;
58 const char *short_archi;
62 static Printer_entry *printers_list;
64 typedef struct _counter_printer_0 {
65 struct _counter_printer_0 *next;
66 struct _counter_printer_0 *prev;
72 static counter_printer_0 *counter_list;
74 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
75 static uint32 smb_connections=0;
78 /* in printing/nt_printing.c */
80 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
82 /* API table for Xcv Monitor functions */
84 struct xcv_api_table {
86 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
89 /********************************************************************
90 * Canonicalize servername.
91 ********************************************************************/
93 static const char *canon_servername(const char *servername)
95 const char *pservername = servername;
96 while (*pservername == '\\') {
102 /* translate between internal status numbers and NT status numbers */
103 static int nt_printj_status(int v)
109 return JOB_STATUS_PAUSED;
111 return JOB_STATUS_SPOOLING;
113 return JOB_STATUS_PRINTING;
115 return JOB_STATUS_ERROR;
117 return JOB_STATUS_DELETING;
119 return JOB_STATUS_OFFLINE;
121 return JOB_STATUS_PAPEROUT;
123 return JOB_STATUS_PRINTED;
125 return JOB_STATUS_DELETED;
127 return JOB_STATUS_BLOCKED_DEVQ;
128 case LPQ_USER_INTERVENTION:
129 return JOB_STATUS_USER_INTERVENTION;
134 static int nt_printq_status(int v)
138 return PRINTER_STATUS_PAUSED;
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
157 * Tell the specific printing tdb we no longer want messages for this printer
158 * by deregistering our PID.
161 if (!print_notify_deregister_pid(snum))
162 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
164 /* weird if the test succeds !!! */
165 if (smb_connections==0) {
166 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
170 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
173 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
174 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
175 win_errstr(result)));
177 /* if it's the last connection, deconnect the IPC$ share */
178 if (smb_connections==1) {
180 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
181 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
183 messaging_deregister(smbd_messaging_context(),
184 MSG_PRINTER_NOTIFY2, NULL);
186 /* Tell the connections db we're no longer interested in
187 * printer notify messages. */
189 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
195 /****************************************************************************
196 Functions to free a printer entry datastruct.
197 ****************************************************************************/
199 static int printer_entry_destructor(Printer_entry *Printer)
201 if (Printer->notify.client_connected==True) {
204 if ( Printer->printer_type == SPLHND_SERVER) {
206 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
207 } else if (Printer->printer_type == SPLHND_PRINTER) {
208 snum = print_queue_snum(Printer->sharename);
210 srv_spoolss_replycloseprinter(snum,
211 &Printer->notify.client_hnd);
215 Printer->notify.flags=0;
216 Printer->notify.options=0;
217 Printer->notify.localmachine[0]='\0';
218 Printer->notify.printerlocal=0;
219 TALLOC_FREE(Printer->notify.option);
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 /* Remove from the internal list. */
226 DLIST_REMOVE(printers_list, Printer);
230 /****************************************************************************
231 find printer index by handle
232 ****************************************************************************/
234 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
235 struct policy_handle *hnd)
237 Printer_entry *find_printer = NULL;
239 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
240 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
247 /****************************************************************************
248 Close printer index by handle.
249 ****************************************************************************/
251 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
253 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
256 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
261 close_policy_hnd(p, hnd);
266 /****************************************************************************
267 Delete a printer given a handle.
268 ****************************************************************************/
270 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
272 char *cmd = lp_deleteprinter_cmd();
273 char *command = NULL;
275 SE_PRIV se_printop = SE_PRINT_OPERATOR;
276 bool is_print_op = False;
278 /* can't fail if we don't try */
283 command = talloc_asprintf(ctx,
290 is_print_op = user_has_privileges( token, &se_printop );
292 DEBUG(10,("Running [%s]\n", command));
294 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
299 if ( (ret = smbrun(command, NULL)) == 0 ) {
300 /* Tell everyone we updated smb.conf. */
301 message_send_all(smbd_messaging_context(),
302 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
308 /********** END SePrintOperatorPrivlege BLOCK **********/
310 DEBUGADD(10,("returned [%d]\n", ret));
312 TALLOC_FREE(command);
315 return WERR_BADFID; /* What to return here? */
317 /* go ahead and re-read the services immediately */
318 reload_services( False );
320 if ( lp_servicenumber( sharename ) < 0 )
321 return WERR_ACCESS_DENIED;
326 /****************************************************************************
327 Delete a printer given a handle.
328 ****************************************************************************/
330 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
332 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
335 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
341 * It turns out that Windows allows delete printer on a handle
342 * opened by an admin user, then used on a pipe handle created
343 * by an anonymous user..... but they're working on security.... riiight !
347 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
348 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
349 return WERR_ACCESS_DENIED;
352 /* this does not need a become root since the access check has been
353 done on the handle already */
355 if (del_a_printer( Printer->sharename ) != 0) {
356 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
360 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
361 Printer->sharename );
364 /****************************************************************************
365 Return the snum of a printer corresponding to an handle.
366 ****************************************************************************/
368 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
369 int *number, struct share_params **params)
371 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
374 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
379 switch (Printer->printer_type) {
381 DEBUG(4,("short name:%s\n", Printer->sharename));
382 *number = print_queue_snum(Printer->sharename);
383 return (*number != -1);
391 /****************************************************************************
392 Set printer handle type.
393 Check if it's \\server or \\server\printer
394 ****************************************************************************/
396 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
398 DEBUG(3,("Setting printer type=%s\n", handlename));
400 if ( strlen(handlename) < 3 ) {
401 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
405 /* it's a print server */
406 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
407 DEBUGADD(4,("Printer is a print server\n"));
408 Printer->printer_type = SPLHND_SERVER;
410 /* it's a printer (set_printer_hnd_name() will handle port monitors */
412 DEBUGADD(4,("Printer is a printer\n"));
413 Printer->printer_type = SPLHND_PRINTER;
419 /****************************************************************************
420 Set printer handle name.. Accept names like \\server, \\server\printer,
421 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
422 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
423 XcvDataPort() interface.
424 ****************************************************************************/
426 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
429 int n_services=lp_numservices();
430 char *aprinter, *printername;
431 const char *servername;
434 NT_PRINTER_INFO_LEVEL *printer = NULL;
437 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
439 aprinter = handlename;
440 if ( *handlename == '\\' ) {
441 servername = canon_servername(handlename);
442 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
450 /* save the servername to fill in replies on this handle */
452 if ( !is_myname_or_ipaddr( servername ) )
455 fstrcpy( Printer->servername, servername );
457 if ( Printer->printer_type == SPLHND_SERVER )
460 if ( Printer->printer_type != SPLHND_PRINTER )
463 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
465 /* check for the Port Monitor Interface */
467 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
468 Printer->printer_type = SPLHND_PORTMON_TCP;
469 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
472 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
473 Printer->printer_type = SPLHND_PORTMON_LOCAL;
474 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
478 /* Search all sharenames first as this is easier than pulling
479 the printer_info_2 off of disk. Don't use find_service() since
480 that calls out to map_username() */
482 /* do another loop to look for printernames */
484 for (snum=0; !found && snum<n_services; snum++) {
486 /* no point going on if this is not a printer */
488 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
491 fstrcpy(sname, lp_servicename(snum));
492 if ( strequal( aprinter, sname ) ) {
497 /* no point looking up the printer object if
498 we aren't allowing printername != sharename */
500 if ( lp_force_printername(snum) )
503 fstrcpy(sname, lp_servicename(snum));
507 /* This call doesn't fill in the location or comment from
508 * a CUPS server for efficiency with large numbers of printers.
512 result = get_a_printer_search( NULL, &printer, 2, sname );
513 if ( !W_ERROR_IS_OK(result) ) {
514 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
515 sname, win_errstr(result)));
519 /* printername is always returned as \\server\printername */
520 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
521 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
522 printer->info_2->printername));
523 free_a_printer( &printer, 2);
529 if ( strequal(printername, aprinter) ) {
530 free_a_printer( &printer, 2);
535 DEBUGADD(10, ("printername: %s\n", printername));
537 free_a_printer( &printer, 2);
540 free_a_printer( &printer, 2);
543 DEBUGADD(4,("Printer not found\n"));
547 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
549 fstrcpy(Printer->sharename, sname);
554 /****************************************************************************
555 Find first available printer slot. creates a printer handle for you.
556 ****************************************************************************/
558 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
559 char *name, uint32_t access_granted)
561 Printer_entry *new_printer;
563 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
565 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
566 if (new_printer == NULL) {
569 talloc_set_destructor(new_printer, printer_entry_destructor);
571 if (!create_policy_hnd(p, hnd, new_printer)) {
572 TALLOC_FREE(new_printer);
576 /* Add to the internal list. */
577 DLIST_ADD(printers_list, new_printer);
579 new_printer->notify.option=NULL;
581 if (!set_printer_hnd_printertype(new_printer, name)) {
582 close_printer_handle(p, hnd);
586 if (!set_printer_hnd_name(new_printer, name)) {
587 close_printer_handle(p, hnd);
591 new_printer->access_granted = access_granted;
593 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
598 /***************************************************************************
599 check to see if the client motify handle is monitoring the notification
600 given by (notify_type, notify_field).
601 **************************************************************************/
603 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
609 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
612 struct spoolss_NotifyOption *option = p->notify.option;
616 * Flags should always be zero when the change notify
617 * is registered by the client's spooler. A user Win32 app
618 * might use the flags though instead of the NOTIFY_OPTION_INFO
627 return is_monitoring_event_flags(
628 p->notify.flags, notify_type, notify_field);
630 for (i = 0; i < option->count; i++) {
632 /* Check match for notify_type */
634 if (option->types[i].type != notify_type)
637 /* Check match for field */
639 for (j = 0; j < option->types[i].count; j++) {
640 if (option->types[i].fields[j].field == notify_field) {
646 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647 p->servername, p->sharename, notify_type, notify_field));
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653 _data->data.integer[0] = _integer; \
654 _data->data.integer[1] = 0;
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659 if (!_data->data.string.string) {\
660 _data->data.string.size = 0; \
662 _data->data.string.size = strlen_m_term(_p) * 2;
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665 _data->data.devmode.devmode = _devmode;
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669 if (!_data->data.sd.sd) { \
670 _data->data.sd.sd_size = 0; \
672 _data->data.sd.sd_size = _size;
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
679 struct spoolss_Time st;
683 if (!init_systemtime(&st, t)) {
687 p = talloc_array(mem_ctx, char, len);
693 * Systemtime must be linearized as a set of UINT16's.
694 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
697 SSVAL(p, 0, st.year);
698 SSVAL(p, 2, st.month);
699 SSVAL(p, 4, st.day_of_week);
701 SSVAL(p, 8, st.hour);
702 SSVAL(p, 10, st.minute);
703 SSVAL(p, 12, st.second);
704 SSVAL(p, 14, st.millisecond);
710 /* Convert a notification message to a struct spoolss_Notify */
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713 struct spoolss_Notify *data,
716 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
719 static void notify_string(struct spoolss_notify_msg *msg,
720 struct spoolss_Notify *data,
723 /* The length of the message includes the trailing \0 */
725 data->data.string.size = msg->len * 2;
726 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727 if (!data->data.string.string) {
728 data->data.string.size = 0;
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734 struct spoolss_Notify *data,
737 data->data.string.string = NULL;
738 data->data.string.size = 0;
740 if (msg->len != sizeof(time_t)) {
741 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
746 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747 &data->data.string.string,
748 &data->data.string.size);
751 struct notify2_message_table {
753 void (*fn)(struct spoolss_notify_msg *msg,
754 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
757 static struct notify2_message_table printer_notify_table[] = {
758 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
779 static struct notify2_message_table job_notify_table[] = {
780 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
807 /***********************************************************************
808 Allocate talloc context for container object
809 **********************************************************************/
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
816 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
821 /***********************************************************************
822 release all allocated memory and zero out structure
823 **********************************************************************/
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
831 talloc_destroy(ctr->ctx);
838 /***********************************************************************
839 **********************************************************************/
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
849 /***********************************************************************
850 **********************************************************************/
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
854 if ( !ctr || !ctr->msg_groups )
857 if ( idx >= ctr->num_groups )
860 return &ctr->msg_groups[idx];
864 /***********************************************************************
865 How many groups of change messages do we have ?
866 **********************************************************************/
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
873 return ctr->num_groups;
876 /***********************************************************************
877 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878 **********************************************************************/
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
882 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
883 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
884 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
890 /* loop over all groups looking for a matching printer name */
892 for ( i=0; i<ctr->num_groups; i++ ) {
893 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
897 /* add a new group? */
899 if ( i == ctr->num_groups ) {
902 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
906 ctr->msg_groups = groups;
908 /* clear the new entry and set the printer name */
910 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
914 /* add the change messages; 'i' is the correct index now regardless */
916 msg_grp = &ctr->msg_groups[i];
920 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
924 msg_grp->msgs = msg_list;
926 new_slot = msg_grp->num_msgs-1;
927 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
929 /* need to allocate own copy of data */
932 msg_grp->msgs[new_slot].notify.data = (char *)
933 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
935 return ctr->num_groups;
938 /***********************************************************************
939 Send a change notication message on all handles which have a call
941 **********************************************************************/
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
946 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
947 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948 SPOOLSS_NOTIFY_MSG *messages;
949 int sending_msg_count;
952 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
956 messages = msg_group->msgs;
959 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
963 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
965 /* loop over all printers */
967 for (p = printers_list; p; p = p->next) {
968 struct spoolss_Notify *notifies;
973 /* Is there notification on this handle? */
975 if ( !p->notify.client_connected )
978 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
980 /* For this printer? Print servers always receive
983 if ( ( p->printer_type == SPLHND_PRINTER ) &&
984 ( !strequal(msg_group->printername, p->sharename) ) )
987 DEBUG(10,("Our printer\n"));
989 /* allocate the max entries possible */
991 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
996 /* build the array of change notifications */
998 sending_msg_count = 0;
1000 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1003 /* Are we monitoring this event? */
1005 if (!is_monitoring_event(p, msg->type, msg->field))
1008 sending_msg_count++;
1011 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012 msg->type, msg->field, p->sharename));
1015 * if the is a printer notification handle and not a job notification
1016 * type, then set the id to 0. Other wise just use what was specified
1019 * When registering change notification on a print server handle
1020 * we always need to send back the id (snum) matching the printer
1021 * for which the change took place. For change notify registered
1022 * on a printer handle, this does not matter and the id should be 0.
1027 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1033 /* Convert unix jobid to smb jobid */
1035 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036 id = sysjob_to_jobid(msg->id);
1039 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1044 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1047 case PRINTER_NOTIFY_TYPE:
1048 if ( printer_notify_table[msg->field].fn )
1049 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1052 case JOB_NOTIFY_TYPE:
1053 if ( job_notify_table[msg->field].fn )
1054 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1058 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1065 if ( sending_msg_count ) {
1068 union spoolss_ReplyPrinterInfo info;
1069 struct spoolss_NotifyInfo info0;
1070 uint32_t reply_result;
1072 info0.version = 0x2;
1073 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074 info0.count = count;
1075 info0.notifies = notifies;
1077 info.info0 = &info0;
1079 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080 &p->notify.client_hnd,
1081 p->notify.change, /* color */
1084 0, /* reply_type, must be 0 */
1087 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089 notify_cli_pipe->srv_name_slash,
1092 switch (reply_result) {
1095 case PRINTER_NOTIFY_INFO_DISCARDED:
1096 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1106 DEBUG(8,("send_notify2_changes: Exit...\n"));
1110 /***********************************************************************
1111 **********************************************************************/
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1116 uint32 tv_sec, tv_usec;
1119 /* Unpack message */
1121 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1124 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1126 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1129 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1130 &msg->notify.value[0], &msg->notify.value[1]);
1132 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1133 &msg->len, &msg->notify.data);
1135 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1138 tv->tv_sec = tv_sec;
1139 tv->tv_usec = tv_usec;
1142 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143 msg->notify.value[1]));
1145 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1150 /********************************************************************
1151 Receive a notify2 message list
1152 ********************************************************************/
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1157 struct server_id server_id,
1160 size_t msg_count, i;
1161 char *buf = (char *)data->data;
1164 SPOOLSS_NOTIFY_MSG notify;
1165 SPOOLSS_NOTIFY_MSG_CTR messages;
1168 if (data->length < 4) {
1169 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1173 msg_count = IVAL(buf, 0);
1176 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1178 if (msg_count == 0) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1183 /* initialize the container */
1185 ZERO_STRUCT( messages );
1186 notify_msg_ctr_init( &messages );
1189 * build message groups for each printer identified
1190 * in a change_notify msg. Remember that a PCN message
1191 * includes the handle returned for the srv_spoolss_replyopenprinter()
1192 * call. Therefore messages are grouped according to printer handle.
1195 for ( i=0; i<msg_count; i++ ) {
1196 struct timeval msg_tv;
1198 if (msg_ptr + 4 - buf > data->length) {
1199 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1203 msg_len = IVAL(msg_ptr,0);
1206 if (msg_ptr + msg_len - buf > data->length) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1211 /* unpack messages */
1213 ZERO_STRUCT( notify );
1214 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1217 /* add to correct list in container */
1219 notify_msg_ctr_addmsg( &messages, ¬ify );
1221 /* free memory that might have been allocated by notify2_unpack_msg() */
1223 if ( notify.len != 0 )
1224 SAFE_FREE( notify.notify.data );
1227 /* process each group of messages */
1229 num_groups = notify_msg_ctr_numgroups( &messages );
1230 for ( i=0; i<num_groups; i++ )
1231 send_notify2_changes( &messages, i );
1236 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1238 notify_msg_ctr_destroy( &messages );
1243 /********************************************************************
1244 Send a message to ourself about new driver being installed
1245 so we can upgrade the information for each printer bound to this
1247 ********************************************************************/
1249 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1251 int len = strlen(drivername);
1256 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1259 messaging_send_buf(smbd_messaging_context(), procid_self(),
1260 MSG_PRINTER_DRVUPGRADE,
1261 (uint8 *)drivername, len+1);
1266 /**********************************************************************
1267 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1268 over all printers, upgrading ones as necessary
1269 **********************************************************************/
1271 void do_drv_upgrade_printer(struct messaging_context *msg,
1274 struct server_id server_id,
1279 int n_services = lp_numservices();
1282 len = MIN(data->length,sizeof(drivername)-1);
1283 strncpy(drivername, (const char *)data->data, len);
1285 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1287 /* Iterate the printer list */
1289 for (snum=0; snum<n_services; snum++)
1291 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1294 NT_PRINTER_INFO_LEVEL *printer = NULL;
1296 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1297 if (!W_ERROR_IS_OK(result))
1300 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1302 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1304 /* all we care about currently is the change_id */
1306 result = mod_a_printer(printer, 2);
1307 if (!W_ERROR_IS_OK(result)) {
1308 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1309 win_errstr(result)));
1313 free_a_printer(&printer, 2);
1320 /********************************************************************
1321 Update the cache for all printq's with a registered client
1323 ********************************************************************/
1325 void update_monitored_printq_cache( void )
1327 Printer_entry *printer = printers_list;
1330 /* loop through all printers and update the cache where
1331 client_connected == True */
1334 if ( (printer->printer_type == SPLHND_PRINTER)
1335 && printer->notify.client_connected )
1337 snum = print_queue_snum(printer->sharename);
1338 print_queue_status( snum, NULL, NULL );
1341 printer = printer->next;
1346 /********************************************************************
1347 Send a message to ourself about new driver being installed
1348 so we can upgrade the information for each printer bound to this
1350 ********************************************************************/
1352 static bool srv_spoolss_reset_printerdata(char* drivername)
1354 int len = strlen(drivername);
1359 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1362 messaging_send_buf(smbd_messaging_context(), procid_self(),
1363 MSG_PRINTERDATA_INIT_RESET,
1364 (uint8 *)drivername, len+1);
1369 /**********************************************************************
1370 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1371 over all printers, resetting printer data as neessary
1372 **********************************************************************/
1374 void reset_all_printerdata(struct messaging_context *msg,
1377 struct server_id server_id,
1382 int n_services = lp_numservices();
1385 len = MIN( data->length, sizeof(drivername)-1 );
1386 strncpy( drivername, (const char *)data->data, len );
1388 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390 /* Iterate the printer list */
1392 for ( snum=0; snum<n_services; snum++ )
1394 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1397 NT_PRINTER_INFO_LEVEL *printer = NULL;
1399 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1400 if ( !W_ERROR_IS_OK(result) )
1404 * if the printer is bound to the driver,
1405 * then reset to the new driver initdata
1408 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412 if ( !set_driver_init(printer, 2) ) {
1413 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1414 printer->info_2->printername, printer->info_2->drivername));
1417 result = mod_a_printer( printer, 2 );
1418 if ( !W_ERROR_IS_OK(result) ) {
1419 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1420 get_dos_error_msg(result)));
1424 free_a_printer( &printer, 2 );
1433 /****************************************************************
1434 _spoolss_OpenPrinter
1435 ****************************************************************/
1437 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1438 struct spoolss_OpenPrinter *r)
1440 struct spoolss_OpenPrinterEx e;
1443 ZERO_STRUCT(e.in.userlevel);
1445 e.in.printername = r->in.printername;
1446 e.in.datatype = r->in.datatype;
1447 e.in.devmode_ctr = r->in.devmode_ctr;
1448 e.in.access_mask = r->in.access_mask;
1451 e.out.handle = r->out.handle;
1453 werr = _spoolss_OpenPrinterEx(p, &e);
1455 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1456 /* OpenPrinterEx returns this for a bad
1457 * printer name. We must return WERR_INVALID_PRINTER_NAME
1460 werr = WERR_INVALID_PRINTER_NAME;
1466 /********************************************************************
1467 ********************************************************************/
1469 bool convert_devicemode(const char *printername,
1470 const struct spoolss_DeviceMode *devmode,
1471 NT_DEVICEMODE **pp_nt_devmode)
1473 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1476 * Ensure nt_devmode is a valid pointer
1477 * as we will be overwriting it.
1480 if (nt_devmode == NULL) {
1481 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1482 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1486 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1487 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1489 nt_devmode->specversion = devmode->specversion;
1490 nt_devmode->driverversion = devmode->driverversion;
1491 nt_devmode->size = devmode->size;
1492 nt_devmode->fields = devmode->fields;
1493 nt_devmode->orientation = devmode->orientation;
1494 nt_devmode->papersize = devmode->papersize;
1495 nt_devmode->paperlength = devmode->paperlength;
1496 nt_devmode->paperwidth = devmode->paperwidth;
1497 nt_devmode->scale = devmode->scale;
1498 nt_devmode->copies = devmode->copies;
1499 nt_devmode->defaultsource = devmode->defaultsource;
1500 nt_devmode->printquality = devmode->printquality;
1501 nt_devmode->color = devmode->color;
1502 nt_devmode->duplex = devmode->duplex;
1503 nt_devmode->yresolution = devmode->yresolution;
1504 nt_devmode->ttoption = devmode->ttoption;
1505 nt_devmode->collate = devmode->collate;
1507 nt_devmode->logpixels = devmode->logpixels;
1508 nt_devmode->bitsperpel = devmode->bitsperpel;
1509 nt_devmode->pelswidth = devmode->pelswidth;
1510 nt_devmode->pelsheight = devmode->pelsheight;
1511 nt_devmode->displayflags = devmode->displayflags;
1512 nt_devmode->displayfrequency = devmode->displayfrequency;
1513 nt_devmode->icmmethod = devmode->icmmethod;
1514 nt_devmode->icmintent = devmode->icmintent;
1515 nt_devmode->mediatype = devmode->mediatype;
1516 nt_devmode->dithertype = devmode->dithertype;
1517 nt_devmode->reserved1 = devmode->reserved1;
1518 nt_devmode->reserved2 = devmode->reserved2;
1519 nt_devmode->panningwidth = devmode->panningwidth;
1520 nt_devmode->panningheight = devmode->panningheight;
1523 * Only change private and driverextra if the incoming devmode
1524 * has a new one. JRA.
1527 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1528 SAFE_FREE(nt_devmode->nt_dev_private);
1529 nt_devmode->driverextra = devmode->__driverextra_length;
1530 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1532 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1535 *pp_nt_devmode = nt_devmode;
1540 /****************************************************************
1541 _spoolss_OpenPrinterEx
1542 ****************************************************************/
1544 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1545 struct spoolss_OpenPrinterEx *r)
1547 char *name = CONST_DISCARD(char *, r->in.printername);
1549 Printer_entry *Printer=NULL;
1552 return WERR_INVALID_PARAM;
1555 /* some sanity check because you can open a printer or a print server */
1556 /* aka: \\server\printer or \\server */
1558 DEBUGADD(3,("checking name: %s\n",name));
1560 if (!open_printer_hnd(p, r->out.handle, name, 0)) {
1561 ZERO_STRUCTP(r->out.handle);
1562 return WERR_INVALID_PARAM;
1565 Printer = find_printer_index_by_hnd(p, r->out.handle);
1567 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1568 "handle we created for printer %s\n", name ));
1569 close_printer_handle(p, r->out.handle);
1570 ZERO_STRUCTP(r->out.handle);
1571 return WERR_INVALID_PARAM;
1575 * First case: the user is opening the print server:
1577 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1578 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1580 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1581 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1582 * or if the user is listed in the smb.conf printer admin parameter.
1584 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1585 * client view printer folder, but does not show the MSAPW.
1587 * Note: this test needs code to check access rights here too. Jeremy
1588 * could you look at this?
1590 * Second case: the user is opening a printer:
1591 * NT doesn't let us connect to a printer if the connecting user
1592 * doesn't have print permission.
1594 * Third case: user is opening a Port Monitor
1595 * access checks same as opening a handle to the print server.
1598 switch (Printer->printer_type )
1601 case SPLHND_PORTMON_TCP:
1602 case SPLHND_PORTMON_LOCAL:
1603 /* Printserver handles use global struct... */
1607 /* Map standard access rights to object specific access rights */
1609 se_map_standard(&r->in.access_mask,
1610 &printserver_std_mapping);
1612 /* Deny any object specific bits that don't apply to print
1613 servers (i.e printer and job specific bits) */
1615 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1617 if (r->in.access_mask &
1618 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1619 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1620 close_printer_handle(p, r->out.handle);
1621 ZERO_STRUCTP(r->out.handle);
1622 return WERR_ACCESS_DENIED;
1625 /* Allow admin access */
1627 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1629 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1631 if (!lp_ms_add_printer_wizard()) {
1632 close_printer_handle(p, r->out.handle);
1633 ZERO_STRUCTP(r->out.handle);
1634 return WERR_ACCESS_DENIED;
1637 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1638 and not a printer admin, then fail */
1640 if ((p->server_info->utok.uid != 0) &&
1641 !user_has_privileges(p->server_info->ptok,
1643 !token_contains_name_in_list(
1644 uidtoname(p->server_info->utok.uid),
1646 p->server_info->ptok,
1647 lp_printer_admin(snum))) {
1648 close_printer_handle(p, r->out.handle);
1649 ZERO_STRUCTP(r->out.handle);
1650 return WERR_ACCESS_DENIED;
1653 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1660 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1661 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1663 /* We fall through to return WERR_OK */
1666 case SPLHND_PRINTER:
1667 /* NT doesn't let us connect to a printer if the connecting user
1668 doesn't have print permission. */
1670 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1671 close_printer_handle(p, r->out.handle);
1672 ZERO_STRUCTP(r->out.handle);
1676 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1678 /* map an empty access mask to the minimum access mask */
1679 if (r->in.access_mask == 0x0)
1680 r->in.access_mask = PRINTER_ACCESS_USE;
1683 * If we are not serving the printer driver for this printer,
1684 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1685 * will keep NT clients happy --jerry
1688 if (lp_use_client_driver(snum)
1689 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1691 r->in.access_mask = PRINTER_ACCESS_USE;
1694 /* check smb.conf parameters and the the sec_desc */
1696 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1697 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1698 ZERO_STRUCTP(r->out.handle);
1699 return WERR_ACCESS_DENIED;
1702 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1703 p->server_info->ptok, snum) ||
1704 !print_access_check(p->server_info, snum,
1705 r->in.access_mask)) {
1706 DEBUG(3, ("access DENIED for printer open\n"));
1707 close_printer_handle(p, r->out.handle);
1708 ZERO_STRUCTP(r->out.handle);
1709 return WERR_ACCESS_DENIED;
1712 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1713 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1714 close_printer_handle(p, r->out.handle);
1715 ZERO_STRUCTP(r->out.handle);
1716 return WERR_ACCESS_DENIED;
1719 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1720 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1722 r->in.access_mask = PRINTER_ACCESS_USE;
1724 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1725 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1730 /* sanity check to prevent programmer error */
1731 ZERO_STRUCTP(r->out.handle);
1735 Printer->access_granted = r->in.access_mask;
1738 * If the client sent a devmode in the OpenPrinter() call, then
1739 * save it here in case we get a job submission on this handle
1742 if ((Printer->printer_type != SPLHND_SERVER) &&
1743 r->in.devmode_ctr.devmode) {
1744 convert_devicemode(Printer->sharename,
1745 r->in.devmode_ctr.devmode,
1746 &Printer->nt_devmode);
1749 #if 0 /* JERRY -- I'm doubtful this is really effective */
1750 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1751 optimization in Windows 2000 clients --jerry */
1753 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1754 && (RA_WIN2K == get_remote_arch()) )
1756 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1757 sys_usleep( 500000 );
1764 /****************************************************************************
1765 ****************************************************************************/
1767 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1768 NT_PRINTER_INFO_LEVEL_2 *d)
1770 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1776 d->attributes = r->attributes;
1777 d->priority = r->priority;
1778 d->default_priority = r->defaultpriority;
1779 d->starttime = r->starttime;
1780 d->untiltime = r->untiltime;
1781 d->status = r->status;
1782 d->cjobs = r->cjobs;
1784 fstrcpy(d->servername, r->servername);
1785 fstrcpy(d->printername, r->printername);
1786 fstrcpy(d->sharename, r->sharename);
1787 fstrcpy(d->portname, r->portname);
1788 fstrcpy(d->drivername, r->drivername);
1789 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1790 fstrcpy(d->location, r->location);
1791 fstrcpy(d->sepfile, r->sepfile);
1792 fstrcpy(d->printprocessor, r->printprocessor);
1793 fstrcpy(d->datatype, r->datatype);
1794 fstrcpy(d->parameters, r->parameters);
1799 /****************************************************************************
1800 ****************************************************************************/
1802 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1803 NT_PRINTER_INFO_LEVEL *printer)
1807 switch (info_ctr->level) {
1809 /* allocate memory if needed. Messy because
1810 convert_printer_info is used to update an existing
1811 printer or build a new one */
1813 if (!printer->info_2) {
1814 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1815 if (!printer->info_2) {
1816 DEBUG(0,("convert_printer_info: "
1817 "talloc() failed!\n"));
1822 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1824 printer->info_2->setuptime = time(NULL);
1831 /*******************************************************************
1832 ********************************************************************/
1834 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1843 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1848 for (i=0; sarray[i] != NULL; i++) {
1849 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1853 fstrcpy((*farray)[i], sarray[i]);
1856 fstrcpy((*farray)[i], "");
1861 /*******************************************************************
1862 ********************************************************************/
1864 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1865 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1867 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1869 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1872 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1881 d->cversion = r->version;
1883 fstrcpy(d->name, r->driver_name);
1884 fstrcpy(d->environment, r->architecture);
1885 fstrcpy(d->driverpath, r->driver_path);
1886 fstrcpy(d->datafile, r->data_file);
1887 fstrcpy(d->configfile, r->config_file);
1888 fstrcpy(d->helpfile, r->help_file);
1889 fstrcpy(d->monitorname, r->monitor_name);
1890 fstrcpy(d->defaultdatatype, r->default_datatype);
1892 DEBUGADD(8,( "version: %d\n", d->cversion));
1893 DEBUGADD(8,( "name: %s\n", d->name));
1894 DEBUGADD(8,( "environment: %s\n", d->environment));
1895 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1896 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1897 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1898 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1899 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1900 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1902 if (r->dependent_files) {
1903 if (!string_array_to_fstring_array(r->dependent_files->string,
1904 &d->dependentfiles)) {
1913 /*******************************************************************
1914 ********************************************************************/
1916 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1917 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1919 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1921 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1924 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1933 d->version = r->version;
1935 fstrcpy(d->name, r->driver_name);
1936 fstrcpy(d->environment, r->architecture);
1937 fstrcpy(d->driverpath, r->driver_path);
1938 fstrcpy(d->datafile, r->data_file);
1939 fstrcpy(d->configfile, r->config_file);
1940 fstrcpy(d->helpfile, r->help_file);
1941 fstrcpy(d->monitorname, r->monitor_name);
1942 fstrcpy(d->defaultdatatype, r->default_datatype);
1944 DEBUGADD(8,( "version: %d\n", d->version));
1945 DEBUGADD(8,( "name: %s\n", d->name));
1946 DEBUGADD(8,( "environment: %s\n", d->environment));
1947 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1948 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1949 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1950 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1951 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1952 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1954 if (r->dependent_files) {
1955 if (!string_array_to_fstring_array(r->dependent_files->string,
1956 &d->dependentfiles)) {
1961 if (r->previous_names) {
1962 if (!string_array_to_fstring_array(r->previous_names->string,
1963 &d->previousnames)) {
1975 /********************************************************************
1976 ********************************************************************/
1978 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1979 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1984 printer->info_3 = NULL;
1985 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1990 printer->info_6 = NULL;
1991 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
2002 /********************************************************************
2003 * _spoolss_enddocprinter_internal.
2004 ********************************************************************/
2006 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
2007 struct policy_handle *handle)
2009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2013 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2017 if (!get_printer_snum(p, handle, &snum, NULL))
2020 Printer->document_started=False;
2021 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2022 /* error codes unhandled so far ... */
2027 /****************************************************************
2028 _spoolss_ClosePrinter
2029 ****************************************************************/
2031 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2032 struct spoolss_ClosePrinter *r)
2034 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2036 if (Printer && Printer->document_started)
2037 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2039 if (!close_printer_handle(p, r->in.handle))
2042 /* clear the returned printer handle. Observed behavior
2043 from Win2k server. Don't think this really matters.
2044 Previous code just copied the value of the closed
2047 ZERO_STRUCTP(r->out.handle);
2052 /****************************************************************
2053 _spoolss_DeletePrinter
2054 ****************************************************************/
2056 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2057 struct spoolss_DeletePrinter *r)
2059 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2062 if (Printer && Printer->document_started)
2063 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2065 result = delete_printer_handle(p, r->in.handle);
2067 update_c_setprinter(False);
2072 /*******************************************************************
2073 * static function to lookup the version id corresponding to an
2074 * long architecture string
2075 ******************************************************************/
2077 static int get_version_id (char * arch)
2080 struct table_node archi_table[]= {
2082 {"Windows 4.0", "WIN40", 0 },
2083 {"Windows NT x86", "W32X86", 2 },
2084 {"Windows NT R4000", "W32MIPS", 2 },
2085 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2086 {"Windows NT PowerPC", "W32PPC", 2 },
2087 {"Windows IA64", "IA64", 3 },
2088 {"Windows x64", "x64", 3 },
2092 for (i=0; archi_table[i].long_archi != NULL; i++)
2094 if (strcmp(arch, archi_table[i].long_archi) == 0)
2095 return (archi_table[i].version);
2101 /****************************************************************
2102 _spoolss_DeletePrinterDriver
2103 ****************************************************************/
2105 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2106 struct spoolss_DeletePrinterDriver *r)
2110 NT_PRINTER_DRIVER_INFO_LEVEL info;
2111 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2114 WERROR status_win2k = WERR_ACCESS_DENIED;
2115 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2117 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2118 and not a printer admin, then fail */
2120 if ( (p->server_info->utok.uid != 0)
2121 && !user_has_privileges(p->server_info->ptok, &se_printop )
2122 && !token_contains_name_in_list(
2123 uidtoname(p->server_info->utok.uid), NULL,
2124 NULL, p->server_info->ptok,
2125 lp_printer_admin(-1)) )
2127 return WERR_ACCESS_DENIED;
2130 driver = CONST_DISCARD(char *, r->in.driver);
2131 arch = CONST_DISCARD(char *, r->in.architecture);
2133 /* check that we have a valid driver name first */
2135 if ((version=get_version_id(arch)) == -1)
2136 return WERR_INVALID_ENVIRONMENT;
2139 ZERO_STRUCT(info_win2k);
2141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2143 /* try for Win2k driver if "Windows NT x86" */
2145 if ( version == 2 ) {
2147 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2148 status = WERR_UNKNOWN_PRINTER_DRIVER;
2152 /* otherwise it was a failure */
2154 status = WERR_UNKNOWN_PRINTER_DRIVER;
2160 if (printer_driver_in_use(info.info_3)) {
2161 status = WERR_PRINTER_DRIVER_IN_USE;
2167 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2169 /* if we get to here, we now have 2 driver info structures to remove */
2170 /* remove the Win2k driver first*/
2172 status_win2k = delete_printer_driver(
2173 p, info_win2k.info_3, 3, False );
2174 free_a_printer_driver( info_win2k, 3 );
2176 /* this should not have failed---if it did, report to client */
2177 if ( !W_ERROR_IS_OK(status_win2k) )
2179 status = status_win2k;
2185 status = delete_printer_driver(p, info.info_3, version, False);
2187 /* if at least one of the deletes succeeded return OK */
2189 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2193 free_a_printer_driver( info, 3 );
2198 /****************************************************************
2199 _spoolss_DeletePrinterDriverEx
2200 ****************************************************************/
2202 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2203 struct spoolss_DeletePrinterDriverEx *r)
2207 NT_PRINTER_DRIVER_INFO_LEVEL info;
2208 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2210 uint32_t flags = r->in.delete_flags;
2213 WERROR status_win2k = WERR_ACCESS_DENIED;
2214 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2216 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2217 and not a printer admin, then fail */
2219 if ( (p->server_info->utok.uid != 0)
2220 && !user_has_privileges(p->server_info->ptok, &se_printop )
2221 && !token_contains_name_in_list(
2222 uidtoname(p->server_info->utok.uid), NULL, NULL,
2223 p->server_info->ptok, lp_printer_admin(-1)) )
2225 return WERR_ACCESS_DENIED;
2228 driver = CONST_DISCARD(char *, r->in.driver);
2229 arch = CONST_DISCARD(char *, r->in.architecture);
2231 /* check that we have a valid driver name first */
2232 if ((version=get_version_id(arch)) == -1) {
2233 /* this is what NT returns */
2234 return WERR_INVALID_ENVIRONMENT;
2237 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2238 version = r->in.version;
2241 ZERO_STRUCT(info_win2k);
2243 status = get_a_printer_driver(&info, 3, driver, arch, version);
2245 if ( !W_ERROR_IS_OK(status) )
2248 * if the client asked for a specific version,
2249 * or this is something other than Windows NT x86,
2253 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2256 /* try for Win2k driver if "Windows NT x86" */
2259 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2260 status = WERR_UNKNOWN_PRINTER_DRIVER;
2265 if ( printer_driver_in_use(info.info_3) ) {
2266 status = WERR_PRINTER_DRIVER_IN_USE;
2271 * we have a couple of cases to consider.
2272 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2273 * then the delete should fail if **any** files overlap with
2275 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2276 * non-overlapping files
2277 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2278 * is set, the do not delete any files
2279 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2282 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2284 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2286 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2287 /* no idea of the correct error here */
2288 status = WERR_ACCESS_DENIED;
2293 /* also check for W32X86/3 if necessary; maybe we already have? */
2295 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2296 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2299 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2300 /* no idea of the correct error here */
2301 free_a_printer_driver( info_win2k, 3 );
2302 status = WERR_ACCESS_DENIED;
2306 /* if we get to here, we now have 2 driver info structures to remove */
2307 /* remove the Win2k driver first*/
2309 status_win2k = delete_printer_driver(
2310 p, info_win2k.info_3, 3, delete_files);
2311 free_a_printer_driver( info_win2k, 3 );
2313 /* this should not have failed---if it did, report to client */
2315 if ( !W_ERROR_IS_OK(status_win2k) )
2320 status = delete_printer_driver(p, info.info_3, version, delete_files);
2322 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2325 free_a_printer_driver( info, 3 );
2331 /****************************************************************************
2332 Internal routine for removing printerdata
2333 ***************************************************************************/
2335 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2337 return delete_printer_data( printer->info_2, key, value );
2340 /****************************************************************************
2341 Internal routine for storing printerdata
2342 ***************************************************************************/
2344 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2345 uint32 type, uint8 *data, int real_len )
2347 /* the registry objects enforce uniqueness based on value name */
2349 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2352 /********************************************************************
2353 GetPrinterData on a printer server Handle.
2354 ********************************************************************/
2356 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2358 enum winreg_Type *type,
2359 union spoolss_PrinterData *data)
2361 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2363 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2369 if (!StrCaseCmp(value, "BeepEnabled")) {
2375 if (!StrCaseCmp(value, "EventLog")) {
2377 /* formally was 0x1b */
2382 if (!StrCaseCmp(value, "NetPopup")) {
2388 if (!StrCaseCmp(value, "MajorVersion")) {
2391 /* Windows NT 4.0 seems to not allow uploading of drivers
2392 to a server that reports 0x3 as the MajorVersion.
2393 need to investigate more how Win2k gets around this .
2396 if (RA_WINNT == get_remote_arch()) {
2405 if (!StrCaseCmp(value, "MinorVersion")) {
2412 * uint32 size = 0x114
2414 * uint32 minor = [0|1]
2415 * uint32 build = [2195|2600]
2416 * extra unicode string = e.g. "Service Pack 3"
2418 if (!StrCaseCmp(value, "OSVersion")) {
2420 enum ndr_err_code ndr_err;
2421 struct spoolss_OSVersion os;
2423 os.major = 5; /* Windows 2000 == 5.0 */
2425 os.build = 2195; /* build */
2426 os.extra_string = ""; /* leave extra string empty */
2428 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2429 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2430 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2431 return WERR_GENERAL_FAILURE;
2435 data->binary = blob;
2441 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2444 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2445 W_ERROR_HAVE_NO_MEMORY(data->string);
2450 if (!StrCaseCmp(value, "Architecture")) {
2453 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2454 W_ERROR_HAVE_NO_MEMORY(data->string);
2459 if (!StrCaseCmp(value, "DsPresent")) {
2462 /* only show the publish check box if we are a
2463 member of a AD domain */
2465 if (lp_security() == SEC_ADS) {
2473 if (!StrCaseCmp(value, "DNSMachineName")) {
2474 const char *hostname = get_mydnsfullname();
2477 return WERR_BADFILE;
2481 data->string = talloc_strdup(mem_ctx, hostname);
2482 W_ERROR_HAVE_NO_MEMORY(data->string);
2487 return WERR_INVALID_PARAM;
2490 /****************************************************************
2491 _spoolss_GetPrinterData
2492 ****************************************************************/
2494 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2495 struct spoolss_GetPrinterData *r)
2498 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2499 NT_PRINTER_INFO_LEVEL *printer = NULL;
2503 * Reminder: when it's a string, the length is in BYTES
2504 * even if UNICODE is negociated.
2509 /* in case of problem, return some default values */
2514 DEBUG(4,("_spoolss_GetPrinterData\n"));
2517 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2518 OUR_HANDLE(r->in.handle)));
2519 result = WERR_BADFID;
2523 if (Printer->printer_type == SPLHND_SERVER) {
2524 result = getprinterdata_printer_server(p->mem_ctx,
2529 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2530 result = WERR_BADFID;
2534 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2535 if (!W_ERROR_IS_OK(result)) {
2539 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2541 if (strequal(r->in.value_name, "ChangeId")) {
2542 *r->out.type = REG_DWORD;
2543 r->out.data->value = printer->info_2->changeid;
2549 v = get_printer_data(printer->info_2,
2550 SPOOL_PRINTERDATA_KEY,
2553 result = WERR_BADFILE;
2557 *r->out.type = v->type;
2559 blob = data_blob_const(v->data_p, v->size);
2561 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2568 /* cleanup & exit */
2571 free_a_printer(&printer, 2);
2574 if (!W_ERROR_IS_OK(result)) {
2578 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2579 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2580 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2582 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2585 /*********************************************************
2586 Connect to the client machine.
2587 **********************************************************/
2589 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2590 struct sockaddr_storage *client_ss, const char *remote_machine)
2593 struct cli_state *the_cli;
2594 struct sockaddr_storage rm_addr;
2596 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2597 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2598 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2602 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2603 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2607 char addr[INET6_ADDRSTRLEN];
2608 rm_addr = *client_ss;
2609 print_sockaddr(addr, sizeof(addr), &rm_addr);
2610 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2614 /* setup the connection */
2616 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2617 &rm_addr, 0, "IPC$", "IPC",
2621 0, lp_client_signing(), NULL );
2623 if ( !NT_STATUS_IS_OK( ret ) ) {
2624 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2629 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2630 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2631 cli_shutdown(the_cli);
2636 * Ok - we have an anonymous connection to the IPC$ share.
2637 * Now start the NT Domain stuff :-).
2640 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2641 if (!NT_STATUS_IS_OK(ret)) {
2642 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2643 remote_machine, nt_errstr(ret)));
2644 cli_shutdown(the_cli);
2651 /***************************************************************************
2652 Connect to the client.
2653 ****************************************************************************/
2655 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2656 uint32 localprinter, uint32 type,
2657 struct policy_handle *handle,
2658 struct sockaddr_storage *client_ss)
2664 * If it's the first connection, contact the client
2665 * and connect to the IPC$ share anonymously
2667 if (smb_connections==0) {
2668 fstring unix_printer;
2670 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2672 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2675 messaging_register(smbd_messaging_context(), NULL,
2676 MSG_PRINTER_NOTIFY2,
2677 receive_notify2_message_list);
2678 /* Tell the connections db we're now interested in printer
2679 * notify messages. */
2680 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2684 * Tell the specific printing tdb we want messages for this printer
2685 * by registering our PID.
2688 if (!print_notify_register_pid(snum))
2689 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2693 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2701 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2702 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2703 win_errstr(result)));
2705 return (W_ERROR_IS_OK(result));
2708 /****************************************************************
2709 ****************************************************************/
2711 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2712 const struct spoolss_NotifyOption *r)
2714 struct spoolss_NotifyOption *option;
2721 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2728 if (!option->count) {
2732 option->types = talloc_zero_array(option,
2733 struct spoolss_NotifyOptionType, option->count);
2734 if (!option->types) {
2735 talloc_free(option);
2739 for (i=0; i < option->count; i++) {
2740 option->types[i] = r->types[i];
2742 if (option->types[i].count) {
2743 option->types[i].fields = talloc_zero_array(option,
2744 union spoolss_Field, option->types[i].count);
2745 if (!option->types[i].fields) {
2746 talloc_free(option);
2749 for (k=0; k<option->types[i].count; k++) {
2750 option->types[i].fields[k] =
2751 r->types[i].fields[k];
2759 /****************************************************************
2760 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2762 * before replying OK: status=0 a rpc call is made to the workstation
2763 * asking ReplyOpenPrinter
2765 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2766 * called from api_spoolss_rffpcnex
2767 ****************************************************************/
2769 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2770 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2773 struct spoolss_NotifyOption *option = r->in.notify_options;
2774 struct sockaddr_storage client_ss;
2776 /* store the notify value in the printer struct */
2778 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2781 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2782 "Invalid handle (%s:%u:%u).\n",
2783 OUR_HANDLE(r->in.handle)));
2787 Printer->notify.flags = r->in.flags;
2788 Printer->notify.options = r->in.options;
2789 Printer->notify.printerlocal = r->in.printer_local;
2791 TALLOC_FREE(Printer->notify.option);
2792 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2794 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2796 /* Connect to the client machine and send a ReplyOpenPrinter */
2798 if ( Printer->printer_type == SPLHND_SERVER)
2800 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2801 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2804 if (!interpret_string_addr(&client_ss, p->client_address,
2806 return WERR_SERVER_UNAVAILABLE;
2809 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2810 Printer->notify.printerlocal, 1,
2811 &Printer->notify.client_hnd, &client_ss))
2812 return WERR_SERVER_UNAVAILABLE;
2814 Printer->notify.client_connected=True;
2819 /*******************************************************************
2820 * fill a notify_info_data with the servername
2821 ********************************************************************/
2823 void spoolss_notify_server_name(int snum,
2824 struct spoolss_Notify *data,
2825 print_queue_struct *queue,
2826 NT_PRINTER_INFO_LEVEL *printer,
2827 TALLOC_CTX *mem_ctx)
2829 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2832 /*******************************************************************
2833 * fill a notify_info_data with the printername (not including the servername).
2834 ********************************************************************/
2836 void spoolss_notify_printer_name(int snum,
2837 struct spoolss_Notify *data,
2838 print_queue_struct *queue,
2839 NT_PRINTER_INFO_LEVEL *printer,
2840 TALLOC_CTX *mem_ctx)
2842 /* the notify name should not contain the \\server\ part */
2843 char *p = strrchr(printer->info_2->printername, '\\');
2846 p = printer->info_2->printername;
2851 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2854 /*******************************************************************
2855 * fill a notify_info_data with the servicename
2856 ********************************************************************/
2858 void spoolss_notify_share_name(int snum,
2859 struct spoolss_Notify *data,
2860 print_queue_struct *queue,
2861 NT_PRINTER_INFO_LEVEL *printer,
2862 TALLOC_CTX *mem_ctx)
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2867 /*******************************************************************
2868 * fill a notify_info_data with the port name
2869 ********************************************************************/
2871 void spoolss_notify_port_name(int snum,
2872 struct spoolss_Notify *data,
2873 print_queue_struct *queue,
2874 NT_PRINTER_INFO_LEVEL *printer,
2875 TALLOC_CTX *mem_ctx)
2877 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2880 /*******************************************************************
2881 * fill a notify_info_data with the printername
2882 * but it doesn't exist, have to see what to do
2883 ********************************************************************/
2885 void spoolss_notify_driver_name(int snum,
2886 struct spoolss_Notify *data,
2887 print_queue_struct *queue,
2888 NT_PRINTER_INFO_LEVEL *printer,
2889 TALLOC_CTX *mem_ctx)
2891 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2894 /*******************************************************************
2895 * fill a notify_info_data with the comment
2896 ********************************************************************/
2898 void spoolss_notify_comment(int snum,
2899 struct spoolss_Notify *data,
2900 print_queue_struct *queue,
2901 NT_PRINTER_INFO_LEVEL *printer,
2902 TALLOC_CTX *mem_ctx)
2906 if (*printer->info_2->comment == '\0') {
2907 p = lp_comment(snum);
2909 p = printer->info_2->comment;
2912 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2915 /*******************************************************************
2916 * fill a notify_info_data with the comment
2917 * location = "Room 1, floor 2, building 3"
2918 ********************************************************************/
2920 void spoolss_notify_location(int snum,
2921 struct spoolss_Notify *data,
2922 print_queue_struct *queue,
2923 NT_PRINTER_INFO_LEVEL *printer,
2924 TALLOC_CTX *mem_ctx)
2926 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2929 /*******************************************************************
2930 * fill a notify_info_data with the device mode
2931 * jfm:xxxx don't to it for know but that's a real problem !!!
2932 ********************************************************************/
2934 static void spoolss_notify_devmode(int snum,
2935 struct spoolss_Notify *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2940 /* for a dummy implementation we have to zero the fields */
2941 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2944 /*******************************************************************
2945 * fill a notify_info_data with the separator file name
2946 ********************************************************************/
2948 void spoolss_notify_sepfile(int snum,
2949 struct spoolss_Notify *data,
2950 print_queue_struct *queue,
2951 NT_PRINTER_INFO_LEVEL *printer,
2952 TALLOC_CTX *mem_ctx)
2954 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2957 /*******************************************************************
2958 * fill a notify_info_data with the print processor
2959 * jfm:xxxx return always winprint to indicate we don't do anything to it
2960 ********************************************************************/
2962 void spoolss_notify_print_processor(int snum,
2963 struct spoolss_Notify *data,
2964 print_queue_struct *queue,
2965 NT_PRINTER_INFO_LEVEL *printer,
2966 TALLOC_CTX *mem_ctx)
2968 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2971 /*******************************************************************
2972 * fill a notify_info_data with the print processor options
2973 * jfm:xxxx send an empty string
2974 ********************************************************************/
2976 void spoolss_notify_parameters(int snum,
2977 struct spoolss_Notify *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2982 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2985 /*******************************************************************
2986 * fill a notify_info_data with the data type
2987 * jfm:xxxx always send RAW as data type
2988 ********************************************************************/
2990 void spoolss_notify_datatype(int snum,
2991 struct spoolss_Notify *data,
2992 print_queue_struct *queue,
2993 NT_PRINTER_INFO_LEVEL *printer,
2994 TALLOC_CTX *mem_ctx)
2996 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2999 /*******************************************************************
3000 * fill a notify_info_data with the security descriptor
3001 * jfm:xxxx send an null pointer to say no security desc
3002 * have to implement security before !
3003 ********************************************************************/
3005 static void spoolss_notify_security_desc(int snum,
3006 struct spoolss_Notify *data,
3007 print_queue_struct *queue,
3008 NT_PRINTER_INFO_LEVEL *printer,
3009 TALLOC_CTX *mem_ctx)
3011 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3012 printer->info_2->secdesc_buf->sd_size,
3013 printer->info_2->secdesc_buf->sd);
3016 /*******************************************************************
3017 * fill a notify_info_data with the attributes
3018 * jfm:xxxx a samba printer is always shared
3019 ********************************************************************/
3021 void spoolss_notify_attributes(int snum,
3022 struct spoolss_Notify *data,
3023 print_queue_struct *queue,
3024 NT_PRINTER_INFO_LEVEL *printer,
3025 TALLOC_CTX *mem_ctx)
3027 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3030 /*******************************************************************
3031 * fill a notify_info_data with the priority
3032 ********************************************************************/
3034 static void spoolss_notify_priority(int snum,
3035 struct spoolss_Notify *data,
3036 print_queue_struct *queue,
3037 NT_PRINTER_INFO_LEVEL *printer,
3038 TALLOC_CTX *mem_ctx)
3040 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3043 /*******************************************************************
3044 * fill a notify_info_data with the default priority
3045 ********************************************************************/
3047 static void spoolss_notify_default_priority(int snum,
3048 struct spoolss_Notify *data,
3049 print_queue_struct *queue,
3050 NT_PRINTER_INFO_LEVEL *printer,
3051 TALLOC_CTX *mem_ctx)
3053 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3056 /*******************************************************************
3057 * fill a notify_info_data with the start time
3058 ********************************************************************/
3060 static void spoolss_notify_start_time(int snum,
3061 struct spoolss_Notify *data,
3062 print_queue_struct *queue,
3063 NT_PRINTER_INFO_LEVEL *printer,
3064 TALLOC_CTX *mem_ctx)
3066 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3069 /*******************************************************************
3070 * fill a notify_info_data with the until time
3071 ********************************************************************/
3073 static void spoolss_notify_until_time(int snum,
3074 struct spoolss_Notify *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3082 /*******************************************************************
3083 * fill a notify_info_data with the status
3084 ********************************************************************/
3086 static void spoolss_notify_status(int snum,
3087 struct spoolss_Notify *data,
3088 print_queue_struct *queue,
3089 NT_PRINTER_INFO_LEVEL *printer,
3090 TALLOC_CTX *mem_ctx)
3092 print_status_struct status;
3094 print_queue_length(snum, &status);
3095 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3098 /*******************************************************************
3099 * fill a notify_info_data with the number of jobs queued
3100 ********************************************************************/
3102 void spoolss_notify_cjobs(int snum,
3103 struct spoolss_Notify *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3108 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3111 /*******************************************************************
3112 * fill a notify_info_data with the average ppm
3113 ********************************************************************/
3115 static void spoolss_notify_average_ppm(int snum,
3116 struct spoolss_Notify *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 /* always respond 8 pages per minutes */
3122 /* a little hard ! */
3123 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3126 /*******************************************************************
3127 * fill a notify_info_data with username
3128 ********************************************************************/
3130 static void spoolss_notify_username(int snum,
3131 struct spoolss_Notify *data,
3132 print_queue_struct *queue,
3133 NT_PRINTER_INFO_LEVEL *printer,
3134 TALLOC_CTX *mem_ctx)
3136 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3139 /*******************************************************************
3140 * fill a notify_info_data with job status
3141 ********************************************************************/
3143 static void spoolss_notify_job_status(int snum,
3144 struct spoolss_Notify *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3152 /*******************************************************************
3153 * fill a notify_info_data with job name
3154 ********************************************************************/
3156 static void spoolss_notify_job_name(int snum,
3157 struct spoolss_Notify *data,
3158 print_queue_struct *queue,
3159 NT_PRINTER_INFO_LEVEL *printer,
3160 TALLOC_CTX *mem_ctx)
3162 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3165 /*******************************************************************
3166 * fill a notify_info_data with job status
3167 ********************************************************************/
3169 static void spoolss_notify_job_status_string(int snum,
3170 struct spoolss_Notify *data,
3171 print_queue_struct *queue,
3172 NT_PRINTER_INFO_LEVEL *printer,
3173 TALLOC_CTX *mem_ctx)
3176 * Now we're returning job status codes we just return a "" here. JRA.
3181 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3184 switch (queue->status) {
3189 p = ""; /* NT provides the paused string */
3198 #endif /* NO LONGER NEEDED. */
3200 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3203 /*******************************************************************
3204 * fill a notify_info_data with job time
3205 ********************************************************************/
3207 static void spoolss_notify_job_time(int snum,
3208 struct spoolss_Notify *data,
3209 print_queue_struct *queue,
3210 NT_PRINTER_INFO_LEVEL *printer,
3211 TALLOC_CTX *mem_ctx)
3213 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3216 /*******************************************************************
3217 * fill a notify_info_data with job size
3218 ********************************************************************/
3220 static void spoolss_notify_job_size(int snum,
3221 struct spoolss_Notify *data,
3222 print_queue_struct *queue,
3223 NT_PRINTER_INFO_LEVEL *printer,
3224 TALLOC_CTX *mem_ctx)
3226 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3229 /*******************************************************************
3230 * fill a notify_info_data with page info
3231 ********************************************************************/
3232 static void spoolss_notify_total_pages(int snum,
3233 struct spoolss_Notify *data,
3234 print_queue_struct *queue,
3235 NT_PRINTER_INFO_LEVEL *printer,
3236 TALLOC_CTX *mem_ctx)
3238 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3241 /*******************************************************************
3242 * fill a notify_info_data with pages printed info.
3243 ********************************************************************/
3244 static void spoolss_notify_pages_printed(int snum,
3245 struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 NT_PRINTER_INFO_LEVEL *printer,
3248 TALLOC_CTX *mem_ctx)
3250 /* Add code when back-end tracks this */
3251 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3254 /*******************************************************************
3255 Fill a notify_info_data with job position.
3256 ********************************************************************/
3258 static void spoolss_notify_job_position(int snum,
3259 struct spoolss_Notify *data,
3260 print_queue_struct *queue,
3261 NT_PRINTER_INFO_LEVEL *printer,
3262 TALLOC_CTX *mem_ctx)
3264 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3267 /*******************************************************************
3268 Fill a notify_info_data with submitted time.
3269 ********************************************************************/
3271 static void spoolss_notify_submitted_time(int snum,
3272 struct spoolss_Notify *data,
3273 print_queue_struct *queue,
3274 NT_PRINTER_INFO_LEVEL *printer,
3275 TALLOC_CTX *mem_ctx)
3277 data->data.string.string = NULL;
3278 data->data.string.size = 0;
3280 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3281 &data->data.string.string,
3282 &data->data.string.size);
3286 struct s_notify_info_data_table
3288 enum spoolss_NotifyType type;
3291 enum spoolss_NotifyTable variable_type;
3292 void (*fn) (int snum, struct spoolss_Notify *data,
3293 print_queue_struct *queue,
3294 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3297 /* A table describing the various print notification constants and
3298 whether the notification data is a pointer to a variable sized
3299 buffer, a one value uint32 or a two value uint32. */
3301 static const struct s_notify_info_data_table notify_info_data_table[] =
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3328 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3349 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3350 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3351 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3354 /*******************************************************************
3355 Return the variable_type of info_data structure.
3356 ********************************************************************/
3358 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3363 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3364 if ( (notify_info_data_table[i].type == type) &&
3365 (notify_info_data_table[i].field == field) ) {
3366 return notify_info_data_table[i].variable_type;
3370 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3375 /****************************************************************************
3376 ****************************************************************************/
3378 static bool search_notify(enum spoolss_NotifyType type,
3384 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3385 if (notify_info_data_table[i].type == type &&
3386 notify_info_data_table[i].field == field &&
3387 notify_info_data_table[i].fn != NULL) {
3396 /****************************************************************************
3397 ****************************************************************************/
3399 void construct_info_data(struct spoolss_Notify *info_data,
3400 enum spoolss_NotifyType type,
3404 info_data->type = type;
3405 info_data->field.field = field;
3406 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3407 info_data->job_id = id;
3410 /*******************************************************************
3412 * fill a notify_info struct with info asked
3414 ********************************************************************/
3416 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3417 struct spoolss_NotifyInfo *info,
3419 const struct spoolss_NotifyOptionType *option_type,
3421 TALLOC_CTX *mem_ctx)
3424 enum spoolss_NotifyType type;
3427 struct spoolss_Notify *current_data;
3428 NT_PRINTER_INFO_LEVEL *printer = NULL;
3429 print_queue_struct *queue=NULL;
3431 type = option_type->type;
3433 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3434 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3435 option_type->count, lp_servicename(snum)));
3437 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3440 for(field_num=0; field_num < option_type->count; field_num++) {
3441 field = option_type->fields[field_num].field;
3443 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3445 if (!search_notify(type, field, &j) )
3448 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3449 struct spoolss_Notify,
3451 if (info->notifies == NULL) {
3452 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3453 free_a_printer(&printer, 2);
3457 current_data = &info->notifies[info->count];
3459 construct_info_data(current_data, type, field, id);
3461 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3462 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3464 notify_info_data_table[j].fn(snum, current_data, queue,
3470 free_a_printer(&printer, 2);
3474 /*******************************************************************
3476 * fill a notify_info struct with info asked
3478 ********************************************************************/
3480 static bool construct_notify_jobs_info(print_queue_struct *queue,
3481 struct spoolss_NotifyInfo *info,
3482 NT_PRINTER_INFO_LEVEL *printer,
3484 const struct spoolss_NotifyOptionType *option_type,
3486 TALLOC_CTX *mem_ctx)
3489 enum spoolss_NotifyType type;
3491 struct spoolss_Notify *current_data;
3493 DEBUG(4,("construct_notify_jobs_info\n"));
3495 type = option_type->type;
3497 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3498 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3499 option_type->count));
3501 for(field_num=0; field_num<option_type->count; field_num++) {
3502 field = option_type->fields[field_num].field;
3504 if (!search_notify(type, field, &j) )
3507 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3508 struct spoolss_Notify,
3510 if (info->notifies == NULL) {
3511 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3515 current_data=&(info->notifies[info->count]);
3517 construct_info_data(current_data, type, field, id);
3518 notify_info_data_table[j].fn(snum, current_data, queue,
3527 * JFM: The enumeration is not that simple, it's even non obvious.
3529 * let's take an example: I want to monitor the PRINTER SERVER for
3530 * the printer's name and the number of jobs currently queued.
3531 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3532 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3534 * I have 3 printers on the back of my server.
3536 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3539 * 1 printer 1 name 1
3540 * 2 printer 1 cjob 1
3541 * 3 printer 2 name 2
3542 * 4 printer 2 cjob 2
3543 * 5 printer 3 name 3
3544 * 6 printer 3 name 3
3546 * that's the print server case, the printer case is even worse.
3549 /*******************************************************************
3551 * enumerate all printers on the printserver
3552 * fill a notify_info struct with info asked
3554 ********************************************************************/
3556 static WERROR printserver_notify_info(pipes_struct *p,
3557 struct policy_handle *hnd,
3558 struct spoolss_NotifyInfo *info,
3559 TALLOC_CTX *mem_ctx)
3562 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3563 int n_services=lp_numservices();
3565 struct spoolss_NotifyOption *option;
3566 struct spoolss_NotifyOptionType option_type;
3568 DEBUG(4,("printserver_notify_info\n"));
3573 option = Printer->notify.option;
3576 info->notifies = NULL;
3579 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3580 sending a ffpcn() request first */
3585 for (i=0; i<option->count; i++) {
3586 option_type = option->types[i];
3588 if (option_type.type != PRINTER_NOTIFY_TYPE)
3591 for (snum=0; snum<n_services; snum++)
3593 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3594 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3600 * Debugging information, don't delete.
3603 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3604 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3605 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3607 for (i=0; i<info->count; i++) {
3608 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3609 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3610 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3617 /*******************************************************************
3619 * fill a notify_info struct with info asked
3621 ********************************************************************/
3623 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3624 struct spoolss_NotifyInfo *info,
3625 TALLOC_CTX *mem_ctx)
3628 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3631 struct spoolss_NotifyOption *option;
3632 struct spoolss_NotifyOptionType option_type;
3634 print_queue_struct *queue=NULL;
3635 print_status_struct status;
3637 DEBUG(4,("printer_notify_info\n"));
3642 option = Printer->notify.option;
3646 info->notifies = NULL;
3649 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3650 sending a ffpcn() request first */
3655 get_printer_snum(p, hnd, &snum, NULL);
3657 for (i=0; i<option->count; i++) {
3658 option_type = option->types[i];
3660 switch (option_type.type) {
3661 case PRINTER_NOTIFY_TYPE:
3662 if(construct_notify_printer_info(Printer, info, snum,
3668 case JOB_NOTIFY_TYPE: {
3669 NT_PRINTER_INFO_LEVEL *printer = NULL;
3671 count = print_queue_status(snum, &queue, &status);
3673 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3676 for (j=0; j<count; j++) {
3677 construct_notify_jobs_info(&queue[j], info,
3684 free_a_printer(&printer, 2);
3694 * Debugging information, don't delete.
3697 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3698 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3699 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3701 for (i=0; i<info->count; i++) {
3702 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3703 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3704 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3710 /****************************************************************
3711 _spoolss_RouterRefreshPrinterChangeNotify
3712 ****************************************************************/
3714 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3715 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3717 struct spoolss_NotifyInfo *info;
3719 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3720 WERROR result = WERR_BADFID;
3722 /* we always have a spoolss_NotifyInfo struct */
3723 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3725 result = WERR_NOMEM;
3729 *r->out.info = info;
3732 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3733 "Invalid handle (%s:%u:%u).\n",
3734 OUR_HANDLE(r->in.handle)));
3738 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3741 * We are now using the change value, and
3742 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3743 * I don't have a global notification system, I'm sending back all the
3744 * informations even when _NOTHING_ has changed.
3747 /* We need to keep track of the change value to send back in
3748 RRPCN replies otherwise our updates are ignored. */
3750 Printer->notify.fnpcn = True;
3752 if (Printer->notify.client_connected) {
3753 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3754 "Saving change value in request [%x]\n",
3756 Printer->notify.change = r->in.change_low;
3759 /* just ignore the spoolss_NotifyOption */
3761 switch (Printer->printer_type) {
3763 result = printserver_notify_info(p, r->in.handle,
3767 case SPLHND_PRINTER:
3768 result = printer_notify_info(p, r->in.handle,
3773 Printer->notify.fnpcn = False;
3779 /********************************************************************
3780 * construct_printer_info_0
3781 * fill a printer_info_0 struct
3782 ********************************************************************/
3784 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3785 const NT_PRINTER_INFO_LEVEL *ntprinter,
3786 struct spoolss_PrinterInfo0 *r,
3790 counter_printer_0 *session_counter;
3792 print_status_struct status;
3794 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3795 W_ERROR_HAVE_NO_MEMORY(r->printername);
3797 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3798 W_ERROR_HAVE_NO_MEMORY(r->servername);
3800 count = print_queue_length(snum, &status);
3802 /* check if we already have a counter for this printer */
3803 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3804 if (session_counter->snum == snum)
3808 /* it's the first time, add it to the list */
3809 if (session_counter == NULL) {
3810 session_counter = SMB_MALLOC_P(counter_printer_0);
3811 W_ERROR_HAVE_NO_MEMORY(session_counter);
3812 ZERO_STRUCTP(session_counter);
3813 session_counter->snum = snum;
3814 session_counter->counter = 0;
3815 DLIST_ADD(counter_list, session_counter);
3819 session_counter->counter++;
3825 setuptime = (time_t)ntprinter->info_2->setuptime;
3827 init_systemtime(&r->time, gmtime(&setuptime));
3830 * the global_counter should be stored in a TDB as it's common to all the clients
3831 * and should be zeroed on samba startup
3833 r->global_counter = session_counter->counter;
3835 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3836 r->version = 0x0005; /* NT 5 */
3837 r->free_build = 0x0893; /* build 2195 */
3839 r->max_spooling = 0;
3840 r->session_counter = session_counter->counter;
3841 r->num_error_out_of_paper = 0x0;
3842 r->num_error_not_ready = 0x0; /* number of print failure */
3844 r->number_of_processors = 0x1;
3845 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3846 r->high_part_total_bytes = 0x0;
3847 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3848 r->last_error = WERR_OK;
3849 r->status = nt_printq_status(status.status);
3850 r->enumerate_network_printers = 0x0;
3851 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3852 r->processor_architecture = 0x0;
3853 r->processor_level = 0x6; /* 6 ???*/
3861 /****************************************************************************
3862 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3863 should be valid upon entry
3864 ****************************************************************************/
3866 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3867 struct spoolss_DeviceMode *r,
3868 const NT_DEVICEMODE *ntdevmode)
3870 if (!r || !ntdevmode) {
3871 return WERR_INVALID_PARAM;
3874 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3875 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3877 r->specversion = ntdevmode->specversion;
3878 r->driverversion = ntdevmode->driverversion;
3879 r->size = ntdevmode->size;
3880 r->__driverextra_length = ntdevmode->driverextra;
3881 r->fields = ntdevmode->fields;
3883 r->orientation = ntdevmode->orientation;
3884 r->papersize = ntdevmode->papersize;
3885 r->paperlength = ntdevmode->paperlength;
3886 r->paperwidth = ntdevmode->paperwidth;
3887 r->scale = ntdevmode->scale;
3888 r->copies = ntdevmode->copies;
3889 r->defaultsource = ntdevmode->defaultsource;
3890 r->printquality = ntdevmode->printquality;
3891 r->color = ntdevmode->color;
3892 r->duplex = ntdevmode->duplex;
3893 r->yresolution = ntdevmode->yresolution;
3894 r->ttoption = ntdevmode->ttoption;
3895 r->collate = ntdevmode->collate;
3897 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3898 W_ERROR_HAVE_NO_MEMORY(r->formname);
3900 /* all 0 below are values that have not been set in the old parsing/copy
3901 * function, maybe they should... - gd */
3907 r->displayflags = 0;
3908 r->displayfrequency = 0;
3909 r->icmmethod = ntdevmode->icmmethod;
3910 r->icmintent = ntdevmode->icmintent;
3911 r->mediatype = ntdevmode->mediatype;
3912 r->dithertype = ntdevmode->dithertype;
3915 r->panningwidth = 0;
3916 r->panningheight = 0;
3918 if (ntdevmode->nt_dev_private != NULL) {
3919 r->driverextra_data = data_blob_talloc(mem_ctx,
3920 ntdevmode->nt_dev_private,
3921 ntdevmode->driverextra);
3922 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3929 /****************************************************************************
3930 Create a spoolss_DeviceMode struct. Returns talloced memory.
3931 ****************************************************************************/
3933 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3934 const char *servicename)
3937 NT_PRINTER_INFO_LEVEL *printer = NULL;
3938 struct spoolss_DeviceMode *devmode = NULL;
3940 DEBUG(7,("construct_dev_mode\n"));
3942 DEBUGADD(8,("getting printer characteristics\n"));
3944 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3947 if (!printer->info_2->devmode) {
3948 DEBUG(5, ("BONG! There was no device mode!\n"));
3952 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3954 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3958 DEBUGADD(8,("loading DEVICEMODE\n"));
3960 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3961 if (!W_ERROR_IS_OK(result)) {
3962 TALLOC_FREE(devmode);
3966 free_a_printer(&printer,2);
3971 /********************************************************************
3972 * construct_printer_info3
3973 * fill a spoolss_PrinterInfo3 struct
3974 ********************************************************************/
3976 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3977 const NT_PRINTER_INFO_LEVEL *ntprinter,
3978 struct spoolss_PrinterInfo3 *r,
3981 /* These are the components of the SD we are returning. */
3983 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3984 /* don't use talloc_steal() here unless you do a deep steal of all
3985 the SEC_DESC members */
3987 r->secdesc = dup_sec_desc(mem_ctx,
3988 ntprinter->info_2->secdesc_buf->sd);
3989 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3995 /********************************************************************
3996 * construct_printer_info4
3997 * fill a spoolss_PrinterInfo4 struct
3998 ********************************************************************/
4000 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4001 const NT_PRINTER_INFO_LEVEL *ntprinter,
4002 struct spoolss_PrinterInfo4 *r,
4005 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4006 W_ERROR_HAVE_NO_MEMORY(r->printername);
4007 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4008 W_ERROR_HAVE_NO_MEMORY(r->servername);
4010 r->attributes = ntprinter->info_2->attributes;
4015 /********************************************************************
4016 * construct_printer_info5
4017 * fill a spoolss_PrinterInfo5 struct
4018 ********************************************************************/
4020 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4021 const NT_PRINTER_INFO_LEVEL *ntprinter,
4022 struct spoolss_PrinterInfo5 *r,
4025 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4026 W_ERROR_HAVE_NO_MEMORY(r->printername);
4027 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4028 W_ERROR_HAVE_NO_MEMORY(r->portname);
4030 r->attributes = ntprinter->info_2->attributes;
4032 /* these two are not used by NT+ according to MSDN */
4034 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4035 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4040 /********************************************************************
4041 * construct_printer_info_6
4042 * fill a spoolss_PrinterInfo6 struct
4043 ********************************************************************/
4045 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4046 const NT_PRINTER_INFO_LEVEL *ntprinter,
4047 struct spoolss_PrinterInfo6 *r,
4051 print_status_struct status;
4053 count = print_queue_length(snum, &status);
4055 r->status = nt_printq_status(status.status);
4060 /********************************************************************
4061 * construct_printer_info7
4062 * fill a spoolss_PrinterInfo7 struct
4063 ********************************************************************/
4065 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4066 Printer_entry *print_hnd,
4067 struct spoolss_PrinterInfo7 *r,
4072 if (is_printer_published(print_hnd, snum, &guid)) {
4073 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4074 r->action = DSPRINT_PUBLISH;
4076 r->guid = talloc_strdup(mem_ctx, "");
4077 r->action = DSPRINT_UNPUBLISH;
4079 W_ERROR_HAVE_NO_MEMORY(r->guid);
4084 /********************************************************************
4085 * construct_printer_info1
4086 * fill a spoolss_PrinterInfo1 struct
4087 ********************************************************************/
4089 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4090 const NT_PRINTER_INFO_LEVEL *ntprinter,
4092 struct spoolss_PrinterInfo1 *r,
4095 char *chaine = NULL;
4098 if (*ntprinter->info_2->comment == '\0') {
4099 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4100 chaine = talloc_asprintf(mem_ctx,
4101 "%s,%s,%s", ntprinter->info_2->printername,
4102 ntprinter->info_2->drivername, lp_comment(snum));
4104 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4105 chaine = talloc_asprintf(mem_ctx,
4106 "%s,%s,%s", ntprinter->info_2->printername,
4107 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4109 W_ERROR_HAVE_NO_MEMORY(chaine);
4110 W_ERROR_HAVE_NO_MEMORY(r->comment);
4112 r->description = talloc_strdup(mem_ctx, chaine);
4113 W_ERROR_HAVE_NO_MEMORY(r->description);
4114 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4115 W_ERROR_HAVE_NO_MEMORY(r->name);
4120 /********************************************************************
4121 * construct_printer_info2
4122 * fill a spoolss_PrinterInfo2 struct
4123 ********************************************************************/
4125 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4126 const NT_PRINTER_INFO_LEVEL *ntprinter,
4127 struct spoolss_PrinterInfo2 *r,
4132 print_status_struct status;
4134 count = print_queue_length(snum, &status);
4136 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4137 W_ERROR_HAVE_NO_MEMORY(r->servername);
4138 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4139 W_ERROR_HAVE_NO_MEMORY(r->printername);
4140 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4141 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4142 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4143 W_ERROR_HAVE_NO_MEMORY(r->portname);
4144 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4145 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4147 if (*ntprinter->info_2->comment == '\0') {
4148 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4150 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4152 W_ERROR_HAVE_NO_MEMORY(r->comment);
4154 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4155 W_ERROR_HAVE_NO_MEMORY(r->location);
4156 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4157 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4158 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4159 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4160 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4161 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4162 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4163 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4165 r->attributes = ntprinter->info_2->attributes;
4167 r->priority = ntprinter->info_2->priority;
4168 r->defaultpriority = ntprinter->info_2->default_priority;
4169 r->starttime = ntprinter->info_2->starttime;
4170 r->untiltime = ntprinter->info_2->untiltime;
4171 r->status = nt_printq_status(status.status);
4173 r->averageppm = ntprinter->info_2->averageppm;
4175 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4177 DEBUG(8,("Returning NULL Devicemode!\n"));
4182 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4183 /* don't use talloc_steal() here unless you do a deep steal of all
4184 the SEC_DESC members */
4186 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4192 /********************************************************************
4193 ********************************************************************/
4195 static bool snum_is_shared_printer(int snum)
4197 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4200 /********************************************************************
4201 Spoolss_enumprinters.
4202 ********************************************************************/
4204 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4206 union spoolss_PrinterInfo **info_p,
4210 int n_services = lp_numservices();
4211 union spoolss_PrinterInfo *info = NULL;
4212 WERROR result = WERR_OK;
4214 DEBUG(4,("enum_all_printers_info_1\n"));
4218 for (snum=0; snum<n_services; snum++) {
4220 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4221 struct spoolss_PrinterInfo1 info1;
4223 if (!snum_is_shared_printer(snum)) {
4227 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4229 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4230 if (!W_ERROR_IS_OK(result)) {
4234 result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
4235 free_a_printer(&ntprinter,2);
4236 if (!W_ERROR_IS_OK(result)) {
4240 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4241 union spoolss_PrinterInfo,
4244 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4245 result = WERR_NOMEM;
4249 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
4251 info[*count].info1 = info1;
4256 if (!W_ERROR_IS_OK(result)) {
4267 /********************************************************************
4268 enum_all_printers_info_1_local.
4269 *********************************************************************/
4271 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4272 union spoolss_PrinterInfo **info,
4275 DEBUG(4,("enum_all_printers_info_1_local\n"));
4277 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4280 /********************************************************************
4281 enum_all_printers_info_1_name.
4282 *********************************************************************/
4284 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4286 union spoolss_PrinterInfo **info,
4289 const char *s = name;
4291 DEBUG(4,("enum_all_printers_info_1_name\n"));
4293 if ((name[0] == '\\') && (name[1] == '\\')) {
4297 if (!is_myname_or_ipaddr(s)) {
4298 return WERR_INVALID_NAME;
4301 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4304 /********************************************************************
4305 enum_all_printers_info_1_network.
4306 *********************************************************************/
4308 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4310 union spoolss_PrinterInfo **info,
4313 const char *s = name;
4315 DEBUG(4,("enum_all_printers_info_1_network\n"));
4317 /* If we respond to a enum_printers level 1 on our name with flags
4318 set to PRINTER_ENUM_REMOTE with a list of printers then these
4319 printers incorrectly appear in the APW browse list.
4320 Specifically the printers for the server appear at the workgroup
4321 level where all the other servers in the domain are
4322 listed. Windows responds to this call with a
4323 WERR_CAN_NOT_COMPLETE so we should do the same. */
4325 if (name[0] == '\\' && name[1] == '\\') {
4329 if (is_myname_or_ipaddr(s)) {
4330 return WERR_CAN_NOT_COMPLETE;
4333 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4336 /********************************************************************
4337 * api_spoolss_enumprinters
4339 * called from api_spoolss_enumprinters (see this to understand)
4340 ********************************************************************/
4342 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4343 union spoolss_PrinterInfo **info_p,
4347 int n_services = lp_numservices();
4348 union spoolss_PrinterInfo *info = NULL;
4349 WERROR result = WERR_OK;
4353 for (snum=0; snum<n_services; snum++) {
4355 struct spoolss_PrinterInfo2 info2;
4356 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4358 if (!snum_is_shared_printer(snum)) {
4362 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4364 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4365 if (!W_ERROR_IS_OK(result)) {
4369 result = construct_printer_info2(info, ntprinter, &info2, snum);
4370 free_a_printer(&ntprinter, 2);
4371 if (!W_ERROR_IS_OK(result)) {
4375 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4376 union spoolss_PrinterInfo,
4379 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4380 result = WERR_NOMEM;
4384 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
4386 info[*count].info2 = info2;
4392 if (!W_ERROR_IS_OK(result)) {
4403 /********************************************************************
4404 * handle enumeration of printers at level 1
4405 ********************************************************************/
4407 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4410 union spoolss_PrinterInfo **info,
4413 /* Not all the flags are equals */
4415 if (flags & PRINTER_ENUM_LOCAL) {
4416 return enum_all_printers_info_1_local(mem_ctx, info, count);
4419 if (flags & PRINTER_ENUM_NAME) {
4420 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4423 if (flags & PRINTER_ENUM_NETWORK) {
4424 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4427 return WERR_OK; /* NT4sp5 does that */
4430 /********************************************************************
4431 * handle enumeration of printers at level 2
4432 ********************************************************************/
4434 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4436 const char *servername,
4437 union spoolss_PrinterInfo **info,
4440 if (flags & PRINTER_ENUM_LOCAL) {
4441 return enum_all_printers_info_2(mem_ctx, info, count);
4444 if (flags & PRINTER_ENUM_NAME) {
4445 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4446 return WERR_INVALID_NAME;
4449 return enum_all_printers_info_2(mem_ctx, info, count);
4452 if (flags & PRINTER_ENUM_REMOTE) {
4453 return WERR_UNKNOWN_LEVEL;
4459 /********************************************************************
4460 * handle enumeration of printers at level 5
4461 ********************************************************************/
4463 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4465 const char *servername,
4466 union spoolss_PrinterInfo **info,
4469 /* return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4473 /****************************************************************
4474 _spoolss_EnumPrinters
4475 ****************************************************************/
4477 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4478 struct spoolss_EnumPrinters *r)
4483 /* that's an [in out] buffer */
4485 if (!r->in.buffer && (r->in.offered != 0)) {
4486 return WERR_INVALID_PARAM;
4489 DEBUG(4,("_spoolss_EnumPrinters\n"));
4493 *r->out.info = NULL;
4497 * flags==PRINTER_ENUM_NAME
4498 * if name=="" then enumerates all printers
4499 * if name!="" then enumerate the printer
4500 * flags==PRINTER_ENUM_REMOTE
4501 * name is NULL, enumerate printers
4502 * Level 2: name!="" enumerates printers, name can't be NULL
4503 * Level 3: doesn't exist
4504 * Level 4: does a local registry lookup
4505 * Level 5: same as Level 2
4508 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4509 W_ERROR_HAVE_NO_MEMORY(name);
4511 switch (r->in.level) {
4513 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4514 r->out.info, r->out.count);
4517 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4518 r->out.info, r->out.count);
4521 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4522 r->out.info, r->out.count);
4526 result = WERR_OK; /* ??? */
4529 return WERR_UNKNOWN_LEVEL;
4532 if (!W_ERROR_IS_OK(result)) {
4536 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4537 spoolss_EnumPrinters, NULL,
4538 *r->out.info, r->in.level,
4540 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4541 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4543 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4546 /****************************************************************
4548 ****************************************************************/
4550 WERROR _spoolss_GetPrinter(pipes_struct *p,
4551 struct spoolss_GetPrinter *r)
4553 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4554 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4555 WERROR result = WERR_OK;
4559 /* that's an [in out] buffer */
4561 if (!r->in.buffer && (r->in.offered != 0)) {
4562 return WERR_INVALID_PARAM;
4567 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4571 result = get_a_printer(Printer, &ntprinter, 2,
4572 lp_const_servicename(snum));
4573 if (!W_ERROR_IS_OK(result)) {
4577 switch (r->in.level) {
4579 result = construct_printer_info0(p->mem_ctx, ntprinter,
4580 &r->out.info->info0, snum);
4583 result = construct_printer_info1(p->mem_ctx, ntprinter,
4585 &r->out.info->info1, snum);
4588 result = construct_printer_info2(p->mem_ctx, ntprinter,
4589 &r->out.info->info2, snum);
4592 result = construct_printer_info3(p->mem_ctx, ntprinter,
4593 &r->out.info->info3, snum);
4596 result = construct_printer_info4(p->mem_ctx, ntprinter,
4597 &r->out.info->info4, snum);
4600 result = construct_printer_info5(p->mem_ctx, ntprinter,
4601 &r->out.info->info5, snum);
4604 result = construct_printer_info6(p->mem_ctx, ntprinter,
4605 &r->out.info->info6, snum);
4608 result = construct_printer_info7(p->mem_ctx, Printer,
4609 &r->out.info->info7, snum);
4612 result = WERR_UNKNOWN_LEVEL;
4616 free_a_printer(&ntprinter, 2);
4618 if (!W_ERROR_IS_OK(result)) {
4619 TALLOC_FREE(r->out.info);
4623 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4624 r->out.info, r->in.level);
4625 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4627 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4630 /********************************************************************
4631 ********************************************************************/
4633 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4634 fstring *fstring_array,
4635 const char *cservername)
4637 int i, num_strings = 0;
4638 const char **array = NULL;
4640 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4642 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4643 cservername, fstring_array[i]);
4650 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4657 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4658 &array, &num_strings);
4664 /********************************************************************
4665 * fill a spoolss_DriverInfo1 struct
4666 ********************************************************************/
4668 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4669 struct spoolss_DriverInfo1 *r,
4670 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4671 const char *servername,
4672 const char *architecture)
4674 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4675 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4680 /********************************************************************
4681 * fill a spoolss_DriverInfo2 struct
4682 ********************************************************************/
4684 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4685 struct spoolss_DriverInfo2 *r,
4686 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4687 const char *servername)
4690 const char *cservername = canon_servername(servername);
4692 r->version = driver->info_3->cversion;
4694 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4695 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4696 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4697 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4699 if (strlen(driver->info_3->driverpath)) {
4700 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4701 cservername, driver->info_3->driverpath);
4703 r->driver_path = talloc_strdup(mem_ctx, "");
4705 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4707 if (strlen(driver->info_3->datafile)) {
4708 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4709 cservername, driver->info_3->datafile);
4711 r->data_file = talloc_strdup(mem_ctx, "");
4713 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4715 if (strlen(driver->info_3->configfile)) {
4716 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4717 cservername, driver->info_3->configfile);
4719 r->config_file = talloc_strdup(mem_ctx, "");
4721 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4726 /********************************************************************
4727 * fill a spoolss_DriverInfo3 struct
4728 ********************************************************************/
4730 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4731 struct spoolss_DriverInfo3 *r,
4732 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4733 const char *servername)
4735 const char *cservername = canon_servername(servername);
4737 r->version = driver->info_3->cversion;
4739 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4740 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4741 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4742 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4744 if (strlen(driver->info_3->driverpath)) {
4745 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4746 cservername, driver->info_3->driverpath);
4748 r->driver_path = talloc_strdup(mem_ctx, "");
4750 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4752 if (strlen(driver->info_3->datafile)) {
4753 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4754 cservername, driver->info_3->datafile);
4756 r->data_file = talloc_strdup(mem_ctx, "");
4758 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4760 if (strlen(driver->info_3->configfile)) {
4761 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4762 cservername, driver->info_3->configfile);
4764 r->config_file = talloc_strdup(mem_ctx, "");
4766 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4768 if (strlen(driver->info_3->helpfile)) {
4769 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4770 cservername, driver->info_3->helpfile);
4772 r->help_file = talloc_strdup(mem_ctx, "");
4774 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4776 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4777 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4778 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4779 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4781 r->dependent_files = string_array_from_driver_info(mem_ctx,
4782 driver->info_3->dependentfiles,
4787 /********************************************************************
4788 * fill a spoolss_DriverInfo6 struct
4789 ********************************************************************/
4791 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4792 struct spoolss_DriverInfo6 *r,
4793 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4794 const char *servername)
4796 const char *cservername = canon_servername(servername);
4798 r->version = driver->info_3->cversion;
4800 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4801 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4802 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4803 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4805 if (strlen(driver->info_3->driverpath)) {
4806 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4807 cservername, driver->info_3->driverpath);
4809 r->driver_path = talloc_strdup(mem_ctx, "");
4811 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4813 if (strlen(driver->info_3->datafile)) {
4814 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4815 cservername, driver->info_3->datafile);
4817 r->data_file = talloc_strdup(mem_ctx, "");
4819 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4821 if (strlen(driver->info_3->configfile)) {
4822 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4823 cservername, driver->info_3->configfile);
4825 r->config_file = talloc_strdup(mem_ctx, "");
4827 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4829 if (strlen(driver->info_3->helpfile)) {
4830 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4831 cservername, driver->info_3->helpfile);
4833 r->help_file = talloc_strdup(mem_ctx, "");
4835 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4837 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4838 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4839 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4840 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4842 r->dependent_files = string_array_from_driver_info(mem_ctx,
4843 driver->info_3->dependentfiles,
4845 r->previous_names = string_array_from_driver_info(mem_ctx,
4850 r->driver_version = 0;
4852 r->manufacturer_name = talloc_strdup(mem_ctx, "");
4853 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4854 r->manufacturer_url = talloc_strdup(mem_ctx, "");
4855 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4856 r->hardware_id = talloc_strdup(mem_ctx, "");
4857 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4858 r->provider = talloc_strdup(mem_ctx, "");
4859 W_ERROR_HAVE_NO_MEMORY(r->provider);
4864 /********************************************************************
4865 * construct_printer_driver_info_1
4866 ********************************************************************/
4868 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
4869 struct spoolss_DriverInfo1 *r,
4871 const char *servername,
4872 const char *architecture,
4875 NT_PRINTER_INFO_LEVEL *printer = NULL;
4876 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4879 ZERO_STRUCT(driver);
4881 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4882 return WERR_INVALID_PRINTER_NAME;
4884 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4885 free_a_printer(&printer, 2);
4886 return WERR_UNKNOWN_PRINTER_DRIVER;
4889 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
4891 free_a_printer(&printer,2);
4896 /********************************************************************
4897 * construct_printer_driver_info_2
4898 * fill a printer_info_2 struct
4899 ********************************************************************/
4901 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
4902 struct spoolss_DriverInfo2 *r,
4904 const char *servername,
4905 const char *architecture,
4908 NT_PRINTER_INFO_LEVEL *printer = NULL;
4909 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4912 ZERO_STRUCT(printer);
4913 ZERO_STRUCT(driver);
4915 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4916 return WERR_INVALID_PRINTER_NAME;
4918 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4919 free_a_printer(&printer, 2);
4920 return WERR_UNKNOWN_PRINTER_DRIVER;
4923 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
4925 free_a_printer(&printer,2);
4930 /********************************************************************
4931 * construct_printer_info_3
4932 * fill a printer_info_3 struct
4933 ********************************************************************/
4935 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
4936 struct spoolss_DriverInfo3 *r,
4938 const char *servername,
4939 const char *architecture,
4942 NT_PRINTER_INFO_LEVEL *printer = NULL;
4943 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4945 ZERO_STRUCT(driver);
4947 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
4948 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4949 if (!W_ERROR_IS_OK(status))
4950 return WERR_INVALID_PRINTER_NAME;
4952 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4953 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4958 * I put this code in during testing. Helpful when commenting out the
4959 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4960 * as win2k always queries the driver using an infor level of 6.
4961 * I've left it in (but ifdef'd out) because I'll probably
4962 * use it in experimentation again in the future. --jerry 22/01/2002
4965 if (!W_ERROR_IS_OK(status)) {
4967 * Is this a W2k client ?
4970 /* Yes - try again with a WinNT driver. */
4972 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4973 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4977 if (!W_ERROR_IS_OK(status)) {
4978 free_a_printer(&printer,2);
4979 return WERR_UNKNOWN_PRINTER_DRIVER;
4987 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
4989 free_a_printer(&printer,2);
4994 /********************************************************************
4995 * construct_printer_info_6
4996 * fill a printer_info_6 struct
4997 ********************************************************************/
4999 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5000 struct spoolss_DriverInfo6 *r,
5002 const char *servername,
5003 const char *architecture,
5006 NT_PRINTER_INFO_LEVEL *printer = NULL;
5007 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5010 ZERO_STRUCT(driver);
5012 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5014 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5016 if (!W_ERROR_IS_OK(status))
5017 return WERR_INVALID_PRINTER_NAME;
5019 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5021 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5023 if (!W_ERROR_IS_OK(status))
5026 * Is this a W2k client ?
5030 free_a_printer(&printer,2);
5031 return WERR_UNKNOWN_PRINTER_DRIVER;
5034 /* Yes - try again with a WinNT driver. */
5036 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5037 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5038 if (!W_ERROR_IS_OK(status)) {
5039 free_a_printer(&printer,2);
5040 return WERR_UNKNOWN_PRINTER_DRIVER;
5044 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5046 free_a_printer(&printer,2);
5047 free_a_printer_driver(driver, 3);
5052 /****************************************************************
5053 _spoolss_GetPrinterDriver2
5054 ****************************************************************/
5056 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5057 struct spoolss_GetPrinterDriver2 *r)
5059 Printer_entry *printer;
5062 const char *servername;
5065 /* that's an [in out] buffer */
5067 if (!r->in.buffer && (r->in.offered != 0)) {
5068 return WERR_INVALID_PARAM;
5071 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5073 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5074 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5075 return WERR_INVALID_PRINTER_NAME;
5079 *r->out.server_major_version = 0;
5080 *r->out.server_minor_version = 0;
5082 servername = get_server_name(printer);
5084 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5088 switch (r->in.level) {
5090 result = construct_printer_driver_info_1(p->mem_ctx,
5091 &r->out.info->info1,
5095 r->in.client_major_version);
5098 result = construct_printer_driver_info_2(p->mem_ctx,
5099 &r->out.info->info2,
5103 r->in.client_major_version);
5106 result = construct_printer_driver_info_3(p->mem_ctx,
5107 &r->out.info->info3,
5111 r->in.client_major_version);
5114 result = construct_printer_driver_info_6(p->mem_ctx,
5115 &r->out.info->info6,
5119 r->in.client_major_version);
5124 /* apparently this call is the equivalent of
5125 EnumPrinterDataEx() for the DsDriver key */
5128 result = WERR_UNKNOWN_LEVEL;
5132 if (!W_ERROR_IS_OK(result)) {
5133 TALLOC_FREE(r->out.info);
5137 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5138 r->out.info, r->in.level);
5139 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5141 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5145 /****************************************************************
5146 _spoolss_StartPagePrinter
5147 ****************************************************************/
5149 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5150 struct spoolss_StartPagePrinter *r)
5152 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5155 DEBUG(3,("_spoolss_StartPagePrinter: "
5156 "Error in startpageprinter printer handle\n"));
5160 Printer->page_started=True;
5164 /****************************************************************
5165 _spoolss_EndPagePrinter
5166 ****************************************************************/
5168 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5169 struct spoolss_EndPagePrinter *r)
5173 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5176 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5177 OUR_HANDLE(r->in.handle)));
5181 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5184 Printer->page_started=False;
5185 print_job_endpage(snum, Printer->jobid);
5190 /****************************************************************
5191 _spoolss_StartDocPrinter
5192 ****************************************************************/
5194 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5195 struct spoolss_StartDocPrinter *r)
5197 uint32_t *jobid = r->out.job_id;
5198 struct spoolss_DocumentInfo1 *info_1;
5200 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5203 DEBUG(2,("_spoolss_StartDocPrinter: "
5204 "Invalid handle (%s:%u:%u)\n",
5205 OUR_HANDLE(r->in.handle)));
5209 if (r->in.level != 1) {
5210 return WERR_UNKNOWN_LEVEL;
5213 info_1 = r->in.info.info1;
5216 * a nice thing with NT is it doesn't listen to what you tell it.
5217 * when asked to send _only_ RAW datas, it tries to send datas
5220 * So I add checks like in NT Server ...
5223 if (info_1->datatype) {
5224 if (strcmp(info_1->datatype, "RAW") != 0) {
5226 return WERR_INVALID_DATATYPE;
5230 /* get the share number of the printer */
5231 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5235 Printer->jobid = print_job_start(p->server_info, snum,
5236 info_1->document_name,
5237 Printer->nt_devmode);
5239 /* An error occured in print_job_start() so return an appropriate
5242 if (Printer->jobid == -1) {
5243 return map_werror_from_unix(errno);
5246 Printer->document_started=True;
5247 (*jobid) = Printer->jobid;
5252 /****************************************************************
5253 _spoolss_EndDocPrinter
5254 ****************************************************************/
5256 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5257 struct spoolss_EndDocPrinter *r)
5259 return _spoolss_enddocprinter_internal(p, r->in.handle);
5262 /****************************************************************
5263 _spoolss_WritePrinter
5264 ****************************************************************/
5266 WERROR _spoolss_WritePrinter(pipes_struct *p,
5267 struct spoolss_WritePrinter *r)
5269 uint32 buffer_size = r->in._data_size;
5270 uint8 *buffer = r->in.data.data;
5271 uint32 *buffer_written = &r->in._data_size;
5273 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5276 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5277 OUR_HANDLE(r->in.handle)));
5278 *r->out.num_written = r->in._data_size;
5282 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5285 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5286 (SMB_OFF_T)-1, (size_t)buffer_size);
5287 if (*buffer_written == (uint32)-1) {
5288 *r->out.num_written = 0;
5289 if (errno == ENOSPC)
5290 return WERR_NO_SPOOL_SPACE;
5292 return WERR_ACCESS_DENIED;
5295 *r->out.num_written = r->in._data_size;
5300 /********************************************************************
5301 * api_spoolss_getprinter
5302 * called from the spoolss dispatcher
5304 ********************************************************************/
5306 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5310 WERROR errcode = WERR_BADFUNC;
5311 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5314 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5315 OUR_HANDLE(handle)));
5319 if (!get_printer_snum(p, handle, &snum, NULL))
5323 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5324 if (print_queue_pause(p->server_info, snum, &errcode)) {
5328 case SPOOLSS_PRINTER_CONTROL_RESUME:
5329 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5330 if (print_queue_resume(p->server_info, snum, &errcode)) {
5334 case SPOOLSS_PRINTER_CONTROL_PURGE:
5335 if (print_queue_purge(p->server_info, snum, &errcode)) {
5340 return WERR_UNKNOWN_LEVEL;
5347 /****************************************************************
5348 _spoolss_AbortPrinter
5349 * From MSDN: "Deletes printer's spool file if printer is configured
5351 ****************************************************************/
5353 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5354 struct spoolss_AbortPrinter *r)
5356 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5358 WERROR errcode = WERR_OK;
5361 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5362 OUR_HANDLE(r->in.handle)));
5366 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5369 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5374 /********************************************************************
5375 * called by spoolss_api_setprinter
5376 * when updating a printer description
5377 ********************************************************************/
5379 static WERROR update_printer_sec(struct policy_handle *handle,
5380 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5382 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5386 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5388 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5389 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5390 OUR_HANDLE(handle)));
5392 result = WERR_BADFID;
5397 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5398 result = WERR_INVALID_PARAM;
5402 /* Check the user has permissions to change the security
5403 descriptor. By experimentation with two NT machines, the user
5404 requires Full Access to the printer to change security
5407 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5408 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5409 result = WERR_ACCESS_DENIED;
5413 /* NT seems to like setting the security descriptor even though
5414 nothing may have actually changed. */
5416 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5417 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5418 result = WERR_BADFID;
5422 if (DEBUGLEVEL >= 10) {
5426 the_acl = old_secdesc_ctr->sd->dacl;
5427 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5428 PRINTERNAME(snum), the_acl->num_aces));
5430 for (i = 0; i < the_acl->num_aces; i++) {
5431 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5432 &the_acl->aces[i].trustee),
5433 the_acl->aces[i].access_mask));
5436 the_acl = secdesc_ctr->sd->dacl;
5439 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5440 PRINTERNAME(snum), the_acl->num_aces));
5442 for (i = 0; i < the_acl->num_aces; i++) {
5443 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5444 &the_acl->aces[i].trustee),
5445 the_acl->aces[i].access_mask));
5448 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5452 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5453 if (!new_secdesc_ctr) {
5454 result = WERR_NOMEM;
5458 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5463 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5470 /********************************************************************
5471 Canonicalize printer info from a client
5473 ATTN: It does not matter what we set the servername to hear
5474 since we do the necessary work in get_a_printer() to set it to
5475 the correct value based on what the client sent in the
5476 _spoolss_open_printer_ex().
5477 ********************************************************************/
5479 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5481 fstring printername;
5484 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5485 "portname=%s drivername=%s comment=%s location=%s\n",
5486 info->servername, info->printername, info->sharename,
5487 info->portname, info->drivername, info->comment, info->location));
5489 /* we force some elements to "correct" values */
5490 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5491 fstrcpy(info->sharename, lp_servicename(snum));
5493 /* check to see if we allow printername != sharename */
5495 if ( lp_force_printername(snum) ) {
5496 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5497 global_myname(), info->sharename );
5500 /* make sure printername is in \\server\printername format */
5502 fstrcpy( printername, info->printername );
5504 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5505 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5509 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5510 global_myname(), p );
5513 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5514 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5521 /****************************************************************************
5522 ****************************************************************************/
5524 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5526 char *cmd = lp_addport_cmd();
5527 char *command = NULL;
5529 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5530 bool is_print_op = False;
5533 return WERR_ACCESS_DENIED;
5536 command = talloc_asprintf(ctx,
5537 "%s \"%s\" \"%s\"", cmd, portname, uri );
5543 is_print_op = user_has_privileges( token, &se_printop );
5545 DEBUG(10,("Running [%s]\n", command));
5547 /********* BEGIN SePrintOperatorPrivilege **********/
5552 ret = smbrun(command, NULL);
5557 /********* END SePrintOperatorPrivilege **********/
5559 DEBUGADD(10,("returned [%d]\n", ret));
5561 TALLOC_FREE(command);
5564 return WERR_ACCESS_DENIED;
5570 /****************************************************************************
5571 ****************************************************************************/
5573 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5575 char *cmd = lp_addprinter_cmd();
5577 char *command = NULL;
5581 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5582 bool is_print_op = False;
5583 char *remote_machine = talloc_strdup(ctx, "%m");
5585 if (!remote_machine) {
5588 remote_machine = talloc_sub_basic(ctx,
5589 current_user_info.smb_name,
5590 current_user_info.domain,
5592 if (!remote_machine) {
5596 command = talloc_asprintf(ctx,
5597 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5598 cmd, printer->info_2->printername, printer->info_2->sharename,
5599 printer->info_2->portname, printer->info_2->drivername,
5600 printer->info_2->location, printer->info_2->comment, remote_machine);
5606 is_print_op = user_has_privileges( token, &se_printop );
5608 DEBUG(10,("Running [%s]\n", command));
5610 /********* BEGIN SePrintOperatorPrivilege **********/
5615 if ( (ret = smbrun(command, &fd)) == 0 ) {
5616 /* Tell everyone we updated smb.conf. */
5617 message_send_all(smbd_messaging_context(),
5618 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5624 /********* END SePrintOperatorPrivilege **********/
5626 DEBUGADD(10,("returned [%d]\n", ret));
5628 TALLOC_FREE(command);
5629 TALLOC_FREE(remote_machine);
5637 /* reload our services immediately */
5638 reload_services( False );
5641 /* Get lines and convert them back to dos-codepage */
5642 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5643 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5646 /* Set the portname to what the script says the portname should be. */
5647 /* but don't require anything to be return from the script exit a good error code */
5650 /* Set the portname to what the script says the portname should be. */
5651 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5652 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5655 TALLOC_FREE(qlines);
5660 /********************************************************************
5661 * Called by spoolss_api_setprinter
5662 * when updating a printer description.
5663 ********************************************************************/
5665 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5666 struct spoolss_SetPrinterInfoCtr *info_ctr,
5667 struct spoolss_DeviceMode *devmode)
5670 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5671 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5676 DEBUG(8,("update_printer\n"));
5681 result = WERR_BADFID;
5685 if (!get_printer_snum(p, handle, &snum, NULL)) {
5686 result = WERR_BADFID;
5690 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5691 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5692 result = WERR_BADFID;
5696 DEBUGADD(8,("Converting info_2 struct\n"));
5699 * convert_printer_info converts the incoming
5700 * info from the client and overwrites the info
5701 * just read from the tdb in the pointer 'printer'.
5704 if (!convert_printer_info(info_ctr, printer)) {
5705 result = WERR_NOMEM;
5710 /* we have a valid devmode
5711 convert it and link it*/
5713 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5714 if (!convert_devicemode(printer->info_2->printername, devmode,
5715 &printer->info_2->devmode)) {
5716 result = WERR_NOMEM;
5721 /* Do sanity check on the requested changes for Samba */
5723 if (!check_printer_ok(printer->info_2, snum)) {
5724 result = WERR_INVALID_PARAM;
5728 /* FIXME!!! If the driver has changed we really should verify that
5729 it is installed before doing much else --jerry */
5731 /* Check calling user has permission to update printer description */
5733 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5734 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5735 result = WERR_ACCESS_DENIED;
5739 /* Call addprinter hook */
5740 /* Check changes to see if this is really needed */
5742 if ( *lp_addprinter_cmd()
5743 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5744 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5745 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5746 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5748 /* add_printer_hook() will call reload_services() */
5750 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5752 result = WERR_ACCESS_DENIED;
5758 * When a *new* driver is bound to a printer, the drivername is used to
5759 * lookup previously saved driver initialization info, which is then
5760 * bound to the printer, simulating what happens in the Windows arch.
5762 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5764 if (!set_driver_init(printer, 2))
5766 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5767 printer->info_2->drivername));
5770 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5771 printer->info_2->drivername));
5773 notify_printer_driver(snum, printer->info_2->drivername);
5777 * flag which changes actually occured. This is a small subset of
5778 * all the possible changes. We also have to update things in the
5782 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5783 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
5784 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5785 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5787 notify_printer_comment(snum, printer->info_2->comment);
5790 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5791 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
5792 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5793 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5795 notify_printer_sharename(snum, printer->info_2->sharename);
5798 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5801 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5804 pname = printer->info_2->printername;
5807 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
5808 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5809 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5811 notify_printer_printername( snum, pname );
5814 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5815 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
5816 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5817 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5819 notify_printer_port(snum, printer->info_2->portname);
5822 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5823 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
5824 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5825 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5827 notify_printer_location(snum, printer->info_2->location);
5830 /* here we need to update some more DsSpooler keys */
5831 /* uNCName, serverName, shortServerName */
5833 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
5834 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5835 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5836 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5837 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5839 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5840 global_myname(), printer->info_2->sharename );
5841 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
5842 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5843 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5845 /* Update printer info */
5846 result = mod_a_printer(printer, 2);
5849 free_a_printer(&printer, 2);
5850 free_a_printer(&old_printer, 2);
5856 /****************************************************************************
5857 ****************************************************************************/
5858 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5859 struct policy_handle *handle,
5860 struct spoolss_SetPrinterInfo7 *info7)
5864 Printer_entry *Printer;
5866 if ( lp_security() != SEC_ADS ) {
5867 return WERR_UNKNOWN_LEVEL;
5870 Printer = find_printer_index_by_hnd(p, handle);
5872 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5877 if (!get_printer_snum(p, handle, &snum, NULL))
5880 nt_printer_publish(Printer, snum, info7->action);
5884 return WERR_UNKNOWN_LEVEL;
5888 /****************************************************************
5890 ****************************************************************/
5892 WERROR _spoolss_SetPrinter(pipes_struct *p,
5893 struct spoolss_SetPrinter *r)
5897 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5900 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5901 OUR_HANDLE(r->in.handle)));
5905 /* check the level */
5906 switch (r->in.info_ctr->level) {
5908 return control_printer(r->in.handle, r->in.command, p);
5910 result = update_printer(p, r->in.handle,
5912 r->in.devmode_ctr->devmode);
5913 if (!W_ERROR_IS_OK(result))
5915 if (r->in.secdesc_ctr->sd)
5916 result = update_printer_sec(r->in.handle, p,
5920 return update_printer_sec(r->in.handle, p,
5923 return publish_or_unpublish_printer(p, r->in.handle,
5924 r->in.info_ctr->info.info7);
5926 return WERR_UNKNOWN_LEVEL;
5930 /****************************************************************
5931 _spoolss_FindClosePrinterNotify
5932 ****************************************************************/
5934 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5935 struct spoolss_FindClosePrinterNotify *r)
5937 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5940 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5941 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5945 if (Printer->notify.client_connected==True) {
5948 if ( Printer->printer_type == SPLHND_SERVER)
5950 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5951 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5954 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5957 Printer->notify.flags=0;
5958 Printer->notify.options=0;
5959 Printer->notify.localmachine[0]='\0';
5960 Printer->notify.printerlocal=0;
5961 TALLOC_FREE(Printer->notify.option);
5962 Printer->notify.client_connected=False;
5967 /****************************************************************
5969 ****************************************************************/
5971 WERROR _spoolss_AddJob(pipes_struct *p,
5972 struct spoolss_AddJob *r)
5974 if (!r->in.buffer && (r->in.offered != 0)) {
5975 return WERR_INVALID_PARAM;
5978 /* this is what a NT server returns for AddJob. AddJob must fail on
5979 * non-local printers */
5981 if (r->in.level != 1) {
5982 return WERR_UNKNOWN_LEVEL;
5985 return WERR_INVALID_PARAM;
5988 /****************************************************************************
5990 ****************************************************************************/
5992 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5993 struct spoolss_JobInfo1 *r,
5994 const print_queue_struct *queue,
5995 int position, int snum,
5996 const NT_PRINTER_INFO_LEVEL *ntprinter)
6000 t = gmtime(&queue->time);
6002 r->job_id = queue->job;
6004 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6005 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6006 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6007 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6008 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6009 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6010 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6011 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6012 r->data_type = talloc_strdup(mem_ctx, "RAW");
6013 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6014 r->text_status = talloc_strdup(mem_ctx, "");
6015 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6017 r->status = nt_printj_status(queue->status);
6018 r->priority = queue->priority;
6019 r->position = position;
6020 r->total_pages = queue->page_count;
6021 r->pages_printed = 0; /* ??? */
6023 init_systemtime(&r->submitted, t);
6028 /****************************************************************************
6030 ****************************************************************************/
6032 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6033 struct spoolss_JobInfo2 *r,
6034 const print_queue_struct *queue,
6035 int position, int snum,
6036 const NT_PRINTER_INFO_LEVEL *ntprinter,
6037 struct spoolss_DeviceMode *devmode)
6041 t = gmtime(&queue->time);
6043 r->job_id = queue->job;
6045 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6046 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6047 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6048 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6049 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6050 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6051 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6052 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6053 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6054 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6055 r->data_type = talloc_strdup(mem_ctx, "RAW");
6056 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6057 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6058 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6059 r->parameters = talloc_strdup(mem_ctx, "");
6060 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6061 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6062 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6064 r->devmode = devmode;
6066 r->text_status = talloc_strdup(mem_ctx, "");
6067 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6071 r->status = nt_printj_status(queue->status);
6072 r->priority = queue->priority;
6073 r->position = position;
6076 r->total_pages = queue->page_count;
6077 r->size = queue->size;
6078 init_systemtime(&r->submitted, t);
6080 r->pages_printed = 0; /* ??? */
6085 /****************************************************************************
6086 Enumjobs at level 1.
6087 ****************************************************************************/
6089 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6090 const print_queue_struct *queue,
6091 uint32_t num_queues, int snum,
6092 const NT_PRINTER_INFO_LEVEL *ntprinter,
6093 union spoolss_JobInfo **info_p,
6096 union spoolss_JobInfo *info;
6098 WERROR result = WERR_OK;
6100 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6101 W_ERROR_HAVE_NO_MEMORY(info);
6103 *count = num_queues;
6105 for (i=0; i<*count; i++) {
6106 result = fill_job_info1(info,
6112 if (!W_ERROR_IS_OK(result)) {
6118 if (!W_ERROR_IS_OK(result)) {
6129 /****************************************************************************
6130 Enumjobs at level 2.
6131 ****************************************************************************/
6133 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6134 const print_queue_struct *queue,
6135 uint32_t num_queues, int snum,
6136 const NT_PRINTER_INFO_LEVEL *ntprinter,
6137 union spoolss_JobInfo **info_p,
6140 union spoolss_JobInfo *info;
6142 WERROR result = WERR_OK;
6144 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6145 W_ERROR_HAVE_NO_MEMORY(info);
6147 *count = num_queues;
6149 for (i=0; i<*count; i++) {
6151 struct spoolss_DeviceMode *devmode;
6153 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6155 result = WERR_NOMEM;
6159 result = fill_job_info2(info,
6166 if (!W_ERROR_IS_OK(result)) {
6172 if (!W_ERROR_IS_OK(result)) {
6183 /****************************************************************
6185 ****************************************************************/
6187 WERROR _spoolss_EnumJobs(pipes_struct *p,
6188 struct spoolss_EnumJobs *r)
6191 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6193 print_status_struct prt_status;
6194 print_queue_struct *queue = NULL;
6197 /* that's an [in out] buffer */
6199 if (!r->in.buffer && (r->in.offered != 0)) {
6200 return WERR_INVALID_PARAM;
6203 DEBUG(4,("_spoolss_EnumJobs\n"));
6207 *r->out.info = NULL;
6209 /* lookup the printer snum and tdb entry */
6211 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6215 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6216 if (!W_ERROR_IS_OK(result)) {
6220 count = print_queue_status(snum, &queue, &prt_status);
6221 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6222 count, prt_status.status, prt_status.message));
6226 free_a_printer(&ntprinter, 2);
6230 switch (r->in.level) {
6232 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6233 ntprinter, r->out.info, r->out.count);
6236 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6237 ntprinter, r->out.info, r->out.count);
6240 result = WERR_UNKNOWN_LEVEL;
6245 free_a_printer(&ntprinter, 2);
6247 if (!W_ERROR_IS_OK(result)) {
6251 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6252 spoolss_EnumJobs, NULL,
6253 *r->out.info, r->in.level,
6255 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6256 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6258 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6261 /****************************************************************
6262 _spoolss_ScheduleJob
6263 ****************************************************************/
6265 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6266 struct spoolss_ScheduleJob *r)
6271 /****************************************************************
6273 ****************************************************************/
6275 WERROR _spoolss_SetJob(pipes_struct *p,
6276 struct spoolss_SetJob *r)
6278 uint32 jobid = r->in.job_id;
6279 uint32 command = r->in.command;
6282 WERROR errcode = WERR_BADFUNC;
6284 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6288 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6289 return WERR_INVALID_PRINTER_NAME;
6293 case SPOOLSS_JOB_CONTROL_CANCEL:
6294 case SPOOLSS_JOB_CONTROL_DELETE:
6295 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6299 case SPOOLSS_JOB_CONTROL_PAUSE:
6300 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6304 case SPOOLSS_JOB_CONTROL_RESTART:
6305 case SPOOLSS_JOB_CONTROL_RESUME:
6306 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6311 return WERR_UNKNOWN_LEVEL;
6317 /****************************************************************************
6318 Enumerates all printer drivers at level 1.
6319 ****************************************************************************/
6321 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6322 const char *servername,
6323 const char *architecture,
6324 union spoolss_DriverInfo **info_p,
6330 fstring *list = NULL;
6331 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6332 union spoolss_DriverInfo *info = NULL;
6333 WERROR result = WERR_OK;
6337 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6339 ndrivers = get_ntdrivers(&list, architecture, version);
6340 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6341 ndrivers, architecture, version));
6343 if (ndrivers == -1) {
6344 result = WERR_NOMEM;
6348 if (ndrivers != 0) {
6349 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6350 union spoolss_DriverInfo,
6353 DEBUG(0,("enumprinterdrivers_level1: "
6354 "failed to enlarge driver info buffer!\n"));
6355 result = WERR_NOMEM;
6360 for (i=0; i<ndrivers; i++) {
6361 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6362 ZERO_STRUCT(driver);
6363 result = get_a_printer_driver(&driver, 3, list[i],
6364 architecture, version);
6365 if (!W_ERROR_IS_OK(result)) {
6368 result = fill_printer_driver_info1(info, &info[*count+i].info1,
6369 &driver, servername,
6371 if (!W_ERROR_IS_OK(result)) {
6372 free_a_printer_driver(driver, 3);
6375 free_a_printer_driver(driver, 3);
6385 if (!W_ERROR_IS_OK(result)) {
6396 /****************************************************************************
6397 Enumerates all printer drivers at level 2.
6398 ****************************************************************************/
6400 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6401 const char *servername,
6402 const char *architecture,
6403 union spoolss_DriverInfo **info_p,
6409 fstring *list = NULL;
6410 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6411 union spoolss_DriverInfo *info = NULL;
6412 WERROR result = WERR_OK;
6416 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6418 ndrivers = get_ntdrivers(&list, architecture, version);
6419 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6420 ndrivers, architecture, version));
6422 if (ndrivers == -1) {
6423 result = WERR_NOMEM;
6427 if (ndrivers != 0) {
6428 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6429 union spoolss_DriverInfo,
6432 DEBUG(0,("enumprinterdrivers_level2: "
6433 "failed to enlarge driver info buffer!\n"));
6434 result = WERR_NOMEM;
6439 for (i=0; i<ndrivers; i++) {
6440 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6441 ZERO_STRUCT(driver);
6442 result = get_a_printer_driver(&driver, 3, list[i],
6443 architecture, version);
6444 if (!W_ERROR_IS_OK(result)) {
6447 result = fill_printer_driver_info2(info, &info[*count+i].info2,
6448 &driver, servername);
6449 if (!W_ERROR_IS_OK(result)) {
6450 free_a_printer_driver(driver, 3);
6453 free_a_printer_driver(driver, 3);
6463 if (!W_ERROR_IS_OK(result)) {
6474 /****************************************************************************
6475 Enumerates all printer drivers at level 3.
6476 ****************************************************************************/
6478 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6479 const char *servername,
6480 const char *architecture,
6481 union spoolss_DriverInfo **info_p,
6487 fstring *list = NULL;
6488 union spoolss_DriverInfo *info = NULL;
6489 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6490 WERROR result = WERR_OK;
6494 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6496 ndrivers = get_ntdrivers(&list, architecture, version);
6497 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6498 ndrivers, architecture, version));
6500 if (ndrivers == -1) {
6501 result = WERR_NOMEM;
6505 if (ndrivers != 0) {
6506 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6507 union spoolss_DriverInfo,
6510 DEBUG(0,("enumprinterdrivers_level3: "
6511 "failed to enlarge driver info buffer!\n"));
6512 result = WERR_NOMEM;
6517 for (i=0; i<ndrivers; i++) {
6518 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6519 ZERO_STRUCT(driver);
6520 result = get_a_printer_driver(&driver, 3, list[i],
6521 architecture, version);
6522 if (!W_ERROR_IS_OK(result)) {
6525 result = fill_printer_driver_info3(info, &info[*count+i].info3,
6526 &driver, servername);
6527 if (!W_ERROR_IS_OK(result)) {
6528 free_a_printer_driver(driver, 3);
6532 free_a_printer_driver(driver, 3);
6542 if (!W_ERROR_IS_OK(result)) {
6553 /****************************************************************
6554 _spoolss_EnumPrinterDrivers
6555 ****************************************************************/
6557 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6558 struct spoolss_EnumPrinterDrivers *r)
6560 const char *cservername;
6563 /* that's an [in out] buffer */
6565 if (!r->in.buffer && (r->in.offered != 0)) {
6566 return WERR_INVALID_PARAM;
6569 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6573 *r->out.info = NULL;
6575 cservername = canon_servername(r->in.server);
6577 if (!is_myname_or_ipaddr(cservername)) {
6578 return WERR_UNKNOWN_PRINTER_DRIVER;
6581 switch (r->in.level) {
6583 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6585 r->out.info, r->out.count);
6588 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6590 r->out.info, r->out.count);
6593 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6595 r->out.info, r->out.count);
6598 return WERR_UNKNOWN_LEVEL;
6601 if (!W_ERROR_IS_OK(result)) {
6605 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6606 spoolss_EnumPrinterDrivers, NULL,
6607 *r->out.info, r->in.level,
6609 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6610 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6612 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6615 /****************************************************************************
6616 ****************************************************************************/
6618 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6619 struct spoolss_FormInfo1 *r,
6620 const nt_forms_struct *form)
6622 r->form_name = talloc_strdup(mem_ctx, form->name);
6623 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6625 r->flags = form->flag;
6626 r->size.width = form->width;
6627 r->size.height = form->length;
6628 r->area.left = form->left;
6629 r->area.top = form->top;
6630 r->area.right = form->right;
6631 r->area.bottom = form->bottom;
6636 /****************************************************************
6637 spoolss_enumforms_level1
6638 ****************************************************************/
6640 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6641 const nt_forms_struct *builtin_forms,
6642 uint32_t num_builtin_forms,
6643 const nt_forms_struct *user_forms,
6644 uint32_t num_user_forms,
6645 union spoolss_FormInfo **info_p,
6648 union spoolss_FormInfo *info;
6649 WERROR result = WERR_OK;
6652 *count = num_builtin_forms + num_user_forms;
6654 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6655 W_ERROR_HAVE_NO_MEMORY(info);
6657 /* construct the list of form structures */
6658 for (i=0; i<num_builtin_forms; i++) {
6659 DEBUGADD(6,("Filling form number [%d]\n",i));
6660 result = fill_form_info_1(info, &info[i].info1,
6662 if (!W_ERROR_IS_OK(result)) {
6667 for (; i<num_user_forms; i++) {
6668 DEBUGADD(6,("Filling form number [%d]\n",i));
6669 result = fill_form_info_1(info, &info[i].info1,
6670 &user_forms[i-num_builtin_forms]);
6671 if (!W_ERROR_IS_OK(result)) {
6677 if (!W_ERROR_IS_OK(result)) {
6688 /****************************************************************
6690 ****************************************************************/
6692 WERROR _spoolss_EnumForms(pipes_struct *p,
6693 struct spoolss_EnumForms *r)
6696 nt_forms_struct *user_forms = NULL;
6697 nt_forms_struct *builtin_forms = NULL;
6698 uint32_t num_user_forms;
6699 uint32_t num_builtin_forms;
6703 *r->out.info = NULL;
6705 /* that's an [in out] buffer */
6707 if (!r->in.buffer && (r->in.offered != 0) ) {
6708 return WERR_INVALID_PARAM;
6711 DEBUG(4,("_spoolss_EnumForms\n"));
6712 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6713 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6715 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6716 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6717 num_user_forms = get_ntforms(&user_forms);
6718 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6720 if (num_user_forms + num_builtin_forms == 0) {
6721 SAFE_FREE(builtin_forms);
6722 SAFE_FREE(user_forms);
6723 return WERR_NO_MORE_ITEMS;
6726 switch (r->in.level) {
6728 result = spoolss_enumforms_level1(p->mem_ctx,
6737 result = WERR_UNKNOWN_LEVEL;
6741 SAFE_FREE(user_forms);
6742 SAFE_FREE(builtin_forms);
6744 if (!W_ERROR_IS_OK(result)) {
6748 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6749 spoolss_EnumForms, NULL,
6750 *r->out.info, r->in.level,
6752 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6753 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6755 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6758 /****************************************************************
6759 ****************************************************************/
6761 static WERROR find_form_byname(const char *name,
6762 nt_forms_struct *form)
6764 nt_forms_struct *list = NULL;
6765 int num_forms = 0, i = 0;
6767 if (get_a_builtin_ntform_by_string(name, form)) {
6771 num_forms = get_ntforms(&list);
6772 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6774 if (num_forms == 0) {
6778 /* Check if the requested name is in the list of form structures */
6779 for (i = 0; i < num_forms; i++) {
6781 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6783 if (strequal(name, list[i].name)) {
6784 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6796 /****************************************************************
6798 ****************************************************************/
6800 WERROR _spoolss_GetForm(pipes_struct *p,
6801 struct spoolss_GetForm *r)
6804 nt_forms_struct form;
6806 /* that's an [in out] buffer */
6808 if (!r->in.buffer && (r->in.offered != 0)) {
6809 return WERR_INVALID_PARAM;
6812 DEBUG(4,("_spoolss_GetForm\n"));
6813 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6814 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6816 result = find_form_byname(r->in.form_name, &form);
6817 if (!W_ERROR_IS_OK(result)) {
6818 TALLOC_FREE(r->out.info);
6822 switch (r->in.level) {
6824 result = fill_form_info_1(p->mem_ctx,
6825 &r->out.info->info1,
6830 result = WERR_UNKNOWN_LEVEL;
6834 if (!W_ERROR_IS_OK(result)) {
6835 TALLOC_FREE(r->out.info);
6839 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6840 r->out.info, r->in.level);
6841 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6843 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6846 /****************************************************************************
6847 ****************************************************************************/
6849 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6850 struct spoolss_PortInfo1 *r,
6853 r->port_name = talloc_strdup(mem_ctx, name);
6854 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6859 /****************************************************************************
6860 TODO: This probably needs distinguish between TCP/IP and Local ports
6862 ****************************************************************************/
6864 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6865 struct spoolss_PortInfo2 *r,
6868 r->port_name = talloc_strdup(mem_ctx, name);
6869 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6871 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6872 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6874 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6875 W_ERROR_HAVE_NO_MEMORY(r->description);
6877 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6884 /****************************************************************************
6885 wrapper around the enumer ports command
6886 ****************************************************************************/
6888 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
6890 char *cmd = lp_enumports_cmd();
6891 char **qlines = NULL;
6892 char *command = NULL;
6900 /* if no hook then just fill in the default port */
6903 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6906 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6907 TALLOC_FREE(qlines);
6914 /* we have a valid enumport command */
6916 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6921 DEBUG(10,("Running [%s]\n", command));
6922 ret = smbrun(command, &fd);
6923 DEBUG(10,("Returned [%d]\n", ret));
6924 TALLOC_FREE(command);
6929 return WERR_ACCESS_DENIED;
6933 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6934 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6944 /****************************************************************************
6946 ****************************************************************************/
6948 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6949 union spoolss_PortInfo **info_p,
6952 union spoolss_PortInfo *info = NULL;
6954 WERROR result = WERR_OK;
6955 char **qlines = NULL;
6958 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6959 if (!W_ERROR_IS_OK(result)) {
6964 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6966 DEBUG(10,("Returning WERR_NOMEM\n"));
6967 result = WERR_NOMEM;
6971 for (i=0; i<numlines; i++) {
6972 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6973 result = fill_port_1(info, &info[i].info1, qlines[i]);
6974 if (!W_ERROR_IS_OK(result)) {
6979 TALLOC_FREE(qlines);
6982 if (!W_ERROR_IS_OK(result)) {
6984 TALLOC_FREE(qlines);
6996 /****************************************************************************
6998 ****************************************************************************/
7000 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7001 union spoolss_PortInfo **info_p,
7004 union spoolss_PortInfo *info = NULL;
7006 WERROR result = WERR_OK;
7007 char **qlines = NULL;
7010 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7011 if (!W_ERROR_IS_OK(result)) {
7016 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7018 DEBUG(10,("Returning WERR_NOMEM\n"));
7019 result = WERR_NOMEM;
7023 for (i=0; i<numlines; i++) {
7024 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7025 result = fill_port_2(info, &info[i].info2, qlines[i]);
7026 if (!W_ERROR_IS_OK(result)) {
7031 TALLOC_FREE(qlines);
7034 if (!W_ERROR_IS_OK(result)) {
7036 TALLOC_FREE(qlines);
7048 /****************************************************************
7050 ****************************************************************/
7052 WERROR _spoolss_EnumPorts(pipes_struct *p,
7053 struct spoolss_EnumPorts *r)
7057 /* that's an [in out] buffer */
7059 if (!r->in.buffer && (r->in.offered != 0)) {
7060 return WERR_INVALID_PARAM;
7063 DEBUG(4,("_spoolss_EnumPorts\n"));
7067 *r->out.info = NULL;
7069 switch (r->in.level) {
7071 result = enumports_level_1(p->mem_ctx, r->out.info,
7075 result = enumports_level_2(p->mem_ctx, r->out.info,
7079 return WERR_UNKNOWN_LEVEL;
7082 if (!W_ERROR_IS_OK(result)) {
7086 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7087 spoolss_EnumPorts, NULL,
7088 *r->out.info, r->in.level,
7090 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7091 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7093 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7096 /****************************************************************************
7097 ****************************************************************************/
7099 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7101 struct spoolss_SetPrinterInfoCtr *info_ctr,
7102 struct spoolss_DeviceMode *devmode,
7103 struct security_descriptor *sec_desc,
7104 struct spoolss_UserLevelCtr *user_ctr,
7105 struct policy_handle *handle)
7107 NT_PRINTER_INFO_LEVEL *printer = NULL;
7110 WERROR err = WERR_OK;
7112 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7113 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7117 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7118 if (!convert_printer_info(info_ctr, printer)) {
7119 free_a_printer(&printer, 2);
7123 /* check to see if the printer already exists */
7125 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7126 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7127 printer->info_2->sharename));
7128 free_a_printer(&printer, 2);
7129 return WERR_PRINTER_ALREADY_EXISTS;
7132 /* FIXME!!! smbd should check to see if the driver is installed before
7133 trying to add a printer like this --jerry */
7135 if (*lp_addprinter_cmd() ) {
7136 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7138 free_a_printer(&printer,2);
7139 return WERR_ACCESS_DENIED;
7142 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7143 "smb.conf parameter \"addprinter command\" is defined. This"
7144 "parameter must exist for this call to succeed\n",
7145 printer->info_2->sharename ));
7148 /* use our primary netbios name since get_a_printer() will convert
7149 it to what the client expects on a case by case basis */
7151 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7152 printer->info_2->sharename);
7155 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7156 free_a_printer(&printer,2);
7157 return WERR_ACCESS_DENIED;
7160 /* you must be a printer admin to add a new printer */
7161 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7162 free_a_printer(&printer,2);
7163 return WERR_ACCESS_DENIED;
7167 * Do sanity check on the requested changes for Samba.
7170 if (!check_printer_ok(printer->info_2, snum)) {
7171 free_a_printer(&printer,2);
7172 return WERR_INVALID_PARAM;
7176 * When a printer is created, the drivername bound to the printer is used
7177 * to lookup previously saved driver initialization info, which is then
7178 * bound to the new printer, simulating what happens in the Windows arch.
7183 set_driver_init(printer, 2);
7187 /* A valid devmode was included, convert and link it
7189 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7191 if (!convert_devicemode(printer->info_2->printername, devmode,
7192 &printer->info_2->devmode)) {
7197 /* write the ASCII on disk */
7198 err = mod_a_printer(printer, 2);
7199 if (!W_ERROR_IS_OK(err)) {
7200 free_a_printer(&printer,2);
7204 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7205 /* Handle open failed - remove addition. */
7206 del_a_printer(printer->info_2->sharename);
7207 free_a_printer(&printer,2);
7208 ZERO_STRUCTP(handle);
7209 return WERR_ACCESS_DENIED;
7212 update_c_setprinter(False);
7213 free_a_printer(&printer,2);
7218 /****************************************************************
7219 _spoolss_AddPrinterEx
7220 ****************************************************************/
7222 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7223 struct spoolss_AddPrinterEx *r)
7225 switch (r->in.info_ctr->level) {
7227 /* we don't handle yet */
7228 /* but I know what to do ... */
7229 return WERR_UNKNOWN_LEVEL;
7231 return spoolss_addprinterex_level_2(p, r->in.server,
7233 r->in.devmode_ctr->devmode,
7234 r->in.secdesc_ctr->sd,
7235 r->in.userlevel_ctr,
7238 return WERR_UNKNOWN_LEVEL;
7242 /****************************************************************
7243 _spoolss_AddPrinterDriver
7244 ****************************************************************/
7246 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7247 struct spoolss_AddPrinterDriver *r)
7249 uint32_t level = r->in.info_ctr->level;
7250 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7251 WERROR err = WERR_OK;
7252 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7253 fstring driver_name;
7257 switch (p->hdr_req.opnum) {
7258 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7259 fn = "_spoolss_AddPrinterDriver";
7261 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7262 fn = "_spoolss_AddPrinterDriverEx";
7265 return WERR_INVALID_PARAM;
7270 if (level != 3 && level != 6) {
7271 /* Clever hack from Martin Zielinski <mz@seh.de>
7272 * to allow downgrade from level 8 (Vista).
7274 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7275 return WERR_UNKNOWN_LEVEL;
7278 ZERO_STRUCT(driver);
7280 if (!convert_printer_driver_info(info, &driver, level)) {
7285 DEBUG(5,("Cleaning driver's information\n"));
7286 err = clean_up_driver_struct(p, driver, level);
7287 if (!W_ERROR_IS_OK(err))
7290 DEBUG(5,("Moving driver to final destination\n"));
7291 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7296 if (add_a_printer_driver(driver, level)!=0) {
7297 err = WERR_ACCESS_DENIED;
7303 fstrcpy(driver_name,
7304 driver.info_3->name ? driver.info_3->name : "");
7307 fstrcpy(driver_name,
7308 driver.info_6->name ? driver.info_6->name : "");
7313 * I think this is where he DrvUpgradePrinter() hook would be
7314 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7315 * server. Right now, we just need to send ourselves a message
7316 * to update each printer bound to this driver. --jerry
7319 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7320 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7325 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7326 * decide if the driver init data should be deleted. The rules are:
7327 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7328 * 2) delete init data only if there is no 2k/Xp driver
7329 * 3) always delete init data
7330 * The generalized rule is always use init data from the highest order driver.
7331 * It is necessary to follow the driver install by an initialization step to
7332 * finish off this process.
7335 version = driver.info_3->cversion;
7336 else if (level == 6)
7337 version = driver.info_6->version;
7342 * 9x printer driver - never delete init data
7345 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7350 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7351 * there is no 2k/Xp driver init data for this driver name.
7355 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7357 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7359 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7361 if (!del_driver_init(driver_name))
7362 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7366 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7368 free_a_printer_driver(driver1,3);
7369 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7376 * 2k or Xp printer driver - always delete init data
7379 if (!del_driver_init(driver_name))
7380 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7385 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7391 free_a_printer_driver(driver, level);
7395 /****************************************************************
7396 _spoolss_AddPrinterDriverEx
7397 ****************************************************************/
7399 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7400 struct spoolss_AddPrinterDriverEx *r)
7402 struct spoolss_AddPrinterDriver a;
7405 * we only support the semantics of AddPrinterDriver()
7406 * i.e. only copy files that are newer than existing ones
7409 if (r->in.flags != APD_COPY_NEW_FILES) {
7410 return WERR_ACCESS_DENIED;
7413 a.in.servername = r->in.servername;
7414 a.in.info_ctr = r->in.info_ctr;
7416 return _spoolss_AddPrinterDriver(p, &a);
7419 /****************************************************************************
7420 ****************************************************************************/
7422 struct _spoolss_paths {
7428 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7430 static const struct _spoolss_paths spoolss_paths[]= {
7431 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7432 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7435 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7436 const char *servername,
7437 const char *environment,
7441 const char *pservername = NULL;
7442 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7443 const char *short_archi;
7447 /* environment may be empty */
7448 if (environment && strlen(environment)) {
7449 long_archi = environment;
7452 /* servername may be empty */
7453 if (servername && strlen(servername)) {
7454 pservername = canon_servername(servername);
7456 if (!is_myname_or_ipaddr(pservername)) {
7457 return WERR_INVALID_PARAM;
7461 if (!(short_archi = get_short_archi(long_archi))) {
7462 return WERR_INVALID_ENVIRONMENT;
7465 switch (component) {
7466 case SPOOLSS_PRTPROCS_PATH:
7467 case SPOOLSS_DRIVER_PATH:
7469 *path = talloc_asprintf(mem_ctx,
7472 spoolss_paths[component].share,
7475 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7476 SPOOLSS_DEFAULT_SERVER_PATH,
7477 spoolss_paths[component].dir,
7482 return WERR_INVALID_PARAM;
7492 /****************************************************************************
7493 ****************************************************************************/
7495 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7496 const char *servername,
7497 const char *environment,
7498 struct spoolss_DriverDirectoryInfo1 *r)
7503 werr = compose_spoolss_server_path(mem_ctx,
7506 SPOOLSS_DRIVER_PATH,
7508 if (!W_ERROR_IS_OK(werr)) {
7512 DEBUG(4,("printer driver directory: [%s]\n", path));
7514 r->directory_name = path;
7519 /****************************************************************
7520 _spoolss_GetPrinterDriverDirectory
7521 ****************************************************************/
7523 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7524 struct spoolss_GetPrinterDriverDirectory *r)
7528 /* that's an [in out] buffer */
7530 if (!r->in.buffer && (r->in.offered != 0)) {
7531 return WERR_INVALID_PARAM;
7534 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7539 /* r->in.level is ignored */
7541 werror = getprinterdriverdir_level_1(p->mem_ctx,
7544 &r->out.info->info1);
7545 if (!W_ERROR_IS_OK(werror)) {
7546 TALLOC_FREE(r->out.info);
7550 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7551 r->out.info, r->in.level);
7552 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7554 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7557 /****************************************************************
7558 _spoolss_EnumPrinterData
7559 ****************************************************************/
7561 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7562 struct spoolss_EnumPrinterData *r)
7564 NT_PRINTER_INFO_LEVEL *printer = NULL;
7565 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7568 REGISTRY_VALUE *val = NULL;
7569 NT_PRINTER_DATA *p_data;
7570 int i, key_index, num_values;
7573 *r->out.value_needed = 0;
7574 *r->out.type = REG_NONE;
7575 *r->out.data_needed = 0;
7577 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7580 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7581 OUR_HANDLE(r->in.handle)));
7585 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7589 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7590 if (!W_ERROR_IS_OK(result)) {
7594 p_data = printer->info_2->data;
7595 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7600 * The NT machine wants to know the biggest size of value and data
7602 * cf: MSDN EnumPrinterData remark section
7605 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7607 uint32_t biggest_valuesize = 0;
7608 uint32_t biggest_datasize = 0;
7610 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7612 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7614 for ( i=0; i<num_values; i++ )
7616 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7618 name_length = strlen(val->valuename);
7619 if ( strlen(val->valuename) > biggest_valuesize )
7620 biggest_valuesize = name_length;
7622 if ( val->size > biggest_datasize )
7623 biggest_datasize = val->size;
7625 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7629 /* the value is an UNICODE string but real_value_size is the length
7630 in bytes including the trailing 0 */
7632 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7633 *r->out.data_needed = biggest_datasize;
7635 DEBUG(6,("final values: [%d], [%d]\n",
7636 *r->out.value_needed, *r->out.data_needed));
7642 * the value len is wrong in NT sp3
7643 * that's the number of bytes not the number of unicode chars
7646 if (key_index != -1) {
7647 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7653 /* out_value should default to "" or else NT4 has
7654 problems unmarshalling the response */
7656 if (r->in.value_offered) {
7657 *r->out.value_needed = 1;
7658 r->out.value_name = talloc_strdup(r, "");
7659 if (!r->out.value_name) {
7660 result = WERR_NOMEM;
7664 r->out.value_name = NULL;
7665 *r->out.value_needed = 0;
7668 /* the data is counted in bytes */
7670 *r->out.data_needed = r->in.data_offered;
7672 result = WERR_NO_MORE_ITEMS;
7676 * - counted in bytes in the request
7677 * - counted in UNICODE chars in the max reply
7678 * - counted in bytes in the real size
7680 * take a pause *before* coding not *during* coding
7684 if (r->in.value_offered) {
7685 r->out.value_name = talloc_strdup(r, regval_name(val));
7686 if (!r->out.value_name) {
7687 result = WERR_NOMEM;
7690 *r->out.value_needed = strlen_m(regval_name(val));
7692 r->out.value_name = NULL;
7693 *r->out.value_needed = 0;
7698 *r->out.type = regval_type(val);
7700 /* data - counted in bytes */
7702 if (r->out.data && regval_size(val)) {
7703 memcpy(r->out.data, regval_data_p(val), regval_size(val));
7706 *r->out.data_needed = regval_size(val);
7710 free_a_printer(&printer, 2);
7714 /****************************************************************
7715 _spoolss_SetPrinterData
7716 ****************************************************************/
7718 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7719 struct spoolss_SetPrinterData *r)
7721 NT_PRINTER_INFO_LEVEL *printer = NULL;
7723 WERROR result = WERR_OK;
7724 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7727 DEBUG(5,("_spoolss_SetPrinterData\n"));
7730 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7731 OUR_HANDLE(r->in.handle)));
7735 if (Printer->printer_type == SPLHND_SERVER) {
7736 DEBUG(10,("_spoolss_SetPrinterData: "
7737 "Not implemented for server handles yet\n"));
7738 return WERR_INVALID_PARAM;
7741 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7746 * Access check : NT returns "access denied" if you make a
7747 * SetPrinterData call without the necessary privildge.
7748 * we were originally returning OK if nothing changed
7749 * which made Win2k issue **a lot** of SetPrinterData
7750 * when connecting to a printer --jerry
7753 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7754 DEBUG(3,("_spoolss_SetPrinterData: "
7755 "change denied by handle access permissions\n"));
7756 result = WERR_ACCESS_DENIED;
7760 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7761 if (!W_ERROR_IS_OK(result)) {
7765 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
7766 r->in.type, &r->in.data);
7767 if (!W_ERROR_IS_OK(result)) {
7772 * When client side code sets a magic printer data key, detect it and save
7773 * the current printer data and the magic key's data (its the DEVMODE) for
7774 * future printer/driver initializations.
7776 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
7777 /* Set devmode and printer initialization info */
7778 result = save_driver_init(printer, 2, blob.data, blob.length);
7780 srv_spoolss_reset_printerdata(printer->info_2->drivername);
7785 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
7786 r->in.value_name, r->in.type,
7787 blob.data, blob.length);
7788 if (W_ERROR_IS_OK(result)) {
7789 result = mod_a_printer(printer, 2);
7793 free_a_printer(&printer, 2);
7798 /****************************************************************
7799 _spoolss_ResetPrinter
7800 ****************************************************************/
7802 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7803 struct spoolss_ResetPrinter *r)
7805 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7808 DEBUG(5,("_spoolss_ResetPrinter\n"));
7811 * All we do is to check to see if the handle and queue is valid.
7812 * This call really doesn't mean anything to us because we only
7813 * support RAW printing. --jerry
7817 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7818 OUR_HANDLE(r->in.handle)));
7822 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7826 /* blindly return success */
7830 /****************************************************************
7831 _spoolss_DeletePrinterData
7832 ****************************************************************/
7834 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7835 struct spoolss_DeletePrinterData *r)
7837 NT_PRINTER_INFO_LEVEL *printer = NULL;
7839 WERROR status = WERR_OK;
7840 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7842 DEBUG(5,("_spoolss_DeletePrinterData\n"));
7845 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
7846 OUR_HANDLE(r->in.handle)));
7850 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7853 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7854 DEBUG(3, ("_spoolss_DeletePrinterData: "
7855 "printer properties change denied by handle\n"));
7856 return WERR_ACCESS_DENIED;
7859 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7860 if (!W_ERROR_IS_OK(status))
7863 if (!r->in.value_name) {
7864 free_a_printer(&printer, 2);
7868 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
7871 if ( W_ERROR_IS_OK(status) )
7872 mod_a_printer( printer, 2 );
7874 free_a_printer(&printer, 2);
7879 /****************************************************************
7881 ****************************************************************/
7883 WERROR _spoolss_AddForm(pipes_struct *p,
7884 struct spoolss_AddForm *r)
7886 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7887 nt_forms_struct tmpForm;
7889 WERROR status = WERR_OK;
7890 NT_PRINTER_INFO_LEVEL *printer = NULL;
7893 nt_forms_struct *list=NULL;
7894 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7896 DEBUG(5,("_spoolss_AddForm\n"));
7899 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7900 OUR_HANDLE(r->in.handle)));
7905 /* forms can be added on printer of on the print server handle */
7907 if ( Printer->printer_type == SPLHND_PRINTER )
7909 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7912 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7913 if (!W_ERROR_IS_OK(status))
7917 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7918 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7919 status = WERR_ACCESS_DENIED;
7923 /* can't add if builtin */
7925 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7926 status = WERR_FILE_EXISTS;
7930 count = get_ntforms(&list);
7932 if(!add_a_form(&list, form, &count)) {
7933 status = WERR_NOMEM;
7937 write_ntforms(&list, count);
7940 * ChangeID must always be set if this is a printer
7943 if ( Printer->printer_type == SPLHND_PRINTER )
7944 status = mod_a_printer(printer, 2);
7948 free_a_printer(&printer, 2);
7954 /****************************************************************
7956 ****************************************************************/
7958 WERROR _spoolss_DeleteForm(pipes_struct *p,
7959 struct spoolss_DeleteForm *r)
7961 const char *form_name = r->in.form_name;
7962 nt_forms_struct tmpForm;
7964 nt_forms_struct *list=NULL;
7965 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7967 WERROR status = WERR_OK;
7968 NT_PRINTER_INFO_LEVEL *printer = NULL;
7970 DEBUG(5,("_spoolss_DeleteForm\n"));
7973 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7974 OUR_HANDLE(r->in.handle)));
7978 /* forms can be deleted on printer of on the print server handle */
7980 if ( Printer->printer_type == SPLHND_PRINTER )
7982 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7985 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7986 if (!W_ERROR_IS_OK(status))
7990 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7991 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
7992 status = WERR_ACCESS_DENIED;
7996 /* can't delete if builtin */
7998 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7999 status = WERR_INVALID_PARAM;
8003 count = get_ntforms(&list);
8005 if ( !delete_a_form(&list, form_name, &count, &status ))
8009 * ChangeID must always be set if this is a printer
8012 if ( Printer->printer_type == SPLHND_PRINTER )
8013 status = mod_a_printer(printer, 2);
8017 free_a_printer(&printer, 2);
8023 /****************************************************************
8025 ****************************************************************/
8027 WERROR _spoolss_SetForm(pipes_struct *p,
8028 struct spoolss_SetForm *r)
8030 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8031 nt_forms_struct tmpForm;
8033 WERROR status = WERR_OK;
8034 NT_PRINTER_INFO_LEVEL *printer = NULL;
8037 nt_forms_struct *list=NULL;
8038 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8040 DEBUG(5,("_spoolss_SetForm\n"));
8043 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8044 OUR_HANDLE(r->in.handle)));
8048 /* forms can be modified on printer of on the print server handle */
8050 if ( Printer->printer_type == SPLHND_PRINTER )
8052 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8055 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8056 if (!W_ERROR_IS_OK(status))
8060 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8061 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8062 status = WERR_ACCESS_DENIED;
8066 /* can't set if builtin */
8067 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8068 status = WERR_INVALID_PARAM;
8072 count = get_ntforms(&list);
8073 update_a_form(&list, form, count);
8074 write_ntforms(&list, count);
8077 * ChangeID must always be set if this is a printer
8080 if ( Printer->printer_type == SPLHND_PRINTER )
8081 status = mod_a_printer(printer, 2);
8086 free_a_printer(&printer, 2);
8092 /****************************************************************************
8093 fill_print_processor1
8094 ****************************************************************************/
8096 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8097 struct spoolss_PrintProcessorInfo1 *r,
8098 const char *print_processor_name)
8100 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8101 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8106 /****************************************************************************
8107 enumprintprocessors level 1.
8108 ****************************************************************************/
8110 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8111 union spoolss_PrintProcessorInfo **info_p,
8114 union spoolss_PrintProcessorInfo *info;
8117 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8118 W_ERROR_HAVE_NO_MEMORY(info);
8122 result = fill_print_processor1(info, &info[0].info1, "winprint");
8123 if (!W_ERROR_IS_OK(result)) {
8128 if (!W_ERROR_IS_OK(result)) {
8139 /****************************************************************
8140 _spoolss_EnumPrintProcessors
8141 ****************************************************************/
8143 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8144 struct spoolss_EnumPrintProcessors *r)
8148 /* that's an [in out] buffer */
8150 if (!r->in.buffer && (r->in.offered != 0)) {
8151 return WERR_INVALID_PARAM;
8154 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8157 * Enumerate the print processors ...
8159 * Just reply with "winprint", to keep NT happy
8160 * and I can use my nice printer checker.
8165 *r->out.info = NULL;
8167 switch (r->in.level) {
8169 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8173 return WERR_UNKNOWN_LEVEL;
8176 if (!W_ERROR_IS_OK(result)) {
8180 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8181 spoolss_EnumPrintProcessors, NULL,
8182 *r->out.info, r->in.level,
8184 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8185 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8187 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8190 /****************************************************************************
8191 fill_printprocdatatype1
8192 ****************************************************************************/
8194 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8195 struct spoolss_PrintProcDataTypesInfo1 *r,
8196 const char *name_array)
8198 r->name_array = talloc_strdup(mem_ctx, name_array);
8199 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8204 /****************************************************************************
8205 enumprintprocdatatypes level 1.
8206 ****************************************************************************/
8208 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8209 union spoolss_PrintProcDataTypesInfo **info_p,
8213 union spoolss_PrintProcDataTypesInfo *info;
8215 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8216 W_ERROR_HAVE_NO_MEMORY(info);
8220 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8221 if (!W_ERROR_IS_OK(result)) {
8226 if (!W_ERROR_IS_OK(result)) {
8237 /****************************************************************
8238 _spoolss_EnumPrintProcDataTypes
8239 ****************************************************************/
8241 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8242 struct spoolss_EnumPrintProcDataTypes *r)
8246 /* that's an [in out] buffer */
8248 if (!r->in.buffer && (r->in.offered != 0)) {
8249 return WERR_INVALID_PARAM;
8252 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8256 *r->out.info = NULL;
8258 switch (r->in.level) {
8260 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8264 return WERR_UNKNOWN_LEVEL;
8267 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8268 spoolss_EnumPrintProcDataTypes, NULL,
8269 *r->out.info, r->in.level,
8271 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8272 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8274 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8277 /****************************************************************************
8279 ****************************************************************************/
8281 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8282 struct spoolss_MonitorInfo1 *r,
8283 const char *monitor_name)
8285 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8286 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8291 /****************************************************************************
8293 ****************************************************************************/
8295 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8296 struct spoolss_MonitorInfo2 *r,
8297 const char *monitor_name,
8298 const char *environment,
8299 const char *dll_name)
8301 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8302 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8303 r->environment = talloc_strdup(mem_ctx, environment);
8304 W_ERROR_HAVE_NO_MEMORY(r->environment);
8305 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8306 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8311 /****************************************************************************
8312 enumprintmonitors level 1.
8313 ****************************************************************************/
8315 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8316 union spoolss_MonitorInfo **info_p,
8319 union spoolss_MonitorInfo *info;
8320 WERROR result = WERR_OK;
8322 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8323 W_ERROR_HAVE_NO_MEMORY(info);
8327 result = fill_monitor_1(info, &info[0].info1,
8329 if (!W_ERROR_IS_OK(result)) {
8333 result = fill_monitor_1(info, &info[1].info1,
8335 if (!W_ERROR_IS_OK(result)) {
8340 if (!W_ERROR_IS_OK(result)) {
8351 /****************************************************************************
8352 enumprintmonitors level 2.
8353 ****************************************************************************/
8355 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8356 union spoolss_MonitorInfo **info_p,
8359 union spoolss_MonitorInfo *info;
8360 WERROR result = WERR_OK;
8362 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8363 W_ERROR_HAVE_NO_MEMORY(info);
8367 result = fill_monitor_2(info, &info[0].info2,
8369 "Windows NT X86", /* FIXME */
8371 if (!W_ERROR_IS_OK(result)) {
8375 result = fill_monitor_2(info, &info[1].info2,
8377 "Windows NT X86", /* FIXME */
8379 if (!W_ERROR_IS_OK(result)) {
8384 if (!W_ERROR_IS_OK(result)) {
8395 /****************************************************************
8396 _spoolss_EnumMonitors
8397 ****************************************************************/
8399 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8400 struct spoolss_EnumMonitors *r)
8404 /* that's an [in out] buffer */
8406 if (!r->in.buffer && (r->in.offered != 0)) {
8407 return WERR_INVALID_PARAM;
8410 DEBUG(5,("_spoolss_EnumMonitors\n"));
8413 * Enumerate the print monitors ...
8415 * Just reply with "Local Port", to keep NT happy
8416 * and I can use my nice printer checker.
8421 *r->out.info = NULL;
8423 switch (r->in.level) {
8425 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8429 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8433 return WERR_UNKNOWN_LEVEL;
8436 if (!W_ERROR_IS_OK(result)) {
8440 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8441 spoolss_EnumMonitors, NULL,
8442 *r->out.info, r->in.level,
8444 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8445 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8447 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8450 /****************************************************************************
8451 ****************************************************************************/
8453 static WERROR getjob_level_1(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_JobInfo1 *r)
8463 for (i=0; i<count && found == false; i++) {
8464 if (queue[i].job == (int)jobid) {
8469 if (found == false) {
8470 /* NT treats not found as bad param... yet another bad choice */
8471 return WERR_INVALID_PARAM;
8474 return fill_job_info1(mem_ctx,
8482 /****************************************************************************
8483 ****************************************************************************/
8485 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8486 const print_queue_struct *queue,
8487 int count, int snum,
8488 const NT_PRINTER_INFO_LEVEL *ntprinter,
8490 struct spoolss_JobInfo2 *r)
8494 struct spoolss_DeviceMode *devmode;
8495 NT_DEVICEMODE *nt_devmode;
8498 for (i=0; i<count && found == false; i++) {
8499 if (queue[i].job == (int)jobid) {
8504 if (found == false) {
8505 /* NT treats not found as bad param... yet another bad
8507 return WERR_INVALID_PARAM;
8511 * if the print job does not have a DEVMODE associated with it,
8512 * just use the one for the printer. A NULL devicemode is not
8513 * a failure condition
8516 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8518 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8519 W_ERROR_HAVE_NO_MEMORY(devmode);
8520 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8521 if (!W_ERROR_IS_OK(result)) {
8525 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8526 W_ERROR_HAVE_NO_MEMORY(devmode);
8529 return fill_job_info2(mem_ctx,
8538 /****************************************************************
8540 ****************************************************************/
8542 WERROR _spoolss_GetJob(pipes_struct *p,
8543 struct spoolss_GetJob *r)
8545 WERROR result = WERR_OK;
8546 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8549 print_queue_struct *queue = NULL;
8550 print_status_struct prt_status;
8552 /* that's an [in out] buffer */
8554 if (!r->in.buffer && (r->in.offered != 0)) {
8555 return WERR_INVALID_PARAM;
8558 DEBUG(5,("_spoolss_GetJob\n"));
8562 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8566 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8567 if (!W_ERROR_IS_OK(result)) {
8571 count = print_queue_status(snum, &queue, &prt_status);
8573 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8574 count, prt_status.status, prt_status.message));
8576 switch (r->in.level) {
8578 result = getjob_level_1(p->mem_ctx,
8579 queue, count, snum, ntprinter,
8580 r->in.job_id, &r->out.info->info1);
8583 result = getjob_level_2(p->mem_ctx,
8584 queue, count, snum, ntprinter,
8585 r->in.job_id, &r->out.info->info2);
8588 result = WERR_UNKNOWN_LEVEL;
8593 free_a_printer(&ntprinter, 2);
8595 if (!W_ERROR_IS_OK(result)) {
8596 TALLOC_FREE(r->out.info);
8600 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8601 r->out.info, r->in.level);
8602 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8604 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8607 /****************************************************************
8608 _spoolss_GetPrinterDataEx
8610 From MSDN documentation of GetPrinterDataEx: pass request
8611 to GetPrinterData if key is "PrinterDriverData".
8612 ****************************************************************/
8614 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8615 struct spoolss_GetPrinterDataEx *r)
8618 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8619 REGISTRY_VALUE *val = NULL;
8620 NT_PRINTER_INFO_LEVEL *printer = NULL;
8622 WERROR result = WERR_OK;
8624 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8626 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8627 r->in.key_name, r->in.value_name));
8629 /* in case of problem, return some default values */
8632 *r->out.type = REG_NONE;
8635 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8636 OUR_HANDLE(r->in.handle)));
8637 result = WERR_BADFID;
8641 /* Is the handle to a printer or to the server? */
8643 if (Printer->printer_type == SPLHND_SERVER) {
8644 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8645 "Not implemented for server handles yet\n"));
8646 result = WERR_INVALID_PARAM;
8650 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8654 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8655 if (!W_ERROR_IS_OK(result)) {
8659 /* check to see if the keyname is valid */
8660 if (!strlen(r->in.key_name)) {
8661 result = WERR_INVALID_PARAM;
8665 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8666 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8667 "Invalid keyname [%s]\n", r->in.key_name ));
8668 result = WERR_BADFILE;
8672 /* When given a new keyname, we should just create it */
8674 val = get_printer_data(printer->info_2,
8675 r->in.key_name, r->in.value_name);
8677 result = WERR_BADFILE;
8681 *r->out.needed = regval_size(val);
8683 if (*r->out.needed > r->in.offered) {
8684 result = WERR_MORE_DATA;
8688 *r->out.type = regval_type(val);
8690 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
8694 free_a_printer(&printer, 2);
8700 /****************************************************************
8701 _spoolss_SetPrinterDataEx
8702 ****************************************************************/
8704 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8705 struct spoolss_SetPrinterDataEx *r)
8707 NT_PRINTER_INFO_LEVEL *printer = NULL;
8709 WERROR result = WERR_OK;
8710 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8713 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8715 /* From MSDN documentation of SetPrinterDataEx: pass request to
8716 SetPrinterData if key is "PrinterDriverData" */
8719 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8720 OUR_HANDLE(r->in.handle)));
8724 if (Printer->printer_type == SPLHND_SERVER) {
8725 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8726 "Not implemented for server handles yet\n"));
8727 return WERR_INVALID_PARAM;
8730 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8735 * Access check : NT returns "access denied" if you make a
8736 * SetPrinterData call without the necessary privildge.
8737 * we were originally returning OK if nothing changed
8738 * which made Win2k issue **a lot** of SetPrinterData
8739 * when connecting to a printer --jerry
8742 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8743 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8744 "change denied by handle access permissions\n"));
8745 return WERR_ACCESS_DENIED;
8748 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8749 if (!W_ERROR_IS_OK(result)) {
8753 /* check for OID in valuename */
8755 oid_string = strchr(r->in.value_name, ',');
8761 /* save the registry data */
8763 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8764 r->in.type, r->in.buffer, r->in.offered);
8766 if (W_ERROR_IS_OK(result)) {
8767 /* save the OID if one was specified */
8769 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8770 r->in.key_name, SPOOL_OID_KEY);
8772 result = WERR_NOMEM;
8777 * I'm not checking the status here on purpose. Don't know
8778 * if this is right, but I'm returning the status from the
8779 * previous set_printer_dataex() call. I have no idea if
8780 * this is right. --jerry
8783 set_printer_dataex(printer, str, r->in.value_name,
8784 REG_SZ, (uint8_t *)oid_string,
8785 strlen(oid_string)+1);
8788 result = mod_a_printer(printer, 2);
8792 free_a_printer(&printer, 2);
8797 /****************************************************************
8798 _spoolss_DeletePrinterDataEx
8799 ****************************************************************/
8801 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8802 struct spoolss_DeletePrinterDataEx *r)
8804 NT_PRINTER_INFO_LEVEL *printer = NULL;
8806 WERROR status = WERR_OK;
8807 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8809 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8812 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8813 "Invalid handle (%s:%u:%u).\n",
8814 OUR_HANDLE(r->in.handle)));
8818 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8821 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8822 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8823 "printer properties change denied by handle\n"));
8824 return WERR_ACCESS_DENIED;
8827 if (!r->in.value_name || !r->in.key_name) {
8831 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8832 if (!W_ERROR_IS_OK(status))
8835 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8837 if ( W_ERROR_IS_OK(status) )
8838 mod_a_printer( printer, 2 );
8840 free_a_printer(&printer, 2);
8845 /****************************************************************
8846 _spoolss_EnumPrinterKey
8847 ****************************************************************/
8849 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8850 struct spoolss_EnumPrinterKey *r)
8852 fstring *keynames = NULL;
8854 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8855 NT_PRINTER_DATA *data;
8856 NT_PRINTER_INFO_LEVEL *printer = NULL;
8858 WERROR result = WERR_BADFILE;
8860 const char **array = NULL;
8863 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8866 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8867 OUR_HANDLE(r->in.handle)));
8871 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8875 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8876 if (!W_ERROR_IS_OK(result)) {
8880 /* get the list of subkey names */
8882 data = printer->info_2->data;
8884 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8885 if (num_keys == -1) {
8886 result = WERR_BADFILE;
8892 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
8894 result = WERR_NOMEM;
8898 for (i=0; i < num_keys; i++) {
8899 array[i] = talloc_strdup(array, keynames[i]);
8901 result = WERR_NOMEM;
8905 *r->out.needed += strlen_m_term(keynames[i]) * 2;
8908 if (r->in.offered < *r->out.needed) {
8909 result = WERR_MORE_DATA;
8915 *r->out.key_buffer = array;
8918 if (!W_ERROR_IS_OK(result)) {
8920 ZERO_STRUCTP(r->out.key_buffer);
8923 free_a_printer(&printer, 2);
8924 SAFE_FREE(keynames);
8929 /****************************************************************
8930 _spoolss_DeletePrinterKey
8931 ****************************************************************/
8933 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8934 struct spoolss_DeletePrinterKey *r)
8936 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8937 NT_PRINTER_INFO_LEVEL *printer = NULL;
8941 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8944 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8945 OUR_HANDLE(r->in.handle)));
8949 /* if keyname == NULL, return error */
8951 if ( !r->in.key_name )
8952 return WERR_INVALID_PARAM;
8954 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8957 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8958 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8959 "printer properties change denied by handle\n"));
8960 return WERR_ACCESS_DENIED;
8963 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8964 if (!W_ERROR_IS_OK(status))
8967 /* delete the key and all subneys */
8969 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8971 if ( W_ERROR_IS_OK(status) )
8972 status = mod_a_printer(printer, 2);
8974 free_a_printer( &printer, 2 );
8979 /****************************************************************
8980 ****************************************************************/
8982 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8984 struct spoolss_PrinterEnumValues *r)
8988 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
8989 W_ERROR_HAVE_NO_MEMORY(r->data);
8991 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
8992 W_ERROR_HAVE_NO_MEMORY(r->value_name);
8994 r->type = regval_type(v);
8995 r->data_length = regval_size(v);
8997 if (r->data_length) {
8998 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9000 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9003 if (!W_ERROR_IS_OK(result)) {
9011 /****************************************************************
9012 _spoolss_EnumPrinterDataEx
9013 ****************************************************************/
9015 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9016 struct spoolss_EnumPrinterDataEx *r)
9019 NT_PRINTER_INFO_LEVEL *printer = NULL;
9020 struct spoolss_PrinterEnumValues *info = NULL;
9021 NT_PRINTER_DATA *p_data;
9022 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9028 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9032 *r->out.info = NULL;
9035 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9036 OUR_HANDLE(r->in.handle)));
9041 * first check for a keyname of NULL or "". Win2k seems to send
9042 * this a lot and we should send back WERR_INVALID_PARAM
9043 * no need to spend time looking up the printer in this case.
9047 if (!strlen(r->in.key_name)) {
9048 result = WERR_INVALID_PARAM;
9052 /* get the printer off of disk */
9054 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9058 ZERO_STRUCT(printer);
9059 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9060 if (!W_ERROR_IS_OK(result)) {
9064 /* now look for a match on the key name */
9066 p_data = printer->info_2->data;
9068 key_index = lookup_printerkey(p_data, r->in.key_name);
9069 if (key_index == -1) {
9070 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9072 result = WERR_INVALID_PARAM;
9076 /* allocate the memory for the array of pointers -- if necessary */
9078 count = regval_ctr_numvals(p_data->keys[key_index].values);
9080 result = WERR_OK; /* ??? */
9084 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9085 struct spoolss_PrinterEnumValues,
9088 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9089 result = WERR_NOMEM;
9094 * loop through all params and build the array to pass
9095 * back to the client
9098 for (i=0; i < count; i++) {
9100 REGISTRY_VALUE *val;
9102 /* lookup the registry value */
9104 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9106 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9110 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9111 if (!W_ERROR_IS_OK(result)) {
9116 #if 0 /* FIXME - gd */
9117 /* housekeeping information in the reply */
9119 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9120 * the hand marshalled container size is a multiple
9121 * of 4 bytes for RPC alignment.
9125 needed += 4-(needed % 4);
9128 *r->out.count = count;
9129 *r->out.info = info;
9134 free_a_printer(&printer, 2);
9137 if (!W_ERROR_IS_OK(result)) {
9141 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9142 spoolss_EnumPrinterDataEx, NULL,
9145 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9146 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9148 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9151 /****************************************************************************
9152 ****************************************************************************/
9154 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9155 const char *servername,
9156 const char *environment,
9157 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9162 werr = compose_spoolss_server_path(mem_ctx,
9165 SPOOLSS_PRTPROCS_PATH,
9167 if (!W_ERROR_IS_OK(werr)) {
9171 DEBUG(4,("print processor directory: [%s]\n", path));
9173 r->directory_name = path;
9178 /****************************************************************
9179 _spoolss_GetPrintProcessorDirectory
9180 ****************************************************************/
9182 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9183 struct spoolss_GetPrintProcessorDirectory *r)
9187 /* that's an [in out] buffer */
9189 if (!r->in.buffer && (r->in.offered != 0)) {
9190 return WERR_INVALID_PARAM;
9193 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9198 /* r->in.level is ignored */
9200 result = getprintprocessordirectory_level_1(p->mem_ctx,
9203 &r->out.info->info1);
9204 if (!W_ERROR_IS_OK(result)) {
9205 TALLOC_FREE(r->out.info);
9209 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9210 r->out.info, r->in.level);
9211 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9213 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9216 /*******************************************************************
9217 ********************************************************************/
9219 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9220 const char *dllname)
9222 enum ndr_err_code ndr_err;
9223 struct spoolss_MonitorUi ui;
9225 ui.dll_name = dllname;
9227 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9228 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9229 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9230 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9232 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9235 /*******************************************************************
9236 Streams the monitor UI DLL name in UNICODE
9237 *******************************************************************/
9239 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9240 NT_USER_TOKEN *token, DATA_BLOB *in,
9241 DATA_BLOB *out, uint32_t *needed)
9243 const char *dllname = "tcpmonui.dll";
9245 *needed = (strlen(dllname)+1) * 2;
9247 if (out->length < *needed) {
9248 return WERR_INSUFFICIENT_BUFFER;
9251 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9258 /*******************************************************************
9259 ********************************************************************/
9261 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9262 struct spoolss_PortData1 *port1,
9263 const DATA_BLOB *buf)
9265 enum ndr_err_code ndr_err;
9266 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9267 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9268 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9269 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9271 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9274 /*******************************************************************
9275 ********************************************************************/
9277 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9278 struct spoolss_PortData2 *port2,
9279 const DATA_BLOB *buf)
9281 enum ndr_err_code ndr_err;
9282 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9283 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9284 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9285 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9287 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9290 /*******************************************************************
9291 Create a new TCP/IP port
9292 *******************************************************************/
9294 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9295 NT_USER_TOKEN *token, DATA_BLOB *in,
9296 DATA_BLOB *out, uint32_t *needed)
9298 struct spoolss_PortData1 port1;
9299 struct spoolss_PortData2 port2;
9300 char *device_uri = NULL;
9303 const char *portname;
9304 const char *hostaddress;
9306 uint32_t port_number;
9309 /* peek for spoolss_PortData version */
9311 if (!in || (in->length < (128 + 4))) {
9312 return WERR_GENERAL_FAILURE;
9315 version = IVAL(in->data, 128);
9321 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9325 portname = port1.portname;
9326 hostaddress = port1.hostaddress;
9327 queue = port1.queue;
9328 protocol = port1.protocol;
9329 port_number = port1.port_number;
9335 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9339 portname = port2.portname;
9340 hostaddress = port2.hostaddress;
9341 queue = port2.queue;
9342 protocol = port2.protocol;
9343 port_number = port2.port_number;
9347 DEBUG(1,("xcvtcp_addport: "
9348 "unknown version of port_data: %d\n", version));
9349 return WERR_UNKNOWN_PORT;
9352 /* create the device URI and call the add_port_hook() */
9355 case PROTOCOL_RAWTCP_TYPE:
9356 device_uri = talloc_asprintf(mem_ctx,
9357 "socket://%s:%d/", hostaddress,
9361 case PROTOCOL_LPR_TYPE:
9362 device_uri = talloc_asprintf(mem_ctx,
9363 "lpr://%s/%s", hostaddress, queue );
9367 return WERR_UNKNOWN_PORT;
9374 return add_port_hook(mem_ctx, token, portname, device_uri);
9377 /*******************************************************************
9378 *******************************************************************/
9380 struct xcv_api_table xcvtcp_cmds[] = {
9381 { "MonitorUI", xcvtcp_monitorui },
9382 { "AddPort", xcvtcp_addport},
9386 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9387 NT_USER_TOKEN *token, const char *command,
9394 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9396 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9397 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9398 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9401 return WERR_BADFUNC;
9404 /*******************************************************************
9405 *******************************************************************/
9406 #if 0 /* don't support management using the "Local Port" monitor */
9408 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9409 NT_USER_TOKEN *token, DATA_BLOB *in,
9410 DATA_BLOB *out, uint32_t *needed)
9412 const char *dllname = "localui.dll";
9414 *needed = (strlen(dllname)+1) * 2;
9416 if (out->length < *needed) {
9417 return WERR_INSUFFICIENT_BUFFER;
9420 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9427 /*******************************************************************
9428 *******************************************************************/
9430 struct xcv_api_table xcvlocal_cmds[] = {
9431 { "MonitorUI", xcvlocal_monitorui },
9435 struct xcv_api_table xcvlocal_cmds[] = {
9442 /*******************************************************************
9443 *******************************************************************/
9445 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9446 NT_USER_TOKEN *token, const char *command,
9447 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9452 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9454 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9455 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9456 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9458 return WERR_BADFUNC;
9461 /****************************************************************
9463 ****************************************************************/
9465 WERROR _spoolss_XcvData(pipes_struct *p,
9466 struct spoolss_XcvData *r)
9468 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9469 DATA_BLOB out_data = data_blob_null;
9473 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9474 OUR_HANDLE(r->in.handle)));
9478 /* Has to be a handle to the TCP/IP port monitor */
9480 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9481 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9485 /* requires administrative access to the server */
9487 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9488 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9489 return WERR_ACCESS_DENIED;
9492 /* Allocate the outgoing buffer */
9494 if (r->in.out_data_size) {
9495 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9496 if (out_data.data == NULL) {
9501 switch ( Printer->printer_type ) {
9502 case SPLHND_PORTMON_TCP:
9503 werror = process_xcvtcp_command(p->mem_ctx,
9504 p->server_info->ptok,
9505 r->in.function_name,
9506 &r->in.in_data, &out_data,
9509 case SPLHND_PORTMON_LOCAL:
9510 werror = process_xcvlocal_command(p->mem_ctx,
9511 p->server_info->ptok,
9512 r->in.function_name,
9513 &r->in.in_data, &out_data,
9517 werror = WERR_INVALID_PRINT_MONITOR;
9520 if (!W_ERROR_IS_OK(werror)) {
9524 *r->out.status_code = 0;
9526 memcpy(r->out.out_data, out_data.data, out_data.length);
9531 /****************************************************************
9532 _spoolss_AddPrintProcessor
9533 ****************************************************************/
9535 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9536 struct spoolss_AddPrintProcessor *r)
9538 /* for now, just indicate success and ignore the add. We'll
9539 automatically set the winprint processor for printer
9540 entries later. Used to debug the LexMark Optra S 1855 PCL
9546 /****************************************************************
9548 ****************************************************************/
9550 WERROR _spoolss_AddPrinter(pipes_struct *p,
9551 struct spoolss_AddPrinter *r)
9553 p->rng_fault_state = true;
9554 return WERR_NOT_SUPPORTED;
9557 /****************************************************************
9558 _spoolss_GetPrinterDriver
9559 ****************************************************************/
9561 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9562 struct spoolss_GetPrinterDriver *r)
9564 p->rng_fault_state = true;
9565 return WERR_NOT_SUPPORTED;
9568 /****************************************************************
9569 _spoolss_ReadPrinter
9570 ****************************************************************/
9572 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9573 struct spoolss_ReadPrinter *r)
9575 p->rng_fault_state = true;
9576 return WERR_NOT_SUPPORTED;
9579 /****************************************************************
9580 _spoolss_WaitForPrinterChange
9581 ****************************************************************/
9583 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9584 struct spoolss_WaitForPrinterChange *r)
9586 p->rng_fault_state = true;
9587 return WERR_NOT_SUPPORTED;
9590 /****************************************************************
9592 ****************************************************************/
9594 WERROR _spoolss_AddPort(pipes_struct *p,
9595 struct spoolss_AddPort *r)
9597 p->rng_fault_state = true;
9598 return WERR_NOT_SUPPORTED;
9601 /****************************************************************
9602 _spoolss_ConfigurePort
9603 ****************************************************************/
9605 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9606 struct spoolss_ConfigurePort *r)
9608 p->rng_fault_state = true;
9609 return WERR_NOT_SUPPORTED;
9612 /****************************************************************
9614 ****************************************************************/
9616 WERROR _spoolss_DeletePort(pipes_struct *p,
9617 struct spoolss_DeletePort *r)
9619 p->rng_fault_state = true;
9620 return WERR_NOT_SUPPORTED;
9623 /****************************************************************
9624 _spoolss_CreatePrinterIC
9625 ****************************************************************/
9627 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9628 struct spoolss_CreatePrinterIC *r)
9630 p->rng_fault_state = true;
9631 return WERR_NOT_SUPPORTED;
9634 /****************************************************************
9635 _spoolss_PlayGDIScriptOnPrinterIC
9636 ****************************************************************/
9638 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9639 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9641 p->rng_fault_state = true;
9642 return WERR_NOT_SUPPORTED;
9645 /****************************************************************
9646 _spoolss_DeletePrinterIC
9647 ****************************************************************/
9649 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9650 struct spoolss_DeletePrinterIC *r)
9652 p->rng_fault_state = true;
9653 return WERR_NOT_SUPPORTED;
9656 /****************************************************************
9657 _spoolss_AddPrinterConnection
9658 ****************************************************************/
9660 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9661 struct spoolss_AddPrinterConnection *r)
9663 p->rng_fault_state = true;
9664 return WERR_NOT_SUPPORTED;
9667 /****************************************************************
9668 _spoolss_DeletePrinterConnection
9669 ****************************************************************/
9671 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9672 struct spoolss_DeletePrinterConnection *r)
9674 p->rng_fault_state = true;
9675 return WERR_NOT_SUPPORTED;
9678 /****************************************************************
9679 _spoolss_PrinterMessageBox
9680 ****************************************************************/
9682 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9683 struct spoolss_PrinterMessageBox *r)
9685 p->rng_fault_state = true;
9686 return WERR_NOT_SUPPORTED;
9689 /****************************************************************
9691 ****************************************************************/
9693 WERROR _spoolss_AddMonitor(pipes_struct *p,
9694 struct spoolss_AddMonitor *r)
9696 p->rng_fault_state = true;
9697 return WERR_NOT_SUPPORTED;
9700 /****************************************************************
9701 _spoolss_DeleteMonitor
9702 ****************************************************************/
9704 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9705 struct spoolss_DeleteMonitor *r)
9707 p->rng_fault_state = true;
9708 return WERR_NOT_SUPPORTED;
9711 /****************************************************************
9712 _spoolss_DeletePrintProcessor
9713 ****************************************************************/
9715 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9716 struct spoolss_DeletePrintProcessor *r)
9718 p->rng_fault_state = true;
9719 return WERR_NOT_SUPPORTED;
9722 /****************************************************************
9723 _spoolss_AddPrintProvidor
9724 ****************************************************************/
9726 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9727 struct spoolss_AddPrintProvidor *r)
9729 p->rng_fault_state = true;
9730 return WERR_NOT_SUPPORTED;
9733 /****************************************************************
9734 _spoolss_DeletePrintProvidor
9735 ****************************************************************/
9737 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9738 struct spoolss_DeletePrintProvidor *r)
9740 p->rng_fault_state = true;
9741 return WERR_NOT_SUPPORTED;
9744 /****************************************************************
9745 _spoolss_FindFirstPrinterChangeNotification
9746 ****************************************************************/
9748 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9749 struct spoolss_FindFirstPrinterChangeNotification *r)
9751 p->rng_fault_state = true;
9752 return WERR_NOT_SUPPORTED;
9755 /****************************************************************
9756 _spoolss_FindNextPrinterChangeNotification
9757 ****************************************************************/
9759 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9760 struct spoolss_FindNextPrinterChangeNotification *r)
9762 p->rng_fault_state = true;
9763 return WERR_NOT_SUPPORTED;
9766 /****************************************************************
9767 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9768 ****************************************************************/
9770 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9771 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9773 p->rng_fault_state = true;
9774 return WERR_NOT_SUPPORTED;
9777 /****************************************************************
9778 _spoolss_ReplyOpenPrinter
9779 ****************************************************************/
9781 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9782 struct spoolss_ReplyOpenPrinter *r)
9784 p->rng_fault_state = true;
9785 return WERR_NOT_SUPPORTED;
9788 /****************************************************************
9789 _spoolss_RouterReplyPrinter
9790 ****************************************************************/
9792 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9793 struct spoolss_RouterReplyPrinter *r)
9795 p->rng_fault_state = true;
9796 return WERR_NOT_SUPPORTED;
9799 /****************************************************************
9800 _spoolss_ReplyClosePrinter
9801 ****************************************************************/
9803 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9804 struct spoolss_ReplyClosePrinter *r)
9806 p->rng_fault_state = true;
9807 return WERR_NOT_SUPPORTED;
9810 /****************************************************************
9812 ****************************************************************/
9814 WERROR _spoolss_AddPortEx(pipes_struct *p,
9815 struct spoolss_AddPortEx *r)
9817 p->rng_fault_state = true;
9818 return WERR_NOT_SUPPORTED;
9821 /****************************************************************
9822 _spoolss_RouterFindFirstPrinterChangeNotification
9823 ****************************************************************/
9825 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9826 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9828 p->rng_fault_state = true;
9829 return WERR_NOT_SUPPORTED;
9832 /****************************************************************
9833 _spoolss_SpoolerInit
9834 ****************************************************************/
9836 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9837 struct spoolss_SpoolerInit *r)
9839 p->rng_fault_state = true;
9840 return WERR_NOT_SUPPORTED;
9843 /****************************************************************
9844 _spoolss_ResetPrinterEx
9845 ****************************************************************/
9847 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9848 struct spoolss_ResetPrinterEx *r)
9850 p->rng_fault_state = true;
9851 return WERR_NOT_SUPPORTED;
9854 /****************************************************************
9855 _spoolss_RouterReplyPrinterEx
9856 ****************************************************************/
9858 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9859 struct spoolss_RouterReplyPrinterEx *r)
9861 p->rng_fault_state = true;
9862 return WERR_NOT_SUPPORTED;
9865 /****************************************************************
9867 ****************************************************************/
9869 WERROR _spoolss_44(pipes_struct *p,
9870 struct spoolss_44 *r)
9872 p->rng_fault_state = true;
9873 return WERR_NOT_SUPPORTED;
9876 /****************************************************************
9878 ****************************************************************/
9880 WERROR _spoolss_47(pipes_struct *p,
9881 struct spoolss_47 *r)
9883 p->rng_fault_state = true;
9884 return WERR_NOT_SUPPORTED;
9887 /****************************************************************
9889 ****************************************************************/
9891 WERROR _spoolss_4a(pipes_struct *p,
9892 struct spoolss_4a *r)
9894 p->rng_fault_state = true;
9895 return WERR_NOT_SUPPORTED;
9898 /****************************************************************
9900 ****************************************************************/
9902 WERROR _spoolss_4b(pipes_struct *p,
9903 struct spoolss_4b *r)
9905 p->rng_fault_state = true;
9906 return WERR_NOT_SUPPORTED;
9909 /****************************************************************
9911 ****************************************************************/
9913 WERROR _spoolss_4c(pipes_struct *p,
9914 struct spoolss_4c *r)
9916 p->rng_fault_state = true;
9917 return WERR_NOT_SUPPORTED;
9920 /****************************************************************
9922 ****************************************************************/
9924 WERROR _spoolss_53(pipes_struct *p,
9925 struct spoolss_53 *r)
9927 p->rng_fault_state = true;
9928 return WERR_NOT_SUPPORTED;
9931 /****************************************************************
9933 ****************************************************************/
9935 WERROR _spoolss_55(pipes_struct *p,
9936 struct spoolss_55 *r)
9938 p->rng_fault_state = true;
9939 return WERR_NOT_SUPPORTED;
9942 /****************************************************************
9944 ****************************************************************/
9946 WERROR _spoolss_56(pipes_struct *p,
9947 struct spoolss_56 *r)
9949 p->rng_fault_state = true;
9950 return WERR_NOT_SUPPORTED;
9953 /****************************************************************
9955 ****************************************************************/
9957 WERROR _spoolss_57(pipes_struct *p,
9958 struct spoolss_57 *r)
9960 p->rng_fault_state = true;
9961 return WERR_NOT_SUPPORTED;
9964 /****************************************************************
9966 ****************************************************************/
9968 WERROR _spoolss_5a(pipes_struct *p,
9969 struct spoolss_5a *r)
9971 p->rng_fault_state = true;
9972 return WERR_NOT_SUPPORTED;
9975 /****************************************************************
9977 ****************************************************************/
9979 WERROR _spoolss_5b(pipes_struct *p,
9980 struct spoolss_5b *r)
9982 p->rng_fault_state = true;
9983 return WERR_NOT_SUPPORTED;
9986 /****************************************************************
9988 ****************************************************************/
9990 WERROR _spoolss_5c(pipes_struct *p,
9991 struct spoolss_5c *r)
9993 p->rng_fault_state = true;
9994 return WERR_NOT_SUPPORTED;
9997 /****************************************************************
9999 ****************************************************************/
10001 WERROR _spoolss_5d(pipes_struct *p,
10002 struct spoolss_5d *r)
10004 p->rng_fault_state = true;
10005 return WERR_NOT_SUPPORTED;
10008 /****************************************************************
10010 ****************************************************************/
10012 WERROR _spoolss_5e(pipes_struct *p,
10013 struct spoolss_5e *r)
10015 p->rng_fault_state = true;
10016 return WERR_NOT_SUPPORTED;
10019 /****************************************************************
10021 ****************************************************************/
10023 WERROR _spoolss_5f(pipes_struct *p,
10024 struct spoolss_5f *r)
10026 p->rng_fault_state = true;
10027 return WERR_NOT_SUPPORTED;