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.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
30 extern userdom_struct current_user_info;
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
43 const char *long_archi;
44 const char *short_archi;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
72 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
75 /********************************************************************
76 * Canonicalize servername.
77 ********************************************************************/
79 static const char *canon_servername(const char *servername)
81 const char *pservername = servername;
82 while (*pservername == '\\') {
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
95 return JOB_STATUS_PAUSED;
97 return JOB_STATUS_SPOOLING;
99 return JOB_STATUS_PRINTING;
101 return JOB_STATUS_ERROR;
103 return JOB_STATUS_DELETING;
105 return JOB_STATUS_OFFLINE;
107 return JOB_STATUS_PAPEROUT;
109 return JOB_STATUS_PRINTED;
111 return JOB_STATUS_DELETED;
113 return JOB_STATUS_BLOCKED_DEVQ;
114 case LPQ_USER_INTERVENTION:
115 return JOB_STATUS_USER_INTERVENTION;
120 static int nt_printq_status(int v)
124 return PRINTER_STATUS_PAUSED;
133 /***************************************************************************
134 Disconnect from the client
135 ****************************************************************************/
137 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
156 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
159 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 win_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 messaging_deregister(smbd_messaging_context(),
170 MSG_PRINTER_NOTIFY2, NULL);
172 /* Tell the connections db we're no longer interested in
173 * printer notify messages. */
175 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
181 /****************************************************************************
182 Functions to free a printer entry datastruct.
183 ****************************************************************************/
185 static int printer_entry_destructor(Printer_entry *Printer)
187 if (Printer->notify.client_connected==True) {
190 if ( Printer->printer_type == SPLHND_SERVER) {
192 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
193 } else if (Printer->printer_type == SPLHND_PRINTER) {
194 snum = print_queue_snum(Printer->sharename);
196 srv_spoolss_replycloseprinter(snum,
197 &Printer->notify.client_hnd);
201 Printer->notify.flags=0;
202 Printer->notify.options=0;
203 Printer->notify.localmachine[0]='\0';
204 Printer->notify.printerlocal=0;
205 TALLOC_FREE(Printer->notify.option);
206 Printer->notify.client_connected=False;
208 free_nt_devicemode( &Printer->nt_devmode );
209 free_a_printer( &Printer->printer_info, 2 );
211 /* Remove from the internal list. */
212 DLIST_REMOVE(printers_list, Printer);
216 /****************************************************************************
217 find printer index by handle
218 ****************************************************************************/
220 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
222 Printer_entry *find_printer = NULL;
224 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
225 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
232 /****************************************************************************
233 Close printer index by handle.
234 ****************************************************************************/
236 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
238 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
241 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
245 close_policy_hnd(p, hnd);
250 /****************************************************************************
251 Delete a printer given a handle.
252 ****************************************************************************/
254 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
256 char *cmd = lp_deleteprinter_cmd();
257 char *command = NULL;
259 SE_PRIV se_printop = SE_PRINT_OPERATOR;
260 bool is_print_op = False;
262 /* can't fail if we don't try */
267 command = talloc_asprintf(ctx,
274 is_print_op = user_has_privileges( token, &se_printop );
276 DEBUG(10,("Running [%s]\n", command));
278 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
283 if ( (ret = smbrun(command, NULL)) == 0 ) {
284 /* Tell everyone we updated smb.conf. */
285 message_send_all(smbd_messaging_context(),
286 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
292 /********** END SePrintOperatorPrivlege BLOCK **********/
294 DEBUGADD(10,("returned [%d]\n", ret));
296 TALLOC_FREE(command);
299 return WERR_BADFID; /* What to return here? */
301 /* go ahead and re-read the services immediately */
302 reload_services( False );
304 if ( lp_servicenumber( sharename ) < 0 )
305 return WERR_ACCESS_DENIED;
310 /****************************************************************************
311 Delete a printer given a handle.
312 ****************************************************************************/
314 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
316 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
319 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
324 * It turns out that Windows allows delete printer on a handle
325 * opened by an admin user, then used on a pipe handle created
326 * by an anonymous user..... but they're working on security.... riiight !
330 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
331 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
332 return WERR_ACCESS_DENIED;
335 /* this does not need a become root since the access check has been
336 done on the handle already */
338 if (del_a_printer( Printer->sharename ) != 0) {
339 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
343 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
344 Printer->sharename );
347 /****************************************************************************
348 Return the snum of a printer corresponding to an handle.
349 ****************************************************************************/
351 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
352 struct share_params **params)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
357 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
361 switch (Printer->printer_type) {
363 DEBUG(4,("short name:%s\n", Printer->sharename));
364 *number = print_queue_snum(Printer->sharename);
365 return (*number != -1);
373 /****************************************************************************
374 Set printer handle type.
375 Check if it's \\server or \\server\printer
376 ****************************************************************************/
378 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
380 DEBUG(3,("Setting printer type=%s\n", handlename));
382 if ( strlen(handlename) < 3 ) {
383 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
387 /* it's a print server */
388 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
389 DEBUGADD(4,("Printer is a print server\n"));
390 Printer->printer_type = SPLHND_SERVER;
392 /* it's a printer (set_printer_hnd_name() will handle port monitors */
394 DEBUGADD(4,("Printer is a printer\n"));
395 Printer->printer_type = SPLHND_PRINTER;
401 /****************************************************************************
402 Set printer handle name.. Accept names like \\server, \\server\printer,
403 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
404 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
405 XcvDataPort() interface.
406 ****************************************************************************/
408 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
411 int n_services=lp_numservices();
412 char *aprinter, *printername;
413 const char *servername;
416 NT_PRINTER_INFO_LEVEL *printer = NULL;
419 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
421 aprinter = handlename;
422 if ( *handlename == '\\' ) {
423 servername = canon_servername(handlename);
424 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
432 /* save the servername to fill in replies on this handle */
434 if ( !is_myname_or_ipaddr( servername ) )
437 fstrcpy( Printer->servername, servername );
439 if ( Printer->printer_type == SPLHND_SERVER )
442 if ( Printer->printer_type != SPLHND_PRINTER )
445 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
447 /* check for the Port Monitor Interface */
449 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
450 Printer->printer_type = SPLHND_PORTMON_TCP;
451 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
454 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
455 Printer->printer_type = SPLHND_PORTMON_LOCAL;
456 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
460 /* Search all sharenames first as this is easier than pulling
461 the printer_info_2 off of disk. Don't use find_service() since
462 that calls out to map_username() */
464 /* do another loop to look for printernames */
466 for (snum=0; !found && snum<n_services; snum++) {
468 /* no point going on if this is not a printer */
470 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
473 fstrcpy(sname, lp_servicename(snum));
474 if ( strequal( aprinter, sname ) ) {
479 /* no point looking up the printer object if
480 we aren't allowing printername != sharename */
482 if ( lp_force_printername(snum) )
485 fstrcpy(sname, lp_servicename(snum));
489 /* This call doesn't fill in the location or comment from
490 * a CUPS server for efficiency with large numbers of printers.
494 result = get_a_printer_search( NULL, &printer, 2, sname );
495 if ( !W_ERROR_IS_OK(result) ) {
496 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
497 sname, win_errstr(result)));
501 /* printername is always returned as \\server\printername */
502 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
503 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
504 printer->info_2->printername));
505 free_a_printer( &printer, 2);
511 if ( strequal(printername, aprinter) ) {
512 free_a_printer( &printer, 2);
517 DEBUGADD(10, ("printername: %s\n", printername));
519 free_a_printer( &printer, 2);
522 free_a_printer( &printer, 2);
525 DEBUGADD(4,("Printer not found\n"));
529 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
531 fstrcpy(Printer->sharename, sname);
536 /****************************************************************************
537 Find first available printer slot. creates a printer handle for you.
538 ****************************************************************************/
540 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
542 Printer_entry *new_printer;
544 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
546 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
547 if (new_printer == NULL) {
550 talloc_set_destructor(new_printer, printer_entry_destructor);
552 if (!create_policy_hnd(p, hnd, new_printer)) {
553 TALLOC_FREE(new_printer);
557 /* Add to the internal list. */
558 DLIST_ADD(printers_list, new_printer);
560 new_printer->notify.option=NULL;
562 if (!set_printer_hnd_printertype(new_printer, name)) {
563 close_printer_handle(p, hnd);
567 if (!set_printer_hnd_name(new_printer, name)) {
568 close_printer_handle(p, hnd);
572 new_printer->access_granted = access_granted;
574 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
579 /***************************************************************************
580 check to see if the client motify handle is monitoring the notification
581 given by (notify_type, notify_field).
582 **************************************************************************/
584 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
590 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
593 struct spoolss_NotifyOption *option = p->notify.option;
597 * Flags should always be zero when the change notify
598 * is registered by the client's spooler. A user Win32 app
599 * might use the flags though instead of the NOTIFY_OPTION_INFO
608 return is_monitoring_event_flags(
609 p->notify.flags, notify_type, notify_field);
611 for (i = 0; i < option->count; i++) {
613 /* Check match for notify_type */
615 if (option->types[i].type != notify_type)
618 /* Check match for field */
620 for (j = 0; j < option->types[i].count; j++) {
621 if (option->types[i].fields[j] == notify_field) {
627 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
628 p->servername, p->sharename, notify_type, notify_field));
633 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
634 _data->data.integer[0] = _integer; \
635 _data->data.integer[1] = 0;
638 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
639 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
640 if (!_data->data.string.string) {\
641 _data->data.string.size = 0; \
643 _data->data.string.size = strlen_m_term(_p) * 2;
645 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
646 _data->data.devmode.devmode = _devmode;
648 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
649 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
650 if (!_data->data.sd.sd) { \
651 _data->data.sd.sd_size = 0; \
653 _data->data.sd.sd_size = _size;
655 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
660 struct spoolss_Time st;
664 if (!init_systemtime(&st, t)) {
668 p = talloc_array(mem_ctx, char, len);
674 * Systemtime must be linearized as a set of UINT16's.
675 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
678 SSVAL(p, 0, st.year);
679 SSVAL(p, 2, st.month);
680 SSVAL(p, 4, st.day_of_week);
682 SSVAL(p, 8, st.hour);
683 SSVAL(p, 10, st.minute);
684 SSVAL(p, 12, st.second);
685 SSVAL(p, 14, st.millisecond);
691 /* Convert a notification message to a struct spoolss_Notify */
693 static void notify_one_value(struct spoolss_notify_msg *msg,
694 struct spoolss_Notify *data,
697 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
700 static void notify_string(struct spoolss_notify_msg *msg,
701 struct spoolss_Notify *data,
704 /* The length of the message includes the trailing \0 */
706 data->data.string.size = msg->len * 2;
707 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
708 if (!data->data.string.string) {
709 data->data.string.size = 0;
714 static void notify_system_time(struct spoolss_notify_msg *msg,
715 struct spoolss_Notify *data,
718 data->data.string.string = NULL;
719 data->data.string.size = 0;
721 if (msg->len != sizeof(time_t)) {
722 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
727 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
728 &data->data.string.string,
729 &data->data.string.size);
732 struct notify2_message_table {
734 void (*fn)(struct spoolss_notify_msg *msg,
735 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
738 static struct notify2_message_table printer_notify_table[] = {
739 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
740 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
741 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
742 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
743 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
744 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
745 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
746 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
747 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
748 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
749 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
750 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
751 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
752 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
753 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
754 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
755 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
756 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
757 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
760 static struct notify2_message_table job_notify_table[] = {
761 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
762 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
763 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
764 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
765 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
766 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
767 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
768 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
769 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
770 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
771 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
772 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
773 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
774 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
775 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
776 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
777 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
778 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
779 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
780 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
781 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
782 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
783 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
784 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
788 /***********************************************************************
789 Allocate talloc context for container object
790 **********************************************************************/
792 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
797 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
802 /***********************************************************************
803 release all allocated memory and zero out structure
804 **********************************************************************/
806 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 talloc_destroy(ctr->ctx);
819 /***********************************************************************
820 **********************************************************************/
822 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 /***********************************************************************
831 **********************************************************************/
833 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
835 if ( !ctr || !ctr->msg_groups )
838 if ( idx >= ctr->num_groups )
841 return &ctr->msg_groups[idx];
845 /***********************************************************************
846 How many groups of change messages do we have ?
847 **********************************************************************/
849 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
854 return ctr->num_groups;
857 /***********************************************************************
858 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
859 **********************************************************************/
861 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
863 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
864 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
865 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
871 /* loop over all groups looking for a matching printer name */
873 for ( i=0; i<ctr->num_groups; i++ ) {
874 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
878 /* add a new group? */
880 if ( i == ctr->num_groups ) {
883 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
884 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
887 ctr->msg_groups = groups;
889 /* clear the new entry and set the printer name */
891 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
892 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
895 /* add the change messages; 'i' is the correct index now regardless */
897 msg_grp = &ctr->msg_groups[i];
901 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
902 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
905 msg_grp->msgs = msg_list;
907 new_slot = msg_grp->num_msgs-1;
908 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
910 /* need to allocate own copy of data */
913 msg_grp->msgs[new_slot].notify.data = (char *)
914 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
916 return ctr->num_groups;
919 /***********************************************************************
920 Send a change notication message on all handles which have a call
922 **********************************************************************/
924 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
927 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
928 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
929 SPOOLSS_NOTIFY_MSG *messages;
930 int sending_msg_count;
933 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
937 messages = msg_group->msgs;
940 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
944 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
946 /* loop over all printers */
948 for (p = printers_list; p; p = p->next) {
949 struct spoolss_Notify *notifies;
954 /* Is there notification on this handle? */
956 if ( !p->notify.client_connected )
959 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
961 /* For this printer? Print servers always receive
964 if ( ( p->printer_type == SPLHND_PRINTER ) &&
965 ( !strequal(msg_group->printername, p->sharename) ) )
968 DEBUG(10,("Our printer\n"));
970 /* allocate the max entries possible */
972 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
977 /* build the array of change notifications */
979 sending_msg_count = 0;
981 for ( i=0; i<msg_group->num_msgs; i++ ) {
982 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
984 /* Are we monitoring this event? */
986 if (!is_monitoring_event(p, msg->type, msg->field))
992 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
993 msg->type, msg->field, p->sharename));
996 * if the is a printer notification handle and not a job notification
997 * type, then set the id to 0. Other wise just use what was specified
1000 * When registering change notification on a print server handle
1001 * we always need to send back the id (snum) matching the printer
1002 * for which the change took place. For change notify registered
1003 * on a printer handle, this does not matter and the id should be 0.
1008 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1014 /* Convert unix jobid to smb jobid */
1016 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1017 id = sysjob_to_jobid(msg->id);
1020 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1025 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1028 case PRINTER_NOTIFY_TYPE:
1029 if ( printer_notify_table[msg->field].fn )
1030 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1033 case JOB_NOTIFY_TYPE:
1034 if ( job_notify_table[msg->field].fn )
1035 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1039 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1046 if ( sending_msg_count ) {
1049 union spoolss_ReplyPrinterInfo info;
1050 struct spoolss_NotifyInfo info0;
1051 uint32_t reply_result;
1053 info0.version = 0x2;
1054 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1055 info0.count = count;
1056 info0.notifies = notifies;
1058 info.info0 = &info0;
1060 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1061 &p->notify.client_hnd,
1062 p->notify.change, /* color */
1065 0, /* reply_type, must be 0 */
1068 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1069 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1070 notify_cli_pipe->srv_name_slash,
1073 switch (reply_result) {
1076 case PRINTER_NOTIFY_INFO_DISCARDED:
1077 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1078 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1087 DEBUG(8,("send_notify2_changes: Exit...\n"));
1091 /***********************************************************************
1092 **********************************************************************/
1094 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1097 uint32 tv_sec, tv_usec;
1100 /* Unpack message */
1102 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1105 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1107 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1110 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1111 &msg->notify.value[0], &msg->notify.value[1]);
1113 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1114 &msg->len, &msg->notify.data);
1116 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1117 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1119 tv->tv_sec = tv_sec;
1120 tv->tv_usec = tv_usec;
1123 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1124 msg->notify.value[1]));
1126 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1131 /********************************************************************
1132 Receive a notify2 message list
1133 ********************************************************************/
1135 static void receive_notify2_message_list(struct messaging_context *msg,
1138 struct server_id server_id,
1141 size_t msg_count, i;
1142 char *buf = (char *)data->data;
1145 SPOOLSS_NOTIFY_MSG notify;
1146 SPOOLSS_NOTIFY_MSG_CTR messages;
1149 if (data->length < 4) {
1150 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1154 msg_count = IVAL(buf, 0);
1157 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1159 if (msg_count == 0) {
1160 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1164 /* initialize the container */
1166 ZERO_STRUCT( messages );
1167 notify_msg_ctr_init( &messages );
1170 * build message groups for each printer identified
1171 * in a change_notify msg. Remember that a PCN message
1172 * includes the handle returned for the srv_spoolss_replyopenprinter()
1173 * call. Therefore messages are grouped according to printer handle.
1176 for ( i=0; i<msg_count; i++ ) {
1177 struct timeval msg_tv;
1179 if (msg_ptr + 4 - buf > data->length) {
1180 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1184 msg_len = IVAL(msg_ptr,0);
1187 if (msg_ptr + msg_len - buf > data->length) {
1188 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1192 /* unpack messages */
1194 ZERO_STRUCT( notify );
1195 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1198 /* add to correct list in container */
1200 notify_msg_ctr_addmsg( &messages, ¬ify );
1202 /* free memory that might have been allocated by notify2_unpack_msg() */
1204 if ( notify.len != 0 )
1205 SAFE_FREE( notify.notify.data );
1208 /* process each group of messages */
1210 num_groups = notify_msg_ctr_numgroups( &messages );
1211 for ( i=0; i<num_groups; i++ )
1212 send_notify2_changes( &messages, i );
1217 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1219 notify_msg_ctr_destroy( &messages );
1224 /********************************************************************
1225 Send a message to ourself about new driver being installed
1226 so we can upgrade the information for each printer bound to this
1228 ********************************************************************/
1230 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1232 int len = strlen(drivername);
1237 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1240 messaging_send_buf(smbd_messaging_context(), procid_self(),
1241 MSG_PRINTER_DRVUPGRADE,
1242 (uint8 *)drivername, len+1);
1247 /**********************************************************************
1248 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1249 over all printers, upgrading ones as necessary
1250 **********************************************************************/
1252 void do_drv_upgrade_printer(struct messaging_context *msg,
1255 struct server_id server_id,
1260 int n_services = lp_numservices();
1263 len = MIN(data->length,sizeof(drivername)-1);
1264 strncpy(drivername, (const char *)data->data, len);
1266 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1268 /* Iterate the printer list */
1270 for (snum=0; snum<n_services; snum++)
1272 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1275 NT_PRINTER_INFO_LEVEL *printer = NULL;
1277 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1278 if (!W_ERROR_IS_OK(result))
1281 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1283 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1285 /* all we care about currently is the change_id */
1287 result = mod_a_printer(printer, 2);
1288 if (!W_ERROR_IS_OK(result)) {
1289 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1290 win_errstr(result)));
1294 free_a_printer(&printer, 2);
1301 /********************************************************************
1302 Update the cache for all printq's with a registered client
1304 ********************************************************************/
1306 void update_monitored_printq_cache( void )
1308 Printer_entry *printer = printers_list;
1311 /* loop through all printers and update the cache where
1312 client_connected == True */
1315 if ( (printer->printer_type == SPLHND_PRINTER)
1316 && printer->notify.client_connected )
1318 snum = print_queue_snum(printer->sharename);
1319 print_queue_status( snum, NULL, NULL );
1322 printer = printer->next;
1327 /********************************************************************
1328 Send a message to ourself about new driver being installed
1329 so we can upgrade the information for each printer bound to this
1331 ********************************************************************/
1333 static bool srv_spoolss_reset_printerdata(char* drivername)
1335 int len = strlen(drivername);
1340 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1343 messaging_send_buf(smbd_messaging_context(), procid_self(),
1344 MSG_PRINTERDATA_INIT_RESET,
1345 (uint8 *)drivername, len+1);
1350 /**********************************************************************
1351 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1352 over all printers, resetting printer data as neessary
1353 **********************************************************************/
1355 void reset_all_printerdata(struct messaging_context *msg,
1358 struct server_id server_id,
1363 int n_services = lp_numservices();
1366 len = MIN( data->length, sizeof(drivername)-1 );
1367 strncpy( drivername, (const char *)data->data, len );
1369 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1371 /* Iterate the printer list */
1373 for ( snum=0; snum<n_services; snum++ )
1375 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1378 NT_PRINTER_INFO_LEVEL *printer = NULL;
1380 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1381 if ( !W_ERROR_IS_OK(result) )
1385 * if the printer is bound to the driver,
1386 * then reset to the new driver initdata
1389 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1391 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1393 if ( !set_driver_init(printer, 2) ) {
1394 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1395 printer->info_2->printername, printer->info_2->drivername));
1398 result = mod_a_printer( printer, 2 );
1399 if ( !W_ERROR_IS_OK(result) ) {
1400 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1401 get_dos_error_msg(result)));
1405 free_a_printer( &printer, 2 );
1414 /****************************************************************
1415 _spoolss_OpenPrinter
1416 ****************************************************************/
1418 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1419 struct spoolss_OpenPrinter *r)
1421 struct spoolss_OpenPrinterEx e;
1424 ZERO_STRUCT(e.in.userlevel);
1426 e.in.printername = r->in.printername;
1427 e.in.datatype = r->in.datatype;
1428 e.in.devmode_ctr = r->in.devmode_ctr;
1429 e.in.access_mask = r->in.access_mask;
1432 e.out.handle = r->out.handle;
1434 werr = _spoolss_OpenPrinterEx(p, &e);
1436 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1437 /* OpenPrinterEx returns this for a bad
1438 * printer name. We must return WERR_INVALID_PRINTER_NAME
1441 werr = WERR_INVALID_PRINTER_NAME;
1447 /********************************************************************
1448 FIXME: temporary convert_devicemode_new function
1449 ********************************************************************/
1451 static bool convert_devicemode_new(const char *printername,
1452 struct spoolss_DeviceMode *devmode,
1453 NT_DEVICEMODE **pp_nt_devmode)
1455 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1458 * Ensure nt_devmode is a valid pointer
1459 * as we will be overwriting it.
1462 if (nt_devmode == NULL) {
1463 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1464 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1468 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1469 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1471 nt_devmode->specversion = devmode->specversion;
1472 nt_devmode->driverversion = devmode->driverversion;
1473 nt_devmode->size = devmode->size;
1474 nt_devmode->fields = devmode->fields;
1475 nt_devmode->orientation = devmode->orientation;
1476 nt_devmode->papersize = devmode->papersize;
1477 nt_devmode->paperlength = devmode->paperlength;
1478 nt_devmode->paperwidth = devmode->paperwidth;
1479 nt_devmode->scale = devmode->scale;
1480 nt_devmode->copies = devmode->copies;
1481 nt_devmode->defaultsource = devmode->defaultsource;
1482 nt_devmode->printquality = devmode->printquality;
1483 nt_devmode->color = devmode->color;
1484 nt_devmode->duplex = devmode->duplex;
1485 nt_devmode->yresolution = devmode->yresolution;
1486 nt_devmode->ttoption = devmode->ttoption;
1487 nt_devmode->collate = devmode->collate;
1489 nt_devmode->logpixels = devmode->logpixels;
1490 nt_devmode->bitsperpel = devmode->bitsperpel;
1491 nt_devmode->pelswidth = devmode->pelswidth;
1492 nt_devmode->pelsheight = devmode->pelsheight;
1493 nt_devmode->displayflags = devmode->displayflags;
1494 nt_devmode->displayfrequency = devmode->displayfrequency;
1495 nt_devmode->icmmethod = devmode->icmmethod;
1496 nt_devmode->icmintent = devmode->icmintent;
1497 nt_devmode->mediatype = devmode->mediatype;
1498 nt_devmode->dithertype = devmode->dithertype;
1499 nt_devmode->reserved1 = devmode->reserved1;
1500 nt_devmode->reserved2 = devmode->reserved2;
1501 nt_devmode->panningwidth = devmode->panningwidth;
1502 nt_devmode->panningheight = devmode->panningheight;
1505 * Only change private and driverextra if the incoming devmode
1506 * has a new one. JRA.
1509 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1510 SAFE_FREE(nt_devmode->nt_dev_private);
1511 nt_devmode->driverextra = devmode->__driverextra_length;
1512 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1514 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1517 *pp_nt_devmode = nt_devmode;
1522 /****************************************************************
1523 _spoolss_OpenPrinterEx
1524 ****************************************************************/
1526 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1527 struct spoolss_OpenPrinterEx *r)
1529 POLICY_HND *handle = r->out.handle;
1530 char *name = CONST_DISCARD(char *, r->in.printername);
1532 Printer_entry *Printer=NULL;
1535 return WERR_INVALID_PARAM;
1538 /* some sanity check because you can open a printer or a print server */
1539 /* aka: \\server\printer or \\server */
1541 DEBUGADD(3,("checking name: %s\n",name));
1543 if (!open_printer_hnd(p, handle, name, 0)) {
1544 ZERO_STRUCTP(r->out.handle);
1545 return WERR_INVALID_PARAM;
1548 Printer=find_printer_index_by_hnd(p, handle);
1550 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1551 "handle we created for printer %s\n", name ));
1552 close_printer_handle(p,handle);
1553 ZERO_STRUCTP(r->out.handle);
1554 return WERR_INVALID_PARAM;
1558 * First case: the user is opening the print server:
1560 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1561 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1563 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1564 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1565 * or if the user is listed in the smb.conf printer admin parameter.
1567 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1568 * client view printer folder, but does not show the MSAPW.
1570 * Note: this test needs code to check access rights here too. Jeremy
1571 * could you look at this?
1573 * Second case: the user is opening a printer:
1574 * NT doesn't let us connect to a printer if the connecting user
1575 * doesn't have print permission.
1577 * Third case: user is opening a Port Monitor
1578 * access checks same as opening a handle to the print server.
1581 switch (Printer->printer_type )
1584 case SPLHND_PORTMON_TCP:
1585 case SPLHND_PORTMON_LOCAL:
1586 /* Printserver handles use global struct... */
1590 /* Map standard access rights to object specific access rights */
1592 se_map_standard(&r->in.access_mask,
1593 &printserver_std_mapping);
1595 /* Deny any object specific bits that don't apply to print
1596 servers (i.e printer and job specific bits) */
1598 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1600 if (r->in.access_mask &
1601 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1602 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1603 close_printer_handle(p, handle);
1604 ZERO_STRUCTP(r->out.handle);
1605 return WERR_ACCESS_DENIED;
1608 /* Allow admin access */
1610 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1612 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1614 if (!lp_ms_add_printer_wizard()) {
1615 close_printer_handle(p, handle);
1616 ZERO_STRUCTP(r->out.handle);
1617 return WERR_ACCESS_DENIED;
1620 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621 and not a printer admin, then fail */
1623 if ((p->server_info->utok.uid != 0) &&
1624 !user_has_privileges(p->server_info->ptok,
1626 !token_contains_name_in_list(
1627 uidtoname(p->server_info->utok.uid),
1629 p->server_info->ptok,
1630 lp_printer_admin(snum))) {
1631 close_printer_handle(p, handle);
1632 ZERO_STRUCTP(r->out.handle);
1633 return WERR_ACCESS_DENIED;
1636 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1640 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1643 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1644 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1646 /* We fall through to return WERR_OK */
1649 case SPLHND_PRINTER:
1650 /* NT doesn't let us connect to a printer if the connecting user
1651 doesn't have print permission. */
1653 if (!get_printer_snum(p, handle, &snum, NULL)) {
1654 close_printer_handle(p, handle);
1655 ZERO_STRUCTP(r->out.handle);
1659 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1661 /* map an empty access mask to the minimum access mask */
1662 if (r->in.access_mask == 0x0)
1663 r->in.access_mask = PRINTER_ACCESS_USE;
1666 * If we are not serving the printer driver for this printer,
1667 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1668 * will keep NT clients happy --jerry
1671 if (lp_use_client_driver(snum)
1672 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1674 r->in.access_mask = PRINTER_ACCESS_USE;
1677 /* check smb.conf parameters and the the sec_desc */
1679 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1680 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1681 ZERO_STRUCTP(r->out.handle);
1682 return WERR_ACCESS_DENIED;
1685 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1686 p->server_info->ptok, snum) ||
1687 !print_access_check(p->server_info, snum,
1688 r->in.access_mask)) {
1689 DEBUG(3, ("access DENIED for printer open\n"));
1690 close_printer_handle(p, handle);
1691 ZERO_STRUCTP(r->out.handle);
1692 return WERR_ACCESS_DENIED;
1695 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1696 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1697 close_printer_handle(p, handle);
1698 ZERO_STRUCTP(r->out.handle);
1699 return WERR_ACCESS_DENIED;
1702 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1703 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1705 r->in.access_mask = PRINTER_ACCESS_USE;
1707 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1708 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1713 /* sanity check to prevent programmer error */
1714 ZERO_STRUCTP(r->out.handle);
1718 Printer->access_granted = r->in.access_mask;
1721 * If the client sent a devmode in the OpenPrinter() call, then
1722 * save it here in case we get a job submission on this handle
1725 if ( (Printer->printer_type != SPLHND_SERVER)
1726 && r->in.devmode_ctr.devmode )
1728 convert_devicemode_new(Printer->sharename,
1729 r->in.devmode_ctr.devmode,
1730 &Printer->nt_devmode);
1733 #if 0 /* JERRY -- I'm doubtful this is really effective */
1734 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1735 optimization in Windows 2000 clients --jerry */
1737 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1738 && (RA_WIN2K == get_remote_arch()) )
1740 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1741 sys_usleep( 500000 );
1748 /****************************************************************************
1749 ****************************************************************************/
1751 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1752 NT_PRINTER_INFO_LEVEL_2 *d)
1754 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1760 d->attributes = r->attributes;
1761 d->priority = r->priority;
1762 d->default_priority = r->defaultpriority;
1763 d->starttime = r->starttime;
1764 d->untiltime = r->untiltime;
1765 d->status = r->status;
1766 d->cjobs = r->cjobs;
1768 fstrcpy(d->servername, r->servername);
1769 fstrcpy(d->printername, r->printername);
1770 fstrcpy(d->sharename, r->sharename);
1771 fstrcpy(d->portname, r->portname);
1772 fstrcpy(d->drivername, r->drivername);
1773 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1774 fstrcpy(d->location, r->location);
1775 fstrcpy(d->sepfile, r->sepfile);
1776 fstrcpy(d->printprocessor, r->printprocessor);
1777 fstrcpy(d->datatype, r->datatype);
1778 fstrcpy(d->parameters, r->parameters);
1783 /****************************************************************************
1784 ****************************************************************************/
1786 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1787 NT_PRINTER_INFO_LEVEL *printer)
1791 switch (info_ctr->level) {
1793 /* allocate memory if needed. Messy because
1794 convert_printer_info is used to update an existing
1795 printer or build a new one */
1797 if (!printer->info_2) {
1798 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1799 if (!printer->info_2) {
1800 DEBUG(0,("convert_printer_info_new: "
1801 "talloc() failed!\n"));
1806 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1808 printer->info_2->setuptime = time(NULL);
1815 /*******************************************************************
1816 ********************************************************************/
1818 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1827 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1832 for (i=0; sarray[i] != NULL; i++) {
1833 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1837 fstrcpy((*farray)[i], sarray[i]);
1840 fstrcpy((*farray)[i], "");
1845 /*******************************************************************
1846 ********************************************************************/
1848 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1849 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1851 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1853 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1856 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1865 d->cversion = r->version;
1867 fstrcpy(d->name, r->driver_name);
1868 fstrcpy(d->environment, r->architecture);
1869 fstrcpy(d->driverpath, r->driver_path);
1870 fstrcpy(d->datafile, r->data_file);
1871 fstrcpy(d->configfile, r->config_file);
1872 fstrcpy(d->helpfile, r->help_file);
1873 fstrcpy(d->monitorname, r->monitor_name);
1874 fstrcpy(d->defaultdatatype, r->default_datatype);
1876 DEBUGADD(8,( "version: %d\n", d->cversion));
1877 DEBUGADD(8,( "name: %s\n", d->name));
1878 DEBUGADD(8,( "environment: %s\n", d->environment));
1879 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1880 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1881 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1882 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1883 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1884 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1886 if (r->dependent_files) {
1887 if (!string_array_to_fstring_array(r->dependent_files->string,
1888 &d->dependentfiles)) {
1897 /*******************************************************************
1898 ********************************************************************/
1900 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1901 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1903 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1905 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1908 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1917 d->version = r->version;
1919 fstrcpy(d->name, r->driver_name);
1920 fstrcpy(d->environment, r->architecture);
1921 fstrcpy(d->driverpath, r->driver_path);
1922 fstrcpy(d->datafile, r->data_file);
1923 fstrcpy(d->configfile, r->config_file);
1924 fstrcpy(d->helpfile, r->help_file);
1925 fstrcpy(d->monitorname, r->monitor_name);
1926 fstrcpy(d->defaultdatatype, r->default_datatype);
1928 DEBUGADD(8,( "version: %d\n", d->version));
1929 DEBUGADD(8,( "name: %s\n", d->name));
1930 DEBUGADD(8,( "environment: %s\n", d->environment));
1931 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1932 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1933 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1934 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1935 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1936 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1938 if (r->dependent_files) {
1939 if (!string_array_to_fstring_array(r->dependent_files->string,
1940 &d->dependentfiles)) {
1945 if (r->previous_names) {
1946 if (!string_array_to_fstring_array(r->previous_names->string,
1947 &d->previousnames)) {
1959 /********************************************************************
1960 ********************************************************************/
1962 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1963 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1968 printer->info_3 = NULL;
1969 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1974 printer->info_6 = NULL;
1975 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1986 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1987 NT_DEVICEMODE **pp_nt_devmode)
1989 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1992 * Ensure nt_devmode is a valid pointer
1993 * as we will be overwriting it.
1996 if (nt_devmode == NULL) {
1997 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1998 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2002 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2003 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2005 nt_devmode->specversion=devmode->specversion;
2006 nt_devmode->driverversion=devmode->driverversion;
2007 nt_devmode->size=devmode->size;
2008 nt_devmode->fields=devmode->fields;
2009 nt_devmode->orientation=devmode->orientation;
2010 nt_devmode->papersize=devmode->papersize;
2011 nt_devmode->paperlength=devmode->paperlength;
2012 nt_devmode->paperwidth=devmode->paperwidth;
2013 nt_devmode->scale=devmode->scale;
2014 nt_devmode->copies=devmode->copies;
2015 nt_devmode->defaultsource=devmode->defaultsource;
2016 nt_devmode->printquality=devmode->printquality;
2017 nt_devmode->color=devmode->color;
2018 nt_devmode->duplex=devmode->duplex;
2019 nt_devmode->yresolution=devmode->yresolution;
2020 nt_devmode->ttoption=devmode->ttoption;
2021 nt_devmode->collate=devmode->collate;
2023 nt_devmode->logpixels=devmode->logpixels;
2024 nt_devmode->bitsperpel=devmode->bitsperpel;
2025 nt_devmode->pelswidth=devmode->pelswidth;
2026 nt_devmode->pelsheight=devmode->pelsheight;
2027 nt_devmode->displayflags=devmode->displayflags;
2028 nt_devmode->displayfrequency=devmode->displayfrequency;
2029 nt_devmode->icmmethod=devmode->icmmethod;
2030 nt_devmode->icmintent=devmode->icmintent;
2031 nt_devmode->mediatype=devmode->mediatype;
2032 nt_devmode->dithertype=devmode->dithertype;
2033 nt_devmode->reserved1=devmode->reserved1;
2034 nt_devmode->reserved2=devmode->reserved2;
2035 nt_devmode->panningwidth=devmode->panningwidth;
2036 nt_devmode->panningheight=devmode->panningheight;
2039 * Only change private and driverextra if the incoming devmode
2040 * has a new one. JRA.
2043 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2044 SAFE_FREE(nt_devmode->nt_dev_private);
2045 nt_devmode->driverextra=devmode->driverextra;
2046 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2048 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2051 *pp_nt_devmode = nt_devmode;
2056 /********************************************************************
2057 * _spoolss_enddocprinter_internal.
2058 ********************************************************************/
2060 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2062 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2066 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2070 if (!get_printer_snum(p, handle, &snum, NULL))
2073 Printer->document_started=False;
2074 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2075 /* error codes unhandled so far ... */
2080 /****************************************************************
2081 _spoolss_ClosePrinter
2082 ****************************************************************/
2084 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2085 struct spoolss_ClosePrinter *r)
2087 POLICY_HND *handle = r->in.handle;
2089 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2091 if (Printer && Printer->document_started)
2092 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2094 if (!close_printer_handle(p, handle))
2097 /* clear the returned printer handle. Observed behavior
2098 from Win2k server. Don't think this really matters.
2099 Previous code just copied the value of the closed
2102 ZERO_STRUCTP(r->out.handle);
2107 /****************************************************************
2108 _spoolss_DeletePrinter
2109 ****************************************************************/
2111 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2112 struct spoolss_DeletePrinter *r)
2114 POLICY_HND *handle = r->in.handle;
2115 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2118 if (Printer && Printer->document_started)
2119 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2121 result = delete_printer_handle(p, handle);
2123 update_c_setprinter(False);
2128 /*******************************************************************
2129 * static function to lookup the version id corresponding to an
2130 * long architecture string
2131 ******************************************************************/
2133 static int get_version_id (char * arch)
2136 struct table_node archi_table[]= {
2138 {"Windows 4.0", "WIN40", 0 },
2139 {"Windows NT x86", "W32X86", 2 },
2140 {"Windows NT R4000", "W32MIPS", 2 },
2141 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2142 {"Windows NT PowerPC", "W32PPC", 2 },
2143 {"Windows IA64", "IA64", 3 },
2144 {"Windows x64", "x64", 3 },
2148 for (i=0; archi_table[i].long_archi != NULL; i++)
2150 if (strcmp(arch, archi_table[i].long_archi) == 0)
2151 return (archi_table[i].version);
2157 /****************************************************************
2158 _spoolss_DeletePrinterDriver
2159 ****************************************************************/
2161 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2162 struct spoolss_DeletePrinterDriver *r)
2166 NT_PRINTER_DRIVER_INFO_LEVEL info;
2167 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2170 WERROR status_win2k = WERR_ACCESS_DENIED;
2171 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2173 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2174 and not a printer admin, then fail */
2176 if ( (p->server_info->utok.uid != 0)
2177 && !user_has_privileges(p->server_info->ptok, &se_printop )
2178 && !token_contains_name_in_list(
2179 uidtoname(p->server_info->utok.uid), NULL,
2180 NULL, p->server_info->ptok,
2181 lp_printer_admin(-1)) )
2183 return WERR_ACCESS_DENIED;
2186 driver = CONST_DISCARD(char *, r->in.driver);
2187 arch = CONST_DISCARD(char *, r->in.architecture);
2189 /* check that we have a valid driver name first */
2191 if ((version=get_version_id(arch)) == -1)
2192 return WERR_INVALID_ENVIRONMENT;
2195 ZERO_STRUCT(info_win2k);
2197 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2199 /* try for Win2k driver if "Windows NT x86" */
2201 if ( version == 2 ) {
2203 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2204 status = WERR_UNKNOWN_PRINTER_DRIVER;
2208 /* otherwise it was a failure */
2210 status = WERR_UNKNOWN_PRINTER_DRIVER;
2216 if (printer_driver_in_use(info.info_3)) {
2217 status = WERR_PRINTER_DRIVER_IN_USE;
2223 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2225 /* if we get to here, we now have 2 driver info structures to remove */
2226 /* remove the Win2k driver first*/
2228 status_win2k = delete_printer_driver(
2229 p, info_win2k.info_3, 3, False );
2230 free_a_printer_driver( info_win2k, 3 );
2232 /* this should not have failed---if it did, report to client */
2233 if ( !W_ERROR_IS_OK(status_win2k) )
2235 status = status_win2k;
2241 status = delete_printer_driver(p, info.info_3, version, False);
2243 /* if at least one of the deletes succeeded return OK */
2245 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2249 free_a_printer_driver( info, 3 );
2254 /****************************************************************
2255 _spoolss_DeletePrinterDriverEx
2256 ****************************************************************/
2258 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2259 struct spoolss_DeletePrinterDriverEx *r)
2263 NT_PRINTER_DRIVER_INFO_LEVEL info;
2264 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2266 uint32_t flags = r->in.delete_flags;
2269 WERROR status_win2k = WERR_ACCESS_DENIED;
2270 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2272 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2273 and not a printer admin, then fail */
2275 if ( (p->server_info->utok.uid != 0)
2276 && !user_has_privileges(p->server_info->ptok, &se_printop )
2277 && !token_contains_name_in_list(
2278 uidtoname(p->server_info->utok.uid), NULL, NULL,
2279 p->server_info->ptok, lp_printer_admin(-1)) )
2281 return WERR_ACCESS_DENIED;
2284 driver = CONST_DISCARD(char *, r->in.driver);
2285 arch = CONST_DISCARD(char *, r->in.architecture);
2287 /* check that we have a valid driver name first */
2288 if ((version=get_version_id(arch)) == -1) {
2289 /* this is what NT returns */
2290 return WERR_INVALID_ENVIRONMENT;
2293 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2294 version = r->in.version;
2297 ZERO_STRUCT(info_win2k);
2299 status = get_a_printer_driver(&info, 3, driver, arch, version);
2301 if ( !W_ERROR_IS_OK(status) )
2304 * if the client asked for a specific version,
2305 * or this is something other than Windows NT x86,
2309 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2312 /* try for Win2k driver if "Windows NT x86" */
2315 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2316 status = WERR_UNKNOWN_PRINTER_DRIVER;
2321 if ( printer_driver_in_use(info.info_3) ) {
2322 status = WERR_PRINTER_DRIVER_IN_USE;
2327 * we have a couple of cases to consider.
2328 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2329 * then the delete should fail if **any** files overlap with
2331 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2332 * non-overlapping files
2333 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2334 * is set, the do not delete any files
2335 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2338 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2340 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2342 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2343 /* no idea of the correct error here */
2344 status = WERR_ACCESS_DENIED;
2349 /* also check for W32X86/3 if necessary; maybe we already have? */
2351 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2352 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2355 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2356 /* no idea of the correct error here */
2357 free_a_printer_driver( info_win2k, 3 );
2358 status = WERR_ACCESS_DENIED;
2362 /* if we get to here, we now have 2 driver info structures to remove */
2363 /* remove the Win2k driver first*/
2365 status_win2k = delete_printer_driver(
2366 p, info_win2k.info_3, 3, delete_files);
2367 free_a_printer_driver( info_win2k, 3 );
2369 /* this should not have failed---if it did, report to client */
2371 if ( !W_ERROR_IS_OK(status_win2k) )
2376 status = delete_printer_driver(p, info.info_3, version, delete_files);
2378 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2381 free_a_printer_driver( info, 3 );
2387 /****************************************************************************
2388 Internal routine for retreiving printerdata
2389 ***************************************************************************/
2391 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2392 const char *key, const char *value, uint32 *type, uint8 **data,
2393 uint32 *needed, uint32 in_size )
2395 REGISTRY_VALUE *val;
2399 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2400 return WERR_BADFILE;
2402 *type = regval_type( val );
2404 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2406 size = regval_size( val );
2408 /* copy the min(in_size, len) */
2411 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2413 /* special case for 0 length values */
2415 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2419 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2428 DEBUG(5,("get_printer_dataex: copy done\n"));
2433 /****************************************************************************
2434 Internal routine for removing printerdata
2435 ***************************************************************************/
2437 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2439 return delete_printer_data( printer->info_2, key, value );
2442 /****************************************************************************
2443 Internal routine for storing printerdata
2444 ***************************************************************************/
2446 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2447 uint32 type, uint8 *data, int real_len )
2449 /* the registry objects enforce uniqueness based on value name */
2451 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2454 /********************************************************************
2455 GetPrinterData on a printer server Handle.
2456 ********************************************************************/
2458 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2462 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2464 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2466 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2468 SIVAL(*data, 0, 0x00);
2473 if (!StrCaseCmp(value, "BeepEnabled")) {
2475 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2477 SIVAL(*data, 0, 0x00);
2482 if (!StrCaseCmp(value, "EventLog")) {
2484 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2486 /* formally was 0x1b */
2487 SIVAL(*data, 0, 0x0);
2492 if (!StrCaseCmp(value, "NetPopup")) {
2494 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2496 SIVAL(*data, 0, 0x00);
2501 if (!StrCaseCmp(value, "MajorVersion")) {
2503 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2506 /* Windows NT 4.0 seems to not allow uploading of drivers
2507 to a server that reports 0x3 as the MajorVersion.
2508 need to investigate more how Win2k gets around this .
2511 if ( RA_WINNT == get_remote_arch() )
2520 if (!StrCaseCmp(value, "MinorVersion")) {
2522 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2530 * uint32 size = 0x114
2532 * uint32 minor = [0|1]
2533 * uint32 build = [2195|2600]
2534 * extra unicode string = e.g. "Service Pack 3"
2536 if (!StrCaseCmp(value, "OSVersion")) {
2540 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2543 SIVAL(*data, 0, *needed); /* size */
2544 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2546 SIVAL(*data, 12, 2195); /* build */
2548 /* leave extra string empty */
2554 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2555 const char *string="C:\\PRINTERS";
2557 *needed = 2*(strlen(string)+1);
2558 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2560 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2562 /* it's done by hand ready to go on the wire */
2563 for (i=0; i<strlen(string); i++) {
2564 (*data)[2*i]=string[i];
2565 (*data)[2*i+1]='\0';
2570 if (!StrCaseCmp(value, "Architecture")) {
2571 const char *string="Windows NT x86";
2573 *needed = 2*(strlen(string)+1);
2574 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2576 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2577 for (i=0; i<strlen(string); i++) {
2578 (*data)[2*i]=string[i];
2579 (*data)[2*i+1]='\0';
2584 if (!StrCaseCmp(value, "DsPresent")) {
2586 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2589 /* only show the publish check box if we are a
2590 memeber of a AD domain */
2592 if ( lp_security() == SEC_ADS )
2593 SIVAL(*data, 0, 0x01);
2595 SIVAL(*data, 0, 0x00);
2601 if (!StrCaseCmp(value, "DNSMachineName")) {
2602 const char *hostname = get_mydnsfullname();
2605 return WERR_BADFILE;
2607 *needed = 2*(strlen(hostname)+1);
2608 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2610 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2611 for (i=0; i<strlen(hostname); i++) {
2612 (*data)[2*i]=hostname[i];
2613 (*data)[2*i+1]='\0';
2619 return WERR_BADFILE;
2622 /********************************************************************
2623 * spoolss_getprinterdata
2624 ********************************************************************/
2626 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2628 POLICY_HND *handle = &q_u->handle;
2629 UNISTR2 *valuename = &q_u->valuename;
2630 uint32 in_size = q_u->size;
2631 uint32 *type = &r_u->type;
2632 uint32 *out_size = &r_u->size;
2633 uint8 **data = &r_u->data;
2634 uint32 *needed = &r_u->needed;
2637 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2638 NT_PRINTER_INFO_LEVEL *printer = NULL;
2642 * Reminder: when it's a string, the length is in BYTES
2643 * even if UNICODE is negociated.
2648 *out_size = in_size;
2650 /* in case of problem, return some default values */
2655 DEBUG(4,("_spoolss_getprinterdata\n"));
2658 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2659 status = WERR_BADFID;
2663 unistr2_to_ascii(value, valuename, sizeof(value));
2665 if ( Printer->printer_type == SPLHND_SERVER )
2666 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2669 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2670 status = WERR_BADFID;
2674 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2675 if ( !W_ERROR_IS_OK(status) )
2678 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2680 if ( strequal(value, "ChangeId") ) {
2682 *needed = sizeof(uint32);
2683 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2684 status = WERR_NOMEM;
2687 SIVAL( *data, 0, printer->info_2->changeid );
2691 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2694 if (*needed > *out_size)
2695 status = WERR_MORE_DATA;
2698 if ( !W_ERROR_IS_OK(status) )
2700 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2702 /* reply this param doesn't exist */
2705 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2707 free_a_printer( &printer, 2 );
2715 /* cleanup & exit */
2718 free_a_printer( &printer, 2 );
2723 /*********************************************************
2724 Connect to the client machine.
2725 **********************************************************/
2727 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2728 struct sockaddr_storage *client_ss, const char *remote_machine)
2731 struct cli_state *the_cli;
2732 struct sockaddr_storage rm_addr;
2734 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2735 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2736 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2740 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2741 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2745 char addr[INET6_ADDRSTRLEN];
2746 rm_addr = *client_ss;
2747 print_sockaddr(addr, sizeof(addr), &rm_addr);
2748 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2752 /* setup the connection */
2754 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2755 &rm_addr, 0, "IPC$", "IPC",
2759 0, lp_client_signing(), NULL );
2761 if ( !NT_STATUS_IS_OK( ret ) ) {
2762 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2767 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2768 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2769 cli_shutdown(the_cli);
2774 * Ok - we have an anonymous connection to the IPC$ share.
2775 * Now start the NT Domain stuff :-).
2778 ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2779 if (!NT_STATUS_IS_OK(ret)) {
2780 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2781 remote_machine, nt_errstr(ret)));
2782 cli_shutdown(the_cli);
2789 /***************************************************************************
2790 Connect to the client.
2791 ****************************************************************************/
2793 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2794 uint32 localprinter, uint32 type,
2795 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2801 * If it's the first connection, contact the client
2802 * and connect to the IPC$ share anonymously
2804 if (smb_connections==0) {
2805 fstring unix_printer;
2807 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2809 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2812 messaging_register(smbd_messaging_context(), NULL,
2813 MSG_PRINTER_NOTIFY2,
2814 receive_notify2_message_list);
2815 /* Tell the connections db we're now interested in printer
2816 * notify messages. */
2817 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2821 * Tell the specific printing tdb we want messages for this printer
2822 * by registering our PID.
2825 if (!print_notify_register_pid(snum))
2826 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2830 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2838 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2839 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2840 win_errstr(result)));
2842 return (W_ERROR_IS_OK(result));
2845 /****************************************************************
2846 ****************************************************************/
2848 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2849 const struct spoolss_NotifyOption *r)
2851 struct spoolss_NotifyOption *option;
2858 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2865 if (!option->count) {
2869 option->types = talloc_zero_array(option,
2870 struct spoolss_NotifyOptionType, option->count);
2871 if (!option->types) {
2872 talloc_free(option);
2876 for (i=0; i < option->count; i++) {
2877 option->types[i] = r->types[i];
2879 if (option->types[i].count) {
2880 option->types[i].fields = talloc_zero_array(option,
2881 enum spoolss_Field, option->types[i].count);
2882 if (!option->types[i].fields) {
2883 talloc_free(option);
2886 for (k=0; k<option->types[i].count; k++) {
2887 option->types[i].fields[k] =
2888 r->types[i].fields[k];
2896 /****************************************************************
2897 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2899 * before replying OK: status=0 a rpc call is made to the workstation
2900 * asking ReplyOpenPrinter
2902 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2903 * called from api_spoolss_rffpcnex
2904 ****************************************************************/
2906 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2907 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2909 POLICY_HND *handle = r->in.handle;
2911 struct spoolss_NotifyOption *option = r->in.notify_options;
2912 struct sockaddr_storage client_ss;
2914 /* store the notify value in the printer struct */
2916 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2919 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2920 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2924 Printer->notify.flags = r->in.flags;
2925 Printer->notify.options = r->in.options;
2926 Printer->notify.printerlocal = r->in.printer_local;
2928 TALLOC_FREE(Printer->notify.option);
2929 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2931 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2933 /* Connect to the client machine and send a ReplyOpenPrinter */
2935 if ( Printer->printer_type == SPLHND_SERVER)
2937 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2938 !get_printer_snum(p, handle, &snum, NULL) )
2941 if (!interpret_string_addr(&client_ss, p->client_address,
2943 return WERR_SERVER_UNAVAILABLE;
2946 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2947 Printer->notify.printerlocal, 1,
2948 &Printer->notify.client_hnd, &client_ss))
2949 return WERR_SERVER_UNAVAILABLE;
2951 Printer->notify.client_connected=True;
2956 /*******************************************************************
2957 * fill a notify_info_data with the servername
2958 ********************************************************************/
2960 void spoolss_notify_server_name(int snum,
2961 struct spoolss_Notify *data,
2962 print_queue_struct *queue,
2963 NT_PRINTER_INFO_LEVEL *printer,
2964 TALLOC_CTX *mem_ctx)
2966 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2969 /*******************************************************************
2970 * fill a notify_info_data with the printername (not including the servername).
2971 ********************************************************************/
2973 void spoolss_notify_printer_name(int snum,
2974 struct spoolss_Notify *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2979 /* the notify name should not contain the \\server\ part */
2980 char *p = strrchr(printer->info_2->printername, '\\');
2983 p = printer->info_2->printername;
2988 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2991 /*******************************************************************
2992 * fill a notify_info_data with the servicename
2993 ********************************************************************/
2995 void spoolss_notify_share_name(int snum,
2996 struct spoolss_Notify *data,
2997 print_queue_struct *queue,
2998 NT_PRINTER_INFO_LEVEL *printer,
2999 TALLOC_CTX *mem_ctx)
3001 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
3004 /*******************************************************************
3005 * fill a notify_info_data with the port name
3006 ********************************************************************/
3008 void spoolss_notify_port_name(int snum,
3009 struct spoolss_Notify *data,
3010 print_queue_struct *queue,
3011 NT_PRINTER_INFO_LEVEL *printer,
3012 TALLOC_CTX *mem_ctx)
3014 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
3017 /*******************************************************************
3018 * fill a notify_info_data with the printername
3019 * but it doesn't exist, have to see what to do
3020 ********************************************************************/
3022 void spoolss_notify_driver_name(int snum,
3023 struct spoolss_Notify *data,
3024 print_queue_struct *queue,
3025 NT_PRINTER_INFO_LEVEL *printer,
3026 TALLOC_CTX *mem_ctx)
3028 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
3031 /*******************************************************************
3032 * fill a notify_info_data with the comment
3033 ********************************************************************/
3035 void spoolss_notify_comment(int snum,
3036 struct spoolss_Notify *data,
3037 print_queue_struct *queue,
3038 NT_PRINTER_INFO_LEVEL *printer,
3039 TALLOC_CTX *mem_ctx)
3043 if (*printer->info_2->comment == '\0') {
3044 p = lp_comment(snum);
3046 p = printer->info_2->comment;
3049 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3052 /*******************************************************************
3053 * fill a notify_info_data with the comment
3054 * location = "Room 1, floor 2, building 3"
3055 ********************************************************************/
3057 void spoolss_notify_location(int snum,
3058 struct spoolss_Notify *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3063 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3066 /*******************************************************************
3067 * fill a notify_info_data with the device mode
3068 * jfm:xxxx don't to it for know but that's a real problem !!!
3069 ********************************************************************/
3071 static void spoolss_notify_devmode(int snum,
3072 struct spoolss_Notify *data,
3073 print_queue_struct *queue,
3074 NT_PRINTER_INFO_LEVEL *printer,
3075 TALLOC_CTX *mem_ctx)
3077 /* for a dummy implementation we have to zero the fields */
3078 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3081 /*******************************************************************
3082 * fill a notify_info_data with the separator file name
3083 ********************************************************************/
3085 void spoolss_notify_sepfile(int snum,
3086 struct spoolss_Notify *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3094 /*******************************************************************
3095 * fill a notify_info_data with the print processor
3096 * jfm:xxxx return always winprint to indicate we don't do anything to it
3097 ********************************************************************/
3099 void spoolss_notify_print_processor(int snum,
3100 struct spoolss_Notify *data,
3101 print_queue_struct *queue,
3102 NT_PRINTER_INFO_LEVEL *printer,
3103 TALLOC_CTX *mem_ctx)
3105 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3108 /*******************************************************************
3109 * fill a notify_info_data with the print processor options
3110 * jfm:xxxx send an empty string
3111 ********************************************************************/
3113 void spoolss_notify_parameters(int snum,
3114 struct spoolss_Notify *data,
3115 print_queue_struct *queue,
3116 NT_PRINTER_INFO_LEVEL *printer,
3117 TALLOC_CTX *mem_ctx)
3119 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3122 /*******************************************************************
3123 * fill a notify_info_data with the data type
3124 * jfm:xxxx always send RAW as data type
3125 ********************************************************************/
3127 void spoolss_notify_datatype(int snum,
3128 struct spoolss_Notify *data,
3129 print_queue_struct *queue,
3130 NT_PRINTER_INFO_LEVEL *printer,
3131 TALLOC_CTX *mem_ctx)
3133 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3136 /*******************************************************************
3137 * fill a notify_info_data with the security descriptor
3138 * jfm:xxxx send an null pointer to say no security desc
3139 * have to implement security before !
3140 ********************************************************************/
3142 static void spoolss_notify_security_desc(int snum,
3143 struct spoolss_Notify *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3149 printer->info_2->secdesc_buf->sd_size,
3150 printer->info_2->secdesc_buf->sd);
3153 /*******************************************************************
3154 * fill a notify_info_data with the attributes
3155 * jfm:xxxx a samba printer is always shared
3156 ********************************************************************/
3158 void spoolss_notify_attributes(int snum,
3159 struct spoolss_Notify *data,
3160 print_queue_struct *queue,
3161 NT_PRINTER_INFO_LEVEL *printer,
3162 TALLOC_CTX *mem_ctx)
3164 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3167 /*******************************************************************
3168 * fill a notify_info_data with the priority
3169 ********************************************************************/
3171 static void spoolss_notify_priority(int snum,
3172 struct spoolss_Notify *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3180 /*******************************************************************
3181 * fill a notify_info_data with the default priority
3182 ********************************************************************/
3184 static void spoolss_notify_default_priority(int snum,
3185 struct spoolss_Notify *data,
3186 print_queue_struct *queue,
3187 NT_PRINTER_INFO_LEVEL *printer,
3188 TALLOC_CTX *mem_ctx)
3190 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3193 /*******************************************************************
3194 * fill a notify_info_data with the start time
3195 ********************************************************************/
3197 static void spoolss_notify_start_time(int snum,
3198 struct spoolss_Notify *data,
3199 print_queue_struct *queue,
3200 NT_PRINTER_INFO_LEVEL *printer,
3201 TALLOC_CTX *mem_ctx)
3203 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3206 /*******************************************************************
3207 * fill a notify_info_data with the until time
3208 ********************************************************************/
3210 static void spoolss_notify_until_time(int snum,
3211 struct spoolss_Notify *data,
3212 print_queue_struct *queue,
3213 NT_PRINTER_INFO_LEVEL *printer,
3214 TALLOC_CTX *mem_ctx)
3216 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3219 /*******************************************************************
3220 * fill a notify_info_data with the status
3221 ********************************************************************/
3223 static void spoolss_notify_status(int snum,
3224 struct spoolss_Notify *data,
3225 print_queue_struct *queue,
3226 NT_PRINTER_INFO_LEVEL *printer,
3227 TALLOC_CTX *mem_ctx)
3229 print_status_struct status;
3231 print_queue_length(snum, &status);
3232 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3235 /*******************************************************************
3236 * fill a notify_info_data with the number of jobs queued
3237 ********************************************************************/
3239 void spoolss_notify_cjobs(int snum,
3240 struct spoolss_Notify *data,
3241 print_queue_struct *queue,
3242 NT_PRINTER_INFO_LEVEL *printer,
3243 TALLOC_CTX *mem_ctx)
3245 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3248 /*******************************************************************
3249 * fill a notify_info_data with the average ppm
3250 ********************************************************************/
3252 static void spoolss_notify_average_ppm(int snum,
3253 struct spoolss_Notify *data,
3254 print_queue_struct *queue,
3255 NT_PRINTER_INFO_LEVEL *printer,
3256 TALLOC_CTX *mem_ctx)
3258 /* always respond 8 pages per minutes */
3259 /* a little hard ! */
3260 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3263 /*******************************************************************
3264 * fill a notify_info_data with username
3265 ********************************************************************/
3267 static void spoolss_notify_username(int snum,
3268 struct spoolss_Notify *data,
3269 print_queue_struct *queue,
3270 NT_PRINTER_INFO_LEVEL *printer,
3271 TALLOC_CTX *mem_ctx)
3273 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3276 /*******************************************************************
3277 * fill a notify_info_data with job status
3278 ********************************************************************/
3280 static void spoolss_notify_job_status(int snum,
3281 struct spoolss_Notify *data,
3282 print_queue_struct *queue,
3283 NT_PRINTER_INFO_LEVEL *printer,
3284 TALLOC_CTX *mem_ctx)
3286 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3289 /*******************************************************************
3290 * fill a notify_info_data with job name
3291 ********************************************************************/
3293 static void spoolss_notify_job_name(int snum,
3294 struct spoolss_Notify *data,
3295 print_queue_struct *queue,
3296 NT_PRINTER_INFO_LEVEL *printer,
3297 TALLOC_CTX *mem_ctx)
3299 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3302 /*******************************************************************
3303 * fill a notify_info_data with job status
3304 ********************************************************************/
3306 static void spoolss_notify_job_status_string(int snum,
3307 struct spoolss_Notify *data,
3308 print_queue_struct *queue,
3309 NT_PRINTER_INFO_LEVEL *printer,
3310 TALLOC_CTX *mem_ctx)
3313 * Now we're returning job status codes we just return a "" here. JRA.
3318 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3321 switch (queue->status) {
3326 p = ""; /* NT provides the paused string */
3335 #endif /* NO LONGER NEEDED. */
3337 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3340 /*******************************************************************
3341 * fill a notify_info_data with job time
3342 ********************************************************************/
3344 static void spoolss_notify_job_time(int snum,
3345 struct spoolss_Notify *data,
3346 print_queue_struct *queue,
3347 NT_PRINTER_INFO_LEVEL *printer,
3348 TALLOC_CTX *mem_ctx)
3350 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3353 /*******************************************************************
3354 * fill a notify_info_data with job size
3355 ********************************************************************/
3357 static void spoolss_notify_job_size(int snum,
3358 struct spoolss_Notify *data,
3359 print_queue_struct *queue,
3360 NT_PRINTER_INFO_LEVEL *printer,
3361 TALLOC_CTX *mem_ctx)
3363 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3366 /*******************************************************************
3367 * fill a notify_info_data with page info
3368 ********************************************************************/
3369 static void spoolss_notify_total_pages(int snum,
3370 struct spoolss_Notify *data,
3371 print_queue_struct *queue,
3372 NT_PRINTER_INFO_LEVEL *printer,
3373 TALLOC_CTX *mem_ctx)
3375 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3378 /*******************************************************************
3379 * fill a notify_info_data with pages printed info.
3380 ********************************************************************/
3381 static void spoolss_notify_pages_printed(int snum,
3382 struct spoolss_Notify *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer,
3385 TALLOC_CTX *mem_ctx)
3387 /* Add code when back-end tracks this */
3388 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3391 /*******************************************************************
3392 Fill a notify_info_data with job position.
3393 ********************************************************************/
3395 static void spoolss_notify_job_position(int snum,
3396 struct spoolss_Notify *data,
3397 print_queue_struct *queue,
3398 NT_PRINTER_INFO_LEVEL *printer,
3399 TALLOC_CTX *mem_ctx)
3401 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3404 /*******************************************************************
3405 Fill a notify_info_data with submitted time.
3406 ********************************************************************/
3408 static void spoolss_notify_submitted_time(int snum,
3409 struct spoolss_Notify *data,
3410 print_queue_struct *queue,
3411 NT_PRINTER_INFO_LEVEL *printer,
3412 TALLOC_CTX *mem_ctx)
3414 data->data.string.string = NULL;
3415 data->data.string.size = 0;
3417 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3418 &data->data.string.string,
3419 &data->data.string.size);
3423 struct s_notify_info_data_table
3425 enum spoolss_NotifyType type;
3426 enum spoolss_Field field;
3428 enum spoolss_NotifyTable variable_type;
3429 void (*fn) (int snum, struct spoolss_Notify *data,
3430 print_queue_struct *queue,
3431 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3434 /* A table describing the various print notification constants and
3435 whether the notification data is a pointer to a variable sized
3436 buffer, a one value uint32 or a two value uint32. */
3438 static const struct s_notify_info_data_table notify_info_data_table[] =
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3491 /*******************************************************************
3492 Return the variable_type of info_data structure.
3493 ********************************************************************/
3495 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3496 enum spoolss_Field field)
3500 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3501 if ( (notify_info_data_table[i].type == type) &&
3502 (notify_info_data_table[i].field == field) ) {
3503 return notify_info_data_table[i].variable_type;
3507 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3512 /****************************************************************************
3513 ****************************************************************************/
3515 static bool search_notify(enum spoolss_NotifyType type,
3516 enum spoolss_Field field,
3521 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3522 if (notify_info_data_table[i].type == type &&
3523 notify_info_data_table[i].field == field &&
3524 notify_info_data_table[i].fn != NULL) {
3533 /****************************************************************************
3534 ****************************************************************************/
3536 void construct_info_data(struct spoolss_Notify *info_data,
3537 enum spoolss_NotifyType type,
3538 enum spoolss_Field field,
3541 info_data->type = type;
3542 info_data->field = field;
3543 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3544 info_data->job_id = id;
3547 /*******************************************************************
3549 * fill a notify_info struct with info asked
3551 ********************************************************************/
3553 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3554 struct spoolss_NotifyInfo *info,
3556 const struct spoolss_NotifyOptionType *option_type,
3558 TALLOC_CTX *mem_ctx)
3561 enum spoolss_NotifyType type;
3562 enum spoolss_Field field;
3564 struct spoolss_Notify *current_data;
3565 NT_PRINTER_INFO_LEVEL *printer = NULL;
3566 print_queue_struct *queue=NULL;
3568 type = option_type->type;
3570 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3571 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3572 option_type->count, lp_servicename(snum)));
3574 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3577 for(field_num=0; field_num < option_type->count; field_num++) {
3578 field = option_type->fields[field_num];
3580 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3582 if (!search_notify(type, field, &j) )
3585 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3586 struct spoolss_Notify,
3588 if (info->notifies == NULL) {
3589 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3590 free_a_printer(&printer, 2);
3594 current_data = &info->notifies[info->count];
3596 construct_info_data(current_data, type, field, id);
3598 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3599 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3601 notify_info_data_table[j].fn(snum, current_data, queue,
3607 free_a_printer(&printer, 2);
3611 /*******************************************************************
3613 * fill a notify_info struct with info asked
3615 ********************************************************************/
3617 static bool construct_notify_jobs_info(print_queue_struct *queue,
3618 struct spoolss_NotifyInfo *info,
3619 NT_PRINTER_INFO_LEVEL *printer,
3621 const struct spoolss_NotifyOptionType *option_type,
3623 TALLOC_CTX *mem_ctx)
3626 enum spoolss_NotifyType type;
3627 enum spoolss_Field field;
3628 struct spoolss_Notify *current_data;
3630 DEBUG(4,("construct_notify_jobs_info\n"));
3632 type = option_type->type;
3634 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3635 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3636 option_type->count));
3638 for(field_num=0; field_num<option_type->count; field_num++) {
3639 field = option_type->fields[field_num];
3641 if (!search_notify(type, field, &j) )
3644 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3645 struct spoolss_Notify,
3647 if (info->notifies == NULL) {
3648 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3652 current_data=&(info->notifies[info->count]);
3654 construct_info_data(current_data, type, field, id);
3655 notify_info_data_table[j].fn(snum, current_data, queue,
3664 * JFM: The enumeration is not that simple, it's even non obvious.
3666 * let's take an example: I want to monitor the PRINTER SERVER for
3667 * the printer's name and the number of jobs currently queued.
3668 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3669 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3671 * I have 3 printers on the back of my server.
3673 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3676 * 1 printer 1 name 1
3677 * 2 printer 1 cjob 1
3678 * 3 printer 2 name 2
3679 * 4 printer 2 cjob 2
3680 * 5 printer 3 name 3
3681 * 6 printer 3 name 3
3683 * that's the print server case, the printer case is even worse.
3686 /*******************************************************************
3688 * enumerate all printers on the printserver
3689 * fill a notify_info struct with info asked
3691 ********************************************************************/
3693 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3694 struct spoolss_NotifyInfo *info,
3695 TALLOC_CTX *mem_ctx)
3698 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3699 int n_services=lp_numservices();
3701 struct spoolss_NotifyOption *option;
3702 struct spoolss_NotifyOptionType option_type;
3704 DEBUG(4,("printserver_notify_info\n"));
3709 option = Printer->notify.option;
3712 info->notifies = NULL;
3715 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3716 sending a ffpcn() request first */
3721 for (i=0; i<option->count; i++) {
3722 option_type = option->types[i];
3724 if (option_type.type != PRINTER_NOTIFY_TYPE)
3727 for (snum=0; snum<n_services; snum++)
3729 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3730 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3736 * Debugging information, don't delete.
3739 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3740 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3741 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3743 for (i=0; i<info->count; i++) {
3744 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3745 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3746 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3753 /*******************************************************************
3755 * fill a notify_info struct with info asked
3757 ********************************************************************/
3759 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3760 TALLOC_CTX *mem_ctx)
3763 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3766 struct spoolss_NotifyOption *option;
3767 struct spoolss_NotifyOptionType option_type;
3769 print_queue_struct *queue=NULL;
3770 print_status_struct status;
3772 DEBUG(4,("printer_notify_info\n"));
3777 option = Printer->notify.option;
3781 info->notifies = NULL;
3784 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3785 sending a ffpcn() request first */
3790 get_printer_snum(p, hnd, &snum, NULL);
3792 for (i=0; i<option->count; i++) {
3793 option_type = option->types[i];
3795 switch (option_type.type) {
3796 case PRINTER_NOTIFY_TYPE:
3797 if(construct_notify_printer_info(Printer, info, snum,
3803 case JOB_NOTIFY_TYPE: {
3804 NT_PRINTER_INFO_LEVEL *printer = NULL;
3806 count = print_queue_status(snum, &queue, &status);
3808 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3811 for (j=0; j<count; j++) {
3812 construct_notify_jobs_info(&queue[j], info,
3819 free_a_printer(&printer, 2);
3829 * Debugging information, don't delete.
3832 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3833 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3834 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3836 for (i=0; i<info->count; i++) {
3837 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3838 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3839 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3845 /****************************************************************
3846 _spoolss_RouterRefreshPrinterChangeNotify
3847 ****************************************************************/
3849 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3850 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3852 POLICY_HND *handle = r->in.handle;
3853 struct spoolss_NotifyInfo *info;
3855 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3856 WERROR result = WERR_BADFID;
3858 /* we always have a spoolss_NotifyInfo struct */
3859 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3861 result = WERR_NOMEM;
3865 *r->out.info = info;
3868 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3869 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3873 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3876 * We are now using the change value, and
3877 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3878 * I don't have a global notification system, I'm sending back all the
3879 * informations even when _NOTHING_ has changed.
3882 /* We need to keep track of the change value to send back in
3883 RRPCN replies otherwise our updates are ignored. */
3885 Printer->notify.fnpcn = True;
3887 if (Printer->notify.client_connected) {
3888 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3889 "Saving change value in request [%x]\n",
3891 Printer->notify.change = r->in.change_low;
3894 /* just ignore the spoolss_NotifyOption */
3896 switch (Printer->printer_type) {
3898 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3901 case SPLHND_PRINTER:
3902 result = printer_notify_info(p, handle, info, p->mem_ctx);
3906 Printer->notify.fnpcn = False;
3912 /********************************************************************
3913 * construct_printer_info_0
3914 * fill a printer_info_0 struct
3915 ********************************************************************/
3917 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3919 char *chaine = NULL;
3921 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3922 counter_printer_0 *session_counter;
3923 uint32 global_counter;
3926 print_status_struct status;
3927 TALLOC_CTX *ctx = talloc_tos();
3929 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3932 init_unistr(&printer->printername, ntprinter->info_2->printername);
3934 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3936 free_a_printer(&ntprinter,2);
3940 count = print_queue_length(snum, &status);
3942 /* check if we already have a counter for this printer */
3943 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3944 if (session_counter->snum == snum)
3948 init_unistr(&printer->servername, chaine);
3950 /* it's the first time, add it to the list */
3951 if (session_counter==NULL) {
3952 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3953 free_a_printer(&ntprinter, 2);
3956 ZERO_STRUCTP(session_counter);
3957 session_counter->snum=snum;
3958 session_counter->counter=0;
3959 DLIST_ADD(counter_list, session_counter);
3963 session_counter->counter++;
3966 * the global_counter should be stored in a TDB as it's common to all the clients
3967 * and should be zeroed on samba startup
3969 global_counter=session_counter->counter;
3970 printer->cjobs = count;
3971 printer->total_jobs = 0;
3972 printer->total_bytes = 0;
3974 setuptime = (time_t)ntprinter->info_2->setuptime;
3975 t=gmtime(&setuptime);
3977 printer->year = t->tm_year+1900;
3978 printer->month = t->tm_mon+1;
3979 printer->dayofweek = t->tm_wday;
3980 printer->day = t->tm_mday;
3981 printer->hour = t->tm_hour;
3982 printer->minute = t->tm_min;
3983 printer->second = t->tm_sec;
3984 printer->milliseconds = 0;
3986 printer->global_counter = global_counter;
3987 printer->total_pages = 0;
3989 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3990 printer->major_version = 0x0005; /* NT 5 */
3991 printer->build_version = 0x0893; /* build 2195 */
3993 printer->unknown7 = 0x1;
3994 printer->unknown8 = 0x0;
3995 printer->unknown9 = 0x0;
3996 printer->session_counter = session_counter->counter;
3997 printer->unknown11 = 0x0;
3998 printer->printer_errors = 0x0; /* number of print failure */
3999 printer->unknown13 = 0x0;
4000 printer->unknown14 = 0x1;
4001 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4002 printer->unknown16 = 0x0;
4003 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4004 printer->unknown18 = 0x0;
4005 printer->status = nt_printq_status(status.status);
4006 printer->unknown20 = 0x0;
4007 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4008 printer->unknown22 = 0x0;
4009 printer->unknown23 = 0x6; /* 6 ???*/
4010 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4011 printer->unknown25 = 0;
4012 printer->unknown26 = 0;
4013 printer->unknown27 = 0;
4014 printer->unknown28 = 0;
4015 printer->unknown29 = 0;
4017 free_a_printer(&ntprinter,2);
4021 /********************************************************************
4022 * construct_printer_info_1
4023 * fill a printer_info_1 struct
4024 ********************************************************************/
4025 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4027 char *chaine = NULL;
4028 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4029 TALLOC_CTX *ctx = talloc_tos();
4031 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4034 printer->flags=flags;
4036 if (*ntprinter->info_2->comment == '\0') {
4037 init_unistr(&printer->comment, lp_comment(snum));
4038 chaine = talloc_asprintf(ctx,
4039 "%s,%s,%s", ntprinter->info_2->printername,
4040 ntprinter->info_2->drivername, lp_comment(snum));
4043 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4044 chaine = talloc_asprintf(ctx,
4045 "%s,%s,%s", ntprinter->info_2->printername,
4046 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4050 free_a_printer(&ntprinter,2);
4054 init_unistr(&printer->description, chaine);
4055 init_unistr(&printer->name, ntprinter->info_2->printername);
4057 free_a_printer(&ntprinter,2);
4062 /****************************************************************************
4063 Free a DEVMODE struct.
4064 ****************************************************************************/
4066 static void free_dev_mode(DEVICEMODE *dev)
4071 SAFE_FREE(dev->dev_private);
4076 /****************************************************************************
4077 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4078 should be valid upon entry
4079 ****************************************************************************/
4081 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4083 if ( !devmode || !ntdevmode )
4086 init_unistr(&devmode->devicename, ntdevmode->devicename);
4088 init_unistr(&devmode->formname, ntdevmode->formname);
4090 devmode->specversion = ntdevmode->specversion;
4091 devmode->driverversion = ntdevmode->driverversion;
4092 devmode->size = ntdevmode->size;
4093 devmode->driverextra = ntdevmode->driverextra;
4094 devmode->fields = ntdevmode->fields;
4096 devmode->orientation = ntdevmode->orientation;
4097 devmode->papersize = ntdevmode->papersize;
4098 devmode->paperlength = ntdevmode->paperlength;
4099 devmode->paperwidth = ntdevmode->paperwidth;
4100 devmode->scale = ntdevmode->scale;
4101 devmode->copies = ntdevmode->copies;
4102 devmode->defaultsource = ntdevmode->defaultsource;
4103 devmode->printquality = ntdevmode->printquality;
4104 devmode->color = ntdevmode->color;
4105 devmode->duplex = ntdevmode->duplex;
4106 devmode->yresolution = ntdevmode->yresolution;
4107 devmode->ttoption = ntdevmode->ttoption;
4108 devmode->collate = ntdevmode->collate;
4109 devmode->icmmethod = ntdevmode->icmmethod;
4110 devmode->icmintent = ntdevmode->icmintent;
4111 devmode->mediatype = ntdevmode->mediatype;
4112 devmode->dithertype = ntdevmode->dithertype;
4114 if (ntdevmode->nt_dev_private != NULL) {
4115 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4122 /****************************************************************************
4123 Create a DEVMODE struct. Returns malloced memory.
4124 ****************************************************************************/
4126 DEVICEMODE *construct_dev_mode(const char *servicename)
4128 NT_PRINTER_INFO_LEVEL *printer = NULL;
4129 DEVICEMODE *devmode = NULL;
4131 DEBUG(7,("construct_dev_mode\n"));
4133 DEBUGADD(8,("getting printer characteristics\n"));
4135 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4138 if ( !printer->info_2->devmode ) {
4139 DEBUG(5, ("BONG! There was no device mode!\n"));
4143 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4144 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4148 ZERO_STRUCTP(devmode);
4150 DEBUGADD(8,("loading DEVICEMODE\n"));
4152 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4153 free_dev_mode( devmode );
4158 free_a_printer(&printer,2);
4163 /********************************************************************
4164 * construct_printer_info_2
4165 * fill a printer_info_2 struct
4166 ********************************************************************/
4168 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4171 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4173 print_status_struct status;
4175 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4178 count = print_queue_length(snum, &status);
4180 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4181 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4182 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4183 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4184 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4186 if (*ntprinter->info_2->comment == '\0')
4187 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4189 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4191 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4192 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4193 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4194 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4195 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4197 printer->attributes = ntprinter->info_2->attributes;
4199 printer->priority = ntprinter->info_2->priority; /* priority */
4200 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4201 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4202 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4203 printer->status = nt_printq_status(status.status); /* status */
4204 printer->cjobs = count; /* jobs */
4205 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4207 if ( !(printer->devmode = construct_dev_mode(
4208 lp_const_servicename(snum))) )
4209 DEBUG(8, ("Returning NULL Devicemode!\n"));
4211 printer->secdesc = NULL;
4213 if ( ntprinter->info_2->secdesc_buf
4214 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4216 /* don't use talloc_steal() here unless you do a deep steal of all
4217 the SEC_DESC members */
4219 printer->secdesc = dup_sec_desc( talloc_tos(),
4220 ntprinter->info_2->secdesc_buf->sd );
4223 free_a_printer(&ntprinter, 2);
4228 /********************************************************************
4229 * construct_printer_info_3
4230 * fill a printer_info_3 struct
4231 ********************************************************************/
4233 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4235 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4236 PRINTER_INFO_3 *printer = NULL;
4238 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4242 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4243 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4244 free_a_printer(&ntprinter, 2);
4248 ZERO_STRUCTP(printer);
4250 /* These are the components of the SD we are returning. */
4252 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4253 /* don't use talloc_steal() here unless you do a deep steal of all
4254 the SEC_DESC members */
4256 printer->secdesc = dup_sec_desc( talloc_tos(),
4257 ntprinter->info_2->secdesc_buf->sd );
4260 free_a_printer(&ntprinter, 2);
4262 *pp_printer = printer;
4266 /********************************************************************
4267 * construct_printer_info_4
4268 * fill a printer_info_4 struct
4269 ********************************************************************/
4271 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4273 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4275 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4278 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4279 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4280 printer->attributes = ntprinter->info_2->attributes;
4282 free_a_printer(&ntprinter, 2);
4286 /********************************************************************
4287 * construct_printer_info_5
4288 * fill a printer_info_5 struct
4289 ********************************************************************/
4291 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4293 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4295 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4298 init_unistr(&printer->printername, ntprinter->info_2->printername);
4299 init_unistr(&printer->portname, ntprinter->info_2->portname);
4300 printer->attributes = ntprinter->info_2->attributes;
4302 /* these two are not used by NT+ according to MSDN */
4304 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4305 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4307 free_a_printer(&ntprinter, 2);
4312 /********************************************************************
4313 * construct_printer_info_6
4314 * fill a printer_info_6 struct
4315 ********************************************************************/
4317 static bool construct_printer_info_6(Printer_entry *print_hnd,
4318 PRINTER_INFO_6 *printer,
4321 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4323 print_status_struct status;
4325 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4326 lp_const_servicename(snum))))
4329 count = print_queue_length(snum, &status);
4331 printer->status = nt_printq_status(status.status);
4333 free_a_printer(&ntprinter, 2);
4338 /********************************************************************
4339 * construct_printer_info_7
4340 * fill a printer_info_7 struct
4341 ********************************************************************/
4343 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4345 char *guid_str = NULL;
4348 if (is_printer_published(print_hnd, snum, &guid)) {
4349 if (asprintf(&guid_str, "{%s}",
4350 GUID_string(talloc_tos(), &guid)) == -1) {
4353 strupper_m(guid_str);
4354 init_unistr(&printer->guid, guid_str);
4355 SAFE_FREE(guid_str);
4356 printer->action = DSPRINT_PUBLISH;
4358 init_unistr(&printer->guid, "");
4359 printer->action = DSPRINT_UNPUBLISH;
4365 /********************************************************************
4366 Spoolss_enumprinters.
4367 ********************************************************************/
4369 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4373 int n_services=lp_numservices();
4374 PRINTER_INFO_1 *printers=NULL;
4375 PRINTER_INFO_1 current_prt;
4376 WERROR result = WERR_OK;
4378 DEBUG(4,("enum_all_printers_info_1\n"));
4380 for (snum=0; snum<n_services; snum++) {
4381 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4382 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4384 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4385 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4386 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4390 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4392 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4398 /* check the required size. */
4399 for (i=0; i<*returned; i++)
4400 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4402 if (*needed > offered) {
4403 result = WERR_INSUFFICIENT_BUFFER;
4407 if (!rpcbuf_alloc_size(buffer, *needed)) {
4408 result = WERR_NOMEM;
4412 /* fill the buffer with the structures */
4413 for (i=0; i<*returned; i++)
4414 smb_io_printer_info_1("", buffer, &printers[i], 0);
4419 SAFE_FREE(printers);
4421 if ( !W_ERROR_IS_OK(result) )
4427 /********************************************************************
4428 enum_all_printers_info_1_local.
4429 *********************************************************************/
4431 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4433 DEBUG(4,("enum_all_printers_info_1_local\n"));
4435 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4438 /********************************************************************
4439 enum_all_printers_info_1_name.
4440 *********************************************************************/
4442 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4446 DEBUG(4,("enum_all_printers_info_1_name\n"));
4448 if ((name[0] == '\\') && (name[1] == '\\'))
4451 if (is_myname_or_ipaddr(s)) {
4452 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4455 return WERR_INVALID_NAME;
4458 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4459 /********************************************************************
4460 enum_all_printers_info_1_remote.
4461 *********************************************************************/
4463 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4465 PRINTER_INFO_1 *printer;
4466 fstring printername;
4469 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4470 WERROR result = WERR_OK;
4472 /* JFM: currently it's more a place holder than anything else.
4473 * In the spooler world there is a notion of server registration.
4474 * the print servers are registered on the PDC (in the same domain)
4476 * We should have a TDB here. The registration is done thru an
4477 * undocumented RPC call.
4480 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4485 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4486 slprintf(desc, sizeof(desc)-1,"%s", name);
4487 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4489 init_unistr(&printer->description, desc);
4490 init_unistr(&printer->name, printername);
4491 init_unistr(&printer->comment, comment);
4492 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4494 /* check the required size. */
4495 *needed += spoolss_size_printer_info_1(printer);
4497 if (*needed > offered) {
4498 result = WERR_INSUFFICIENT_BUFFER;
4502 if (!rpcbuf_alloc_size(buffer, *needed)) {
4503 result = WERR_NOMEM;
4507 /* fill the buffer with the structures */
4508 smb_io_printer_info_1("", buffer, printer, 0);
4514 if ( !W_ERROR_IS_OK(result) )
4522 /********************************************************************
4523 enum_all_printers_info_1_network.
4524 *********************************************************************/
4526 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4530 DEBUG(4,("enum_all_printers_info_1_network\n"));
4532 /* If we respond to a enum_printers level 1 on our name with flags
4533 set to PRINTER_ENUM_REMOTE with a list of printers then these
4534 printers incorrectly appear in the APW browse list.
4535 Specifically the printers for the server appear at the workgroup
4536 level where all the other servers in the domain are
4537 listed. Windows responds to this call with a
4538 WERR_CAN_NOT_COMPLETE so we should do the same. */
4540 if (name[0] == '\\' && name[1] == '\\')
4543 if (is_myname_or_ipaddr(s))
4544 return WERR_CAN_NOT_COMPLETE;
4546 return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4549 /********************************************************************
4550 * api_spoolss_enumprinters
4552 * called from api_spoolss_enumprinters (see this to understand)
4553 ********************************************************************/
4555 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4559 int n_services=lp_numservices();
4560 PRINTER_INFO_2 *printers=NULL;
4561 PRINTER_INFO_2 current_prt;
4562 WERROR result = WERR_OK;
4566 for (snum=0; snum<n_services; snum++) {
4567 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4568 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4570 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4571 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4572 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4577 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4579 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4586 /* check the required size. */
4587 for (i=0; i<*returned; i++)
4588 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4590 if (*needed > offered) {
4591 result = WERR_INSUFFICIENT_BUFFER;
4595 if (!rpcbuf_alloc_size(buffer, *needed)) {
4596 result = WERR_NOMEM;
4600 /* fill the buffer with the structures */
4601 for (i=0; i<*returned; i++)
4602 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4607 for (i=0; i<*returned; i++)
4608 free_devmode(printers[i].devmode);
4610 SAFE_FREE(printers);
4612 if ( !W_ERROR_IS_OK(result) )
4618 /********************************************************************
4619 * handle enumeration of printers at level 1
4620 ********************************************************************/
4622 static WERROR enumprinters_level1( uint32 flags, fstring name,
4623 RPC_BUFFER *buffer, uint32 offered,
4624 uint32 *needed, uint32 *returned)
4626 /* Not all the flags are equals */
4628 if (flags & PRINTER_ENUM_LOCAL)
4629 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4631 if (flags & PRINTER_ENUM_NAME)
4632 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4634 #if 0 /* JERRY - disabled for now */
4635 if (flags & PRINTER_ENUM_REMOTE)
4636 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4639 if (flags & PRINTER_ENUM_NETWORK)
4640 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4642 return WERR_OK; /* NT4sp5 does that */
4645 /********************************************************************
4646 * handle enumeration of printers at level 2
4647 ********************************************************************/
4649 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4650 RPC_BUFFER *buffer, uint32 offered,
4651 uint32 *needed, uint32 *returned)
4653 if (flags & PRINTER_ENUM_LOCAL) {
4654 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 if (flags & PRINTER_ENUM_NAME) {
4658 if (is_myname_or_ipaddr(canon_servername(servername)))
4659 return enum_all_printers_info_2(buffer, offered, needed, returned);
4661 return WERR_INVALID_NAME;
4664 if (flags & PRINTER_ENUM_REMOTE)
4665 return WERR_UNKNOWN_LEVEL;
4670 /********************************************************************
4671 * handle enumeration of printers at level 5
4672 ********************************************************************/
4674 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4675 RPC_BUFFER *buffer, uint32 offered,
4676 uint32 *needed, uint32 *returned)
4678 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4682 /********************************************************************
4683 * api_spoolss_enumprinters
4685 * called from api_spoolss_enumprinters (see this to understand)
4686 ********************************************************************/
4688 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4690 uint32 flags = q_u->flags;
4691 UNISTR2 *servername = &q_u->servername;
4692 uint32 level = q_u->level;
4693 RPC_BUFFER *buffer = NULL;
4694 uint32 offered = q_u->offered;
4695 uint32 *needed = &r_u->needed;
4696 uint32 *returned = &r_u->returned;
4700 /* that's an [in out] buffer */
4702 if (!q_u->buffer && (offered!=0)) {
4703 return WERR_INVALID_PARAM;
4706 if (offered > MAX_RPC_DATA_SIZE) {
4707 return WERR_INVALID_PARAM;
4710 rpcbuf_move(q_u->buffer, &r_u->buffer);
4711 buffer = r_u->buffer;
4713 DEBUG(4,("_spoolss_enumprinters\n"));
4720 * flags==PRINTER_ENUM_NAME
4721 * if name=="" then enumerates all printers
4722 * if name!="" then enumerate the printer
4723 * flags==PRINTER_ENUM_REMOTE
4724 * name is NULL, enumerate printers
4725 * Level 2: name!="" enumerates printers, name can't be NULL
4726 * Level 3: doesn't exist
4727 * Level 4: does a local registry lookup
4728 * Level 5: same as Level 2
4731 unistr2_to_ascii(name, servername, sizeof(name));
4736 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4738 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4740 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4745 return WERR_UNKNOWN_LEVEL;
4748 /****************************************************************************
4749 ****************************************************************************/
4751 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4753 PRINTER_INFO_0 *printer=NULL;
4754 WERROR result = WERR_OK;
4756 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4759 construct_printer_info_0(print_hnd, printer, snum);
4761 /* check the required size. */
4762 *needed += spoolss_size_printer_info_0(printer);
4764 if (*needed > offered) {
4765 result = WERR_INSUFFICIENT_BUFFER;
4769 if (!rpcbuf_alloc_size(buffer, *needed)) {
4770 result = WERR_NOMEM;
4774 /* fill the buffer with the structures */
4775 smb_io_printer_info_0("", buffer, printer, 0);
4785 /****************************************************************************
4786 ****************************************************************************/
4788 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4790 PRINTER_INFO_1 *printer=NULL;
4791 WERROR result = WERR_OK;
4793 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4796 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4798 /* check the required size. */
4799 *needed += spoolss_size_printer_info_1(printer);
4801 if (*needed > offered) {
4802 result = WERR_INSUFFICIENT_BUFFER;
4806 if (!rpcbuf_alloc_size(buffer, *needed)) {
4807 result = WERR_NOMEM;
4811 /* fill the buffer with the structures */
4812 smb_io_printer_info_1("", buffer, printer, 0);
4821 /****************************************************************************
4822 ****************************************************************************/
4824 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4826 PRINTER_INFO_2 *printer=NULL;
4827 WERROR result = WERR_OK;
4829 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4832 construct_printer_info_2(print_hnd, printer, snum);
4834 /* check the required size. */
4835 *needed += spoolss_size_printer_info_2(printer);
4837 if (*needed > offered) {
4838 result = WERR_INSUFFICIENT_BUFFER;
4842 if (!rpcbuf_alloc_size(buffer, *needed)) {
4843 result = WERR_NOMEM;
4847 /* fill the buffer with the structures */
4848 if (!smb_io_printer_info_2("", buffer, printer, 0))
4849 result = WERR_NOMEM;
4853 free_printer_info_2(printer);
4858 /****************************************************************************
4859 ****************************************************************************/
4861 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4863 PRINTER_INFO_3 *printer=NULL;
4864 WERROR result = WERR_OK;
4866 if (!construct_printer_info_3(print_hnd, &printer, snum))
4869 /* check the required size. */
4870 *needed += spoolss_size_printer_info_3(printer);
4872 if (*needed > offered) {
4873 result = WERR_INSUFFICIENT_BUFFER;
4877 if (!rpcbuf_alloc_size(buffer, *needed)) {
4878 result = WERR_NOMEM;
4882 /* fill the buffer with the structures */
4883 smb_io_printer_info_3("", buffer, printer, 0);
4887 free_printer_info_3(printer);
4892 /****************************************************************************
4893 ****************************************************************************/
4895 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4897 PRINTER_INFO_4 *printer=NULL;
4898 WERROR result = WERR_OK;
4900 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4903 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4908 /* check the required size. */
4909 *needed += spoolss_size_printer_info_4(printer);
4911 if (*needed > offered) {
4912 result = WERR_INSUFFICIENT_BUFFER;
4916 if (!rpcbuf_alloc_size(buffer, *needed)) {
4917 result = WERR_NOMEM;
4921 /* fill the buffer with the structures */
4922 smb_io_printer_info_4("", buffer, printer, 0);
4926 free_printer_info_4(printer);
4931 /****************************************************************************
4932 ****************************************************************************/
4934 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4936 PRINTER_INFO_5 *printer=NULL;
4937 WERROR result = WERR_OK;
4939 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4942 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4943 free_printer_info_5(printer);
4947 /* check the required size. */
4948 *needed += spoolss_size_printer_info_5(printer);
4950 if (*needed > offered) {
4951 result = WERR_INSUFFICIENT_BUFFER;
4955 if (!rpcbuf_alloc_size(buffer, *needed)) {
4956 result = WERR_NOMEM;
4960 /* fill the buffer with the structures */
4961 smb_io_printer_info_5("", buffer, printer, 0);
4965 free_printer_info_5(printer);
4970 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4972 RPC_BUFFER *buffer, uint32 offered,
4975 PRINTER_INFO_6 *printer;
4976 WERROR result = WERR_OK;
4978 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4982 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4983 free_printer_info_6(printer);
4987 /* check the required size. */
4988 *needed += spoolss_size_printer_info_6(printer);
4990 if (*needed > offered) {
4991 result = WERR_INSUFFICIENT_BUFFER;
4995 if (!rpcbuf_alloc_size(buffer, *needed)) {
4996 result = WERR_NOMEM;
5000 /* fill the buffer with the structures */
5001 smb_io_printer_info_6("", buffer, printer, 0);
5005 free_printer_info_6(printer);
5010 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5012 PRINTER_INFO_7 *printer=NULL;
5013 WERROR result = WERR_OK;
5015 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5018 if (!construct_printer_info_7(print_hnd, printer, snum)) {
5019 result = WERR_NOMEM;
5023 /* check the required size. */
5024 *needed += spoolss_size_printer_info_7(printer);
5026 if (*needed > offered) {
5027 result = WERR_INSUFFICIENT_BUFFER;
5031 if (!rpcbuf_alloc_size(buffer, *needed)) {
5032 result = WERR_NOMEM;
5037 /* fill the buffer with the structures */
5038 smb_io_printer_info_7("", buffer, printer, 0);
5042 free_printer_info_7(printer);
5047 /****************************************************************************
5048 ****************************************************************************/
5050 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5052 POLICY_HND *handle = &q_u->handle;
5053 uint32 level = q_u->level;
5054 RPC_BUFFER *buffer = NULL;
5055 uint32 offered = q_u->offered;
5056 uint32 *needed = &r_u->needed;
5057 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5061 /* that's an [in out] buffer */
5063 if (!q_u->buffer && (offered!=0)) {
5064 return WERR_INVALID_PARAM;
5067 if (offered > MAX_RPC_DATA_SIZE) {
5068 return WERR_INVALID_PARAM;
5071 rpcbuf_move(q_u->buffer, &r_u->buffer);
5072 buffer = r_u->buffer;
5076 if (!get_printer_snum(p, handle, &snum, NULL))
5081 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5083 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5085 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5087 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5089 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5091 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5093 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5095 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5097 return WERR_UNKNOWN_LEVEL;
5100 /********************************************************************
5101 * fill a DRIVER_INFO_1 struct
5102 ********************************************************************/
5104 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5106 init_unistr( &info->name, driver.info_3->name);
5109 /********************************************************************
5110 * construct_printer_driver_info_1
5111 ********************************************************************/
5113 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5115 NT_PRINTER_INFO_LEVEL *printer = NULL;
5116 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5118 ZERO_STRUCT(driver);
5120 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5121 return WERR_INVALID_PRINTER_NAME;
5123 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5124 free_a_printer(&printer, 2);
5125 return WERR_UNKNOWN_PRINTER_DRIVER;
5128 fill_printer_driver_info_1(info, driver, servername, architecture);
5130 free_a_printer(&printer,2);
5135 /********************************************************************
5136 * construct_printer_driver_info_2
5137 * fill a printer_info_2 struct
5138 ********************************************************************/
5140 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5142 TALLOC_CTX *ctx = talloc_tos();
5144 const char *cservername = canon_servername(servername);
5146 info->version=driver.info_3->cversion;
5148 init_unistr( &info->name, driver.info_3->name );
5149 init_unistr( &info->architecture, driver.info_3->environment );
5151 if (strlen(driver.info_3->driverpath)) {
5152 temp = talloc_asprintf(ctx,
5155 driver.info_3->driverpath);
5156 init_unistr( &info->driverpath, temp );
5158 init_unistr( &info->driverpath, "" );
5162 if (strlen(driver.info_3->datafile)) {
5163 temp = talloc_asprintf(ctx,
5166 driver.info_3->datafile);
5167 init_unistr( &info->datafile, temp );
5169 init_unistr( &info->datafile, "" );
5172 if (strlen(driver.info_3->configfile)) {
5173 temp = talloc_asprintf(ctx,
5176 driver.info_3->configfile);
5177 init_unistr( &info->configfile, temp );
5179 init_unistr( &info->configfile, "" );
5182 /********************************************************************
5183 * construct_printer_driver_info_2
5184 * fill a printer_info_2 struct
5185 ********************************************************************/
5187 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5189 NT_PRINTER_INFO_LEVEL *printer = NULL;
5190 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5192 ZERO_STRUCT(printer);
5193 ZERO_STRUCT(driver);
5195 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5196 return WERR_INVALID_PRINTER_NAME;
5198 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5199 free_a_printer(&printer, 2);
5200 return WERR_UNKNOWN_PRINTER_DRIVER;
5203 fill_printer_driver_info_2(info, driver, servername);
5205 free_a_printer(&printer,2);
5210 /********************************************************************
5211 * copy a strings array and convert to UNICODE
5213 * convert an array of ascii string to a UNICODE string
5214 ********************************************************************/
5216 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5222 TALLOC_CTX *ctx = talloc_tos();
5224 DEBUG(6,("init_unistr_array\n"));
5228 if ( !char_array ) {
5233 v = ""; /* hack to handle null lists */
5236 /* hack to allow this to be used in places other than when generating
5237 the list of dependent files */
5241 line = talloc_asprintf(ctx,
5243 canon_servername(servername),
5246 line = talloc_strdup(ctx, v);
5250 SAFE_FREE(*uni_array);
5253 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5255 /* add one extra unit16 for the second terminating NULL */
5257 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5258 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5265 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5270 /* special case for ""; we need to add both NULL's here */
5272 (*uni_array)[j++]=0x0000;
5273 (*uni_array)[j]=0x0000;
5276 DEBUGADD(6,("last one:done\n"));
5278 /* return size of array in uint16's */
5283 /********************************************************************
5284 * construct_printer_info_3
5285 * fill a printer_info_3 struct
5286 ********************************************************************/
5288 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5291 TALLOC_CTX *ctx = talloc_tos();
5292 const char *cservername = canon_servername(servername);
5296 info->version=driver.info_3->cversion;
5298 init_unistr( &info->name, driver.info_3->name );
5299 init_unistr( &info->architecture, driver.info_3->environment );
5301 if (strlen(driver.info_3->driverpath)) {
5302 temp = talloc_asprintf(ctx,
5305 driver.info_3->driverpath);
5306 init_unistr( &info->driverpath, temp );
5308 init_unistr( &info->driverpath, "" );
5311 if (strlen(driver.info_3->datafile)) {
5312 temp = talloc_asprintf(ctx,
5315 driver.info_3->datafile);
5316 init_unistr( &info->datafile, temp );
5318 init_unistr( &info->datafile, "" );
5321 if (strlen(driver.info_3->configfile)) {
5322 temp = talloc_asprintf(ctx,
5325 driver.info_3->configfile);
5326 init_unistr( &info->configfile, temp );
5328 init_unistr( &info->configfile, "" );
5331 if (strlen(driver.info_3->helpfile)) {
5332 temp = talloc_asprintf(ctx,
5335 driver.info_3->helpfile);
5336 init_unistr( &info->helpfile, temp );
5338 init_unistr( &info->helpfile, "" );
5341 init_unistr( &info->monitorname, driver.info_3->monitorname );
5342 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5344 info->dependentfiles=NULL;
5345 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5348 /********************************************************************
5349 * construct_printer_info_3
5350 * fill a printer_info_3 struct
5351 ********************************************************************/
5353 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5355 NT_PRINTER_INFO_LEVEL *printer = NULL;
5356 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5358 ZERO_STRUCT(driver);
5360 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5361 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5362 if (!W_ERROR_IS_OK(status))
5363 return WERR_INVALID_PRINTER_NAME;
5365 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5366 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5371 * I put this code in during testing. Helpful when commenting out the
5372 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5373 * as win2k always queries the driver using an infor level of 6.
5374 * I've left it in (but ifdef'd out) because I'll probably
5375 * use it in experimentation again in the future. --jerry 22/01/2002
5378 if (!W_ERROR_IS_OK(status)) {
5380 * Is this a W2k client ?
5383 /* Yes - try again with a WinNT driver. */
5385 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5386 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5390 if (!W_ERROR_IS_OK(status)) {
5391 free_a_printer(&printer,2);
5392 return WERR_UNKNOWN_PRINTER_DRIVER;
5400 fill_printer_driver_info_3(info, driver, servername);
5402 free_a_printer(&printer,2);
5407 /********************************************************************
5408 * construct_printer_info_6
5409 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5410 ********************************************************************/
5412 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5416 TALLOC_CTX *ctx = talloc_tos();
5417 const char *cservername = canon_servername(servername);
5420 memset(&nullstr, '\0', sizeof(fstring));
5422 info->version=driver.info_3->cversion;
5424 init_unistr( &info->name, driver.info_3->name );
5425 init_unistr( &info->architecture, driver.info_3->environment );
5427 if (strlen(driver.info_3->driverpath)) {
5428 temp = talloc_asprintf(ctx,
5431 driver.info_3->driverpath);
5432 init_unistr( &info->driverpath, temp );
5434 init_unistr( &info->driverpath, "" );
5437 if (strlen(driver.info_3->datafile)) {
5438 temp = talloc_asprintf(ctx,
5441 driver.info_3->datafile);
5442 init_unistr( &info->datafile, temp );
5444 init_unistr( &info->datafile, "" );
5447 if (strlen(driver.info_3->configfile)) {
5448 temp = talloc_asprintf(ctx,
5451 driver.info_3->configfile);
5452 init_unistr( &info->configfile, temp );
5454 init_unistr( &info->configfile, "" );
5457 if (strlen(driver.info_3->helpfile)) {
5458 temp = talloc_asprintf(ctx,
5461 driver.info_3->helpfile);
5462 init_unistr( &info->helpfile, temp );
5464 init_unistr( &info->helpfile, "" );
5467 init_unistr( &info->monitorname, driver.info_3->monitorname );
5468 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5470 info->dependentfiles = NULL;
5471 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5473 info->previousdrivernames=NULL;
5474 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5476 info->driver_date=0;
5479 info->driver_version_low=0;
5480 info->driver_version_high=0;
5482 init_unistr( &info->mfgname, "");
5483 init_unistr( &info->oem_url, "");
5484 init_unistr( &info->hardware_id, "");
5485 init_unistr( &info->provider, "");
5488 /********************************************************************
5489 * construct_printer_info_6
5490 * fill a printer_info_6 struct
5491 ********************************************************************/
5493 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5494 const char *servername, fstring architecture, uint32 version)
5496 NT_PRINTER_INFO_LEVEL *printer = NULL;
5497 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5500 ZERO_STRUCT(driver);
5502 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5504 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5506 if (!W_ERROR_IS_OK(status))
5507 return WERR_INVALID_PRINTER_NAME;
5509 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5511 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5513 if (!W_ERROR_IS_OK(status))
5516 * Is this a W2k client ?
5520 free_a_printer(&printer,2);
5521 return WERR_UNKNOWN_PRINTER_DRIVER;
5524 /* Yes - try again with a WinNT driver. */
5526 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5527 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5528 if (!W_ERROR_IS_OK(status)) {
5529 free_a_printer(&printer,2);
5530 return WERR_UNKNOWN_PRINTER_DRIVER;
5534 fill_printer_driver_info_6(info, driver, servername);
5536 free_a_printer(&printer,2);
5537 free_a_printer_driver(driver, 3);
5542 /****************************************************************************
5543 ****************************************************************************/
5545 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5547 SAFE_FREE(info->dependentfiles);
5550 /****************************************************************************
5551 ****************************************************************************/
5553 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5555 SAFE_FREE(info->dependentfiles);
5558 /****************************************************************************
5559 ****************************************************************************/
5561 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5563 DRIVER_INFO_1 *info=NULL;
5566 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5569 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5570 if (!W_ERROR_IS_OK(result))
5573 /* check the required size. */
5574 *needed += spoolss_size_printer_driver_info_1(info);
5576 if (*needed > offered) {
5577 result = WERR_INSUFFICIENT_BUFFER;
5581 if (!rpcbuf_alloc_size(buffer, *needed)) {
5582 result = WERR_NOMEM;
5586 /* fill the buffer with the structures */
5587 smb_io_printer_driver_info_1("", buffer, info, 0);
5596 /****************************************************************************
5597 ****************************************************************************/
5599 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5601 DRIVER_INFO_2 *info=NULL;
5604 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5607 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5608 if (!W_ERROR_IS_OK(result))
5611 /* check the required size. */
5612 *needed += spoolss_size_printer_driver_info_2(info);
5614 if (*needed > offered) {
5615 result = WERR_INSUFFICIENT_BUFFER;
5619 if (!rpcbuf_alloc_size(buffer, *needed)) {
5620 result = WERR_NOMEM;
5624 /* fill the buffer with the structures */
5625 smb_io_printer_driver_info_2("", buffer, info, 0);
5634 /****************************************************************************
5635 ****************************************************************************/
5637 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5644 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5645 if (!W_ERROR_IS_OK(result))
5648 /* check the required size. */
5649 *needed += spoolss_size_printer_driver_info_3(&info);
5651 if (*needed > offered) {
5652 result = WERR_INSUFFICIENT_BUFFER;
5656 if (!rpcbuf_alloc_size(buffer, *needed)) {
5657 result = WERR_NOMEM;
5661 /* fill the buffer with the structures */
5662 smb_io_printer_driver_info_3("", buffer, &info, 0);
5665 free_printer_driver_info_3(&info);
5670 /****************************************************************************
5671 ****************************************************************************/
5673 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5680 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5681 if (!W_ERROR_IS_OK(result))
5684 /* check the required size. */
5685 *needed += spoolss_size_printer_driver_info_6(&info);
5687 if (*needed > offered) {
5688 result = WERR_INSUFFICIENT_BUFFER;
5692 if (!rpcbuf_alloc_size(buffer, *needed)) {
5693 result = WERR_NOMEM;
5697 /* fill the buffer with the structures */
5698 smb_io_printer_driver_info_6("", buffer, &info, 0);
5701 free_printer_driver_info_6(&info);
5706 /****************************************************************************
5707 ****************************************************************************/
5709 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 UNISTR2 *uni_arch = &q_u->architecture;
5713 uint32 level = q_u->level;
5714 uint32 clientmajorversion = q_u->clientmajorversion;
5715 RPC_BUFFER *buffer = NULL;
5716 uint32 offered = q_u->offered;
5717 uint32 *needed = &r_u->needed;
5718 uint32 *servermajorversion = &r_u->servermajorversion;
5719 uint32 *serverminorversion = &r_u->serverminorversion;
5720 Printer_entry *printer;
5723 fstring architecture;
5726 /* that's an [in out] buffer */
5728 if (!q_u->buffer && (offered!=0)) {
5729 return WERR_INVALID_PARAM;
5732 if (offered > MAX_RPC_DATA_SIZE) {
5733 return WERR_INVALID_PARAM;
5736 rpcbuf_move(q_u->buffer, &r_u->buffer);
5737 buffer = r_u->buffer;
5739 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5741 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5742 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5743 return WERR_INVALID_PRINTER_NAME;
5747 *servermajorversion = 0;
5748 *serverminorversion = 0;
5750 fstrcpy(servername, get_server_name( printer ));
5751 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5753 if (!get_printer_snum(p, handle, &snum, NULL))
5758 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5760 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5762 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5764 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5767 /* apparently this call is the equivalent of
5768 EnumPrinterDataEx() for the DsDriver key */
5773 return WERR_UNKNOWN_LEVEL;
5777 /****************************************************************
5778 _spoolss_StartPagePrinter
5779 ****************************************************************/
5781 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5782 struct spoolss_StartPagePrinter *r)
5784 POLICY_HND *handle = r->in.handle;
5786 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5789 DEBUG(3,("_spoolss_StartPagePrinter: "
5790 "Error in startpageprinter printer handle\n"));
5794 Printer->page_started=True;
5798 /****************************************************************
5799 _spoolss_EndPagePrinter
5800 ****************************************************************/
5802 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5803 struct spoolss_EndPagePrinter *r)
5805 POLICY_HND *handle = r->in.handle;
5808 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5811 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5812 OUR_HANDLE(handle)));
5816 if (!get_printer_snum(p, handle, &snum, NULL))
5819 Printer->page_started=False;
5820 print_job_endpage(snum, Printer->jobid);
5825 /****************************************************************
5826 _spoolss_StartDocPrinter
5827 ****************************************************************/
5829 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5830 struct spoolss_StartDocPrinter *r)
5832 POLICY_HND *handle = r->in.handle;
5833 uint32_t *jobid = r->out.job_id;
5834 struct spoolss_DocumentInfo1 *info_1;
5836 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5839 DEBUG(2,("_spoolss_StartDocPrinter: "
5840 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5844 if (r->in.level != 1) {
5845 return WERR_UNKNOWN_LEVEL;
5848 info_1 = r->in.info.info1;
5851 * a nice thing with NT is it doesn't listen to what you tell it.
5852 * when asked to send _only_ RAW datas, it tries to send datas
5855 * So I add checks like in NT Server ...
5858 if (info_1->datatype) {
5859 if (strcmp(info_1->datatype, "RAW") != 0) {
5861 return WERR_INVALID_DATATYPE;
5865 /* get the share number of the printer */
5866 if (!get_printer_snum(p, handle, &snum, NULL)) {
5870 Printer->jobid = print_job_start(p->server_info, snum,
5871 CONST_DISCARD(char *,info_1->document_name),
5872 Printer->nt_devmode);
5874 /* An error occured in print_job_start() so return an appropriate
5877 if (Printer->jobid == -1) {
5878 return map_werror_from_unix(errno);
5881 Printer->document_started=True;
5882 (*jobid) = Printer->jobid;
5887 /****************************************************************
5888 _spoolss_EndDocPrinter
5889 ****************************************************************/
5891 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5892 struct spoolss_EndDocPrinter *r)
5894 POLICY_HND *handle = r->in.handle;
5896 return _spoolss_enddocprinter_internal(p, handle);
5899 /****************************************************************
5900 _spoolss_WritePrinter
5901 ****************************************************************/
5903 WERROR _spoolss_WritePrinter(pipes_struct *p,
5904 struct spoolss_WritePrinter *r)
5906 POLICY_HND *handle = r->in.handle;
5907 uint32 buffer_size = r->in._data_size;
5908 uint8 *buffer = r->in.data.data;
5909 uint32 *buffer_written = &r->in._data_size;
5911 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5914 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5915 OUR_HANDLE(handle)));
5916 *r->out.num_written = r->in._data_size;
5920 if (!get_printer_snum(p, handle, &snum, NULL))
5923 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5924 (SMB_OFF_T)-1, (size_t)buffer_size);
5925 if (*buffer_written == (uint32)-1) {
5926 *r->out.num_written = 0;
5927 if (errno == ENOSPC)
5928 return WERR_NO_SPOOL_SPACE;
5930 return WERR_ACCESS_DENIED;
5933 *r->out.num_written = r->in._data_size;
5938 /********************************************************************
5939 * api_spoolss_getprinter
5940 * called from the spoolss dispatcher
5942 ********************************************************************/
5944 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5948 WERROR errcode = WERR_BADFUNC;
5949 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5952 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5956 if (!get_printer_snum(p, handle, &snum, NULL))
5960 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5961 if (print_queue_pause(p->server_info, snum, &errcode)) {
5965 case SPOOLSS_PRINTER_CONTROL_RESUME:
5966 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5967 if (print_queue_resume(p->server_info, snum, &errcode)) {
5971 case SPOOLSS_PRINTER_CONTROL_PURGE:
5972 if (print_queue_purge(p->server_info, snum, &errcode)) {
5977 return WERR_UNKNOWN_LEVEL;
5984 /****************************************************************
5985 _spoolss_AbortPrinter
5986 * From MSDN: "Deletes printer's spool file if printer is configured
5988 ****************************************************************/
5990 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5991 struct spoolss_AbortPrinter *r)
5993 POLICY_HND *handle = r->in.handle;
5994 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5996 WERROR errcode = WERR_OK;
5999 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6000 OUR_HANDLE(handle)));
6004 if (!get_printer_snum(p, handle, &snum, NULL))
6007 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6012 /********************************************************************
6013 * called by spoolss_api_setprinter
6014 * when updating a printer description
6015 ********************************************************************/
6017 static WERROR update_printer_sec(POLICY_HND *handle,
6018 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6020 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6024 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6026 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6027 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6028 OUR_HANDLE(handle)));
6030 result = WERR_BADFID;
6035 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6036 result = WERR_INVALID_PARAM;
6040 /* Check the user has permissions to change the security
6041 descriptor. By experimentation with two NT machines, the user
6042 requires Full Access to the printer to change security
6045 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6046 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6047 result = WERR_ACCESS_DENIED;
6051 /* NT seems to like setting the security descriptor even though
6052 nothing may have actually changed. */
6054 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6055 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6056 result = WERR_BADFID;
6060 if (DEBUGLEVEL >= 10) {
6064 the_acl = old_secdesc_ctr->sd->dacl;
6065 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6066 PRINTERNAME(snum), the_acl->num_aces));
6068 for (i = 0; i < the_acl->num_aces; i++) {
6069 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6070 &the_acl->aces[i].trustee),
6071 the_acl->aces[i].access_mask));
6074 the_acl = secdesc_ctr->sd->dacl;
6077 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6078 PRINTERNAME(snum), the_acl->num_aces));
6080 for (i = 0; i < the_acl->num_aces; i++) {
6081 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6082 &the_acl->aces[i].trustee),
6083 the_acl->aces[i].access_mask));
6086 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6090 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6091 if (!new_secdesc_ctr) {
6092 result = WERR_NOMEM;
6096 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6101 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6108 /********************************************************************
6109 Canonicalize printer info from a client
6111 ATTN: It does not matter what we set the servername to hear
6112 since we do the necessary work in get_a_printer() to set it to
6113 the correct value based on what the client sent in the
6114 _spoolss_open_printer_ex().
6115 ********************************************************************/
6117 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6119 fstring printername;
6122 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6123 "portname=%s drivername=%s comment=%s location=%s\n",
6124 info->servername, info->printername, info->sharename,
6125 info->portname, info->drivername, info->comment, info->location));
6127 /* we force some elements to "correct" values */
6128 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6129 fstrcpy(info->sharename, lp_servicename(snum));
6131 /* check to see if we allow printername != sharename */
6133 if ( lp_force_printername(snum) ) {
6134 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6135 global_myname(), info->sharename );
6138 /* make sure printername is in \\server\printername format */
6140 fstrcpy( printername, info->printername );
6142 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6143 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6147 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6148 global_myname(), p );
6151 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6152 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6159 /****************************************************************************
6160 ****************************************************************************/
6162 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6164 char *cmd = lp_addport_cmd();
6165 char *command = NULL;
6167 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6168 bool is_print_op = False;
6171 return WERR_ACCESS_DENIED;
6174 command = talloc_asprintf(ctx,
6175 "%s \"%s\" \"%s\"", cmd, portname, uri );
6181 is_print_op = user_has_privileges( token, &se_printop );
6183 DEBUG(10,("Running [%s]\n", command));
6185 /********* BEGIN SePrintOperatorPrivilege **********/
6190 ret = smbrun(command, NULL);
6195 /********* END SePrintOperatorPrivilege **********/
6197 DEBUGADD(10,("returned [%d]\n", ret));
6199 TALLOC_FREE(command);
6202 return WERR_ACCESS_DENIED;
6208 /****************************************************************************
6209 ****************************************************************************/
6211 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6213 char *cmd = lp_addprinter_cmd();
6215 char *command = NULL;
6219 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6220 bool is_print_op = False;
6221 char *remote_machine = talloc_strdup(ctx, "%m");
6223 if (!remote_machine) {
6226 remote_machine = talloc_sub_basic(ctx,
6227 current_user_info.smb_name,
6228 current_user_info.domain,
6230 if (!remote_machine) {
6234 command = talloc_asprintf(ctx,
6235 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6236 cmd, printer->info_2->printername, printer->info_2->sharename,
6237 printer->info_2->portname, printer->info_2->drivername,
6238 printer->info_2->location, printer->info_2->comment, remote_machine);
6244 is_print_op = user_has_privileges( token, &se_printop );
6246 DEBUG(10,("Running [%s]\n", command));
6248 /********* BEGIN SePrintOperatorPrivilege **********/
6253 if ( (ret = smbrun(command, &fd)) == 0 ) {
6254 /* Tell everyone we updated smb.conf. */
6255 message_send_all(smbd_messaging_context(),
6256 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6262 /********* END SePrintOperatorPrivilege **********/
6264 DEBUGADD(10,("returned [%d]\n", ret));
6266 TALLOC_FREE(command);
6267 TALLOC_FREE(remote_machine);
6275 /* reload our services immediately */
6276 reload_services( False );
6279 /* Get lines and convert them back to dos-codepage */
6280 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6281 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6284 /* Set the portname to what the script says the portname should be. */
6285 /* but don't require anything to be return from the script exit a good error code */
6288 /* Set the portname to what the script says the portname should be. */
6289 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6290 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6293 TALLOC_FREE(qlines);
6298 /********************************************************************
6299 * Called by spoolss_api_setprinter
6300 * when updating a printer description.
6301 ********************************************************************/
6303 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6304 struct spoolss_SetPrinterInfoCtr *info_ctr,
6305 struct spoolss_DeviceMode *devmode)
6308 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6309 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6314 DEBUG(8,("update_printer\n"));
6319 result = WERR_BADFID;
6323 if (!get_printer_snum(p, handle, &snum, NULL)) {
6324 result = WERR_BADFID;
6328 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6329 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6330 result = WERR_BADFID;
6334 DEBUGADD(8,("Converting info_2 struct\n"));
6337 * convert_printer_info converts the incoming
6338 * info from the client and overwrites the info
6339 * just read from the tdb in the pointer 'printer'.
6342 if (!convert_printer_info_new(info_ctr, printer)) {
6343 result = WERR_NOMEM;
6348 /* we have a valid devmode
6349 convert it and link it*/
6351 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6352 if (!convert_devicemode_new(printer->info_2->printername,
6354 &printer->info_2->devmode)) {
6355 result = WERR_NOMEM;
6360 /* Do sanity check on the requested changes for Samba */
6362 if (!check_printer_ok(printer->info_2, snum)) {
6363 result = WERR_INVALID_PARAM;
6367 /* FIXME!!! If the driver has changed we really should verify that
6368 it is installed before doing much else --jerry */
6370 /* Check calling user has permission to update printer description */
6372 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6373 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6374 result = WERR_ACCESS_DENIED;
6378 /* Call addprinter hook */
6379 /* Check changes to see if this is really needed */
6381 if ( *lp_addprinter_cmd()
6382 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6383 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6384 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6385 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6387 /* add_printer_hook() will call reload_services() */
6389 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6391 result = WERR_ACCESS_DENIED;
6397 * When a *new* driver is bound to a printer, the drivername is used to
6398 * lookup previously saved driver initialization info, which is then
6399 * bound to the printer, simulating what happens in the Windows arch.
6401 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6403 if (!set_driver_init(printer, 2))
6405 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6406 printer->info_2->drivername));
6409 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6410 printer->info_2->drivername));
6412 notify_printer_driver(snum, printer->info_2->drivername);
6416 * flag which changes actually occured. This is a small subset of
6417 * all the possible changes. We also have to update things in the
6421 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6422 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6423 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6424 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6426 notify_printer_comment(snum, printer->info_2->comment);
6429 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6430 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6431 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6432 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6434 notify_printer_sharename(snum, printer->info_2->sharename);
6437 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6440 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6443 pname = printer->info_2->printername;
6446 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6447 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6448 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6450 notify_printer_printername( snum, pname );
6453 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6454 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6455 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6456 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6458 notify_printer_port(snum, printer->info_2->portname);
6461 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6462 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6463 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6464 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6466 notify_printer_location(snum, printer->info_2->location);
6469 /* here we need to update some more DsSpooler keys */
6470 /* uNCName, serverName, shortServerName */
6472 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6473 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6474 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6475 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6476 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6478 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6479 global_myname(), printer->info_2->sharename );
6480 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6481 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6482 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6484 /* Update printer info */
6485 result = mod_a_printer(printer, 2);
6488 free_a_printer(&printer, 2);
6489 free_a_printer(&old_printer, 2);
6495 /****************************************************************************
6496 ****************************************************************************/
6497 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6498 struct spoolss_SetPrinterInfo7 *info7)
6502 Printer_entry *Printer;
6504 if ( lp_security() != SEC_ADS ) {
6505 return WERR_UNKNOWN_LEVEL;
6508 Printer = find_printer_index_by_hnd(p, handle);
6510 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6515 if (!get_printer_snum(p, handle, &snum, NULL))
6518 nt_printer_publish(Printer, snum, info7->action);
6522 return WERR_UNKNOWN_LEVEL;
6526 /****************************************************************
6528 ****************************************************************/
6530 WERROR _spoolss_SetPrinter(pipes_struct *p,
6531 struct spoolss_SetPrinter *r)
6533 POLICY_HND *handle = r->in.handle;
6536 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6539 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6540 OUR_HANDLE(handle)));
6544 /* check the level */
6545 switch (r->in.info_ctr->level) {
6547 return control_printer(handle, r->in.command, p);
6549 result = update_printer(p, handle,
6551 r->in.devmode_ctr->devmode);
6552 if (!W_ERROR_IS_OK(result))
6554 if (r->in.secdesc_ctr->sd)
6555 result = update_printer_sec(handle, p,
6559 return update_printer_sec(handle, p,
6562 return publish_or_unpublish_printer(p, handle,
6563 r->in.info_ctr->info.info7);
6565 return WERR_UNKNOWN_LEVEL;
6569 /****************************************************************
6570 _spoolss_FindClosePrinterNotify
6571 ****************************************************************/
6573 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6574 struct spoolss_FindClosePrinterNotify *r)
6576 POLICY_HND *handle = r->in.handle;
6577 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6580 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6581 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6585 if (Printer->notify.client_connected==True) {
6588 if ( Printer->printer_type == SPLHND_SERVER)
6590 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6591 !get_printer_snum(p, handle, &snum, NULL) )
6594 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6597 Printer->notify.flags=0;
6598 Printer->notify.options=0;
6599 Printer->notify.localmachine[0]='\0';
6600 Printer->notify.printerlocal=0;
6601 TALLOC_FREE(Printer->notify.option);
6602 Printer->notify.client_connected=False;
6607 /****************************************************************
6609 ****************************************************************/
6611 WERROR _spoolss_AddJob(pipes_struct *p,
6612 struct spoolss_AddJob *r)
6614 if (!r->in.buffer && (r->in.offered != 0)) {
6615 return WERR_INVALID_PARAM;
6618 /* this is what a NT server returns for AddJob. AddJob must fail on
6619 * non-local printers */
6621 if (r->in.level != 1) {
6622 return WERR_UNKNOWN_LEVEL;
6625 return WERR_INVALID_PARAM;
6628 /****************************************************************************
6629 ****************************************************************************/
6631 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6632 int position, int snum,
6633 const NT_PRINTER_INFO_LEVEL *ntprinter)
6637 t=gmtime(&queue->time);
6639 job_info->jobid=queue->job;
6640 init_unistr(&job_info->printername, lp_servicename(snum));
6641 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6642 init_unistr(&job_info->username, queue->fs_user);
6643 init_unistr(&job_info->document, queue->fs_file);
6644 init_unistr(&job_info->datatype, "RAW");
6645 init_unistr(&job_info->text_status, "");
6646 job_info->status=nt_printj_status(queue->status);
6647 job_info->priority=queue->priority;
6648 job_info->position=position;
6649 job_info->totalpages=queue->page_count;
6650 job_info->pagesprinted=0;
6652 make_systemtime(&job_info->submitted, t);
6655 /****************************************************************************
6656 ****************************************************************************/
6658 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6659 int position, int snum,
6660 const NT_PRINTER_INFO_LEVEL *ntprinter,
6661 DEVICEMODE *devmode)
6665 t=gmtime(&queue->time);
6667 job_info->jobid=queue->job;
6669 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6671 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6672 init_unistr(&job_info->username, queue->fs_user);
6673 init_unistr(&job_info->document, queue->fs_file);
6674 init_unistr(&job_info->notifyname, queue->fs_user);
6675 init_unistr(&job_info->datatype, "RAW");
6676 init_unistr(&job_info->printprocessor, "winprint");
6677 init_unistr(&job_info->parameters, "");
6678 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6679 init_unistr(&job_info->text_status, "");
6681 /* and here the security descriptor */
6683 job_info->status=nt_printj_status(queue->status);
6684 job_info->priority=queue->priority;
6685 job_info->position=position;
6686 job_info->starttime=0;
6687 job_info->untiltime=0;
6688 job_info->totalpages=queue->page_count;
6689 job_info->size=queue->size;
6690 make_systemtime(&(job_info->submitted), t);
6691 job_info->timeelapsed=0;
6692 job_info->pagesprinted=0;
6694 job_info->devmode = devmode;
6699 /****************************************************************************
6700 Enumjobs at level 1.
6701 ****************************************************************************/
6703 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6704 const NT_PRINTER_INFO_LEVEL *ntprinter,
6705 RPC_BUFFER *buffer, uint32 offered,
6706 uint32 *needed, uint32 *returned)
6710 WERROR result = WERR_OK;
6712 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6718 for (i=0; i<*returned; i++)
6719 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6721 /* check the required size. */
6722 for (i=0; i<*returned; i++)
6723 (*needed) += spoolss_size_job_info_1(&info[i]);
6725 if (*needed > offered) {
6726 result = WERR_INSUFFICIENT_BUFFER;
6730 if (!rpcbuf_alloc_size(buffer, *needed)) {
6731 result = WERR_NOMEM;
6735 /* fill the buffer with the structures */
6736 for (i=0; i<*returned; i++)
6737 smb_io_job_info_1("", buffer, &info[i], 0);
6743 if ( !W_ERROR_IS_OK(result) )
6749 /****************************************************************************
6750 Enumjobs at level 2.
6751 ****************************************************************************/
6753 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6754 const NT_PRINTER_INFO_LEVEL *ntprinter,
6755 RPC_BUFFER *buffer, uint32 offered,
6756 uint32 *needed, uint32 *returned)
6758 JOB_INFO_2 *info = NULL;
6760 WERROR result = WERR_OK;
6761 DEVICEMODE *devmode = NULL;
6763 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6768 /* this should not be a failure condition if the devmode is NULL */
6770 devmode = construct_dev_mode(lp_const_servicename(snum));
6772 for (i=0; i<*returned; i++)
6773 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6775 /* check the required size. */
6776 for (i=0; i<*returned; i++)
6777 (*needed) += spoolss_size_job_info_2(&info[i]);
6779 if (*needed > offered) {
6780 result = WERR_INSUFFICIENT_BUFFER;
6784 if (!rpcbuf_alloc_size(buffer, *needed)) {
6785 result = WERR_NOMEM;
6789 /* fill the buffer with the structures */
6790 for (i=0; i<*returned; i++)
6791 smb_io_job_info_2("", buffer, &info[i], 0);
6794 free_devmode(devmode);
6797 if ( !W_ERROR_IS_OK(result) )
6804 /****************************************************************************
6806 ****************************************************************************/
6808 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6810 POLICY_HND *handle = &q_u->handle;
6811 uint32 level = q_u->level;
6812 RPC_BUFFER *buffer = NULL;
6813 uint32 offered = q_u->offered;
6814 uint32 *needed = &r_u->needed;
6815 uint32 *returned = &r_u->returned;
6817 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6819 print_status_struct prt_status;
6820 print_queue_struct *queue=NULL;
6822 /* that's an [in out] buffer */
6824 if (!q_u->buffer && (offered!=0)) {
6825 return WERR_INVALID_PARAM;
6828 if (offered > MAX_RPC_DATA_SIZE) {
6829 return WERR_INVALID_PARAM;
6832 rpcbuf_move(q_u->buffer, &r_u->buffer);
6833 buffer = r_u->buffer;
6835 DEBUG(4,("_spoolss_enumjobs\n"));
6840 /* lookup the printer snum and tdb entry */
6842 if (!get_printer_snum(p, handle, &snum, NULL))
6845 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6846 if ( !W_ERROR_IS_OK(wret) )
6849 *returned = print_queue_status(snum, &queue, &prt_status);
6850 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6852 if (*returned == 0) {
6854 free_a_printer(&ntprinter, 2);
6860 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6863 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6867 wret = WERR_UNKNOWN_LEVEL;
6872 free_a_printer( &ntprinter, 2 );
6876 /****************************************************************
6877 _spoolss_ScheduleJob
6878 ****************************************************************/
6880 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6881 struct spoolss_ScheduleJob *r)
6886 /****************************************************************
6888 ****************************************************************/
6890 WERROR _spoolss_SetJob(pipes_struct *p,
6891 struct spoolss_SetJob *r)
6893 POLICY_HND *handle = r->in.handle;
6894 uint32 jobid = r->in.job_id;
6895 uint32 command = r->in.command;
6898 WERROR errcode = WERR_BADFUNC;
6900 if (!get_printer_snum(p, handle, &snum, NULL)) {
6904 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6905 return WERR_INVALID_PRINTER_NAME;
6909 case SPOOLSS_JOB_CONTROL_CANCEL:
6910 case SPOOLSS_JOB_CONTROL_DELETE:
6911 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6915 case SPOOLSS_JOB_CONTROL_PAUSE:
6916 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6920 case SPOOLSS_JOB_CONTROL_RESTART:
6921 case SPOOLSS_JOB_CONTROL_RESUME:
6922 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6927 return WERR_UNKNOWN_LEVEL;
6933 /****************************************************************************
6934 Enumerates all printer drivers at level 1.
6935 ****************************************************************************/
6937 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6942 fstring *list = NULL;
6943 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6944 DRIVER_INFO_1 *driver_info_1=NULL;
6945 WERROR result = WERR_OK;
6949 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6951 ndrivers=get_ntdrivers(&list, architecture, version);
6952 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6954 if(ndrivers == -1) {
6955 SAFE_FREE(driver_info_1);
6960 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6961 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6967 for (i=0; i<ndrivers; i++) {
6969 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6970 ZERO_STRUCT(driver);
6971 status = get_a_printer_driver(&driver, 3, list[i],
6972 architecture, version);
6973 if (!W_ERROR_IS_OK(status)) {
6975 SAFE_FREE(driver_info_1);
6978 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6979 free_a_printer_driver(driver, 3);
6982 *returned+=ndrivers;
6986 /* check the required size. */
6987 for (i=0; i<*returned; i++) {
6988 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6989 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6992 if (*needed > offered) {
6993 result = WERR_INSUFFICIENT_BUFFER;
6997 if (!rpcbuf_alloc_size(buffer, *needed)) {
6998 result = WERR_NOMEM;
7002 /* fill the buffer with the driver structures */
7003 for (i=0; i<*returned; i++) {
7004 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7005 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7009 SAFE_FREE(driver_info_1);
7011 if ( !W_ERROR_IS_OK(result) )
7017 /****************************************************************************
7018 Enumerates all printer drivers at level 2.
7019 ****************************************************************************/
7021 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7026 fstring *list = NULL;
7027 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7028 DRIVER_INFO_2 *driver_info_2=NULL;
7029 WERROR result = WERR_OK;
7033 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7035 ndrivers=get_ntdrivers(&list, architecture, version);
7036 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7038 if(ndrivers == -1) {
7039 SAFE_FREE(driver_info_2);
7044 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7045 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7051 for (i=0; i<ndrivers; i++) {
7054 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7055 ZERO_STRUCT(driver);
7056 status = get_a_printer_driver(&driver, 3, list[i],
7057 architecture, version);
7058 if (!W_ERROR_IS_OK(status)) {
7060 SAFE_FREE(driver_info_2);
7063 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7064 free_a_printer_driver(driver, 3);
7067 *returned+=ndrivers;
7071 /* check the required size. */
7072 for (i=0; i<*returned; i++) {
7073 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7074 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7077 if (*needed > offered) {
7078 result = WERR_INSUFFICIENT_BUFFER;
7082 if (!rpcbuf_alloc_size(buffer, *needed)) {
7083 result = WERR_NOMEM;
7087 /* fill the buffer with the form structures */
7088 for (i=0; i<*returned; i++) {
7089 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7090 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7094 SAFE_FREE(driver_info_2);
7096 if ( !W_ERROR_IS_OK(result) )
7102 /****************************************************************************
7103 Enumerates all printer drivers at level 3.
7104 ****************************************************************************/
7106 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7111 fstring *list = NULL;
7112 DRIVER_INFO_3 *driver_info_3=NULL;
7113 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7114 WERROR result = WERR_OK;
7118 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7120 ndrivers=get_ntdrivers(&list, architecture, version);
7121 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7123 if(ndrivers == -1) {
7124 SAFE_FREE(driver_info_3);
7129 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7130 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7136 for (i=0; i<ndrivers; i++) {
7139 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7140 ZERO_STRUCT(driver);
7141 status = get_a_printer_driver(&driver, 3, list[i],
7142 architecture, version);
7143 if (!W_ERROR_IS_OK(status)) {
7145 SAFE_FREE(driver_info_3);
7148 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7149 free_a_printer_driver(driver, 3);
7152 *returned+=ndrivers;
7156 /* check the required size. */
7157 for (i=0; i<*returned; i++) {
7158 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7159 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7162 if (*needed > offered) {
7163 result = WERR_INSUFFICIENT_BUFFER;
7167 if (!rpcbuf_alloc_size(buffer, *needed)) {
7168 result = WERR_NOMEM;
7172 /* fill the buffer with the driver structures */
7173 for (i=0; i<*returned; i++) {
7174 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7175 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7179 for (i=0; i<*returned; i++) {
7180 SAFE_FREE(driver_info_3[i].dependentfiles);
7183 SAFE_FREE(driver_info_3);
7185 if ( !W_ERROR_IS_OK(result) )
7191 /****************************************************************************
7192 Enumerates all printer drivers.
7193 ****************************************************************************/
7195 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7197 uint32 level = q_u->level;
7198 RPC_BUFFER *buffer = NULL;
7199 uint32 offered = q_u->offered;
7200 uint32 *needed = &r_u->needed;
7201 uint32 *returned = &r_u->returned;
7202 const char *cservername;
7204 fstring architecture;
7206 /* that's an [in out] buffer */
7208 if (!q_u->buffer && (offered!=0)) {
7209 return WERR_INVALID_PARAM;
7212 if (offered > MAX_RPC_DATA_SIZE) {
7213 return WERR_INVALID_PARAM;
7216 rpcbuf_move(q_u->buffer, &r_u->buffer);
7217 buffer = r_u->buffer;
7219 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7224 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7225 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7227 cservername = canon_servername(servername);
7229 if (!is_myname_or_ipaddr(cservername))
7230 return WERR_UNKNOWN_PRINTER_DRIVER;
7234 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7236 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7238 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7240 return WERR_UNKNOWN_LEVEL;
7244 /****************************************************************************
7245 ****************************************************************************/
7247 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7248 struct spoolss_FormInfo1 *form,
7249 nt_forms_struct *list)
7251 form->form_name = talloc_strdup(mem_ctx, list->name);
7252 W_ERROR_HAVE_NO_MEMORY(form->form_name);
7254 form->flags = list->flag;
7255 form->size.width = list->width;
7256 form->size.height = list->length;
7257 form->area.left = list->left;
7258 form->area.top = list->top;
7259 form->area.right = list->right;
7260 form->area.bottom = list->bottom;
7265 /****************************************************************
7267 ****************************************************************/
7269 WERROR _spoolss_EnumForms(pipes_struct *p,
7270 struct spoolss_EnumForms *r)
7272 nt_forms_struct *list=NULL;
7273 nt_forms_struct *builtinlist=NULL;
7274 union spoolss_FormInfo *info;
7276 uint32_t numbuiltinforms;
7277 size_t buffer_size = 0;
7282 /* that's an [in out] buffer */
7284 if (!r->in.buffer && (r->in.offered != 0) ) {
7285 return WERR_INVALID_PARAM;
7288 DEBUG(4,("_spoolss_EnumForms\n"));
7289 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7290 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7292 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7293 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7294 count = get_ntforms(&list);
7295 DEBUGADD(5,("Number of user forms [%d]\n", count));
7296 count += numbuiltinforms;
7299 SAFE_FREE(builtinlist);
7301 return WERR_NO_MORE_ITEMS;
7304 info = TALLOC_ARRAY(p->mem_ctx, union spoolss_FormInfo, count);
7306 SAFE_FREE(builtinlist);
7311 switch (r->in.level) {
7313 /* construct the list of form structures */
7314 for (i=0; i<numbuiltinforms; i++) {
7315 DEBUGADD(6,("Filling form number [%d]\n",i));
7316 fill_form_info_1(info, &info[i].info1, &builtinlist[i]);
7319 SAFE_FREE(builtinlist);
7321 for (; i<count; i++) {
7322 DEBUGADD(6,("Filling form number [%d]\n",i));
7323 fill_form_info_1(info, &info[i].info1, &list[i-numbuiltinforms]);
7328 /* check the required size. */
7329 for (i=0; i<numbuiltinforms; i++) {
7330 DEBUGADD(6,("adding form [%d]'s size\n",i));
7331 buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7333 for (; i<count; i++) {
7334 DEBUGADD(6,("adding form [%d]'s size\n",i));
7335 buffer_size += ndr_size_spoolss_FormInfo1(&info[i].info1, NULL, 0);
7338 *r->out.needed = buffer_size;
7340 if (*r->out.needed > r->in.offered) {
7342 return WERR_INSUFFICIENT_BUFFER;
7345 *r->out.count = count;
7346 *r->out.info = info;
7352 SAFE_FREE(builtinlist);
7353 return WERR_UNKNOWN_LEVEL;
7357 /****************************************************************
7359 ****************************************************************/
7361 WERROR _spoolss_GetForm(pipes_struct *p,
7362 struct spoolss_GetForm *r)
7364 uint32 level = r->in.level;
7365 uint32 offered = r->in.offered;
7366 uint32 *needed = r->out.needed;
7368 nt_forms_struct *list=NULL;
7369 nt_forms_struct builtin_form;
7371 union spoolss_FormInfo info;
7372 struct spoolss_FormInfo1 form_1;
7373 int numofforms=0, i=0;
7375 /* that's an [in out] buffer */
7377 if (!r->in.buffer && (offered!=0)) {
7378 return WERR_INVALID_PARAM;
7381 DEBUG(4,("_spoolss_GetForm\n"));
7382 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7383 DEBUGADD(5,("Info level [%d]\n", level));
7385 foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7386 if (!foundBuiltin) {
7387 numofforms = get_ntforms(&list);
7388 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7390 if (numofforms == 0)
7394 ZERO_STRUCT(form_1);
7399 fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7402 /* Check if the requested name is in the list of form structures */
7403 for (i=0; i<numofforms; i++) {
7405 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7406 list[i].name, r->in.form_name));
7408 if (strequal(r->in.form_name, list[i].name)) {
7409 DEBUGADD(6,("Found form %s number [%d]\n",
7410 r->in.form_name, i));
7411 fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7417 if (i == numofforms) {
7421 /* check the required size. */
7423 info.info1 = form_1;
7425 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7427 if (*needed > offered) {
7429 return WERR_INSUFFICIENT_BUFFER;
7432 r->out.info->info1 = form_1;
7434 /* fill the buffer with the form structures */
7435 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7436 r->in.form_name, i));
7442 return WERR_UNKNOWN_LEVEL;
7446 /****************************************************************************
7447 ****************************************************************************/
7449 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7450 struct spoolss_PortInfo1 *r,
7453 r->port_name = talloc_strdup(mem_ctx, name);
7454 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7459 /****************************************************************************
7460 TODO: This probably needs distinguish between TCP/IP and Local ports
7462 ****************************************************************************/
7464 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7465 struct spoolss_PortInfo2 *r,
7468 r->port_name = talloc_strdup(mem_ctx, name);
7469 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7471 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7472 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7474 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
7475 W_ERROR_HAVE_NO_MEMORY(r->description);
7477 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7484 /****************************************************************************
7485 wrapper around the enumer ports command
7486 ****************************************************************************/
7488 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7490 char *cmd = lp_enumports_cmd();
7491 char **qlines = NULL;
7492 char *command = NULL;
7500 /* if no hook then just fill in the default port */
7503 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7506 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7507 TALLOC_FREE(qlines);
7514 /* we have a valid enumport command */
7516 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7521 DEBUG(10,("Running [%s]\n", command));
7522 ret = smbrun(command, &fd);
7523 DEBUG(10,("Returned [%d]\n", ret));
7524 TALLOC_FREE(command);
7529 return WERR_ACCESS_DENIED;
7533 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7534 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7544 /****************************************************************************
7546 ****************************************************************************/
7548 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7549 union spoolss_PortInfo **info_p,
7554 union spoolss_PortInfo *info = NULL;
7556 WERROR result = WERR_OK;
7557 char **qlines = NULL;
7560 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7561 if (!W_ERROR_IS_OK(result)) {
7566 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7568 DEBUG(10,("Returning WERR_NOMEM\n"));
7569 result = WERR_NOMEM;
7573 for (i=0; i<numlines; i++) {
7574 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7575 result = fill_port_1(info, &info[i].info1, qlines[i]);
7576 if (!W_ERROR_IS_OK(result)) {
7581 TALLOC_FREE(qlines);
7583 /* check the required size. */
7584 for (i=0; i<numlines; i++) {
7585 DEBUGADD(6,("adding port [%d]'s size\n", i));
7586 *needed += ndr_size_spoolss_PortInfo1(&info[i].info1, NULL, 0);
7589 if (*needed > offered) {
7590 result = WERR_INSUFFICIENT_BUFFER;
7595 if (!W_ERROR_IS_OK(result)) {
7597 TALLOC_FREE(qlines);
7609 /****************************************************************************
7611 ****************************************************************************/
7613 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7614 union spoolss_PortInfo **info_p,
7619 union spoolss_PortInfo *info = NULL;
7621 WERROR result = WERR_OK;
7622 char **qlines = NULL;
7625 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7626 if (!W_ERROR_IS_OK(result)) {
7631 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7633 DEBUG(10,("Returning WERR_NOMEM\n"));
7634 result = WERR_NOMEM;
7638 for (i=0; i<numlines; i++) {
7639 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7640 result = fill_port_2(info, &info[i].info2, qlines[i]);
7641 if (!W_ERROR_IS_OK(result)) {
7646 TALLOC_FREE(qlines);
7648 /* check the required size. */
7649 for (i=0; i<numlines; i++) {
7650 DEBUGADD(6,("adding port [%d]'s size\n", i));
7651 *needed += ndr_size_spoolss_PortInfo2(&info[i].info2, NULL, 0);
7654 if (*needed > offered) {
7655 result = WERR_INSUFFICIENT_BUFFER;
7660 if (!W_ERROR_IS_OK(result)) {
7662 TALLOC_FREE(qlines);
7674 /****************************************************************
7676 ****************************************************************/
7678 WERROR _spoolss_EnumPorts(pipes_struct *p,
7679 struct spoolss_EnumPorts *r)
7681 /* that's an [in out] buffer */
7683 if (!r->in.buffer && (r->in.offered != 0)) {
7684 return WERR_INVALID_PARAM;
7687 DEBUG(4,("_spoolss_EnumPorts\n"));
7691 *r->out.info = NULL;
7693 switch (r->in.level) {
7695 return enumports_level_1(p->mem_ctx, r->out.info,
7696 r->in.offered, r->out.needed,
7699 return enumports_level_2(p->mem_ctx, r->out.info,
7700 r->in.offered, r->out.needed,
7703 return WERR_UNKNOWN_LEVEL;
7707 /****************************************************************************
7708 ****************************************************************************/
7710 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7712 struct spoolss_SetPrinterInfoCtr *info_ctr,
7713 struct spoolss_DeviceMode *devmode,
7714 struct security_descriptor *sec_desc,
7715 struct spoolss_UserLevelCtr *user_ctr,
7718 NT_PRINTER_INFO_LEVEL *printer = NULL;
7721 WERROR err = WERR_OK;
7723 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7724 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7728 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7729 if (!convert_printer_info_new(info_ctr, printer)) {
7730 free_a_printer(&printer, 2);
7734 /* check to see if the printer already exists */
7736 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7737 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7738 printer->info_2->sharename));
7739 free_a_printer(&printer, 2);
7740 return WERR_PRINTER_ALREADY_EXISTS;
7743 /* FIXME!!! smbd should check to see if the driver is installed before
7744 trying to add a printer like this --jerry */
7746 if (*lp_addprinter_cmd() ) {
7747 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7749 free_a_printer(&printer,2);
7750 return WERR_ACCESS_DENIED;
7753 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7754 "smb.conf parameter \"addprinter command\" is defined. This"
7755 "parameter must exist for this call to succeed\n",
7756 printer->info_2->sharename ));
7759 /* use our primary netbios name since get_a_printer() will convert
7760 it to what the client expects on a case by case basis */
7762 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7763 printer->info_2->sharename);
7766 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7767 free_a_printer(&printer,2);
7768 return WERR_ACCESS_DENIED;
7771 /* you must be a printer admin to add a new printer */
7772 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7773 free_a_printer(&printer,2);
7774 return WERR_ACCESS_DENIED;
7778 * Do sanity check on the requested changes for Samba.
7781 if (!check_printer_ok(printer->info_2, snum)) {
7782 free_a_printer(&printer,2);
7783 return WERR_INVALID_PARAM;
7787 * When a printer is created, the drivername bound to the printer is used
7788 * to lookup previously saved driver initialization info, which is then
7789 * bound to the new printer, simulating what happens in the Windows arch.
7794 set_driver_init(printer, 2);
7798 /* A valid devmode was included, convert and link it
7800 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7802 if (!convert_devicemode_new(printer->info_2->printername,
7804 &printer->info_2->devmode))
7808 /* write the ASCII on disk */
7809 err = mod_a_printer(printer, 2);
7810 if (!W_ERROR_IS_OK(err)) {
7811 free_a_printer(&printer,2);
7815 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7816 /* Handle open failed - remove addition. */
7817 del_a_printer(printer->info_2->sharename);
7818 free_a_printer(&printer,2);
7819 ZERO_STRUCTP(handle);
7820 return WERR_ACCESS_DENIED;
7823 update_c_setprinter(False);
7824 free_a_printer(&printer,2);
7829 /****************************************************************
7830 _spoolss_AddPrinterEx
7831 ****************************************************************/
7833 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7834 struct spoolss_AddPrinterEx *r)
7836 switch (r->in.info_ctr->level) {
7838 /* we don't handle yet */
7839 /* but I know what to do ... */
7840 return WERR_UNKNOWN_LEVEL;
7842 return spoolss_addprinterex_level_2(p, r->in.server,
7844 r->in.devmode_ctr->devmode,
7845 r->in.secdesc_ctr->sd,
7846 r->in.userlevel_ctr,
7849 return WERR_UNKNOWN_LEVEL;
7853 /****************************************************************
7854 _spoolss_AddPrinterDriver
7855 ****************************************************************/
7857 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7858 struct spoolss_AddPrinterDriver *r)
7860 uint32_t level = r->in.info_ctr->level;
7861 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7862 WERROR err = WERR_OK;
7863 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7864 fstring driver_name;
7868 switch (p->hdr_req.opnum) {
7869 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7870 fn = "_spoolss_AddPrinterDriver";
7872 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7873 fn = "_spoolss_AddPrinterDriverEx";
7876 return WERR_INVALID_PARAM;
7881 if (level != 3 && level != 6) {
7882 /* Clever hack from Martin Zielinski <mz@seh.de>
7883 * to allow downgrade from level 8 (Vista).
7885 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7886 return WERR_UNKNOWN_LEVEL;
7889 ZERO_STRUCT(driver);
7891 if (!convert_printer_driver_info(info, &driver, level)) {
7896 DEBUG(5,("Cleaning driver's information\n"));
7897 err = clean_up_driver_struct(p, driver, level);
7898 if (!W_ERROR_IS_OK(err))
7901 DEBUG(5,("Moving driver to final destination\n"));
7902 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7907 if (add_a_printer_driver(driver, level)!=0) {
7908 err = WERR_ACCESS_DENIED;
7914 fstrcpy(driver_name,
7915 driver.info_3->name ? driver.info_3->name : "");
7918 fstrcpy(driver_name,
7919 driver.info_6->name ? driver.info_6->name : "");
7924 * I think this is where he DrvUpgradePrinter() hook would be
7925 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7926 * server. Right now, we just need to send ourselves a message
7927 * to update each printer bound to this driver. --jerry
7930 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7931 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7936 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7937 * decide if the driver init data should be deleted. The rules are:
7938 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7939 * 2) delete init data only if there is no 2k/Xp driver
7940 * 3) always delete init data
7941 * The generalized rule is always use init data from the highest order driver.
7942 * It is necessary to follow the driver install by an initialization step to
7943 * finish off this process.
7946 version = driver.info_3->cversion;
7947 else if (level == 6)
7948 version = driver.info_6->version;
7953 * 9x printer driver - never delete init data
7956 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7961 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7962 * there is no 2k/Xp driver init data for this driver name.
7966 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7968 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7970 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7972 if (!del_driver_init(driver_name))
7973 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7977 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7979 free_a_printer_driver(driver1,3);
7980 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7987 * 2k or Xp printer driver - always delete init data
7990 if (!del_driver_init(driver_name))
7991 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7996 DEBUG(0,("%s: invalid level=%d\n", fn, level));
8002 free_a_printer_driver(driver, level);
8006 /****************************************************************
8007 _spoolss_AddPrinterDriverEx
8008 ****************************************************************/
8010 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
8011 struct spoolss_AddPrinterDriverEx *r)
8013 struct spoolss_AddPrinterDriver a;
8016 * we only support the semantics of AddPrinterDriver()
8017 * i.e. only copy files that are newer than existing ones
8020 if (r->in.flags != APD_COPY_NEW_FILES) {
8021 return WERR_ACCESS_DENIED;
8024 a.in.servername = r->in.servername;
8025 a.in.info_ctr = r->in.info_ctr;
8027 return _spoolss_AddPrinterDriver(p, &a);
8030 /****************************************************************************
8031 ****************************************************************************/
8033 struct _spoolss_paths {
8039 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8041 static const struct _spoolss_paths spoolss_paths[]= {
8042 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8043 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8046 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8047 const char *servername,
8048 const char *environment,
8052 const char *pservername = NULL;
8053 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8054 const char *short_archi;
8058 /* environment may be empty */
8059 if (environment && strlen(environment)) {
8060 long_archi = environment;
8063 /* servername may be empty */
8064 if (servername && strlen(servername)) {
8065 pservername = canon_servername(servername);
8067 if (!is_myname_or_ipaddr(pservername)) {
8068 return WERR_INVALID_PARAM;
8072 if (!(short_archi = get_short_archi(long_archi))) {
8073 return WERR_INVALID_ENVIRONMENT;
8076 switch (component) {
8077 case SPOOLSS_PRTPROCS_PATH:
8078 case SPOOLSS_DRIVER_PATH:
8080 *path = talloc_asprintf(mem_ctx,
8083 spoolss_paths[component].share,
8086 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8087 SPOOLSS_DEFAULT_SERVER_PATH,
8088 spoolss_paths[component].dir,
8093 return WERR_INVALID_PARAM;
8103 /****************************************************************************
8104 ****************************************************************************/
8106 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8107 const char *servername,
8108 const char *environment,
8109 struct spoolss_DriverDirectoryInfo1 *r,
8116 werr = compose_spoolss_server_path(mem_ctx,
8119 SPOOLSS_DRIVER_PATH,
8121 if (!W_ERROR_IS_OK(werr)) {
8125 DEBUG(4,("printer driver directory: [%s]\n", path));
8127 r->directory_name = path;
8129 *needed += ndr_size_spoolss_DriverDirectoryInfo1(r, NULL, 0);
8131 if (*needed > offered) {
8133 return WERR_INSUFFICIENT_BUFFER;
8139 /****************************************************************
8140 _spoolss_GetPrinterDriverDirectory
8141 ****************************************************************/
8143 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8144 struct spoolss_GetPrinterDriverDirectory *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_GetPrinterDriverDirectory: level %d\n",
8159 /* r->in.level is ignored */
8161 werror = getprinterdriverdir_level_1(p->mem_ctx,
8164 &r->out.info->info1,
8167 if (!W_ERROR_IS_OK(werror)) {
8168 TALLOC_FREE(r->out.info);
8174 /****************************************************************************
8175 ****************************************************************************/
8177 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8179 POLICY_HND *handle = &q_u->handle;
8180 uint32 idx = q_u->index;
8181 uint32 in_value_len = q_u->valuesize;
8182 uint32 in_data_len = q_u->datasize;
8183 uint32 *out_max_value_len = &r_u->valuesize;
8184 uint16 **out_value = &r_u->value;
8185 uint32 *out_value_len = &r_u->realvaluesize;
8186 uint32 *out_type = &r_u->type;
8187 uint32 *out_max_data_len = &r_u->datasize;
8188 uint8 **data_out = &r_u->data;
8189 uint32 *out_data_len = &r_u->realdatasize;
8191 NT_PRINTER_INFO_LEVEL *printer = NULL;
8193 uint32 biggest_valuesize;
8194 uint32 biggest_datasize;
8196 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8199 REGISTRY_VALUE *val = NULL;
8200 NT_PRINTER_DATA *p_data;
8201 int i, key_index, num_values;
8206 *out_max_data_len = 0;
8210 DEBUG(5,("spoolss_enumprinterdata\n"));
8213 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8217 if (!get_printer_snum(p,handle, &snum, NULL))
8220 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8221 if (!W_ERROR_IS_OK(result))
8224 p_data = printer->info_2->data;
8225 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8230 * The NT machine wants to know the biggest size of value and data
8232 * cf: MSDN EnumPrinterData remark section
8235 if ( !in_value_len && !in_data_len && (key_index != -1) )
8237 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8239 biggest_valuesize = 0;
8240 biggest_datasize = 0;
8242 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8244 for ( i=0; i<num_values; i++ )
8246 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8248 name_length = strlen(val->valuename);
8249 if ( strlen(val->valuename) > biggest_valuesize )
8250 biggest_valuesize = name_length;
8252 if ( val->size > biggest_datasize )
8253 biggest_datasize = val->size;
8255 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8259 /* the value is an UNICODE string but real_value_size is the length
8260 in bytes including the trailing 0 */
8262 *out_value_len = 2 * (1+biggest_valuesize);
8263 *out_data_len = biggest_datasize;
8265 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8271 * the value len is wrong in NT sp3
8272 * that's the number of bytes not the number of unicode chars
8275 if ( key_index != -1 )
8276 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8281 /* out_value should default to "" or else NT4 has
8282 problems unmarshalling the response */
8284 *out_max_value_len=(in_value_len/sizeof(uint16));
8287 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8289 result = WERR_NOMEM;
8292 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8298 /* the data is counted in bytes */
8300 *out_max_data_len = in_data_len;
8301 *out_data_len = in_data_len;
8303 /* only allocate when given a non-zero data_len */
8305 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8307 result = WERR_NOMEM;
8311 result = WERR_NO_MORE_ITEMS;
8317 * - counted in bytes in the request
8318 * - counted in UNICODE chars in the max reply
8319 * - counted in bytes in the real size
8321 * take a pause *before* coding not *during* coding
8325 *out_max_value_len=(in_value_len/sizeof(uint16));
8327 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8329 result = WERR_NOMEM;
8333 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8341 *out_type = regval_type( val );
8343 /* data - counted in bytes */
8345 *out_max_data_len = in_data_len;
8346 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8348 result = WERR_NOMEM;
8351 data_len = regval_size(val);
8352 if ( *data_out && data_len )
8353 memcpy( *data_out, regval_data_p(val), data_len );
8354 *out_data_len = data_len;
8358 free_a_printer(&printer, 2);
8362 /****************************************************************************
8363 ****************************************************************************/
8365 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8367 POLICY_HND *handle = &q_u->handle;
8368 UNISTR2 *value = &q_u->value;
8369 uint32 type = q_u->type;
8370 uint8 *data = q_u->data;
8371 uint32 real_len = q_u->real_len;
8373 NT_PRINTER_INFO_LEVEL *printer = NULL;
8375 WERROR status = WERR_OK;
8376 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8379 DEBUG(5,("spoolss_setprinterdata\n"));
8382 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8386 if ( Printer->printer_type == SPLHND_SERVER ) {
8387 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8388 return WERR_INVALID_PARAM;
8391 if (!get_printer_snum(p,handle, &snum, NULL))
8395 * Access check : NT returns "access denied" if you make a
8396 * SetPrinterData call without the necessary privildge.
8397 * we were originally returning OK if nothing changed
8398 * which made Win2k issue **a lot** of SetPrinterData
8399 * when connecting to a printer --jerry
8402 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8404 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8405 status = WERR_ACCESS_DENIED;
8409 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8410 if (!W_ERROR_IS_OK(status))
8413 unistr2_to_ascii(valuename, value, sizeof(valuename));
8416 * When client side code sets a magic printer data key, detect it and save
8417 * the current printer data and the magic key's data (its the DEVMODE) for
8418 * future printer/driver initializations.
8420 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8422 /* Set devmode and printer initialization info */
8423 status = save_driver_init( printer, 2, data, real_len );
8425 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8429 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8430 type, data, real_len );
8431 if ( W_ERROR_IS_OK(status) )
8432 status = mod_a_printer(printer, 2);
8436 free_a_printer(&printer, 2);
8441 /****************************************************************
8442 _spoolss_ResetPrinter
8443 ****************************************************************/
8445 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8446 struct spoolss_ResetPrinter *r)
8448 POLICY_HND *handle = r->in.handle;
8449 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8452 DEBUG(5,("_spoolss_ResetPrinter\n"));
8455 * All we do is to check to see if the handle and queue is valid.
8456 * This call really doesn't mean anything to us because we only
8457 * support RAW printing. --jerry
8461 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8462 OUR_HANDLE(handle)));
8466 if (!get_printer_snum(p,handle, &snum, NULL))
8470 /* blindly return success */
8474 /****************************************************************
8475 _spoolss_DeletePrinterData
8476 ****************************************************************/
8478 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8479 struct spoolss_DeletePrinterData *r)
8481 POLICY_HND *handle = r->in.handle;
8482 NT_PRINTER_INFO_LEVEL *printer = NULL;
8484 WERROR status = WERR_OK;
8485 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8487 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8490 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8491 OUR_HANDLE(handle)));
8495 if (!get_printer_snum(p, handle, &snum, NULL))
8498 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8499 DEBUG(3, ("_spoolss_DeletePrinterData: "
8500 "printer properties change denied by handle\n"));
8501 return WERR_ACCESS_DENIED;
8504 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8505 if (!W_ERROR_IS_OK(status))
8508 if (!r->in.value_name) {
8509 free_a_printer(&printer, 2);
8513 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8516 if ( W_ERROR_IS_OK(status) )
8517 mod_a_printer( printer, 2 );
8519 free_a_printer(&printer, 2);
8524 /****************************************************************
8526 ****************************************************************/
8528 WERROR _spoolss_AddForm(pipes_struct *p,
8529 struct spoolss_AddForm *r)
8531 POLICY_HND *handle = r->in.handle;
8532 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8533 nt_forms_struct tmpForm;
8535 WERROR status = WERR_OK;
8536 NT_PRINTER_INFO_LEVEL *printer = NULL;
8539 nt_forms_struct *list=NULL;
8540 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8542 DEBUG(5,("_spoolss_AddForm\n"));
8545 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8546 OUR_HANDLE(handle)));
8551 /* forms can be added on printer of on the print server handle */
8553 if ( Printer->printer_type == SPLHND_PRINTER )
8555 if (!get_printer_snum(p,handle, &snum, NULL))
8558 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8559 if (!W_ERROR_IS_OK(status))
8563 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8564 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8565 status = WERR_ACCESS_DENIED;
8569 /* can't add if builtin */
8571 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8572 status = WERR_FILE_EXISTS;
8576 count = get_ntforms(&list);
8578 if(!add_a_form(&list, form, &count)) {
8579 status = WERR_NOMEM;
8583 write_ntforms(&list, count);
8586 * ChangeID must always be set if this is a printer
8589 if ( Printer->printer_type == SPLHND_PRINTER )
8590 status = mod_a_printer(printer, 2);
8594 free_a_printer(&printer, 2);
8600 /****************************************************************
8602 ****************************************************************/
8604 WERROR _spoolss_DeleteForm(pipes_struct *p,
8605 struct spoolss_DeleteForm *r)
8607 POLICY_HND *handle = r->in.handle;
8608 const char *form_name = r->in.form_name;
8609 nt_forms_struct tmpForm;
8611 nt_forms_struct *list=NULL;
8612 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8614 WERROR status = WERR_OK;
8615 NT_PRINTER_INFO_LEVEL *printer = NULL;
8617 DEBUG(5,("_spoolss_DeleteForm\n"));
8620 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8621 OUR_HANDLE(handle)));
8625 /* forms can be deleted on printer of on the print server handle */
8627 if ( Printer->printer_type == SPLHND_PRINTER )
8629 if (!get_printer_snum(p,handle, &snum, NULL))
8632 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8633 if (!W_ERROR_IS_OK(status))
8637 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8638 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8639 status = WERR_ACCESS_DENIED;
8643 /* can't delete if builtin */
8645 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8646 status = WERR_INVALID_PARAM;
8650 count = get_ntforms(&list);
8652 if ( !delete_a_form(&list, form_name, &count, &status ))
8656 * ChangeID must always be set if this is a printer
8659 if ( Printer->printer_type == SPLHND_PRINTER )
8660 status = mod_a_printer(printer, 2);
8664 free_a_printer(&printer, 2);
8670 /****************************************************************
8672 ****************************************************************/
8674 WERROR _spoolss_SetForm(pipes_struct *p,
8675 struct spoolss_SetForm *r)
8677 POLICY_HND *handle = r->in.handle;
8678 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8679 nt_forms_struct tmpForm;
8681 WERROR status = WERR_OK;
8682 NT_PRINTER_INFO_LEVEL *printer = NULL;
8685 nt_forms_struct *list=NULL;
8686 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8688 DEBUG(5,("_spoolss_SetForm\n"));
8691 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8692 OUR_HANDLE(handle)));
8696 /* forms can be modified on printer of on the print server handle */
8698 if ( Printer->printer_type == SPLHND_PRINTER )
8700 if (!get_printer_snum(p,handle, &snum, NULL))
8703 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8704 if (!W_ERROR_IS_OK(status))
8708 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8709 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8710 status = WERR_ACCESS_DENIED;
8714 /* can't set if builtin */
8715 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8716 status = WERR_INVALID_PARAM;
8720 count = get_ntforms(&list);
8721 update_a_form(&list, form, count);
8722 write_ntforms(&list, count);
8725 * ChangeID must always be set if this is a printer
8728 if ( Printer->printer_type == SPLHND_PRINTER )
8729 status = mod_a_printer(printer, 2);
8734 free_a_printer(&printer, 2);
8740 /****************************************************************************
8741 fill_print_processor1
8742 ****************************************************************************/
8744 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8745 struct spoolss_PrintProcessorInfo1 *r,
8746 const char *print_processor_name)
8748 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8749 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8754 /****************************************************************************
8755 enumprintprocessors level 1.
8756 ****************************************************************************/
8758 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8759 union spoolss_PrintProcessorInfo **info_p,
8764 union spoolss_PrintProcessorInfo *info;
8767 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8768 W_ERROR_HAVE_NO_MEMORY(info);
8772 result = fill_print_processor1(info, &info[0].info1, "winprint");
8773 if (!W_ERROR_IS_OK(result)) {
8777 *needed += ndr_size_spoolss_PrintProcessorInfo1(&info[0].info1, NULL, 0);
8779 if (*needed > offered) {
8780 result = WERR_INSUFFICIENT_BUFFER;
8785 if (!W_ERROR_IS_OK(result)) {
8796 /****************************************************************
8797 _spoolss_EnumPrintProcessors
8798 ****************************************************************/
8800 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8801 struct spoolss_EnumPrintProcessors *r)
8803 /* that's an [in out] buffer */
8805 if (!r->in.buffer && (r->in.offered != 0)) {
8806 return WERR_INVALID_PARAM;
8809 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8812 * Enumerate the print processors ...
8814 * Just reply with "winprint", to keep NT happy
8815 * and I can use my nice printer checker.
8820 *r->out.info = NULL;
8822 switch (r->in.level) {
8824 return enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8825 r->in.offered, r->out.needed,
8828 return WERR_UNKNOWN_LEVEL;
8832 /****************************************************************************
8833 fill_printprocdatatype1
8834 ****************************************************************************/
8836 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8837 struct spoolss_PrintProcDataTypesInfo1 *r,
8838 const char *name_array)
8840 r->name_array = talloc_strdup(mem_ctx, name_array);
8841 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8846 /****************************************************************************
8847 enumprintprocdatatypes level 1.
8848 ****************************************************************************/
8850 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8851 union spoolss_PrintProcDataTypesInfo **info_p,
8857 union spoolss_PrintProcDataTypesInfo *info;
8859 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8860 W_ERROR_HAVE_NO_MEMORY(info);
8864 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8865 if (!W_ERROR_IS_OK(result)) {
8869 *needed += ndr_size_spoolss_PrintProcDataTypesInfo1(&info[0].info1, NULL, 0);
8871 if (*needed > offered) {
8872 result = WERR_INSUFFICIENT_BUFFER;
8877 if (!W_ERROR_IS_OK(result)) {
8888 /****************************************************************
8889 _spoolss_EnumPrintProcDataTypes
8890 ****************************************************************/
8892 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8893 struct spoolss_EnumPrintProcDataTypes *r)
8895 /* that's an [in out] buffer */
8897 if (!r->in.buffer && (r->in.offered != 0)) {
8898 return WERR_INVALID_PARAM;
8901 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8905 *r->out.info = NULL;
8907 switch (r->in.level) {
8909 return enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8910 r->in.offered, r->out.needed,
8913 return WERR_UNKNOWN_LEVEL;
8917 /****************************************************************************
8919 ****************************************************************************/
8921 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8922 struct spoolss_MonitorInfo1 *r,
8923 const char *monitor_name)
8925 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8926 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8931 /****************************************************************************
8933 ****************************************************************************/
8935 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8936 struct spoolss_MonitorInfo2 *r,
8937 const char *monitor_name,
8938 const char *environment,
8939 const char *dll_name)
8941 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8942 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8943 r->environment = talloc_strdup(mem_ctx, environment);
8944 W_ERROR_HAVE_NO_MEMORY(r->environment);
8945 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8946 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8951 /****************************************************************************
8952 enumprintmonitors level 1.
8953 ****************************************************************************/
8955 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8956 union spoolss_MonitorInfo **info_p,
8961 union spoolss_MonitorInfo *info;
8962 WERROR result = WERR_OK;
8965 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8966 W_ERROR_HAVE_NO_MEMORY(info);
8970 result = fill_monitor_1(info, &info[0].info1,
8971 SPL_LOCAL_PORT /* FIXME */);
8972 if (!W_ERROR_IS_OK(result)) {
8976 result = fill_monitor_1(info, &info[1].info1,
8977 SPL_TCPIP_PORT /* FIXME */);
8978 if (!W_ERROR_IS_OK(result)) {
8982 for (i=0; i<*count; i++) {
8983 *needed += ndr_size_spoolss_MonitorInfo1(&info[i].info1, NULL, 0);
8986 if (*needed > offered) {
8987 result = WERR_INSUFFICIENT_BUFFER;
8992 if (!W_ERROR_IS_OK(result)) {
9003 /****************************************************************************
9004 enumprintmonitors level 2.
9005 ****************************************************************************/
9007 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9008 union spoolss_MonitorInfo **info_p,
9013 union spoolss_MonitorInfo *info;
9014 WERROR result = WERR_OK;
9017 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
9018 W_ERROR_HAVE_NO_MEMORY(info);
9022 result = fill_monitor_2(info, &info[0].info2,
9023 SPL_LOCAL_PORT, /* FIXME */
9024 "Windows NT X86", /* FIXME */
9026 if (!W_ERROR_IS_OK(result)) {
9030 result = fill_monitor_2(info, &info[1].info2,
9031 SPL_TCPIP_PORT, /* FIXME */
9032 "Windows NT X86", /* FIXME */
9034 if (!W_ERROR_IS_OK(result)) {
9038 for (i=0; i<*count; i++) {
9039 *needed += ndr_size_spoolss_MonitorInfo2(&info[i].info2, NULL, 0);
9042 if (*needed > offered) {
9043 result = WERR_INSUFFICIENT_BUFFER;
9048 if (!W_ERROR_IS_OK(result)) {
9059 /****************************************************************
9060 _spoolss_EnumMonitors
9061 ****************************************************************/
9063 WERROR _spoolss_EnumMonitors(pipes_struct *p,
9064 struct spoolss_EnumMonitors *r)
9066 /* that's an [in out] buffer */
9068 if (!r->in.buffer && (r->in.offered != 0)) {
9069 return WERR_INVALID_PARAM;
9072 DEBUG(5,("_spoolss_EnumMonitors\n"));
9075 * Enumerate the print monitors ...
9077 * Just reply with "Local Port", to keep NT happy
9078 * and I can use my nice printer checker.
9083 *r->out.info = NULL;
9085 switch (r->in.level) {
9087 return enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9088 r->in.offered, r->out.needed,
9091 return enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9092 r->in.offered, r->out.needed,
9095 return WERR_UNKNOWN_LEVEL;
9099 /****************************************************************************
9100 ****************************************************************************/
9102 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
9103 NT_PRINTER_INFO_LEVEL *ntprinter,
9104 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9109 JOB_INFO_1 *info_1=NULL;
9110 WERROR result = WERR_OK;
9112 info_1=SMB_MALLOC_P(JOB_INFO_1);
9114 if (info_1 == NULL) {
9118 for (i=0; i<count && found==False; i++) {
9119 if ((*queue)[i].job==(int)jobid)
9125 /* NT treats not found as bad param... yet another bad choice */
9126 return WERR_INVALID_PARAM;
9129 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
9131 *needed += spoolss_size_job_info_1(info_1);
9133 if (*needed > offered) {
9134 result = WERR_INSUFFICIENT_BUFFER;
9138 if (!rpcbuf_alloc_size(buffer, *needed)) {
9139 result = WERR_NOMEM;
9143 smb_io_job_info_1("", buffer, info_1, 0);
9151 /****************************************************************************
9152 ****************************************************************************/
9154 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9155 NT_PRINTER_INFO_LEVEL *ntprinter,
9156 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9163 DEVICEMODE *devmode = NULL;
9164 NT_DEVICEMODE *nt_devmode = NULL;
9166 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9169 ZERO_STRUCTP(info_2);
9171 for ( i=0; i<count && found==False; i++ )
9173 if ((*queue)[i].job == (int)jobid)
9178 /* NT treats not found as bad param... yet another bad
9180 result = WERR_INVALID_PARAM;
9185 * if the print job does not have a DEVMODE associated with it,
9186 * just use the one for the printer. A NULL devicemode is not
9187 * a failure condition
9190 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9191 devmode = construct_dev_mode(lp_const_servicename(snum));
9193 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9194 ZERO_STRUCTP( devmode );
9195 convert_nt_devicemode( devmode, nt_devmode );
9199 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9201 *needed += spoolss_size_job_info_2(info_2);
9203 if (*needed > offered) {
9204 result = WERR_INSUFFICIENT_BUFFER;
9208 if (!rpcbuf_alloc_size(buffer, *needed)) {
9209 result = WERR_NOMEM;
9213 smb_io_job_info_2("", buffer, info_2, 0);
9218 /* Cleanup allocated memory */
9220 free_job_info_2(info_2); /* Also frees devmode */
9226 /****************************************************************************
9227 ****************************************************************************/
9229 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9231 POLICY_HND *handle = &q_u->handle;
9232 uint32 jobid = q_u->jobid;
9233 uint32 level = q_u->level;
9234 RPC_BUFFER *buffer = NULL;
9235 uint32 offered = q_u->offered;
9236 uint32 *needed = &r_u->needed;
9237 WERROR wstatus = WERR_OK;
9238 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9241 print_queue_struct *queue = NULL;
9242 print_status_struct prt_status;
9244 /* that's an [in out] buffer */
9246 if (!q_u->buffer && (offered!=0)) {
9247 return WERR_INVALID_PARAM;
9250 if (offered > MAX_RPC_DATA_SIZE) {
9251 return WERR_INVALID_PARAM;
9254 rpcbuf_move(q_u->buffer, &r_u->buffer);
9255 buffer = r_u->buffer;
9257 DEBUG(5,("spoolss_getjob\n"));
9261 if (!get_printer_snum(p, handle, &snum, NULL))
9264 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9265 if ( !W_ERROR_IS_OK(wstatus) )
9268 count = print_queue_status(snum, &queue, &prt_status);
9270 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9271 count, prt_status.status, prt_status.message));
9275 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9276 buffer, offered, needed);
9279 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9280 buffer, offered, needed);
9283 wstatus = WERR_UNKNOWN_LEVEL;
9288 free_a_printer( &ntprinter, 2 );
9293 /****************************************************************
9294 _spoolss_GetPrinterDataEx
9296 From MSDN documentation of GetPrinterDataEx: pass request
9297 to GetPrinterData if key is "PrinterDriverData".
9298 ****************************************************************/
9300 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9301 struct spoolss_GetPrinterDataEx *r)
9303 POLICY_HND *handle = r->in.handle;
9305 const char *keyname = r->in.key_name;
9306 const char *valuename = r->in.value_name;
9308 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9310 NT_PRINTER_INFO_LEVEL *printer = NULL;
9312 WERROR status = WERR_OK;
9314 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9316 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9317 keyname, valuename));
9319 /* in case of problem, return some default values */
9325 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9326 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9327 status = WERR_BADFID;
9331 /* Is the handle to a printer or to the server? */
9333 if (Printer->printer_type == SPLHND_SERVER) {
9334 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9335 "Not implemented for server handles yet\n"));
9336 status = WERR_INVALID_PARAM;
9340 if ( !get_printer_snum(p,handle, &snum, NULL) )
9343 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9344 if ( !W_ERROR_IS_OK(status) )
9347 /* check to see if the keyname is valid */
9348 if ( !strlen(keyname) ) {
9349 status = WERR_INVALID_PARAM;
9353 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9354 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9355 "Invalid keyname [%s]\n", keyname ));
9356 free_a_printer( &printer, 2 );
9357 status = WERR_BADFILE;
9361 /* When given a new keyname, we should just create it */
9363 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9364 r->out.type, &data, r->out.needed,
9367 if (*r->out.needed > r->in.offered) {
9368 status = WERR_MORE_DATA;
9371 if (W_ERROR_IS_OK(status)) {
9372 memcpy(r->out.buffer, data, r->in.offered);
9377 free_a_printer( &printer, 2 );
9382 /****************************************************************
9383 _spoolss_SetPrinterDataEx
9384 ****************************************************************/
9386 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9387 struct spoolss_SetPrinterDataEx *r)
9389 POLICY_HND *handle = r->in.handle;
9390 NT_PRINTER_INFO_LEVEL *printer = NULL;
9392 WERROR status = WERR_OK;
9393 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9396 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9398 /* From MSDN documentation of SetPrinterDataEx: pass request to
9399 SetPrinterData if key is "PrinterDriverData" */
9402 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9403 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9407 if ( Printer->printer_type == SPLHND_SERVER ) {
9408 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9409 "Not implemented for server handles yet\n"));
9410 return WERR_INVALID_PARAM;
9413 if ( !get_printer_snum(p,handle, &snum, NULL) )
9417 * Access check : NT returns "access denied" if you make a
9418 * SetPrinterData call without the necessary privildge.
9419 * we were originally returning OK if nothing changed
9420 * which made Win2k issue **a lot** of SetPrinterData
9421 * when connecting to a printer --jerry
9424 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9426 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9427 "change denied by handle access permissions\n"));
9428 return WERR_ACCESS_DENIED;
9431 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9432 if (!W_ERROR_IS_OK(status))
9435 /* check for OID in valuename */
9437 if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9443 /* save the registry data */
9445 status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9446 r->in.type, r->in.buffer, r->in.offered );
9448 if ( W_ERROR_IS_OK(status) )
9450 /* save the OID if one was specified */
9452 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9453 r->in.key_name, SPOOL_OID_KEY);
9459 * I'm not checking the status here on purpose. Don't know
9460 * if this is right, but I'm returning the status from the
9461 * previous set_printer_dataex() call. I have no idea if
9462 * this is right. --jerry
9465 set_printer_dataex( printer, str, r->in.value_name,
9466 REG_SZ, (uint8 *)oid_string,
9467 strlen(oid_string)+1 );
9470 status = mod_a_printer(printer, 2);
9473 free_a_printer(&printer, 2);
9478 /****************************************************************
9479 _spoolss_DeletePrinterDataEx
9480 ****************************************************************/
9482 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9483 struct spoolss_DeletePrinterDataEx *r)
9485 POLICY_HND *handle = r->in.handle;
9486 NT_PRINTER_INFO_LEVEL *printer = NULL;
9488 WERROR status = WERR_OK;
9489 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9491 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9494 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9495 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9499 if (!get_printer_snum(p, handle, &snum, NULL))
9502 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9503 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9504 "printer properties change denied by handle\n"));
9505 return WERR_ACCESS_DENIED;
9508 if (!r->in.value_name || !r->in.key_name) {
9512 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9513 if (!W_ERROR_IS_OK(status))
9516 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9518 if ( W_ERROR_IS_OK(status) )
9519 mod_a_printer( printer, 2 );
9521 free_a_printer(&printer, 2);
9526 /********************************************************************
9527 * spoolss_enumprinterkey
9528 ********************************************************************/
9531 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9534 fstring *keynames = NULL;
9535 uint16 *enumkeys = NULL;
9538 POLICY_HND *handle = &q_u->handle;
9539 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9540 NT_PRINTER_DATA *data;
9541 NT_PRINTER_INFO_LEVEL *printer = NULL;
9543 WERROR status = WERR_BADFILE;
9546 DEBUG(4,("_spoolss_enumprinterkey\n"));
9549 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9553 if ( !get_printer_snum(p,handle, &snum, NULL) )
9556 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9557 if (!W_ERROR_IS_OK(status))
9560 /* get the list of subkey names */
9562 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9563 data = printer->info_2->data;
9565 num_keys = get_printer_subkeys( data, key, &keynames );
9567 if ( num_keys == -1 ) {
9568 status = WERR_BADFILE;
9572 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9574 r_u->needed = printerkey_len*2;
9576 if ( q_u->size < r_u->needed ) {
9577 status = WERR_MORE_DATA;
9581 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9582 status = WERR_NOMEM;
9588 if ( q_u->size < r_u->needed )
9589 status = WERR_MORE_DATA;
9592 free_a_printer( &printer, 2 );
9593 SAFE_FREE( keynames );
9598 /****************************************************************
9599 _spoolss_DeletePrinterKey
9600 ****************************************************************/
9602 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9603 struct spoolss_DeletePrinterKey *r)
9605 POLICY_HND *handle = r->in.handle;
9606 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9607 NT_PRINTER_INFO_LEVEL *printer = NULL;
9611 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9614 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9615 OUR_HANDLE(handle)));
9619 /* if keyname == NULL, return error */
9621 if ( !r->in.key_name )
9622 return WERR_INVALID_PARAM;
9624 if (!get_printer_snum(p, handle, &snum, NULL))
9627 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9628 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9629 "printer properties change denied by handle\n"));
9630 return WERR_ACCESS_DENIED;
9633 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9634 if (!W_ERROR_IS_OK(status))
9637 /* delete the key and all subneys */
9639 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9641 if ( W_ERROR_IS_OK(status) )
9642 status = mod_a_printer(printer, 2);
9644 free_a_printer( &printer, 2 );
9650 /********************************************************************
9651 * spoolss_enumprinterdataex
9652 ********************************************************************/
9654 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9656 POLICY_HND *handle = &q_u->handle;
9657 uint32 in_size = q_u->size;
9660 NT_PRINTER_INFO_LEVEL *printer = NULL;
9661 PRINTER_ENUM_VALUES *enum_values = NULL;
9662 NT_PRINTER_DATA *p_data;
9664 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9669 REGISTRY_VALUE *val;
9674 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9677 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9682 * first check for a keyname of NULL or "". Win2k seems to send
9683 * this a lot and we should send back WERR_INVALID_PARAM
9684 * no need to spend time looking up the printer in this case.
9688 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9689 if ( !strlen(key) ) {
9690 result = WERR_INVALID_PARAM;
9694 /* get the printer off of disk */
9696 if (!get_printer_snum(p,handle, &snum, NULL))
9699 ZERO_STRUCT(printer);
9700 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9701 if (!W_ERROR_IS_OK(result))
9704 /* now look for a match on the key name */
9706 p_data = printer->info_2->data;
9708 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9709 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9711 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9712 result = WERR_INVALID_PARAM;
9719 /* allocate the memory for the array of pointers -- if necessary */
9721 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9724 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9726 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9727 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9728 result = WERR_NOMEM;
9732 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9736 * loop through all params and build the array to pass
9737 * back to the client
9740 for ( i=0; i<num_entries; i++ )
9742 /* lookup the registry value */
9744 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9745 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9749 value_name = regval_name( val );
9750 init_unistr( &enum_values[i].valuename, value_name );
9751 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9752 enum_values[i].type = regval_type( val );
9754 data_len = regval_size( val );
9756 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9758 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9760 result = WERR_NOMEM;
9764 enum_values[i].data_len = data_len;
9766 /* keep track of the size of the array in bytes */
9768 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9771 /* housekeeping information in the reply */
9773 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9774 * the hand marshalled container size is a multiple
9775 * of 4 bytes for RPC alignment.
9779 needed += 4-(needed % 4);
9782 r_u->needed = needed;
9783 r_u->returned = num_entries;
9785 if (needed > in_size) {
9786 result = WERR_MORE_DATA;
9790 /* copy data into the reply */
9792 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9793 response buffer size is != the offered buffer size
9795 r_u->ctr.size = r_u->needed;
9797 r_u->ctr.size = in_size;
9799 r_u->ctr.size_of_array = r_u->returned;
9800 r_u->ctr.values = enum_values;
9804 free_a_printer(&printer, 2);
9809 /****************************************************************************
9810 ****************************************************************************/
9812 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9813 const char *servername,
9814 const char *environment,
9815 struct spoolss_PrintProcessorDirectoryInfo1 *r,
9822 werr = compose_spoolss_server_path(mem_ctx,
9825 SPOOLSS_PRTPROCS_PATH,
9827 if (!W_ERROR_IS_OK(werr)) {
9831 DEBUG(4,("print processor directory: [%s]\n", path));
9833 r->directory_name = path;
9835 *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(r, NULL, 0);
9837 if (*needed > offered) {
9839 return WERR_INSUFFICIENT_BUFFER;
9845 /****************************************************************
9846 _spoolss_GetPrintProcessorDirectory
9847 ****************************************************************/
9849 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9850 struct spoolss_GetPrintProcessorDirectory *r)
9854 /* that's an [in out] buffer */
9856 if (!r->in.buffer && (r->in.offered != 0)) {
9857 return WERR_INVALID_PARAM;
9860 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9865 /* r->in.level is ignored */
9867 result = getprintprocessordirectory_level_1(p->mem_ctx,
9870 &r->out.info->info1,
9873 if (!W_ERROR_IS_OK(result)) {
9874 TALLOC_FREE(r->out.info);
9880 /*******************************************************************
9881 ********************************************************************/
9883 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9884 const char *dllname)
9886 enum ndr_err_code ndr_err;
9887 struct spoolss_MonitorUi ui;
9889 ui.dll_name = dllname;
9891 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9892 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9893 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9894 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9896 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9899 /*******************************************************************
9900 Streams the monitor UI DLL name in UNICODE
9901 *******************************************************************/
9903 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9904 NT_USER_TOKEN *token, DATA_BLOB *in,
9905 DATA_BLOB *out, uint32_t *needed)
9907 const char *dllname = "tcpmonui.dll";
9909 *needed = (strlen(dllname)+1) * 2;
9911 if (out->length < *needed) {
9912 return WERR_INSUFFICIENT_BUFFER;
9915 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9922 /*******************************************************************
9923 ********************************************************************/
9925 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9926 struct spoolss_PortData1 *port1,
9927 const DATA_BLOB *buf)
9929 enum ndr_err_code ndr_err;
9930 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9931 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9932 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9933 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9935 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9938 /*******************************************************************
9939 ********************************************************************/
9941 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9942 struct spoolss_PortData2 *port2,
9943 const DATA_BLOB *buf)
9945 enum ndr_err_code ndr_err;
9946 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9947 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9948 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9949 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9951 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9954 /*******************************************************************
9955 Create a new TCP/IP port
9956 *******************************************************************/
9958 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9959 NT_USER_TOKEN *token, DATA_BLOB *in,
9960 DATA_BLOB *out, uint32_t *needed)
9962 struct spoolss_PortData1 port1;
9963 struct spoolss_PortData2 port2;
9964 char *device_uri = NULL;
9967 const char *portname;
9968 const char *hostaddress;
9970 uint32_t port_number;
9973 /* peek for spoolss_PortData version */
9975 if (!in || (in->length < (128 + 4))) {
9976 return WERR_GENERAL_FAILURE;
9979 version = IVAL(in->data, 128);
9985 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9989 portname = port1.portname;
9990 hostaddress = port1.hostaddress;
9991 queue = port1.queue;
9992 protocol = port1.protocol;
9993 port_number = port1.port_number;
9999 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10003 portname = port2.portname;
10004 hostaddress = port2.hostaddress;
10005 queue = port2.queue;
10006 protocol = port2.protocol;
10007 port_number = port2.port_number;
10011 DEBUG(1,("xcvtcp_addport: "
10012 "unknown version of port_data: %d\n", version));
10013 return WERR_UNKNOWN_PORT;
10016 /* create the device URI and call the add_port_hook() */
10018 switch (protocol) {
10019 case PROTOCOL_RAWTCP_TYPE:
10020 device_uri = talloc_asprintf(mem_ctx,
10021 "socket://%s:%d/", hostaddress,
10025 case PROTOCOL_LPR_TYPE:
10026 device_uri = talloc_asprintf(mem_ctx,
10027 "lpr://%s/%s", hostaddress, queue );
10031 return WERR_UNKNOWN_PORT;
10038 return add_port_hook(mem_ctx, token, portname, device_uri);
10041 /*******************************************************************
10042 *******************************************************************/
10044 struct xcv_api_table xcvtcp_cmds[] = {
10045 { "MonitorUI", xcvtcp_monitorui },
10046 { "AddPort", xcvtcp_addport},
10050 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10051 NT_USER_TOKEN *token, const char *command,
10058 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10060 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10061 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10062 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10065 return WERR_BADFUNC;
10068 /*******************************************************************
10069 *******************************************************************/
10070 #if 0 /* don't support management using the "Local Port" monitor */
10072 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10073 NT_USER_TOKEN *token, DATA_BLOB *in,
10074 DATA_BLOB *out, uint32_t *needed)
10076 const char *dllname = "localui.dll";
10078 *needed = (strlen(dllname)+1) * 2;
10080 if (out->length < *needed) {
10081 return WERR_INSUFFICIENT_BUFFER;
10084 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10091 /*******************************************************************
10092 *******************************************************************/
10094 struct xcv_api_table xcvlocal_cmds[] = {
10095 { "MonitorUI", xcvlocal_monitorui },
10099 struct xcv_api_table xcvlocal_cmds[] = {
10106 /*******************************************************************
10107 *******************************************************************/
10109 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10110 NT_USER_TOKEN *token, const char *command,
10111 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10116 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10118 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10119 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10120 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10122 return WERR_BADFUNC;
10125 /****************************************************************
10127 ****************************************************************/
10129 WERROR _spoolss_XcvData(pipes_struct *p,
10130 struct spoolss_XcvData *r)
10132 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10133 DATA_BLOB out_data = data_blob_null;
10137 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10138 OUR_HANDLE(r->in.handle)));
10139 return WERR_BADFID;
10142 /* Has to be a handle to the TCP/IP port monitor */
10144 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10145 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10146 return WERR_BADFID;
10149 /* requires administrative access to the server */
10151 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10152 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10153 return WERR_ACCESS_DENIED;
10156 /* Allocate the outgoing buffer */
10158 if (r->in.out_data_size) {
10159 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10160 if (out_data.data == NULL) {
10165 switch ( Printer->printer_type ) {
10166 case SPLHND_PORTMON_TCP:
10167 werror = process_xcvtcp_command(p->mem_ctx,
10168 p->server_info->ptok,
10169 r->in.function_name,
10170 &r->in.in_data, &out_data,
10173 case SPLHND_PORTMON_LOCAL:
10174 werror = process_xcvlocal_command(p->mem_ctx,
10175 p->server_info->ptok,
10176 r->in.function_name,
10177 &r->in.in_data, &out_data,
10181 werror = WERR_INVALID_PRINT_MONITOR;
10184 if (!W_ERROR_IS_OK(werror)) {
10188 *r->out.status_code = 0;
10190 memcpy(r->out.out_data, out_data.data, out_data.length);
10195 /****************************************************************
10196 _spoolss_AddPrintProcessor
10197 ****************************************************************/
10199 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10200 struct spoolss_AddPrintProcessor *r)
10202 /* for now, just indicate success and ignore the add. We'll
10203 automatically set the winprint processor for printer
10204 entries later. Used to debug the LexMark Optra S 1855 PCL
10210 /****************************************************************
10211 _spoolss_EnumPrinters
10212 ****************************************************************/
10214 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10215 struct spoolss_EnumPrinters *r)
10217 p->rng_fault_state = true;
10218 return WERR_NOT_SUPPORTED;
10221 /****************************************************************
10223 ****************************************************************/
10225 WERROR _spoolss_GetJob(pipes_struct *p,
10226 struct spoolss_GetJob *r)
10228 p->rng_fault_state = true;
10229 return WERR_NOT_SUPPORTED;
10232 /****************************************************************
10234 ****************************************************************/
10236 WERROR _spoolss_EnumJobs(pipes_struct *p,
10237 struct spoolss_EnumJobs *r)
10239 p->rng_fault_state = true;
10240 return WERR_NOT_SUPPORTED;
10243 /****************************************************************
10244 _spoolss_AddPrinter
10245 ****************************************************************/
10247 WERROR _spoolss_AddPrinter(pipes_struct *p,
10248 struct spoolss_AddPrinter *r)
10250 p->rng_fault_state = true;
10251 return WERR_NOT_SUPPORTED;
10254 /****************************************************************
10255 _spoolss_GetPrinter
10256 ****************************************************************/
10258 WERROR _spoolss_GetPrinter(pipes_struct *p,
10259 struct spoolss_GetPrinter *r)
10261 p->rng_fault_state = true;
10262 return WERR_NOT_SUPPORTED;
10265 /****************************************************************
10266 _spoolss_EnumPrinterDrivers
10267 ****************************************************************/
10269 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10270 struct spoolss_EnumPrinterDrivers *r)
10272 p->rng_fault_state = true;
10273 return WERR_NOT_SUPPORTED;
10276 /****************************************************************
10277 _spoolss_GetPrinterDriver
10278 ****************************************************************/
10280 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10281 struct spoolss_GetPrinterDriver *r)
10283 p->rng_fault_state = true;
10284 return WERR_NOT_SUPPORTED;
10287 /****************************************************************
10288 _spoolss_ReadPrinter
10289 ****************************************************************/
10291 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10292 struct spoolss_ReadPrinter *r)
10294 p->rng_fault_state = true;
10295 return WERR_NOT_SUPPORTED;
10298 /****************************************************************
10299 _spoolss_GetPrinterData
10300 ****************************************************************/
10302 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10303 struct spoolss_GetPrinterData *r)
10305 p->rng_fault_state = true;
10306 return WERR_NOT_SUPPORTED;
10309 /****************************************************************
10310 _spoolss_SetPrinterData
10311 ****************************************************************/
10313 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10314 struct spoolss_SetPrinterData *r)
10316 p->rng_fault_state = true;
10317 return WERR_NOT_SUPPORTED;
10320 /****************************************************************
10321 _spoolss_WaitForPrinterChange
10322 ****************************************************************/
10324 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10325 struct spoolss_WaitForPrinterChange *r)
10327 p->rng_fault_state = true;
10328 return WERR_NOT_SUPPORTED;
10331 /****************************************************************
10333 ****************************************************************/
10335 WERROR _spoolss_AddPort(pipes_struct *p,
10336 struct spoolss_AddPort *r)
10338 p->rng_fault_state = true;
10339 return WERR_NOT_SUPPORTED;
10342 /****************************************************************
10343 _spoolss_ConfigurePort
10344 ****************************************************************/
10346 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10347 struct spoolss_ConfigurePort *r)
10349 p->rng_fault_state = true;
10350 return WERR_NOT_SUPPORTED;
10353 /****************************************************************
10354 _spoolss_DeletePort
10355 ****************************************************************/
10357 WERROR _spoolss_DeletePort(pipes_struct *p,
10358 struct spoolss_DeletePort *r)
10360 p->rng_fault_state = true;
10361 return WERR_NOT_SUPPORTED;
10364 /****************************************************************
10365 _spoolss_CreatePrinterIC
10366 ****************************************************************/
10368 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10369 struct spoolss_CreatePrinterIC *r)
10371 p->rng_fault_state = true;
10372 return WERR_NOT_SUPPORTED;
10375 /****************************************************************
10376 _spoolss_PlayGDIScriptOnPrinterIC
10377 ****************************************************************/
10379 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10380 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10382 p->rng_fault_state = true;
10383 return WERR_NOT_SUPPORTED;
10386 /****************************************************************
10387 _spoolss_DeletePrinterIC
10388 ****************************************************************/
10390 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10391 struct spoolss_DeletePrinterIC *r)
10393 p->rng_fault_state = true;
10394 return WERR_NOT_SUPPORTED;
10397 /****************************************************************
10398 _spoolss_AddPrinterConnection
10399 ****************************************************************/
10401 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10402 struct spoolss_AddPrinterConnection *r)
10404 p->rng_fault_state = true;
10405 return WERR_NOT_SUPPORTED;
10408 /****************************************************************
10409 _spoolss_DeletePrinterConnection
10410 ****************************************************************/
10412 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10413 struct spoolss_DeletePrinterConnection *r)
10415 p->rng_fault_state = true;
10416 return WERR_NOT_SUPPORTED;
10419 /****************************************************************
10420 _spoolss_PrinterMessageBox
10421 ****************************************************************/
10423 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10424 struct spoolss_PrinterMessageBox *r)
10426 p->rng_fault_state = true;
10427 return WERR_NOT_SUPPORTED;
10430 /****************************************************************
10431 _spoolss_AddMonitor
10432 ****************************************************************/
10434 WERROR _spoolss_AddMonitor(pipes_struct *p,
10435 struct spoolss_AddMonitor *r)
10437 p->rng_fault_state = true;
10438 return WERR_NOT_SUPPORTED;
10441 /****************************************************************
10442 _spoolss_DeleteMonitor
10443 ****************************************************************/
10445 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10446 struct spoolss_DeleteMonitor *r)
10448 p->rng_fault_state = true;
10449 return WERR_NOT_SUPPORTED;
10452 /****************************************************************
10453 _spoolss_DeletePrintProcessor
10454 ****************************************************************/
10456 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10457 struct spoolss_DeletePrintProcessor *r)
10459 p->rng_fault_state = true;
10460 return WERR_NOT_SUPPORTED;
10463 /****************************************************************
10464 _spoolss_AddPrintProvidor
10465 ****************************************************************/
10467 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10468 struct spoolss_AddPrintProvidor *r)
10470 p->rng_fault_state = true;
10471 return WERR_NOT_SUPPORTED;
10474 /****************************************************************
10475 _spoolss_DeletePrintProvidor
10476 ****************************************************************/
10478 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10479 struct spoolss_DeletePrintProvidor *r)
10481 p->rng_fault_state = true;
10482 return WERR_NOT_SUPPORTED;
10485 /****************************************************************
10486 _spoolss_GetPrinterDriver2
10487 ****************************************************************/
10489 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10490 struct spoolss_GetPrinterDriver2 *r)
10492 p->rng_fault_state = true;
10493 return WERR_NOT_SUPPORTED;
10496 /****************************************************************
10497 _spoolss_FindFirstPrinterChangeNotification
10498 ****************************************************************/
10500 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10501 struct spoolss_FindFirstPrinterChangeNotification *r)
10503 p->rng_fault_state = true;
10504 return WERR_NOT_SUPPORTED;
10507 /****************************************************************
10508 _spoolss_FindNextPrinterChangeNotification
10509 ****************************************************************/
10511 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10512 struct spoolss_FindNextPrinterChangeNotification *r)
10514 p->rng_fault_state = true;
10515 return WERR_NOT_SUPPORTED;
10518 /****************************************************************
10519 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10520 ****************************************************************/
10522 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10523 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10525 p->rng_fault_state = true;
10526 return WERR_NOT_SUPPORTED;
10529 /****************************************************************
10530 _spoolss_ReplyOpenPrinter
10531 ****************************************************************/
10533 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10534 struct spoolss_ReplyOpenPrinter *r)
10536 p->rng_fault_state = true;
10537 return WERR_NOT_SUPPORTED;
10540 /****************************************************************
10541 _spoolss_RouterReplyPrinter
10542 ****************************************************************/
10544 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10545 struct spoolss_RouterReplyPrinter *r)
10547 p->rng_fault_state = true;
10548 return WERR_NOT_SUPPORTED;
10551 /****************************************************************
10552 _spoolss_ReplyClosePrinter
10553 ****************************************************************/
10555 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10556 struct spoolss_ReplyClosePrinter *r)
10558 p->rng_fault_state = true;
10559 return WERR_NOT_SUPPORTED;
10562 /****************************************************************
10564 ****************************************************************/
10566 WERROR _spoolss_AddPortEx(pipes_struct *p,
10567 struct spoolss_AddPortEx *r)
10569 p->rng_fault_state = true;
10570 return WERR_NOT_SUPPORTED;
10573 /****************************************************************
10574 _spoolss_RouterFindFirstPrinterChangeNotification
10575 ****************************************************************/
10577 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10578 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10580 p->rng_fault_state = true;
10581 return WERR_NOT_SUPPORTED;
10584 /****************************************************************
10585 _spoolss_SpoolerInit
10586 ****************************************************************/
10588 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10589 struct spoolss_SpoolerInit *r)
10591 p->rng_fault_state = true;
10592 return WERR_NOT_SUPPORTED;
10595 /****************************************************************
10596 _spoolss_ResetPrinterEx
10597 ****************************************************************/
10599 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10600 struct spoolss_ResetPrinterEx *r)
10602 p->rng_fault_state = true;
10603 return WERR_NOT_SUPPORTED;
10606 /****************************************************************
10607 _spoolss_RouterReplyPrinterEx
10608 ****************************************************************/
10610 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10611 struct spoolss_RouterReplyPrinterEx *r)
10613 p->rng_fault_state = true;
10614 return WERR_NOT_SUPPORTED;
10617 /****************************************************************
10619 ****************************************************************/
10621 WERROR _spoolss_44(pipes_struct *p,
10622 struct spoolss_44 *r)
10624 p->rng_fault_state = true;
10625 return WERR_NOT_SUPPORTED;
10628 /****************************************************************
10630 ****************************************************************/
10632 WERROR _spoolss_47(pipes_struct *p,
10633 struct spoolss_47 *r)
10635 p->rng_fault_state = true;
10636 return WERR_NOT_SUPPORTED;
10639 /****************************************************************
10640 _spoolss_EnumPrinterData
10641 ****************************************************************/
10643 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10644 struct spoolss_EnumPrinterData *r)
10646 p->rng_fault_state = true;
10647 return WERR_NOT_SUPPORTED;
10650 /****************************************************************
10652 ****************************************************************/
10654 WERROR _spoolss_4a(pipes_struct *p,
10655 struct spoolss_4a *r)
10657 p->rng_fault_state = true;
10658 return WERR_NOT_SUPPORTED;
10661 /****************************************************************
10663 ****************************************************************/
10665 WERROR _spoolss_4b(pipes_struct *p,
10666 struct spoolss_4b *r)
10668 p->rng_fault_state = true;
10669 return WERR_NOT_SUPPORTED;
10672 /****************************************************************
10674 ****************************************************************/
10676 WERROR _spoolss_4c(pipes_struct *p,
10677 struct spoolss_4c *r)
10679 p->rng_fault_state = true;
10680 return WERR_NOT_SUPPORTED;
10683 /****************************************************************
10684 _spoolss_EnumPrinterDataEx
10685 ****************************************************************/
10687 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10688 struct spoolss_EnumPrinterDataEx *r)
10690 p->rng_fault_state = true;
10691 return WERR_NOT_SUPPORTED;
10694 /****************************************************************
10695 _spoolss_EnumPrinterKey
10696 ****************************************************************/
10698 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10699 struct spoolss_EnumPrinterKey *r)
10701 p->rng_fault_state = true;
10702 return WERR_NOT_SUPPORTED;
10705 /****************************************************************
10707 ****************************************************************/
10709 WERROR _spoolss_53(pipes_struct *p,
10710 struct spoolss_53 *r)
10712 p->rng_fault_state = true;
10713 return WERR_NOT_SUPPORTED;
10716 /****************************************************************
10718 ****************************************************************/
10720 WERROR _spoolss_55(pipes_struct *p,
10721 struct spoolss_55 *r)
10723 p->rng_fault_state = true;
10724 return WERR_NOT_SUPPORTED;
10727 /****************************************************************
10729 ****************************************************************/
10731 WERROR _spoolss_56(pipes_struct *p,
10732 struct spoolss_56 *r)
10734 p->rng_fault_state = true;
10735 return WERR_NOT_SUPPORTED;
10738 /****************************************************************
10740 ****************************************************************/
10742 WERROR _spoolss_57(pipes_struct *p,
10743 struct spoolss_57 *r)
10745 p->rng_fault_state = true;
10746 return WERR_NOT_SUPPORTED;
10749 /****************************************************************
10751 ****************************************************************/
10753 WERROR _spoolss_5a(pipes_struct *p,
10754 struct spoolss_5a *r)
10756 p->rng_fault_state = true;
10757 return WERR_NOT_SUPPORTED;
10760 /****************************************************************
10762 ****************************************************************/
10764 WERROR _spoolss_5b(pipes_struct *p,
10765 struct spoolss_5b *r)
10767 p->rng_fault_state = true;
10768 return WERR_NOT_SUPPORTED;
10771 /****************************************************************
10773 ****************************************************************/
10775 WERROR _spoolss_5c(pipes_struct *p,
10776 struct spoolss_5c *r)
10778 p->rng_fault_state = true;
10779 return WERR_NOT_SUPPORTED;
10782 /****************************************************************
10784 ****************************************************************/
10786 WERROR _spoolss_5d(pipes_struct *p,
10787 struct spoolss_5d *r)
10789 p->rng_fault_state = true;
10790 return WERR_NOT_SUPPORTED;
10793 /****************************************************************
10795 ****************************************************************/
10797 WERROR _spoolss_5e(pipes_struct *p,
10798 struct spoolss_5e *r)
10800 p->rng_fault_state = true;
10801 return WERR_NOT_SUPPORTED;
10804 /****************************************************************
10806 ****************************************************************/
10808 WERROR _spoolss_5f(pipes_struct *p,
10809 struct spoolss_5f *r)
10811 p->rng_fault_state = true;
10812 return WERR_NOT_SUPPORTED;