2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33 ((info)?ndr_size_##fn(info, level, ic, 0):0)
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44 extern userdom_struct current_user_info;
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57 const char *long_archi;
58 const char *short_archi;
62 static Printer_entry *printers_list;
64 typedef struct _counter_printer_0 {
65 struct _counter_printer_0 *next;
66 struct _counter_printer_0 *prev;
72 static counter_printer_0 *counter_list;
74 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
75 static uint32 smb_connections=0;
78 /* in printing/nt_printing.c */
80 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
82 /* API table for Xcv Monitor functions */
84 struct xcv_api_table {
86 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
89 /********************************************************************
90 * Canonicalize servername.
91 ********************************************************************/
93 static const char *canon_servername(const char *servername)
95 const char *pservername = servername;
96 while (*pservername == '\\') {
102 /* translate between internal status numbers and NT status numbers */
103 static int nt_printj_status(int v)
109 return JOB_STATUS_PAUSED;
111 return JOB_STATUS_SPOOLING;
113 return JOB_STATUS_PRINTING;
115 return JOB_STATUS_ERROR;
117 return JOB_STATUS_DELETING;
119 return JOB_STATUS_OFFLINE;
121 return JOB_STATUS_PAPEROUT;
123 return JOB_STATUS_PRINTED;
125 return JOB_STATUS_DELETED;
127 return JOB_STATUS_BLOCKED_DEVQ;
128 case LPQ_USER_INTERVENTION:
129 return JOB_STATUS_USER_INTERVENTION;
134 static int nt_printq_status(int v)
138 return PRINTER_STATUS_PAUSED;
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
157 * Tell the specific printing tdb we no longer want messages for this printer
158 * by deregistering our PID.
161 if (!print_notify_deregister_pid(snum))
162 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
164 /* weird if the test succeds !!! */
165 if (smb_connections==0) {
166 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
170 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
173 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
174 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
175 win_errstr(result)));
177 /* if it's the last connection, deconnect the IPC$ share */
178 if (smb_connections==1) {
180 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
181 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
183 messaging_deregister(smbd_messaging_context(),
184 MSG_PRINTER_NOTIFY2, NULL);
186 /* Tell the connections db we're no longer interested in
187 * printer notify messages. */
189 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
195 /****************************************************************************
196 Functions to free a printer entry datastruct.
197 ****************************************************************************/
199 static int printer_entry_destructor(Printer_entry *Printer)
201 if (Printer->notify.client_connected==True) {
204 if ( Printer->printer_type == SPLHND_SERVER) {
206 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
207 } else if (Printer->printer_type == SPLHND_PRINTER) {
208 snum = print_queue_snum(Printer->sharename);
210 srv_spoolss_replycloseprinter(snum,
211 &Printer->notify.client_hnd);
215 Printer->notify.flags=0;
216 Printer->notify.options=0;
217 Printer->notify.localmachine[0]='\0';
218 Printer->notify.printerlocal=0;
219 TALLOC_FREE(Printer->notify.option);
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 /* Remove from the internal list. */
226 DLIST_REMOVE(printers_list, Printer);
230 /****************************************************************************
231 find printer index by handle
232 ****************************************************************************/
234 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
236 Printer_entry *find_printer = NULL;
238 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
239 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
246 /****************************************************************************
247 Close printer index by handle.
248 ****************************************************************************/
250 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
252 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
255 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
259 close_policy_hnd(p, hnd);
264 /****************************************************************************
265 Delete a printer given a handle.
266 ****************************************************************************/
268 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
270 char *cmd = lp_deleteprinter_cmd();
271 char *command = NULL;
273 SE_PRIV se_printop = SE_PRINT_OPERATOR;
274 bool is_print_op = False;
276 /* can't fail if we don't try */
281 command = talloc_asprintf(ctx,
288 is_print_op = user_has_privileges( token, &se_printop );
290 DEBUG(10,("Running [%s]\n", command));
292 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
297 if ( (ret = smbrun(command, NULL)) == 0 ) {
298 /* Tell everyone we updated smb.conf. */
299 message_send_all(smbd_messaging_context(),
300 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
306 /********** END SePrintOperatorPrivlege BLOCK **********/
308 DEBUGADD(10,("returned [%d]\n", ret));
310 TALLOC_FREE(command);
313 return WERR_BADFID; /* What to return here? */
315 /* go ahead and re-read the services immediately */
316 reload_services( False );
318 if ( lp_servicenumber( sharename ) < 0 )
319 return WERR_ACCESS_DENIED;
324 /****************************************************************************
325 Delete a printer given a handle.
326 ****************************************************************************/
328 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
330 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
333 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
338 * It turns out that Windows allows delete printer on a handle
339 * opened by an admin user, then used on a pipe handle created
340 * by an anonymous user..... but they're working on security.... riiight !
344 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
345 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
346 return WERR_ACCESS_DENIED;
349 /* this does not need a become root since the access check has been
350 done on the handle already */
352 if (del_a_printer( Printer->sharename ) != 0) {
353 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
357 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
358 Printer->sharename );
361 /****************************************************************************
362 Return the snum of a printer corresponding to an handle.
363 ****************************************************************************/
365 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
366 struct share_params **params)
368 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
371 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
375 switch (Printer->printer_type) {
377 DEBUG(4,("short name:%s\n", Printer->sharename));
378 *number = print_queue_snum(Printer->sharename);
379 return (*number != -1);
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
401 /* it's a print server */
402 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = SPLHND_SERVER;
406 /* it's a printer (set_printer_hnd_name() will handle port monitors */
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = SPLHND_PRINTER;
415 /****************************************************************************
416 Set printer handle name.. Accept names like \\server, \\server\printer,
417 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
418 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
419 XcvDataPort() interface.
420 ****************************************************************************/
422 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
425 int n_services=lp_numservices();
426 char *aprinter, *printername;
427 const char *servername;
430 NT_PRINTER_INFO_LEVEL *printer = NULL;
433 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
435 aprinter = handlename;
436 if ( *handlename == '\\' ) {
437 servername = canon_servername(handlename);
438 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
446 /* save the servername to fill in replies on this handle */
448 if ( !is_myname_or_ipaddr( servername ) )
451 fstrcpy( Printer->servername, servername );
453 if ( Printer->printer_type == SPLHND_SERVER )
456 if ( Printer->printer_type != SPLHND_PRINTER )
459 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
461 /* check for the Port Monitor Interface */
463 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
464 Printer->printer_type = SPLHND_PORTMON_TCP;
465 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
468 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
469 Printer->printer_type = SPLHND_PORTMON_LOCAL;
470 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
474 /* Search all sharenames first as this is easier than pulling
475 the printer_info_2 off of disk. Don't use find_service() since
476 that calls out to map_username() */
478 /* do another loop to look for printernames */
480 for (snum=0; !found && snum<n_services; snum++) {
482 /* no point going on if this is not a printer */
484 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
487 fstrcpy(sname, lp_servicename(snum));
488 if ( strequal( aprinter, sname ) ) {
493 /* no point looking up the printer object if
494 we aren't allowing printername != sharename */
496 if ( lp_force_printername(snum) )
499 fstrcpy(sname, lp_servicename(snum));
503 /* This call doesn't fill in the location or comment from
504 * a CUPS server for efficiency with large numbers of printers.
508 result = get_a_printer_search( NULL, &printer, 2, sname );
509 if ( !W_ERROR_IS_OK(result) ) {
510 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
511 sname, win_errstr(result)));
515 /* printername is always returned as \\server\printername */
516 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
517 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
518 printer->info_2->printername));
519 free_a_printer( &printer, 2);
525 if ( strequal(printername, aprinter) ) {
526 free_a_printer( &printer, 2);
531 DEBUGADD(10, ("printername: %s\n", printername));
533 free_a_printer( &printer, 2);
536 free_a_printer( &printer, 2);
539 DEBUGADD(4,("Printer not found\n"));
543 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
545 fstrcpy(Printer->sharename, sname);
550 /****************************************************************************
551 Find first available printer slot. creates a printer handle for you.
552 ****************************************************************************/
554 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
556 Printer_entry *new_printer;
558 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
560 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
561 if (new_printer == NULL) {
564 talloc_set_destructor(new_printer, printer_entry_destructor);
566 if (!create_policy_hnd(p, hnd, new_printer)) {
567 TALLOC_FREE(new_printer);
571 /* Add to the internal list. */
572 DLIST_ADD(printers_list, new_printer);
574 new_printer->notify.option=NULL;
576 if (!set_printer_hnd_printertype(new_printer, name)) {
577 close_printer_handle(p, hnd);
581 if (!set_printer_hnd_name(new_printer, name)) {
582 close_printer_handle(p, hnd);
586 new_printer->access_granted = access_granted;
588 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
593 /***************************************************************************
594 check to see if the client motify handle is monitoring the notification
595 given by (notify_type, notify_field).
596 **************************************************************************/
598 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
604 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
607 struct spoolss_NotifyOption *option = p->notify.option;
611 * Flags should always be zero when the change notify
612 * is registered by the client's spooler. A user Win32 app
613 * might use the flags though instead of the NOTIFY_OPTION_INFO
622 return is_monitoring_event_flags(
623 p->notify.flags, notify_type, notify_field);
625 for (i = 0; i < option->count; i++) {
627 /* Check match for notify_type */
629 if (option->types[i].type != notify_type)
632 /* Check match for field */
634 for (j = 0; j < option->types[i].count; j++) {
635 if (option->types[i].fields[j].field == notify_field) {
641 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
642 p->servername, p->sharename, notify_type, notify_field));
647 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
648 _data->data.integer[0] = _integer; \
649 _data->data.integer[1] = 0;
652 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
653 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
654 if (!_data->data.string.string) {\
655 _data->data.string.size = 0; \
657 _data->data.string.size = strlen_m_term(_p) * 2;
659 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
660 _data->data.devmode.devmode = _devmode;
662 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
663 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
664 if (!_data->data.sd.sd) { \
665 _data->data.sd.sd_size = 0; \
667 _data->data.sd.sd_size = _size;
669 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
674 struct spoolss_Time st;
678 if (!init_systemtime(&st, t)) {
682 p = talloc_array(mem_ctx, char, len);
688 * Systemtime must be linearized as a set of UINT16's.
689 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
692 SSVAL(p, 0, st.year);
693 SSVAL(p, 2, st.month);
694 SSVAL(p, 4, st.day_of_week);
696 SSVAL(p, 8, st.hour);
697 SSVAL(p, 10, st.minute);
698 SSVAL(p, 12, st.second);
699 SSVAL(p, 14, st.millisecond);
705 /* Convert a notification message to a struct spoolss_Notify */
707 static void notify_one_value(struct spoolss_notify_msg *msg,
708 struct spoolss_Notify *data,
711 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
714 static void notify_string(struct spoolss_notify_msg *msg,
715 struct spoolss_Notify *data,
718 /* The length of the message includes the trailing \0 */
720 data->data.string.size = msg->len * 2;
721 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
722 if (!data->data.string.string) {
723 data->data.string.size = 0;
728 static void notify_system_time(struct spoolss_notify_msg *msg,
729 struct spoolss_Notify *data,
732 data->data.string.string = NULL;
733 data->data.string.size = 0;
735 if (msg->len != sizeof(time_t)) {
736 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
741 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
742 &data->data.string.string,
743 &data->data.string.size);
746 struct notify2_message_table {
748 void (*fn)(struct spoolss_notify_msg *msg,
749 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
752 static struct notify2_message_table printer_notify_table[] = {
753 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
754 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
755 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
756 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
757 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
758 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
759 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
760 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
761 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
762 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
763 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
764 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
765 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
766 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
767 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
768 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
769 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
770 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
771 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
774 static struct notify2_message_table job_notify_table[] = {
775 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
776 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
777 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
778 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
779 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
780 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
781 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
782 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
783 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
784 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
785 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
786 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
787 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
788 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
789 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
790 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
791 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
792 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
793 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
794 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
795 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
796 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
797 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
798 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
802 /***********************************************************************
803 Allocate talloc context for container object
804 **********************************************************************/
806 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
811 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
816 /***********************************************************************
817 release all allocated memory and zero out structure
818 **********************************************************************/
820 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 talloc_destroy(ctr->ctx);
833 /***********************************************************************
834 **********************************************************************/
836 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 /***********************************************************************
845 **********************************************************************/
847 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
849 if ( !ctr || !ctr->msg_groups )
852 if ( idx >= ctr->num_groups )
855 return &ctr->msg_groups[idx];
859 /***********************************************************************
860 How many groups of change messages do we have ?
861 **********************************************************************/
863 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
868 return ctr->num_groups;
871 /***********************************************************************
872 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
873 **********************************************************************/
875 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
877 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
878 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
879 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
885 /* loop over all groups looking for a matching printer name */
887 for ( i=0; i<ctr->num_groups; i++ ) {
888 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
892 /* add a new group? */
894 if ( i == ctr->num_groups ) {
897 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
898 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
901 ctr->msg_groups = groups;
903 /* clear the new entry and set the printer name */
905 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
906 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
909 /* add the change messages; 'i' is the correct index now regardless */
911 msg_grp = &ctr->msg_groups[i];
915 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
916 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
919 msg_grp->msgs = msg_list;
921 new_slot = msg_grp->num_msgs-1;
922 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
924 /* need to allocate own copy of data */
927 msg_grp->msgs[new_slot].notify.data = (char *)
928 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
930 return ctr->num_groups;
933 /***********************************************************************
934 Send a change notication message on all handles which have a call
936 **********************************************************************/
938 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
941 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
942 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
943 SPOOLSS_NOTIFY_MSG *messages;
944 int sending_msg_count;
947 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
951 messages = msg_group->msgs;
954 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
958 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
960 /* loop over all printers */
962 for (p = printers_list; p; p = p->next) {
963 struct spoolss_Notify *notifies;
968 /* Is there notification on this handle? */
970 if ( !p->notify.client_connected )
973 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
975 /* For this printer? Print servers always receive
978 if ( ( p->printer_type == SPLHND_PRINTER ) &&
979 ( !strequal(msg_group->printername, p->sharename) ) )
982 DEBUG(10,("Our printer\n"));
984 /* allocate the max entries possible */
986 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
991 /* build the array of change notifications */
993 sending_msg_count = 0;
995 for ( i=0; i<msg_group->num_msgs; i++ ) {
996 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
998 /* Are we monitoring this event? */
1000 if (!is_monitoring_event(p, msg->type, msg->field))
1003 sending_msg_count++;
1006 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1007 msg->type, msg->field, p->sharename));
1010 * if the is a printer notification handle and not a job notification
1011 * type, then set the id to 0. Other wise just use what was specified
1014 * When registering change notification on a print server handle
1015 * we always need to send back the id (snum) matching the printer
1016 * for which the change took place. For change notify registered
1017 * on a printer handle, this does not matter and the id should be 0.
1022 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028 /* Convert unix jobid to smb jobid */
1030 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1031 id = sysjob_to_jobid(msg->id);
1034 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1039 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1042 case PRINTER_NOTIFY_TYPE:
1043 if ( printer_notify_table[msg->field].fn )
1044 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1047 case JOB_NOTIFY_TYPE:
1048 if ( job_notify_table[msg->field].fn )
1049 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1053 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1060 if ( sending_msg_count ) {
1063 union spoolss_ReplyPrinterInfo info;
1064 struct spoolss_NotifyInfo info0;
1065 uint32_t reply_result;
1067 info0.version = 0x2;
1068 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1069 info0.count = count;
1070 info0.notifies = notifies;
1072 info.info0 = &info0;
1074 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1075 &p->notify.client_hnd,
1076 p->notify.change, /* color */
1079 0, /* reply_type, must be 0 */
1082 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1083 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1084 notify_cli_pipe->srv_name_slash,
1087 switch (reply_result) {
1090 case PRINTER_NOTIFY_INFO_DISCARDED:
1091 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1092 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1101 DEBUG(8,("send_notify2_changes: Exit...\n"));
1105 /***********************************************************************
1106 **********************************************************************/
1108 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1111 uint32 tv_sec, tv_usec;
1114 /* Unpack message */
1116 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1119 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1121 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1124 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1125 &msg->notify.value[0], &msg->notify.value[1]);
1127 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1128 &msg->len, &msg->notify.data);
1130 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1131 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1133 tv->tv_sec = tv_sec;
1134 tv->tv_usec = tv_usec;
1137 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1138 msg->notify.value[1]));
1140 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1145 /********************************************************************
1146 Receive a notify2 message list
1147 ********************************************************************/
1149 static void receive_notify2_message_list(struct messaging_context *msg,
1152 struct server_id server_id,
1155 size_t msg_count, i;
1156 char *buf = (char *)data->data;
1159 SPOOLSS_NOTIFY_MSG notify;
1160 SPOOLSS_NOTIFY_MSG_CTR messages;
1163 if (data->length < 4) {
1164 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1168 msg_count = IVAL(buf, 0);
1171 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1173 if (msg_count == 0) {
1174 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1178 /* initialize the container */
1180 ZERO_STRUCT( messages );
1181 notify_msg_ctr_init( &messages );
1184 * build message groups for each printer identified
1185 * in a change_notify msg. Remember that a PCN message
1186 * includes the handle returned for the srv_spoolss_replyopenprinter()
1187 * call. Therefore messages are grouped according to printer handle.
1190 for ( i=0; i<msg_count; i++ ) {
1191 struct timeval msg_tv;
1193 if (msg_ptr + 4 - buf > data->length) {
1194 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1198 msg_len = IVAL(msg_ptr,0);
1201 if (msg_ptr + msg_len - buf > data->length) {
1202 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1206 /* unpack messages */
1208 ZERO_STRUCT( notify );
1209 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1212 /* add to correct list in container */
1214 notify_msg_ctr_addmsg( &messages, ¬ify );
1216 /* free memory that might have been allocated by notify2_unpack_msg() */
1218 if ( notify.len != 0 )
1219 SAFE_FREE( notify.notify.data );
1222 /* process each group of messages */
1224 num_groups = notify_msg_ctr_numgroups( &messages );
1225 for ( i=0; i<num_groups; i++ )
1226 send_notify2_changes( &messages, i );
1231 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1233 notify_msg_ctr_destroy( &messages );
1238 /********************************************************************
1239 Send a message to ourself about new driver being installed
1240 so we can upgrade the information for each printer bound to this
1242 ********************************************************************/
1244 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1246 int len = strlen(drivername);
1251 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1254 messaging_send_buf(smbd_messaging_context(), procid_self(),
1255 MSG_PRINTER_DRVUPGRADE,
1256 (uint8 *)drivername, len+1);
1261 /**********************************************************************
1262 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1263 over all printers, upgrading ones as necessary
1264 **********************************************************************/
1266 void do_drv_upgrade_printer(struct messaging_context *msg,
1269 struct server_id server_id,
1274 int n_services = lp_numservices();
1277 len = MIN(data->length,sizeof(drivername)-1);
1278 strncpy(drivername, (const char *)data->data, len);
1280 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1282 /* Iterate the printer list */
1284 for (snum=0; snum<n_services; snum++)
1286 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1289 NT_PRINTER_INFO_LEVEL *printer = NULL;
1291 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1292 if (!W_ERROR_IS_OK(result))
1295 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1297 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1299 /* all we care about currently is the change_id */
1301 result = mod_a_printer(printer, 2);
1302 if (!W_ERROR_IS_OK(result)) {
1303 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1304 win_errstr(result)));
1308 free_a_printer(&printer, 2);
1315 /********************************************************************
1316 Update the cache for all printq's with a registered client
1318 ********************************************************************/
1320 void update_monitored_printq_cache( void )
1322 Printer_entry *printer = printers_list;
1325 /* loop through all printers and update the cache where
1326 client_connected == True */
1329 if ( (printer->printer_type == SPLHND_PRINTER)
1330 && printer->notify.client_connected )
1332 snum = print_queue_snum(printer->sharename);
1333 print_queue_status( snum, NULL, NULL );
1336 printer = printer->next;
1341 /********************************************************************
1342 Send a message to ourself about new driver being installed
1343 so we can upgrade the information for each printer bound to this
1345 ********************************************************************/
1347 static bool srv_spoolss_reset_printerdata(char* drivername)
1349 int len = strlen(drivername);
1354 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1357 messaging_send_buf(smbd_messaging_context(), procid_self(),
1358 MSG_PRINTERDATA_INIT_RESET,
1359 (uint8 *)drivername, len+1);
1364 /**********************************************************************
1365 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1366 over all printers, resetting printer data as neessary
1367 **********************************************************************/
1369 void reset_all_printerdata(struct messaging_context *msg,
1372 struct server_id server_id,
1377 int n_services = lp_numservices();
1380 len = MIN( data->length, sizeof(drivername)-1 );
1381 strncpy( drivername, (const char *)data->data, len );
1383 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1385 /* Iterate the printer list */
1387 for ( snum=0; snum<n_services; snum++ )
1389 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1392 NT_PRINTER_INFO_LEVEL *printer = NULL;
1394 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1395 if ( !W_ERROR_IS_OK(result) )
1399 * if the printer is bound to the driver,
1400 * then reset to the new driver initdata
1403 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1405 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1407 if ( !set_driver_init(printer, 2) ) {
1408 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1409 printer->info_2->printername, printer->info_2->drivername));
1412 result = mod_a_printer( printer, 2 );
1413 if ( !W_ERROR_IS_OK(result) ) {
1414 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1415 get_dos_error_msg(result)));
1419 free_a_printer( &printer, 2 );
1428 /****************************************************************
1429 _spoolss_OpenPrinter
1430 ****************************************************************/
1432 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1433 struct spoolss_OpenPrinter *r)
1435 struct spoolss_OpenPrinterEx e;
1438 ZERO_STRUCT(e.in.userlevel);
1440 e.in.printername = r->in.printername;
1441 e.in.datatype = r->in.datatype;
1442 e.in.devmode_ctr = r->in.devmode_ctr;
1443 e.in.access_mask = r->in.access_mask;
1446 e.out.handle = r->out.handle;
1448 werr = _spoolss_OpenPrinterEx(p, &e);
1450 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1451 /* OpenPrinterEx returns this for a bad
1452 * printer name. We must return WERR_INVALID_PRINTER_NAME
1455 werr = WERR_INVALID_PRINTER_NAME;
1461 /********************************************************************
1462 ********************************************************************/
1464 bool convert_devicemode(const char *printername,
1465 const struct spoolss_DeviceMode *devmode,
1466 NT_DEVICEMODE **pp_nt_devmode)
1468 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1471 * Ensure nt_devmode is a valid pointer
1472 * as we will be overwriting it.
1475 if (nt_devmode == NULL) {
1476 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1477 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1481 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1482 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1484 nt_devmode->specversion = devmode->specversion;
1485 nt_devmode->driverversion = devmode->driverversion;
1486 nt_devmode->size = devmode->size;
1487 nt_devmode->fields = devmode->fields;
1488 nt_devmode->orientation = devmode->orientation;
1489 nt_devmode->papersize = devmode->papersize;
1490 nt_devmode->paperlength = devmode->paperlength;
1491 nt_devmode->paperwidth = devmode->paperwidth;
1492 nt_devmode->scale = devmode->scale;
1493 nt_devmode->copies = devmode->copies;
1494 nt_devmode->defaultsource = devmode->defaultsource;
1495 nt_devmode->printquality = devmode->printquality;
1496 nt_devmode->color = devmode->color;
1497 nt_devmode->duplex = devmode->duplex;
1498 nt_devmode->yresolution = devmode->yresolution;
1499 nt_devmode->ttoption = devmode->ttoption;
1500 nt_devmode->collate = devmode->collate;
1502 nt_devmode->logpixels = devmode->logpixels;
1503 nt_devmode->bitsperpel = devmode->bitsperpel;
1504 nt_devmode->pelswidth = devmode->pelswidth;
1505 nt_devmode->pelsheight = devmode->pelsheight;
1506 nt_devmode->displayflags = devmode->displayflags;
1507 nt_devmode->displayfrequency = devmode->displayfrequency;
1508 nt_devmode->icmmethod = devmode->icmmethod;
1509 nt_devmode->icmintent = devmode->icmintent;
1510 nt_devmode->mediatype = devmode->mediatype;
1511 nt_devmode->dithertype = devmode->dithertype;
1512 nt_devmode->reserved1 = devmode->reserved1;
1513 nt_devmode->reserved2 = devmode->reserved2;
1514 nt_devmode->panningwidth = devmode->panningwidth;
1515 nt_devmode->panningheight = devmode->panningheight;
1518 * Only change private and driverextra if the incoming devmode
1519 * has a new one. JRA.
1522 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1523 SAFE_FREE(nt_devmode->nt_dev_private);
1524 nt_devmode->driverextra = devmode->__driverextra_length;
1525 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1527 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1530 *pp_nt_devmode = nt_devmode;
1535 /****************************************************************
1536 _spoolss_OpenPrinterEx
1537 ****************************************************************/
1539 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1540 struct spoolss_OpenPrinterEx *r)
1542 POLICY_HND *handle = r->out.handle;
1543 char *name = CONST_DISCARD(char *, r->in.printername);
1545 Printer_entry *Printer=NULL;
1548 return WERR_INVALID_PARAM;
1551 /* some sanity check because you can open a printer or a print server */
1552 /* aka: \\server\printer or \\server */
1554 DEBUGADD(3,("checking name: %s\n",name));
1556 if (!open_printer_hnd(p, handle, name, 0)) {
1557 ZERO_STRUCTP(r->out.handle);
1558 return WERR_INVALID_PARAM;
1561 Printer=find_printer_index_by_hnd(p, handle);
1563 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1564 "handle we created for printer %s\n", name ));
1565 close_printer_handle(p,handle);
1566 ZERO_STRUCTP(r->out.handle);
1567 return WERR_INVALID_PARAM;
1571 * First case: the user is opening the print server:
1573 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1574 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1576 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1577 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1578 * or if the user is listed in the smb.conf printer admin parameter.
1580 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1581 * client view printer folder, but does not show the MSAPW.
1583 * Note: this test needs code to check access rights here too. Jeremy
1584 * could you look at this?
1586 * Second case: the user is opening a printer:
1587 * NT doesn't let us connect to a printer if the connecting user
1588 * doesn't have print permission.
1590 * Third case: user is opening a Port Monitor
1591 * access checks same as opening a handle to the print server.
1594 switch (Printer->printer_type )
1597 case SPLHND_PORTMON_TCP:
1598 case SPLHND_PORTMON_LOCAL:
1599 /* Printserver handles use global struct... */
1603 /* Map standard access rights to object specific access rights */
1605 se_map_standard(&r->in.access_mask,
1606 &printserver_std_mapping);
1608 /* Deny any object specific bits that don't apply to print
1609 servers (i.e printer and job specific bits) */
1611 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1613 if (r->in.access_mask &
1614 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1615 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1616 close_printer_handle(p, handle);
1617 ZERO_STRUCTP(r->out.handle);
1618 return WERR_ACCESS_DENIED;
1621 /* Allow admin access */
1623 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1625 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1627 if (!lp_ms_add_printer_wizard()) {
1628 close_printer_handle(p, handle);
1629 ZERO_STRUCTP(r->out.handle);
1630 return WERR_ACCESS_DENIED;
1633 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1634 and not a printer admin, then fail */
1636 if ((p->server_info->utok.uid != 0) &&
1637 !user_has_privileges(p->server_info->ptok,
1639 !token_contains_name_in_list(
1640 uidtoname(p->server_info->utok.uid),
1642 p->server_info->ptok,
1643 lp_printer_admin(snum))) {
1644 close_printer_handle(p, handle);
1645 ZERO_STRUCTP(r->out.handle);
1646 return WERR_ACCESS_DENIED;
1649 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1653 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1656 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1657 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1659 /* We fall through to return WERR_OK */
1662 case SPLHND_PRINTER:
1663 /* NT doesn't let us connect to a printer if the connecting user
1664 doesn't have print permission. */
1666 if (!get_printer_snum(p, handle, &snum, NULL)) {
1667 close_printer_handle(p, handle);
1668 ZERO_STRUCTP(r->out.handle);
1672 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1674 /* map an empty access mask to the minimum access mask */
1675 if (r->in.access_mask == 0x0)
1676 r->in.access_mask = PRINTER_ACCESS_USE;
1679 * If we are not serving the printer driver for this printer,
1680 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1681 * will keep NT clients happy --jerry
1684 if (lp_use_client_driver(snum)
1685 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1687 r->in.access_mask = PRINTER_ACCESS_USE;
1690 /* check smb.conf parameters and the the sec_desc */
1692 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1693 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1694 ZERO_STRUCTP(r->out.handle);
1695 return WERR_ACCESS_DENIED;
1698 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1699 p->server_info->ptok, snum) ||
1700 !print_access_check(p->server_info, snum,
1701 r->in.access_mask)) {
1702 DEBUG(3, ("access DENIED for printer open\n"));
1703 close_printer_handle(p, handle);
1704 ZERO_STRUCTP(r->out.handle);
1705 return WERR_ACCESS_DENIED;
1708 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1709 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1710 close_printer_handle(p, handle);
1711 ZERO_STRUCTP(r->out.handle);
1712 return WERR_ACCESS_DENIED;
1715 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1716 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1718 r->in.access_mask = PRINTER_ACCESS_USE;
1720 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1721 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1726 /* sanity check to prevent programmer error */
1727 ZERO_STRUCTP(r->out.handle);
1731 Printer->access_granted = r->in.access_mask;
1734 * If the client sent a devmode in the OpenPrinter() call, then
1735 * save it here in case we get a job submission on this handle
1738 if ((Printer->printer_type != SPLHND_SERVER) &&
1739 r->in.devmode_ctr.devmode) {
1740 convert_devicemode(Printer->sharename,
1741 r->in.devmode_ctr.devmode,
1742 &Printer->nt_devmode);
1745 #if 0 /* JERRY -- I'm doubtful this is really effective */
1746 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1747 optimization in Windows 2000 clients --jerry */
1749 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1750 && (RA_WIN2K == get_remote_arch()) )
1752 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1753 sys_usleep( 500000 );
1760 /****************************************************************************
1761 ****************************************************************************/
1763 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1764 NT_PRINTER_INFO_LEVEL_2 *d)
1766 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1772 d->attributes = r->attributes;
1773 d->priority = r->priority;
1774 d->default_priority = r->defaultpriority;
1775 d->starttime = r->starttime;
1776 d->untiltime = r->untiltime;
1777 d->status = r->status;
1778 d->cjobs = r->cjobs;
1780 fstrcpy(d->servername, r->servername);
1781 fstrcpy(d->printername, r->printername);
1782 fstrcpy(d->sharename, r->sharename);
1783 fstrcpy(d->portname, r->portname);
1784 fstrcpy(d->drivername, r->drivername);
1785 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1786 fstrcpy(d->location, r->location);
1787 fstrcpy(d->sepfile, r->sepfile);
1788 fstrcpy(d->printprocessor, r->printprocessor);
1789 fstrcpy(d->datatype, r->datatype);
1790 fstrcpy(d->parameters, r->parameters);
1795 /****************************************************************************
1796 ****************************************************************************/
1798 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1799 NT_PRINTER_INFO_LEVEL *printer)
1803 switch (info_ctr->level) {
1805 /* allocate memory if needed. Messy because
1806 convert_printer_info is used to update an existing
1807 printer or build a new one */
1809 if (!printer->info_2) {
1810 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1811 if (!printer->info_2) {
1812 DEBUG(0,("convert_printer_info: "
1813 "talloc() failed!\n"));
1818 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1820 printer->info_2->setuptime = time(NULL);
1827 /*******************************************************************
1828 ********************************************************************/
1830 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1839 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1844 for (i=0; sarray[i] != NULL; i++) {
1845 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1849 fstrcpy((*farray)[i], sarray[i]);
1852 fstrcpy((*farray)[i], "");
1857 /*******************************************************************
1858 ********************************************************************/
1860 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1861 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1863 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1865 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1868 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1877 d->cversion = r->version;
1879 fstrcpy(d->name, r->driver_name);
1880 fstrcpy(d->environment, r->architecture);
1881 fstrcpy(d->driverpath, r->driver_path);
1882 fstrcpy(d->datafile, r->data_file);
1883 fstrcpy(d->configfile, r->config_file);
1884 fstrcpy(d->helpfile, r->help_file);
1885 fstrcpy(d->monitorname, r->monitor_name);
1886 fstrcpy(d->defaultdatatype, r->default_datatype);
1888 DEBUGADD(8,( "version: %d\n", d->cversion));
1889 DEBUGADD(8,( "name: %s\n", d->name));
1890 DEBUGADD(8,( "environment: %s\n", d->environment));
1891 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1892 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1893 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1894 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1895 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1896 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1898 if (r->dependent_files) {
1899 if (!string_array_to_fstring_array(r->dependent_files->string,
1900 &d->dependentfiles)) {
1909 /*******************************************************************
1910 ********************************************************************/
1912 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1913 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1915 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1917 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1920 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1929 d->version = r->version;
1931 fstrcpy(d->name, r->driver_name);
1932 fstrcpy(d->environment, r->architecture);
1933 fstrcpy(d->driverpath, r->driver_path);
1934 fstrcpy(d->datafile, r->data_file);
1935 fstrcpy(d->configfile, r->config_file);
1936 fstrcpy(d->helpfile, r->help_file);
1937 fstrcpy(d->monitorname, r->monitor_name);
1938 fstrcpy(d->defaultdatatype, r->default_datatype);
1940 DEBUGADD(8,( "version: %d\n", d->version));
1941 DEBUGADD(8,( "name: %s\n", d->name));
1942 DEBUGADD(8,( "environment: %s\n", d->environment));
1943 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1944 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1945 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1946 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1947 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1948 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1950 if (r->dependent_files) {
1951 if (!string_array_to_fstring_array(r->dependent_files->string,
1952 &d->dependentfiles)) {
1957 if (r->previous_names) {
1958 if (!string_array_to_fstring_array(r->previous_names->string,
1959 &d->previousnames)) {
1971 /********************************************************************
1972 ********************************************************************/
1974 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1975 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1980 printer->info_3 = NULL;
1981 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1986 printer->info_6 = NULL;
1987 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1998 /********************************************************************
1999 * _spoolss_enddocprinter_internal.
2000 ********************************************************************/
2002 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2004 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2008 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2012 if (!get_printer_snum(p, handle, &snum, NULL))
2015 Printer->document_started=False;
2016 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2017 /* error codes unhandled so far ... */
2022 /****************************************************************
2023 _spoolss_ClosePrinter
2024 ****************************************************************/
2026 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2027 struct spoolss_ClosePrinter *r)
2029 POLICY_HND *handle = r->in.handle;
2031 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2033 if (Printer && Printer->document_started)
2034 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2036 if (!close_printer_handle(p, handle))
2039 /* clear the returned printer handle. Observed behavior
2040 from Win2k server. Don't think this really matters.
2041 Previous code just copied the value of the closed
2044 ZERO_STRUCTP(r->out.handle);
2049 /****************************************************************
2050 _spoolss_DeletePrinter
2051 ****************************************************************/
2053 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2054 struct spoolss_DeletePrinter *r)
2056 POLICY_HND *handle = r->in.handle;
2057 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2060 if (Printer && Printer->document_started)
2061 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
2063 result = delete_printer_handle(p, handle);
2065 update_c_setprinter(False);
2070 /*******************************************************************
2071 * static function to lookup the version id corresponding to an
2072 * long architecture string
2073 ******************************************************************/
2075 static int get_version_id (char * arch)
2078 struct table_node archi_table[]= {
2080 {"Windows 4.0", "WIN40", 0 },
2081 {"Windows NT x86", "W32X86", 2 },
2082 {"Windows NT R4000", "W32MIPS", 2 },
2083 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2084 {"Windows NT PowerPC", "W32PPC", 2 },
2085 {"Windows IA64", "IA64", 3 },
2086 {"Windows x64", "x64", 3 },
2090 for (i=0; archi_table[i].long_archi != NULL; i++)
2092 if (strcmp(arch, archi_table[i].long_archi) == 0)
2093 return (archi_table[i].version);
2099 /****************************************************************
2100 _spoolss_DeletePrinterDriver
2101 ****************************************************************/
2103 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2104 struct spoolss_DeletePrinterDriver *r)
2108 NT_PRINTER_DRIVER_INFO_LEVEL info;
2109 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2112 WERROR status_win2k = WERR_ACCESS_DENIED;
2113 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2115 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2116 and not a printer admin, then fail */
2118 if ( (p->server_info->utok.uid != 0)
2119 && !user_has_privileges(p->server_info->ptok, &se_printop )
2120 && !token_contains_name_in_list(
2121 uidtoname(p->server_info->utok.uid), NULL,
2122 NULL, p->server_info->ptok,
2123 lp_printer_admin(-1)) )
2125 return WERR_ACCESS_DENIED;
2128 driver = CONST_DISCARD(char *, r->in.driver);
2129 arch = CONST_DISCARD(char *, r->in.architecture);
2131 /* check that we have a valid driver name first */
2133 if ((version=get_version_id(arch)) == -1)
2134 return WERR_INVALID_ENVIRONMENT;
2137 ZERO_STRUCT(info_win2k);
2139 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2141 /* try for Win2k driver if "Windows NT x86" */
2143 if ( version == 2 ) {
2145 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2146 status = WERR_UNKNOWN_PRINTER_DRIVER;
2150 /* otherwise it was a failure */
2152 status = WERR_UNKNOWN_PRINTER_DRIVER;
2158 if (printer_driver_in_use(info.info_3)) {
2159 status = WERR_PRINTER_DRIVER_IN_USE;
2165 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2167 /* if we get to here, we now have 2 driver info structures to remove */
2168 /* remove the Win2k driver first*/
2170 status_win2k = delete_printer_driver(
2171 p, info_win2k.info_3, 3, False );
2172 free_a_printer_driver( info_win2k, 3 );
2174 /* this should not have failed---if it did, report to client */
2175 if ( !W_ERROR_IS_OK(status_win2k) )
2177 status = status_win2k;
2183 status = delete_printer_driver(p, info.info_3, version, False);
2185 /* if at least one of the deletes succeeded return OK */
2187 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2191 free_a_printer_driver( info, 3 );
2196 /****************************************************************
2197 _spoolss_DeletePrinterDriverEx
2198 ****************************************************************/
2200 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2201 struct spoolss_DeletePrinterDriverEx *r)
2205 NT_PRINTER_DRIVER_INFO_LEVEL info;
2206 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2208 uint32_t flags = r->in.delete_flags;
2211 WERROR status_win2k = WERR_ACCESS_DENIED;
2212 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2214 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2215 and not a printer admin, then fail */
2217 if ( (p->server_info->utok.uid != 0)
2218 && !user_has_privileges(p->server_info->ptok, &se_printop )
2219 && !token_contains_name_in_list(
2220 uidtoname(p->server_info->utok.uid), NULL, NULL,
2221 p->server_info->ptok, lp_printer_admin(-1)) )
2223 return WERR_ACCESS_DENIED;
2226 driver = CONST_DISCARD(char *, r->in.driver);
2227 arch = CONST_DISCARD(char *, r->in.architecture);
2229 /* check that we have a valid driver name first */
2230 if ((version=get_version_id(arch)) == -1) {
2231 /* this is what NT returns */
2232 return WERR_INVALID_ENVIRONMENT;
2235 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2236 version = r->in.version;
2239 ZERO_STRUCT(info_win2k);
2241 status = get_a_printer_driver(&info, 3, driver, arch, version);
2243 if ( !W_ERROR_IS_OK(status) )
2246 * if the client asked for a specific version,
2247 * or this is something other than Windows NT x86,
2251 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2254 /* try for Win2k driver if "Windows NT x86" */
2257 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2258 status = WERR_UNKNOWN_PRINTER_DRIVER;
2263 if ( printer_driver_in_use(info.info_3) ) {
2264 status = WERR_PRINTER_DRIVER_IN_USE;
2269 * we have a couple of cases to consider.
2270 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2271 * then the delete should fail if **any** files overlap with
2273 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2274 * non-overlapping files
2275 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2276 * is set, the do not delete any files
2277 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2280 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2282 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2284 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2285 /* no idea of the correct error here */
2286 status = WERR_ACCESS_DENIED;
2291 /* also check for W32X86/3 if necessary; maybe we already have? */
2293 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2294 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2297 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2298 /* no idea of the correct error here */
2299 free_a_printer_driver( info_win2k, 3 );
2300 status = WERR_ACCESS_DENIED;
2304 /* if we get to here, we now have 2 driver info structures to remove */
2305 /* remove the Win2k driver first*/
2307 status_win2k = delete_printer_driver(
2308 p, info_win2k.info_3, 3, delete_files);
2309 free_a_printer_driver( info_win2k, 3 );
2311 /* this should not have failed---if it did, report to client */
2313 if ( !W_ERROR_IS_OK(status_win2k) )
2318 status = delete_printer_driver(p, info.info_3, version, delete_files);
2320 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2323 free_a_printer_driver( info, 3 );
2329 /****************************************************************************
2330 Internal routine for removing printerdata
2331 ***************************************************************************/
2333 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2335 return delete_printer_data( printer->info_2, key, value );
2338 /****************************************************************************
2339 Internal routine for storing printerdata
2340 ***************************************************************************/
2342 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2343 uint32 type, uint8 *data, int real_len )
2345 /* the registry objects enforce uniqueness based on value name */
2347 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2350 /********************************************************************
2351 GetPrinterData on a printer server Handle.
2352 ********************************************************************/
2354 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2356 enum winreg_Type *type,
2357 union spoolss_PrinterData *data)
2359 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2361 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2367 if (!StrCaseCmp(value, "BeepEnabled")) {
2373 if (!StrCaseCmp(value, "EventLog")) {
2375 /* formally was 0x1b */
2380 if (!StrCaseCmp(value, "NetPopup")) {
2386 if (!StrCaseCmp(value, "MajorVersion")) {
2389 /* Windows NT 4.0 seems to not allow uploading of drivers
2390 to a server that reports 0x3 as the MajorVersion.
2391 need to investigate more how Win2k gets around this .
2394 if (RA_WINNT == get_remote_arch()) {
2403 if (!StrCaseCmp(value, "MinorVersion")) {
2410 * uint32 size = 0x114
2412 * uint32 minor = [0|1]
2413 * uint32 build = [2195|2600]
2414 * extra unicode string = e.g. "Service Pack 3"
2416 if (!StrCaseCmp(value, "OSVersion")) {
2418 enum ndr_err_code ndr_err;
2419 struct spoolss_OSVersion os;
2421 os.major = 5; /* Windows 2000 == 5.0 */
2423 os.build = 2195; /* build */
2424 os.extra_string = ""; /* leave extra string empty */
2426 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2427 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2428 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2429 return WERR_GENERAL_FAILURE;
2433 data->binary = blob;
2439 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2442 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2443 W_ERROR_HAVE_NO_MEMORY(data->string);
2448 if (!StrCaseCmp(value, "Architecture")) {
2451 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2452 W_ERROR_HAVE_NO_MEMORY(data->string);
2457 if (!StrCaseCmp(value, "DsPresent")) {
2460 /* only show the publish check box if we are a
2461 member of a AD domain */
2463 if (lp_security() == SEC_ADS) {
2471 if (!StrCaseCmp(value, "DNSMachineName")) {
2472 const char *hostname = get_mydnsfullname();
2475 return WERR_BADFILE;
2479 data->string = talloc_strdup(mem_ctx, hostname);
2480 W_ERROR_HAVE_NO_MEMORY(data->string);
2485 return WERR_BADFILE;
2488 /****************************************************************
2489 _spoolss_GetPrinterData
2490 ****************************************************************/
2492 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2493 struct spoolss_GetPrinterData *r)
2496 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2497 NT_PRINTER_INFO_LEVEL *printer = NULL;
2501 * Reminder: when it's a string, the length is in BYTES
2502 * even if UNICODE is negociated.
2507 /* in case of problem, return some default values */
2512 DEBUG(4,("_spoolss_GetPrinterData\n"));
2515 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2516 OUR_HANDLE(r->in.handle)));
2517 result = WERR_BADFID;
2521 if (Printer->printer_type == SPLHND_SERVER) {
2522 result = getprinterdata_printer_server(p->mem_ctx,
2527 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2528 result = WERR_BADFID;
2532 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2533 if (!W_ERROR_IS_OK(result)) {
2537 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2539 if (strequal(r->in.value_name, "ChangeId")) {
2540 *r->out.type = REG_DWORD;
2541 r->out.data->value = printer->info_2->changeid;
2547 v = get_printer_data(printer->info_2,
2548 SPOOL_PRINTERDATA_KEY,
2551 result = WERR_BADFILE;
2555 *r->out.type = v->type;
2557 blob = data_blob_const(v->data_p, v->size);
2559 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2566 /* cleanup & exit */
2569 free_a_printer(&printer, 2);
2572 if (!W_ERROR_IS_OK(result)) {
2576 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2577 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2578 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2580 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2583 /*********************************************************
2584 Connect to the client machine.
2585 **********************************************************/
2587 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2588 struct sockaddr_storage *client_ss, const char *remote_machine)
2591 struct cli_state *the_cli;
2592 struct sockaddr_storage rm_addr;
2594 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2595 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2596 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2600 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2601 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2605 char addr[INET6_ADDRSTRLEN];
2606 rm_addr = *client_ss;
2607 print_sockaddr(addr, sizeof(addr), &rm_addr);
2608 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2612 /* setup the connection */
2614 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2615 &rm_addr, 0, "IPC$", "IPC",
2619 0, lp_client_signing(), NULL );
2621 if ( !NT_STATUS_IS_OK( ret ) ) {
2622 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2627 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2628 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2629 cli_shutdown(the_cli);
2634 * Ok - we have an anonymous connection to the IPC$ share.
2635 * Now start the NT Domain stuff :-).
2638 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2639 if (!NT_STATUS_IS_OK(ret)) {
2640 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2641 remote_machine, nt_errstr(ret)));
2642 cli_shutdown(the_cli);
2649 /***************************************************************************
2650 Connect to the client.
2651 ****************************************************************************/
2653 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2654 uint32 localprinter, uint32 type,
2655 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2661 * If it's the first connection, contact the client
2662 * and connect to the IPC$ share anonymously
2664 if (smb_connections==0) {
2665 fstring unix_printer;
2667 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2669 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2672 messaging_register(smbd_messaging_context(), NULL,
2673 MSG_PRINTER_NOTIFY2,
2674 receive_notify2_message_list);
2675 /* Tell the connections db we're now interested in printer
2676 * notify messages. */
2677 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2681 * Tell the specific printing tdb we want messages for this printer
2682 * by registering our PID.
2685 if (!print_notify_register_pid(snum))
2686 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2690 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2698 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2699 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2700 win_errstr(result)));
2702 return (W_ERROR_IS_OK(result));
2705 /****************************************************************
2706 ****************************************************************/
2708 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2709 const struct spoolss_NotifyOption *r)
2711 struct spoolss_NotifyOption *option;
2718 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2725 if (!option->count) {
2729 option->types = talloc_zero_array(option,
2730 struct spoolss_NotifyOptionType, option->count);
2731 if (!option->types) {
2732 talloc_free(option);
2736 for (i=0; i < option->count; i++) {
2737 option->types[i] = r->types[i];
2739 if (option->types[i].count) {
2740 option->types[i].fields = talloc_zero_array(option,
2741 union spoolss_Field, option->types[i].count);
2742 if (!option->types[i].fields) {
2743 talloc_free(option);
2746 for (k=0; k<option->types[i].count; k++) {
2747 option->types[i].fields[k] =
2748 r->types[i].fields[k];
2756 /****************************************************************
2757 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2759 * before replying OK: status=0 a rpc call is made to the workstation
2760 * asking ReplyOpenPrinter
2762 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2763 * called from api_spoolss_rffpcnex
2764 ****************************************************************/
2766 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2767 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2769 POLICY_HND *handle = r->in.handle;
2771 struct spoolss_NotifyOption *option = r->in.notify_options;
2772 struct sockaddr_storage client_ss;
2774 /* store the notify value in the printer struct */
2776 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2779 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2780 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2784 Printer->notify.flags = r->in.flags;
2785 Printer->notify.options = r->in.options;
2786 Printer->notify.printerlocal = r->in.printer_local;
2788 TALLOC_FREE(Printer->notify.option);
2789 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2791 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2793 /* Connect to the client machine and send a ReplyOpenPrinter */
2795 if ( Printer->printer_type == SPLHND_SERVER)
2797 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2798 !get_printer_snum(p, handle, &snum, NULL) )
2801 if (!interpret_string_addr(&client_ss, p->client_address,
2803 return WERR_SERVER_UNAVAILABLE;
2806 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2807 Printer->notify.printerlocal, 1,
2808 &Printer->notify.client_hnd, &client_ss))
2809 return WERR_SERVER_UNAVAILABLE;
2811 Printer->notify.client_connected=True;
2816 /*******************************************************************
2817 * fill a notify_info_data with the servername
2818 ********************************************************************/
2820 void spoolss_notify_server_name(int snum,
2821 struct spoolss_Notify *data,
2822 print_queue_struct *queue,
2823 NT_PRINTER_INFO_LEVEL *printer,
2824 TALLOC_CTX *mem_ctx)
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2829 /*******************************************************************
2830 * fill a notify_info_data with the printername (not including the servername).
2831 ********************************************************************/
2833 void spoolss_notify_printer_name(int snum,
2834 struct spoolss_Notify *data,
2835 print_queue_struct *queue,
2836 NT_PRINTER_INFO_LEVEL *printer,
2837 TALLOC_CTX *mem_ctx)
2839 /* the notify name should not contain the \\server\ part */
2840 char *p = strrchr(printer->info_2->printername, '\\');
2843 p = printer->info_2->printername;
2848 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2851 /*******************************************************************
2852 * fill a notify_info_data with the servicename
2853 ********************************************************************/
2855 void spoolss_notify_share_name(int snum,
2856 struct spoolss_Notify *data,
2857 print_queue_struct *queue,
2858 NT_PRINTER_INFO_LEVEL *printer,
2859 TALLOC_CTX *mem_ctx)
2861 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2864 /*******************************************************************
2865 * fill a notify_info_data with the port name
2866 ********************************************************************/
2868 void spoolss_notify_port_name(int snum,
2869 struct spoolss_Notify *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2874 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2877 /*******************************************************************
2878 * fill a notify_info_data with the printername
2879 * but it doesn't exist, have to see what to do
2880 ********************************************************************/
2882 void spoolss_notify_driver_name(int snum,
2883 struct spoolss_Notify *data,
2884 print_queue_struct *queue,
2885 NT_PRINTER_INFO_LEVEL *printer,
2886 TALLOC_CTX *mem_ctx)
2888 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2891 /*******************************************************************
2892 * fill a notify_info_data with the comment
2893 ********************************************************************/
2895 void spoolss_notify_comment(int snum,
2896 struct spoolss_Notify *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2903 if (*printer->info_2->comment == '\0') {
2904 p = lp_comment(snum);
2906 p = printer->info_2->comment;
2909 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2912 /*******************************************************************
2913 * fill a notify_info_data with the comment
2914 * location = "Room 1, floor 2, building 3"
2915 ********************************************************************/
2917 void spoolss_notify_location(int snum,
2918 struct spoolss_Notify *data,
2919 print_queue_struct *queue,
2920 NT_PRINTER_INFO_LEVEL *printer,
2921 TALLOC_CTX *mem_ctx)
2923 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2926 /*******************************************************************
2927 * fill a notify_info_data with the device mode
2928 * jfm:xxxx don't to it for know but that's a real problem !!!
2929 ********************************************************************/
2931 static void spoolss_notify_devmode(int snum,
2932 struct spoolss_Notify *data,
2933 print_queue_struct *queue,
2934 NT_PRINTER_INFO_LEVEL *printer,
2935 TALLOC_CTX *mem_ctx)
2937 /* for a dummy implementation we have to zero the fields */
2938 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2941 /*******************************************************************
2942 * fill a notify_info_data with the separator file name
2943 ********************************************************************/
2945 void spoolss_notify_sepfile(int snum,
2946 struct spoolss_Notify *data,
2947 print_queue_struct *queue,
2948 NT_PRINTER_INFO_LEVEL *printer,
2949 TALLOC_CTX *mem_ctx)
2951 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2954 /*******************************************************************
2955 * fill a notify_info_data with the print processor
2956 * jfm:xxxx return always winprint to indicate we don't do anything to it
2957 ********************************************************************/
2959 void spoolss_notify_print_processor(int snum,
2960 struct spoolss_Notify *data,
2961 print_queue_struct *queue,
2962 NT_PRINTER_INFO_LEVEL *printer,
2963 TALLOC_CTX *mem_ctx)
2965 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2968 /*******************************************************************
2969 * fill a notify_info_data with the print processor options
2970 * jfm:xxxx send an empty string
2971 ********************************************************************/
2973 void spoolss_notify_parameters(int snum,
2974 struct spoolss_Notify *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2979 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2982 /*******************************************************************
2983 * fill a notify_info_data with the data type
2984 * jfm:xxxx always send RAW as data type
2985 ********************************************************************/
2987 void spoolss_notify_datatype(int snum,
2988 struct spoolss_Notify *data,
2989 print_queue_struct *queue,
2990 NT_PRINTER_INFO_LEVEL *printer,
2991 TALLOC_CTX *mem_ctx)
2993 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2996 /*******************************************************************
2997 * fill a notify_info_data with the security descriptor
2998 * jfm:xxxx send an null pointer to say no security desc
2999 * have to implement security before !
3000 ********************************************************************/
3002 static void spoolss_notify_security_desc(int snum,
3003 struct spoolss_Notify *data,
3004 print_queue_struct *queue,
3005 NT_PRINTER_INFO_LEVEL *printer,
3006 TALLOC_CTX *mem_ctx)
3008 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3009 printer->info_2->secdesc_buf->sd_size,
3010 printer->info_2->secdesc_buf->sd);
3013 /*******************************************************************
3014 * fill a notify_info_data with the attributes
3015 * jfm:xxxx a samba printer is always shared
3016 ********************************************************************/
3018 void spoolss_notify_attributes(int snum,
3019 struct spoolss_Notify *data,
3020 print_queue_struct *queue,
3021 NT_PRINTER_INFO_LEVEL *printer,
3022 TALLOC_CTX *mem_ctx)
3024 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3027 /*******************************************************************
3028 * fill a notify_info_data with the priority
3029 ********************************************************************/
3031 static void spoolss_notify_priority(int snum,
3032 struct spoolss_Notify *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3037 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3040 /*******************************************************************
3041 * fill a notify_info_data with the default priority
3042 ********************************************************************/
3044 static void spoolss_notify_default_priority(int snum,
3045 struct spoolss_Notify *data,
3046 print_queue_struct *queue,
3047 NT_PRINTER_INFO_LEVEL *printer,
3048 TALLOC_CTX *mem_ctx)
3050 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3053 /*******************************************************************
3054 * fill a notify_info_data with the start time
3055 ********************************************************************/
3057 static void spoolss_notify_start_time(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_INTEGER(data, printer->info_2->starttime);
3066 /*******************************************************************
3067 * fill a notify_info_data with the until time
3068 ********************************************************************/
3070 static void spoolss_notify_until_time(int snum,
3071 struct spoolss_Notify *data,
3072 print_queue_struct *queue,
3073 NT_PRINTER_INFO_LEVEL *printer,
3074 TALLOC_CTX *mem_ctx)
3076 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3079 /*******************************************************************
3080 * fill a notify_info_data with the status
3081 ********************************************************************/
3083 static void spoolss_notify_status(int snum,
3084 struct spoolss_Notify *data,
3085 print_queue_struct *queue,
3086 NT_PRINTER_INFO_LEVEL *printer,
3087 TALLOC_CTX *mem_ctx)
3089 print_status_struct status;
3091 print_queue_length(snum, &status);
3092 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3095 /*******************************************************************
3096 * fill a notify_info_data with the number of jobs queued
3097 ********************************************************************/
3099 void spoolss_notify_cjobs(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_INTEGER(data, print_queue_length(snum, NULL));
3108 /*******************************************************************
3109 * fill a notify_info_data with the average ppm
3110 ********************************************************************/
3112 static void spoolss_notify_average_ppm(int snum,
3113 struct spoolss_Notify *data,
3114 print_queue_struct *queue,
3115 NT_PRINTER_INFO_LEVEL *printer,
3116 TALLOC_CTX *mem_ctx)
3118 /* always respond 8 pages per minutes */
3119 /* a little hard ! */
3120 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3123 /*******************************************************************
3124 * fill a notify_info_data with username
3125 ********************************************************************/
3127 static void spoolss_notify_username(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, queue->fs_user);
3136 /*******************************************************************
3137 * fill a notify_info_data with job status
3138 ********************************************************************/
3140 static void spoolss_notify_job_status(int snum,
3141 struct spoolss_Notify *data,
3142 print_queue_struct *queue,
3143 NT_PRINTER_INFO_LEVEL *printer,
3144 TALLOC_CTX *mem_ctx)
3146 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3149 /*******************************************************************
3150 * fill a notify_info_data with job name
3151 ********************************************************************/
3153 static void spoolss_notify_job_name(int snum,
3154 struct spoolss_Notify *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3162 /*******************************************************************
3163 * fill a notify_info_data with job status
3164 ********************************************************************/
3166 static void spoolss_notify_job_status_string(int snum,
3167 struct spoolss_Notify *data,
3168 print_queue_struct *queue,
3169 NT_PRINTER_INFO_LEVEL *printer,
3170 TALLOC_CTX *mem_ctx)
3173 * Now we're returning job status codes we just return a "" here. JRA.
3178 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3181 switch (queue->status) {
3186 p = ""; /* NT provides the paused string */
3195 #endif /* NO LONGER NEEDED. */
3197 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3200 /*******************************************************************
3201 * fill a notify_info_data with job time
3202 ********************************************************************/
3204 static void spoolss_notify_job_time(int snum,
3205 struct spoolss_Notify *data,
3206 print_queue_struct *queue,
3207 NT_PRINTER_INFO_LEVEL *printer,
3208 TALLOC_CTX *mem_ctx)
3210 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3213 /*******************************************************************
3214 * fill a notify_info_data with job size
3215 ********************************************************************/
3217 static void spoolss_notify_job_size(int snum,
3218 struct spoolss_Notify *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3223 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3226 /*******************************************************************
3227 * fill a notify_info_data with page info
3228 ********************************************************************/
3229 static void spoolss_notify_total_pages(int snum,
3230 struct spoolss_Notify *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer,
3233 TALLOC_CTX *mem_ctx)
3235 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3238 /*******************************************************************
3239 * fill a notify_info_data with pages printed info.
3240 ********************************************************************/
3241 static void spoolss_notify_pages_printed(int snum,
3242 struct spoolss_Notify *data,
3243 print_queue_struct *queue,
3244 NT_PRINTER_INFO_LEVEL *printer,
3245 TALLOC_CTX *mem_ctx)
3247 /* Add code when back-end tracks this */
3248 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3251 /*******************************************************************
3252 Fill a notify_info_data with job position.
3253 ********************************************************************/
3255 static void spoolss_notify_job_position(int snum,
3256 struct spoolss_Notify *data,
3257 print_queue_struct *queue,
3258 NT_PRINTER_INFO_LEVEL *printer,
3259 TALLOC_CTX *mem_ctx)
3261 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3264 /*******************************************************************
3265 Fill a notify_info_data with submitted time.
3266 ********************************************************************/
3268 static void spoolss_notify_submitted_time(int snum,
3269 struct spoolss_Notify *data,
3270 print_queue_struct *queue,
3271 NT_PRINTER_INFO_LEVEL *printer,
3272 TALLOC_CTX *mem_ctx)
3274 data->data.string.string = NULL;
3275 data->data.string.size = 0;
3277 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3278 &data->data.string.string,
3279 &data->data.string.size);
3283 struct s_notify_info_data_table
3285 enum spoolss_NotifyType type;
3288 enum spoolss_NotifyTable variable_type;
3289 void (*fn) (int snum, struct spoolss_Notify *data,
3290 print_queue_struct *queue,
3291 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3294 /* A table describing the various print notification constants and
3295 whether the notification data is a pointer to a variable sized
3296 buffer, a one value uint32 or a two value uint32. */
3298 static const struct s_notify_info_data_table notify_info_data_table[] =
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3351 /*******************************************************************
3352 Return the variable_type of info_data structure.
3353 ********************************************************************/
3355 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3360 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3361 if ( (notify_info_data_table[i].type == type) &&
3362 (notify_info_data_table[i].field == field) ) {
3363 return notify_info_data_table[i].variable_type;
3367 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3372 /****************************************************************************
3373 ****************************************************************************/
3375 static bool search_notify(enum spoolss_NotifyType type,
3381 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3382 if (notify_info_data_table[i].type == type &&
3383 notify_info_data_table[i].field == field &&
3384 notify_info_data_table[i].fn != NULL) {
3393 /****************************************************************************
3394 ****************************************************************************/
3396 void construct_info_data(struct spoolss_Notify *info_data,
3397 enum spoolss_NotifyType type,
3401 info_data->type = type;
3402 info_data->field.field = field;
3403 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3404 info_data->job_id = id;
3407 /*******************************************************************
3409 * fill a notify_info struct with info asked
3411 ********************************************************************/
3413 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3414 struct spoolss_NotifyInfo *info,
3416 const struct spoolss_NotifyOptionType *option_type,
3418 TALLOC_CTX *mem_ctx)
3421 enum spoolss_NotifyType type;
3424 struct spoolss_Notify *current_data;
3425 NT_PRINTER_INFO_LEVEL *printer = NULL;
3426 print_queue_struct *queue=NULL;
3428 type = option_type->type;
3430 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3431 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3432 option_type->count, lp_servicename(snum)));
3434 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3437 for(field_num=0; field_num < option_type->count; field_num++) {
3438 field = option_type->fields[field_num].field;
3440 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3442 if (!search_notify(type, field, &j) )
3445 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3446 struct spoolss_Notify,
3448 if (info->notifies == NULL) {
3449 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3450 free_a_printer(&printer, 2);
3454 current_data = &info->notifies[info->count];
3456 construct_info_data(current_data, type, field, id);
3458 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3459 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3461 notify_info_data_table[j].fn(snum, current_data, queue,
3467 free_a_printer(&printer, 2);
3471 /*******************************************************************
3473 * fill a notify_info struct with info asked
3475 ********************************************************************/
3477 static bool construct_notify_jobs_info(print_queue_struct *queue,
3478 struct spoolss_NotifyInfo *info,
3479 NT_PRINTER_INFO_LEVEL *printer,
3481 const struct spoolss_NotifyOptionType *option_type,
3483 TALLOC_CTX *mem_ctx)
3486 enum spoolss_NotifyType type;
3488 struct spoolss_Notify *current_data;
3490 DEBUG(4,("construct_notify_jobs_info\n"));
3492 type = option_type->type;
3494 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3495 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3496 option_type->count));
3498 for(field_num=0; field_num<option_type->count; field_num++) {
3499 field = option_type->fields[field_num].field;
3501 if (!search_notify(type, field, &j) )
3504 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3505 struct spoolss_Notify,
3507 if (info->notifies == NULL) {
3508 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3512 current_data=&(info->notifies[info->count]);
3514 construct_info_data(current_data, type, field, id);
3515 notify_info_data_table[j].fn(snum, current_data, queue,
3524 * JFM: The enumeration is not that simple, it's even non obvious.
3526 * let's take an example: I want to monitor the PRINTER SERVER for
3527 * the printer's name and the number of jobs currently queued.
3528 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3529 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3531 * I have 3 printers on the back of my server.
3533 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3536 * 1 printer 1 name 1
3537 * 2 printer 1 cjob 1
3538 * 3 printer 2 name 2
3539 * 4 printer 2 cjob 2
3540 * 5 printer 3 name 3
3541 * 6 printer 3 name 3
3543 * that's the print server case, the printer case is even worse.
3546 /*******************************************************************
3548 * enumerate all printers on the printserver
3549 * fill a notify_info struct with info asked
3551 ********************************************************************/
3553 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3554 struct spoolss_NotifyInfo *info,
3555 TALLOC_CTX *mem_ctx)
3558 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3559 int n_services=lp_numservices();
3561 struct spoolss_NotifyOption *option;
3562 struct spoolss_NotifyOptionType option_type;
3564 DEBUG(4,("printserver_notify_info\n"));
3569 option = Printer->notify.option;
3572 info->notifies = NULL;
3575 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3576 sending a ffpcn() request first */
3581 for (i=0; i<option->count; i++) {
3582 option_type = option->types[i];
3584 if (option_type.type != PRINTER_NOTIFY_TYPE)
3587 for (snum=0; snum<n_services; snum++)
3589 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3590 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3596 * Debugging information, don't delete.
3599 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3600 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3601 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3603 for (i=0; i<info->count; i++) {
3604 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3605 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3606 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3613 /*******************************************************************
3615 * fill a notify_info struct with info asked
3617 ********************************************************************/
3619 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3620 TALLOC_CTX *mem_ctx)
3623 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3626 struct spoolss_NotifyOption *option;
3627 struct spoolss_NotifyOptionType option_type;
3629 print_queue_struct *queue=NULL;
3630 print_status_struct status;
3632 DEBUG(4,("printer_notify_info\n"));
3637 option = Printer->notify.option;
3641 info->notifies = NULL;
3644 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3645 sending a ffpcn() request first */
3650 get_printer_snum(p, hnd, &snum, NULL);
3652 for (i=0; i<option->count; i++) {
3653 option_type = option->types[i];
3655 switch (option_type.type) {
3656 case PRINTER_NOTIFY_TYPE:
3657 if(construct_notify_printer_info(Printer, info, snum,
3663 case JOB_NOTIFY_TYPE: {
3664 NT_PRINTER_INFO_LEVEL *printer = NULL;
3666 count = print_queue_status(snum, &queue, &status);
3668 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3671 for (j=0; j<count; j++) {
3672 construct_notify_jobs_info(&queue[j], info,
3679 free_a_printer(&printer, 2);
3689 * Debugging information, don't delete.
3692 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3693 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3694 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3696 for (i=0; i<info->count; i++) {
3697 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3698 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3699 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3705 /****************************************************************
3706 _spoolss_RouterRefreshPrinterChangeNotify
3707 ****************************************************************/
3709 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3710 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3712 POLICY_HND *handle = r->in.handle;
3713 struct spoolss_NotifyInfo *info;
3715 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3716 WERROR result = WERR_BADFID;
3718 /* we always have a spoolss_NotifyInfo struct */
3719 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3721 result = WERR_NOMEM;
3725 *r->out.info = info;
3728 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3729 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3733 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3736 * We are now using the change value, and
3737 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3738 * I don't have a global notification system, I'm sending back all the
3739 * informations even when _NOTHING_ has changed.
3742 /* We need to keep track of the change value to send back in
3743 RRPCN replies otherwise our updates are ignored. */
3745 Printer->notify.fnpcn = True;
3747 if (Printer->notify.client_connected) {
3748 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3749 "Saving change value in request [%x]\n",
3751 Printer->notify.change = r->in.change_low;
3754 /* just ignore the spoolss_NotifyOption */
3756 switch (Printer->printer_type) {
3758 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3761 case SPLHND_PRINTER:
3762 result = printer_notify_info(p, handle, info, p->mem_ctx);
3766 Printer->notify.fnpcn = False;
3772 /********************************************************************
3773 * construct_printer_info_0
3774 * fill a printer_info_0 struct
3775 ********************************************************************/
3777 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3778 const NT_PRINTER_INFO_LEVEL *ntprinter,
3779 struct spoolss_PrinterInfo0 *r,
3783 counter_printer_0 *session_counter;
3785 print_status_struct status;
3787 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3788 W_ERROR_HAVE_NO_MEMORY(r->printername);
3790 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3791 W_ERROR_HAVE_NO_MEMORY(r->servername);
3793 count = print_queue_length(snum, &status);
3795 /* check if we already have a counter for this printer */
3796 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3797 if (session_counter->snum == snum)
3801 /* it's the first time, add it to the list */
3802 if (session_counter == NULL) {
3803 session_counter = SMB_MALLOC_P(counter_printer_0);
3804 W_ERROR_HAVE_NO_MEMORY(session_counter);
3805 ZERO_STRUCTP(session_counter);
3806 session_counter->snum = snum;
3807 session_counter->counter = 0;
3808 DLIST_ADD(counter_list, session_counter);
3812 session_counter->counter++;
3818 setuptime = (time_t)ntprinter->info_2->setuptime;
3820 init_systemtime(&r->time, gmtime(&setuptime));
3823 * the global_counter should be stored in a TDB as it's common to all the clients
3824 * and should be zeroed on samba startup
3826 r->global_counter = session_counter->counter;
3828 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3829 r->version = 0x0005; /* NT 5 */
3830 r->free_build = 0x0893; /* build 2195 */
3832 r->max_spooling = 0;
3833 r->session_counter = session_counter->counter;
3834 r->num_error_out_of_paper = 0x0;
3835 r->num_error_not_ready = 0x0; /* number of print failure */
3837 r->number_of_processors = 0x1;
3838 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3839 r->high_part_total_bytes = 0x0;
3840 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3841 r->last_error = WERR_OK;
3842 r->status = nt_printq_status(status.status);
3843 r->enumerate_network_printers = 0x0;
3844 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3845 r->processor_architecture = 0x0;
3846 r->processor_level = 0x6; /* 6 ???*/
3854 /****************************************************************************
3855 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3856 should be valid upon entry
3857 ****************************************************************************/
3859 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3860 struct spoolss_DeviceMode *r,
3861 const NT_DEVICEMODE *ntdevmode)
3863 if (!r || !ntdevmode) {
3864 return WERR_INVALID_PARAM;
3867 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3868 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3870 r->specversion = ntdevmode->specversion;
3871 r->driverversion = ntdevmode->driverversion;
3872 r->size = ntdevmode->size;
3873 r->__driverextra_length = ntdevmode->driverextra;
3874 r->fields = ntdevmode->fields;
3876 r->orientation = ntdevmode->orientation;
3877 r->papersize = ntdevmode->papersize;
3878 r->paperlength = ntdevmode->paperlength;
3879 r->paperwidth = ntdevmode->paperwidth;
3880 r->scale = ntdevmode->scale;
3881 r->copies = ntdevmode->copies;
3882 r->defaultsource = ntdevmode->defaultsource;
3883 r->printquality = ntdevmode->printquality;
3884 r->color = ntdevmode->color;
3885 r->duplex = ntdevmode->duplex;
3886 r->yresolution = ntdevmode->yresolution;
3887 r->ttoption = ntdevmode->ttoption;
3888 r->collate = ntdevmode->collate;
3890 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3891 W_ERROR_HAVE_NO_MEMORY(r->formname);
3893 /* all 0 below are values that have not been set in the old parsing/copy
3894 * function, maybe they should... - gd */
3900 r->displayflags = 0;
3901 r->displayfrequency = 0;
3902 r->icmmethod = ntdevmode->icmmethod;
3903 r->icmintent = ntdevmode->icmintent;
3904 r->mediatype = ntdevmode->mediatype;
3905 r->dithertype = ntdevmode->dithertype;
3908 r->panningwidth = 0;
3909 r->panningheight = 0;
3911 if (ntdevmode->nt_dev_private != NULL) {
3912 r->driverextra_data = data_blob_talloc(mem_ctx,
3913 ntdevmode->nt_dev_private,
3914 ntdevmode->driverextra);
3915 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3922 /****************************************************************************
3923 Create a spoolss_DeviceMode struct. Returns talloced memory.
3924 ****************************************************************************/
3926 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3927 const char *servicename)
3930 NT_PRINTER_INFO_LEVEL *printer = NULL;
3931 struct spoolss_DeviceMode *devmode = NULL;
3933 DEBUG(7,("construct_dev_mode\n"));
3935 DEBUGADD(8,("getting printer characteristics\n"));
3937 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3940 if (!printer->info_2->devmode) {
3941 DEBUG(5, ("BONG! There was no device mode!\n"));
3945 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3947 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3951 DEBUGADD(8,("loading DEVICEMODE\n"));
3953 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3954 if (!W_ERROR_IS_OK(result)) {
3955 TALLOC_FREE(devmode);
3959 free_a_printer(&printer,2);
3964 /********************************************************************
3965 * construct_printer_info3
3966 * fill a spoolss_PrinterInfo3 struct
3967 ********************************************************************/
3969 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3970 const NT_PRINTER_INFO_LEVEL *ntprinter,
3971 struct spoolss_PrinterInfo3 *r,
3974 /* These are the components of the SD we are returning. */
3976 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3977 /* don't use talloc_steal() here unless you do a deep steal of all
3978 the SEC_DESC members */
3980 r->secdesc = dup_sec_desc(mem_ctx,
3981 ntprinter->info_2->secdesc_buf->sd);
3982 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3988 /********************************************************************
3989 * construct_printer_info4
3990 * fill a spoolss_PrinterInfo4 struct
3991 ********************************************************************/
3993 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3994 const NT_PRINTER_INFO_LEVEL *ntprinter,
3995 struct spoolss_PrinterInfo4 *r,
3998 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3999 W_ERROR_HAVE_NO_MEMORY(r->printername);
4000 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4001 W_ERROR_HAVE_NO_MEMORY(r->servername);
4003 r->attributes = ntprinter->info_2->attributes;
4008 /********************************************************************
4009 * construct_printer_info5
4010 * fill a spoolss_PrinterInfo5 struct
4011 ********************************************************************/
4013 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4014 const NT_PRINTER_INFO_LEVEL *ntprinter,
4015 struct spoolss_PrinterInfo5 *r,
4018 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4019 W_ERROR_HAVE_NO_MEMORY(r->printername);
4020 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4021 W_ERROR_HAVE_NO_MEMORY(r->portname);
4023 r->attributes = ntprinter->info_2->attributes;
4025 /* these two are not used by NT+ according to MSDN */
4027 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4028 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4033 /********************************************************************
4034 * construct_printer_info_6
4035 * fill a spoolss_PrinterInfo6 struct
4036 ********************************************************************/
4038 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4039 const NT_PRINTER_INFO_LEVEL *ntprinter,
4040 struct spoolss_PrinterInfo6 *r,
4044 print_status_struct status;
4046 count = print_queue_length(snum, &status);
4048 r->status = nt_printq_status(status.status);
4053 /********************************************************************
4054 * construct_printer_info7
4055 * fill a spoolss_PrinterInfo7 struct
4056 ********************************************************************/
4058 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4059 Printer_entry *print_hnd,
4060 struct spoolss_PrinterInfo7 *r,
4065 if (is_printer_published(print_hnd, snum, &guid)) {
4066 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4067 r->action = DSPRINT_PUBLISH;
4069 r->guid = talloc_strdup(mem_ctx, "");
4070 r->action = DSPRINT_UNPUBLISH;
4072 W_ERROR_HAVE_NO_MEMORY(r->guid);
4077 /********************************************************************
4078 * construct_printer_info1
4079 * fill a spoolss_PrinterInfo1 struct
4080 ********************************************************************/
4082 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4083 const NT_PRINTER_INFO_LEVEL *ntprinter,
4085 struct spoolss_PrinterInfo1 *r,
4088 char *chaine = NULL;
4091 if (*ntprinter->info_2->comment == '\0') {
4092 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4093 chaine = talloc_asprintf(mem_ctx,
4094 "%s,%s,%s", ntprinter->info_2->printername,
4095 ntprinter->info_2->drivername, lp_comment(snum));
4097 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4098 chaine = talloc_asprintf(mem_ctx,
4099 "%s,%s,%s", ntprinter->info_2->printername,
4100 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4102 W_ERROR_HAVE_NO_MEMORY(chaine);
4103 W_ERROR_HAVE_NO_MEMORY(r->comment);
4105 r->description = talloc_strdup(mem_ctx, chaine);
4106 W_ERROR_HAVE_NO_MEMORY(r->description);
4107 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4108 W_ERROR_HAVE_NO_MEMORY(r->name);
4113 /********************************************************************
4114 * construct_printer_info2
4115 * fill a spoolss_PrinterInfo2 struct
4116 ********************************************************************/
4118 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4119 const NT_PRINTER_INFO_LEVEL *ntprinter,
4120 struct spoolss_PrinterInfo2 *r,
4125 print_status_struct status;
4127 count = print_queue_length(snum, &status);
4129 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4130 W_ERROR_HAVE_NO_MEMORY(r->servername);
4131 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4132 W_ERROR_HAVE_NO_MEMORY(r->printername);
4133 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4134 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4135 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4136 W_ERROR_HAVE_NO_MEMORY(r->portname);
4137 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4138 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4140 if (*ntprinter->info_2->comment == '\0') {
4141 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4143 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4145 W_ERROR_HAVE_NO_MEMORY(r->comment);
4147 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4148 W_ERROR_HAVE_NO_MEMORY(r->location);
4149 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4150 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4151 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4152 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4153 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4154 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4155 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4156 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4158 r->attributes = ntprinter->info_2->attributes;
4160 r->priority = ntprinter->info_2->priority;
4161 r->defaultpriority = ntprinter->info_2->default_priority;
4162 r->starttime = ntprinter->info_2->starttime;
4163 r->untiltime = ntprinter->info_2->untiltime;
4164 r->status = nt_printq_status(status.status);
4166 r->averageppm = ntprinter->info_2->averageppm;
4168 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4170 DEBUG(8,("Returning NULL Devicemode!\n"));
4175 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4176 /* don't use talloc_steal() here unless you do a deep steal of all
4177 the SEC_DESC members */
4179 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4185 /********************************************************************
4186 ********************************************************************/
4188 static bool snum_is_shared_printer(int snum)
4190 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4193 /********************************************************************
4194 Spoolss_enumprinters.
4195 ********************************************************************/
4197 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4199 union spoolss_PrinterInfo **info_p,
4203 int n_services = lp_numservices();
4204 union spoolss_PrinterInfo *info = NULL;
4205 WERROR result = WERR_OK;
4207 DEBUG(4,("enum_all_printers_info_1\n"));
4211 for (snum=0; snum<n_services; snum++) {
4213 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4214 struct spoolss_PrinterInfo1 info1;
4216 if (!snum_is_shared_printer(snum)) {
4220 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4222 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4223 if (!W_ERROR_IS_OK(result)) {
4227 result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
4228 free_a_printer(&ntprinter,2);
4229 if (!W_ERROR_IS_OK(result)) {
4233 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4234 union spoolss_PrinterInfo,
4237 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4238 result = WERR_NOMEM;
4242 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
4244 info[*count].info1 = info1;
4249 if (!W_ERROR_IS_OK(result)) {
4260 /********************************************************************
4261 enum_all_printers_info_1_local.
4262 *********************************************************************/
4264 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4265 union spoolss_PrinterInfo **info,
4268 DEBUG(4,("enum_all_printers_info_1_local\n"));
4270 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4273 /********************************************************************
4274 enum_all_printers_info_1_name.
4275 *********************************************************************/
4277 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4279 union spoolss_PrinterInfo **info,
4282 const char *s = name;
4284 DEBUG(4,("enum_all_printers_info_1_name\n"));
4286 if ((name[0] == '\\') && (name[1] == '\\')) {
4290 if (!is_myname_or_ipaddr(s)) {
4291 return WERR_INVALID_NAME;
4294 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4297 /********************************************************************
4298 enum_all_printers_info_1_network.
4299 *********************************************************************/
4301 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4303 union spoolss_PrinterInfo **info,
4306 const char *s = name;
4308 DEBUG(4,("enum_all_printers_info_1_network\n"));
4310 /* If we respond to a enum_printers level 1 on our name with flags
4311 set to PRINTER_ENUM_REMOTE with a list of printers then these
4312 printers incorrectly appear in the APW browse list.
4313 Specifically the printers for the server appear at the workgroup
4314 level where all the other servers in the domain are
4315 listed. Windows responds to this call with a
4316 WERR_CAN_NOT_COMPLETE so we should do the same. */
4318 if (name[0] == '\\' && name[1] == '\\') {
4322 if (is_myname_or_ipaddr(s)) {
4323 return WERR_CAN_NOT_COMPLETE;
4326 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4329 /********************************************************************
4330 * api_spoolss_enumprinters
4332 * called from api_spoolss_enumprinters (see this to understand)
4333 ********************************************************************/
4335 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4336 union spoolss_PrinterInfo **info_p,
4340 int n_services = lp_numservices();
4341 union spoolss_PrinterInfo *info = NULL;
4342 WERROR result = WERR_OK;
4346 for (snum=0; snum<n_services; snum++) {
4348 struct spoolss_PrinterInfo2 info2;
4349 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4351 if (!snum_is_shared_printer(snum)) {
4355 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4357 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4358 if (!W_ERROR_IS_OK(result)) {
4362 result = construct_printer_info2(info, ntprinter, &info2, snum);
4363 free_a_printer(&ntprinter, 2);
4364 if (!W_ERROR_IS_OK(result)) {
4368 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4369 union spoolss_PrinterInfo,
4372 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4373 result = WERR_NOMEM;
4377 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
4379 info[*count].info2 = info2;
4385 if (!W_ERROR_IS_OK(result)) {
4396 /********************************************************************
4397 * handle enumeration of printers at level 1
4398 ********************************************************************/
4400 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4403 union spoolss_PrinterInfo **info,
4406 /* Not all the flags are equals */
4408 if (flags & PRINTER_ENUM_LOCAL) {
4409 return enum_all_printers_info_1_local(mem_ctx, info, count);
4412 if (flags & PRINTER_ENUM_NAME) {
4413 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4416 if (flags & PRINTER_ENUM_NETWORK) {
4417 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4420 return WERR_OK; /* NT4sp5 does that */
4423 /********************************************************************
4424 * handle enumeration of printers at level 2
4425 ********************************************************************/
4427 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4429 const char *servername,
4430 union spoolss_PrinterInfo **info,
4433 if (flags & PRINTER_ENUM_LOCAL) {
4434 return enum_all_printers_info_2(mem_ctx, info, count);
4437 if (flags & PRINTER_ENUM_NAME) {
4438 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4439 return WERR_INVALID_NAME;
4442 return enum_all_printers_info_2(mem_ctx, info, count);
4445 if (flags & PRINTER_ENUM_REMOTE) {
4446 return WERR_UNKNOWN_LEVEL;
4452 /********************************************************************
4453 * handle enumeration of printers at level 5
4454 ********************************************************************/
4456 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4458 const char *servername,
4459 union spoolss_PrinterInfo **info,
4462 /* return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4466 /****************************************************************
4467 _spoolss_EnumPrinters
4468 ****************************************************************/
4470 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4471 struct spoolss_EnumPrinters *r)
4476 /* that's an [in out] buffer */
4478 if (!r->in.buffer && (r->in.offered != 0)) {
4479 return WERR_INVALID_PARAM;
4482 DEBUG(4,("_spoolss_EnumPrinters\n"));
4486 *r->out.info = NULL;
4490 * flags==PRINTER_ENUM_NAME
4491 * if name=="" then enumerates all printers
4492 * if name!="" then enumerate the printer
4493 * flags==PRINTER_ENUM_REMOTE
4494 * name is NULL, enumerate printers
4495 * Level 2: name!="" enumerates printers, name can't be NULL
4496 * Level 3: doesn't exist
4497 * Level 4: does a local registry lookup
4498 * Level 5: same as Level 2
4501 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4502 W_ERROR_HAVE_NO_MEMORY(name);
4504 switch (r->in.level) {
4506 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4507 r->out.info, r->out.count);
4510 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4511 r->out.info, r->out.count);
4514 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4515 r->out.info, r->out.count);
4519 result = WERR_OK; /* ??? */
4522 return WERR_UNKNOWN_LEVEL;
4525 if (!W_ERROR_IS_OK(result)) {
4529 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4530 spoolss_EnumPrinters, NULL,
4531 *r->out.info, r->in.level,
4533 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4534 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4536 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4539 /****************************************************************
4541 ****************************************************************/
4543 WERROR _spoolss_GetPrinter(pipes_struct *p,
4544 struct spoolss_GetPrinter *r)
4546 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4547 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4548 WERROR result = WERR_OK;
4552 /* that's an [in out] buffer */
4554 if (!r->in.buffer && (r->in.offered != 0)) {
4555 return WERR_INVALID_PARAM;
4560 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4564 result = get_a_printer(Printer, &ntprinter, 2,
4565 lp_const_servicename(snum));
4566 if (!W_ERROR_IS_OK(result)) {
4570 switch (r->in.level) {
4572 result = construct_printer_info0(p->mem_ctx, ntprinter,
4573 &r->out.info->info0, snum);
4576 result = construct_printer_info1(p->mem_ctx, ntprinter,
4578 &r->out.info->info1, snum);
4581 result = construct_printer_info2(p->mem_ctx, ntprinter,
4582 &r->out.info->info2, snum);
4585 result = construct_printer_info3(p->mem_ctx, ntprinter,
4586 &r->out.info->info3, snum);
4589 result = construct_printer_info4(p->mem_ctx, ntprinter,
4590 &r->out.info->info4, snum);
4593 result = construct_printer_info5(p->mem_ctx, ntprinter,
4594 &r->out.info->info5, snum);
4597 result = construct_printer_info6(p->mem_ctx, ntprinter,
4598 &r->out.info->info6, snum);
4601 result = construct_printer_info7(p->mem_ctx, Printer,
4602 &r->out.info->info7, snum);
4605 result = WERR_UNKNOWN_LEVEL;
4609 free_a_printer(&ntprinter, 2);
4611 if (!W_ERROR_IS_OK(result)) {
4612 TALLOC_FREE(r->out.info);
4616 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4617 r->out.info, r->in.level);
4618 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4620 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4623 /********************************************************************
4624 ********************************************************************/
4626 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4627 fstring *fstring_array,
4628 const char *cservername)
4630 int i, num_strings = 0;
4631 const char **array = NULL;
4633 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4635 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4636 cservername, fstring_array[i]);
4643 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4650 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4651 &array, &num_strings);
4657 /********************************************************************
4658 * fill a spoolss_DriverInfo1 struct
4659 ********************************************************************/
4661 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4662 struct spoolss_DriverInfo1 *r,
4663 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4664 const char *servername,
4665 const char *architecture)
4667 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4668 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4673 /********************************************************************
4674 * fill a spoolss_DriverInfo2 struct
4675 ********************************************************************/
4677 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4678 struct spoolss_DriverInfo2 *r,
4679 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4680 const char *servername)
4683 const char *cservername = canon_servername(servername);
4685 r->version = driver->info_3->cversion;
4687 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4688 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4689 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4690 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4692 if (strlen(driver->info_3->driverpath)) {
4693 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4694 cservername, driver->info_3->driverpath);
4696 r->driver_path = talloc_strdup(mem_ctx, "");
4698 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4700 if (strlen(driver->info_3->datafile)) {
4701 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4702 cservername, driver->info_3->datafile);
4704 r->data_file = talloc_strdup(mem_ctx, "");
4706 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4708 if (strlen(driver->info_3->configfile)) {
4709 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4710 cservername, driver->info_3->configfile);
4712 r->config_file = talloc_strdup(mem_ctx, "");
4714 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4719 /********************************************************************
4720 * fill a spoolss_DriverInfo3 struct
4721 ********************************************************************/
4723 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4724 struct spoolss_DriverInfo3 *r,
4725 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4726 const char *servername)
4728 const char *cservername = canon_servername(servername);
4730 r->version = driver->info_3->cversion;
4732 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4733 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4734 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4735 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4737 if (strlen(driver->info_3->driverpath)) {
4738 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4739 cservername, driver->info_3->driverpath);
4741 r->driver_path = talloc_strdup(mem_ctx, "");
4743 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4745 if (strlen(driver->info_3->datafile)) {
4746 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4747 cservername, driver->info_3->datafile);
4749 r->data_file = talloc_strdup(mem_ctx, "");
4751 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4753 if (strlen(driver->info_3->configfile)) {
4754 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4755 cservername, driver->info_3->configfile);
4757 r->config_file = talloc_strdup(mem_ctx, "");
4759 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4761 if (strlen(driver->info_3->helpfile)) {
4762 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4763 cservername, driver->info_3->helpfile);
4765 r->help_file = talloc_strdup(mem_ctx, "");
4767 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4769 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4770 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4771 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4772 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4774 r->dependent_files = string_array_from_driver_info(mem_ctx,
4775 driver->info_3->dependentfiles,
4780 /********************************************************************
4781 * fill a spoolss_DriverInfo6 struct
4782 ********************************************************************/
4784 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4785 struct spoolss_DriverInfo6 *r,
4786 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4787 const char *servername)
4789 const char *cservername = canon_servername(servername);
4791 r->version = driver->info_3->cversion;
4793 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4794 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4795 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4796 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4798 if (strlen(driver->info_3->driverpath)) {
4799 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4800 cservername, driver->info_3->driverpath);
4802 r->driver_path = talloc_strdup(mem_ctx, "");
4804 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4806 if (strlen(driver->info_3->datafile)) {
4807 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4808 cservername, driver->info_3->datafile);
4810 r->data_file = talloc_strdup(mem_ctx, "");
4812 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4814 if (strlen(driver->info_3->configfile)) {
4815 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4816 cservername, driver->info_3->configfile);
4818 r->config_file = talloc_strdup(mem_ctx, "");
4820 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4822 if (strlen(driver->info_3->helpfile)) {
4823 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4824 cservername, driver->info_3->helpfile);
4826 r->help_file = talloc_strdup(mem_ctx, "");
4828 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4830 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4831 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4832 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4833 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4835 r->dependent_files = string_array_from_driver_info(mem_ctx,
4836 driver->info_3->dependentfiles,
4838 r->previous_names = string_array_from_driver_info(mem_ctx,
4843 r->driver_version = 0;
4845 r->manufacturer_name = talloc_strdup(mem_ctx, "");
4846 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4847 r->manufacturer_url = talloc_strdup(mem_ctx, "");
4848 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4849 r->hardware_id = talloc_strdup(mem_ctx, "");
4850 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4851 r->provider = talloc_strdup(mem_ctx, "");
4852 W_ERROR_HAVE_NO_MEMORY(r->provider);
4857 /********************************************************************
4858 * construct_printer_driver_info_1
4859 ********************************************************************/
4861 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
4862 struct spoolss_DriverInfo1 *r,
4864 const char *servername,
4865 const char *architecture,
4868 NT_PRINTER_INFO_LEVEL *printer = NULL;
4869 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4872 ZERO_STRUCT(driver);
4874 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4875 return WERR_INVALID_PRINTER_NAME;
4877 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4878 free_a_printer(&printer, 2);
4879 return WERR_UNKNOWN_PRINTER_DRIVER;
4882 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
4884 free_a_printer(&printer,2);
4889 /********************************************************************
4890 * construct_printer_driver_info_2
4891 * fill a printer_info_2 struct
4892 ********************************************************************/
4894 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
4895 struct spoolss_DriverInfo2 *r,
4897 const char *servername,
4898 const char *architecture,
4901 NT_PRINTER_INFO_LEVEL *printer = NULL;
4902 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4905 ZERO_STRUCT(printer);
4906 ZERO_STRUCT(driver);
4908 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4909 return WERR_INVALID_PRINTER_NAME;
4911 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4912 free_a_printer(&printer, 2);
4913 return WERR_UNKNOWN_PRINTER_DRIVER;
4916 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
4918 free_a_printer(&printer,2);
4923 /********************************************************************
4924 * construct_printer_info_3
4925 * fill a printer_info_3 struct
4926 ********************************************************************/
4928 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
4929 struct spoolss_DriverInfo3 *r,
4931 const char *servername,
4932 const char *architecture,
4935 NT_PRINTER_INFO_LEVEL *printer = NULL;
4936 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4938 ZERO_STRUCT(driver);
4940 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
4941 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4942 if (!W_ERROR_IS_OK(status))
4943 return WERR_INVALID_PRINTER_NAME;
4945 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4946 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4951 * I put this code in during testing. Helpful when commenting out the
4952 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4953 * as win2k always queries the driver using an infor level of 6.
4954 * I've left it in (but ifdef'd out) because I'll probably
4955 * use it in experimentation again in the future. --jerry 22/01/2002
4958 if (!W_ERROR_IS_OK(status)) {
4960 * Is this a W2k client ?
4963 /* Yes - try again with a WinNT driver. */
4965 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
4966 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4970 if (!W_ERROR_IS_OK(status)) {
4971 free_a_printer(&printer,2);
4972 return WERR_UNKNOWN_PRINTER_DRIVER;
4980 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
4982 free_a_printer(&printer,2);
4987 /********************************************************************
4988 * construct_printer_info_6
4989 * fill a printer_info_6 struct
4990 ********************************************************************/
4992 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
4993 struct spoolss_DriverInfo6 *r,
4995 const char *servername,
4996 const char *architecture,
4999 NT_PRINTER_INFO_LEVEL *printer = NULL;
5000 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5003 ZERO_STRUCT(driver);
5005 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5007 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5009 if (!W_ERROR_IS_OK(status))
5010 return WERR_INVALID_PRINTER_NAME;
5012 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5014 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5016 if (!W_ERROR_IS_OK(status))
5019 * Is this a W2k client ?
5023 free_a_printer(&printer,2);
5024 return WERR_UNKNOWN_PRINTER_DRIVER;
5027 /* Yes - try again with a WinNT driver. */
5029 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5030 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5031 if (!W_ERROR_IS_OK(status)) {
5032 free_a_printer(&printer,2);
5033 return WERR_UNKNOWN_PRINTER_DRIVER;
5037 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5039 free_a_printer(&printer,2);
5040 free_a_printer_driver(driver, 3);
5045 /****************************************************************
5046 _spoolss_GetPrinterDriver2
5047 ****************************************************************/
5049 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5050 struct spoolss_GetPrinterDriver2 *r)
5052 Printer_entry *printer;
5055 const char *servername;
5058 /* that's an [in out] buffer */
5060 if (!r->in.buffer && (r->in.offered != 0)) {
5061 return WERR_INVALID_PARAM;
5064 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5066 if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
5067 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5068 return WERR_INVALID_PRINTER_NAME;
5072 *r->out.server_major_version = 0;
5073 *r->out.server_minor_version = 0;
5075 servername = get_server_name(printer);
5077 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5081 switch (r->in.level) {
5083 result = construct_printer_driver_info_1(p->mem_ctx,
5084 &r->out.info->info1,
5088 r->in.client_major_version);
5091 result = construct_printer_driver_info_2(p->mem_ctx,
5092 &r->out.info->info2,
5096 r->in.client_major_version);
5099 result = construct_printer_driver_info_3(p->mem_ctx,
5100 &r->out.info->info3,
5104 r->in.client_major_version);
5107 result = construct_printer_driver_info_6(p->mem_ctx,
5108 &r->out.info->info6,
5112 r->in.client_major_version);
5117 /* apparently this call is the equivalent of
5118 EnumPrinterDataEx() for the DsDriver key */
5121 result = WERR_UNKNOWN_LEVEL;
5125 if (!W_ERROR_IS_OK(result)) {
5126 TALLOC_FREE(r->out.info);
5130 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5131 r->out.info, r->in.level);
5132 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5134 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5138 /****************************************************************
5139 _spoolss_StartPagePrinter
5140 ****************************************************************/
5142 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5143 struct spoolss_StartPagePrinter *r)
5145 POLICY_HND *handle = r->in.handle;
5147 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5150 DEBUG(3,("_spoolss_StartPagePrinter: "
5151 "Error in startpageprinter printer handle\n"));
5155 Printer->page_started=True;
5159 /****************************************************************
5160 _spoolss_EndPagePrinter
5161 ****************************************************************/
5163 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5164 struct spoolss_EndPagePrinter *r)
5166 POLICY_HND *handle = r->in.handle;
5169 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5172 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5173 OUR_HANDLE(handle)));
5177 if (!get_printer_snum(p, handle, &snum, NULL))
5180 Printer->page_started=False;
5181 print_job_endpage(snum, Printer->jobid);
5186 /****************************************************************
5187 _spoolss_StartDocPrinter
5188 ****************************************************************/
5190 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5191 struct spoolss_StartDocPrinter *r)
5193 POLICY_HND *handle = r->in.handle;
5194 uint32_t *jobid = r->out.job_id;
5195 struct spoolss_DocumentInfo1 *info_1;
5197 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5200 DEBUG(2,("_spoolss_StartDocPrinter: "
5201 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5205 if (r->in.level != 1) {
5206 return WERR_UNKNOWN_LEVEL;
5209 info_1 = r->in.info.info1;
5212 * a nice thing with NT is it doesn't listen to what you tell it.
5213 * when asked to send _only_ RAW datas, it tries to send datas
5216 * So I add checks like in NT Server ...
5219 if (info_1->datatype) {
5220 if (strcmp(info_1->datatype, "RAW") != 0) {
5222 return WERR_INVALID_DATATYPE;
5226 /* get the share number of the printer */
5227 if (!get_printer_snum(p, handle, &snum, NULL)) {
5231 Printer->jobid = print_job_start(p->server_info, snum,
5232 info_1->document_name,
5233 Printer->nt_devmode);
5235 /* An error occured in print_job_start() so return an appropriate
5238 if (Printer->jobid == -1) {
5239 return map_werror_from_unix(errno);
5242 Printer->document_started=True;
5243 (*jobid) = Printer->jobid;
5248 /****************************************************************
5249 _spoolss_EndDocPrinter
5250 ****************************************************************/
5252 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5253 struct spoolss_EndDocPrinter *r)
5255 POLICY_HND *handle = r->in.handle;
5257 return _spoolss_enddocprinter_internal(p, handle);
5260 /****************************************************************
5261 _spoolss_WritePrinter
5262 ****************************************************************/
5264 WERROR _spoolss_WritePrinter(pipes_struct *p,
5265 struct spoolss_WritePrinter *r)
5267 POLICY_HND *handle = r->in.handle;
5268 uint32 buffer_size = r->in._data_size;
5269 uint8 *buffer = r->in.data.data;
5270 uint32 *buffer_written = &r->in._data_size;
5272 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5275 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5276 OUR_HANDLE(handle)));
5277 *r->out.num_written = r->in._data_size;
5281 if (!get_printer_snum(p, handle, &snum, NULL))
5284 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5285 (SMB_OFF_T)-1, (size_t)buffer_size);
5286 if (*buffer_written == (uint32)-1) {
5287 *r->out.num_written = 0;
5288 if (errno == ENOSPC)
5289 return WERR_NO_SPOOL_SPACE;
5291 return WERR_ACCESS_DENIED;
5294 *r->out.num_written = r->in._data_size;
5299 /********************************************************************
5300 * api_spoolss_getprinter
5301 * called from the spoolss dispatcher
5303 ********************************************************************/
5305 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5309 WERROR errcode = WERR_BADFUNC;
5310 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5313 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5317 if (!get_printer_snum(p, handle, &snum, NULL))
5321 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5322 if (print_queue_pause(p->server_info, snum, &errcode)) {
5326 case SPOOLSS_PRINTER_CONTROL_RESUME:
5327 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5328 if (print_queue_resume(p->server_info, snum, &errcode)) {
5332 case SPOOLSS_PRINTER_CONTROL_PURGE:
5333 if (print_queue_purge(p->server_info, snum, &errcode)) {
5338 return WERR_UNKNOWN_LEVEL;
5345 /****************************************************************
5346 _spoolss_AbortPrinter
5347 * From MSDN: "Deletes printer's spool file if printer is configured
5349 ****************************************************************/
5351 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5352 struct spoolss_AbortPrinter *r)
5354 POLICY_HND *handle = r->in.handle;
5355 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5357 WERROR errcode = WERR_OK;
5360 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5361 OUR_HANDLE(handle)));
5365 if (!get_printer_snum(p, handle, &snum, NULL))
5368 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5373 /********************************************************************
5374 * called by spoolss_api_setprinter
5375 * when updating a printer description
5376 ********************************************************************/
5378 static WERROR update_printer_sec(POLICY_HND *handle,
5379 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5381 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5385 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5387 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5388 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5389 OUR_HANDLE(handle)));
5391 result = WERR_BADFID;
5396 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5397 result = WERR_INVALID_PARAM;
5401 /* Check the user has permissions to change the security
5402 descriptor. By experimentation with two NT machines, the user
5403 requires Full Access to the printer to change security
5406 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5407 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5408 result = WERR_ACCESS_DENIED;
5412 /* NT seems to like setting the security descriptor even though
5413 nothing may have actually changed. */
5415 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5416 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5417 result = WERR_BADFID;
5421 if (DEBUGLEVEL >= 10) {
5425 the_acl = old_secdesc_ctr->sd->dacl;
5426 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5427 PRINTERNAME(snum), the_acl->num_aces));
5429 for (i = 0; i < the_acl->num_aces; i++) {
5430 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5431 &the_acl->aces[i].trustee),
5432 the_acl->aces[i].access_mask));
5435 the_acl = secdesc_ctr->sd->dacl;
5438 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5439 PRINTERNAME(snum), the_acl->num_aces));
5441 for (i = 0; i < the_acl->num_aces; i++) {
5442 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5443 &the_acl->aces[i].trustee),
5444 the_acl->aces[i].access_mask));
5447 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5451 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5452 if (!new_secdesc_ctr) {
5453 result = WERR_NOMEM;
5457 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5462 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5469 /********************************************************************
5470 Canonicalize printer info from a client
5472 ATTN: It does not matter what we set the servername to hear
5473 since we do the necessary work in get_a_printer() to set it to
5474 the correct value based on what the client sent in the
5475 _spoolss_open_printer_ex().
5476 ********************************************************************/
5478 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5480 fstring printername;
5483 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5484 "portname=%s drivername=%s comment=%s location=%s\n",
5485 info->servername, info->printername, info->sharename,
5486 info->portname, info->drivername, info->comment, info->location));
5488 /* we force some elements to "correct" values */
5489 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5490 fstrcpy(info->sharename, lp_servicename(snum));
5492 /* check to see if we allow printername != sharename */
5494 if ( lp_force_printername(snum) ) {
5495 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5496 global_myname(), info->sharename );
5499 /* make sure printername is in \\server\printername format */
5501 fstrcpy( printername, info->printername );
5503 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5504 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5508 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5509 global_myname(), p );
5512 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5513 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5520 /****************************************************************************
5521 ****************************************************************************/
5523 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5525 char *cmd = lp_addport_cmd();
5526 char *command = NULL;
5528 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5529 bool is_print_op = False;
5532 return WERR_ACCESS_DENIED;
5535 command = talloc_asprintf(ctx,
5536 "%s \"%s\" \"%s\"", cmd, portname, uri );
5542 is_print_op = user_has_privileges( token, &se_printop );
5544 DEBUG(10,("Running [%s]\n", command));
5546 /********* BEGIN SePrintOperatorPrivilege **********/
5551 ret = smbrun(command, NULL);
5556 /********* END SePrintOperatorPrivilege **********/
5558 DEBUGADD(10,("returned [%d]\n", ret));
5560 TALLOC_FREE(command);
5563 return WERR_ACCESS_DENIED;
5569 /****************************************************************************
5570 ****************************************************************************/
5572 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5574 char *cmd = lp_addprinter_cmd();
5576 char *command = NULL;
5580 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5581 bool is_print_op = False;
5582 char *remote_machine = talloc_strdup(ctx, "%m");
5584 if (!remote_machine) {
5587 remote_machine = talloc_sub_basic(ctx,
5588 current_user_info.smb_name,
5589 current_user_info.domain,
5591 if (!remote_machine) {
5595 command = talloc_asprintf(ctx,
5596 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5597 cmd, printer->info_2->printername, printer->info_2->sharename,
5598 printer->info_2->portname, printer->info_2->drivername,
5599 printer->info_2->location, printer->info_2->comment, remote_machine);
5605 is_print_op = user_has_privileges( token, &se_printop );
5607 DEBUG(10,("Running [%s]\n", command));
5609 /********* BEGIN SePrintOperatorPrivilege **********/
5614 if ( (ret = smbrun(command, &fd)) == 0 ) {
5615 /* Tell everyone we updated smb.conf. */
5616 message_send_all(smbd_messaging_context(),
5617 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5623 /********* END SePrintOperatorPrivilege **********/
5625 DEBUGADD(10,("returned [%d]\n", ret));
5627 TALLOC_FREE(command);
5628 TALLOC_FREE(remote_machine);
5636 /* reload our services immediately */
5637 reload_services( False );
5640 /* Get lines and convert them back to dos-codepage */
5641 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5642 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5645 /* Set the portname to what the script says the portname should be. */
5646 /* but don't require anything to be return from the script exit a good error code */
5649 /* Set the portname to what the script says the portname should be. */
5650 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5651 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5654 TALLOC_FREE(qlines);
5659 /********************************************************************
5660 * Called by spoolss_api_setprinter
5661 * when updating a printer description.
5662 ********************************************************************/
5664 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
5665 struct spoolss_SetPrinterInfoCtr *info_ctr,
5666 struct spoolss_DeviceMode *devmode)
5669 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5670 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5675 DEBUG(8,("update_printer\n"));
5680 result = WERR_BADFID;
5684 if (!get_printer_snum(p, handle, &snum, NULL)) {
5685 result = WERR_BADFID;
5689 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5690 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5691 result = WERR_BADFID;
5695 DEBUGADD(8,("Converting info_2 struct\n"));
5698 * convert_printer_info converts the incoming
5699 * info from the client and overwrites the info
5700 * just read from the tdb in the pointer 'printer'.
5703 if (!convert_printer_info(info_ctr, printer)) {
5704 result = WERR_NOMEM;
5709 /* we have a valid devmode
5710 convert it and link it*/
5712 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5713 if (!convert_devicemode(printer->info_2->printername, devmode,
5714 &printer->info_2->devmode)) {
5715 result = WERR_NOMEM;
5720 /* Do sanity check on the requested changes for Samba */
5722 if (!check_printer_ok(printer->info_2, snum)) {
5723 result = WERR_INVALID_PARAM;
5727 /* FIXME!!! If the driver has changed we really should verify that
5728 it is installed before doing much else --jerry */
5730 /* Check calling user has permission to update printer description */
5732 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5733 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5734 result = WERR_ACCESS_DENIED;
5738 /* Call addprinter hook */
5739 /* Check changes to see if this is really needed */
5741 if ( *lp_addprinter_cmd()
5742 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5743 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5744 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5745 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5747 /* add_printer_hook() will call reload_services() */
5749 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5751 result = WERR_ACCESS_DENIED;
5757 * When a *new* driver is bound to a printer, the drivername is used to
5758 * lookup previously saved driver initialization info, which is then
5759 * bound to the printer, simulating what happens in the Windows arch.
5761 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5763 if (!set_driver_init(printer, 2))
5765 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5766 printer->info_2->drivername));
5769 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5770 printer->info_2->drivername));
5772 notify_printer_driver(snum, printer->info_2->drivername);
5776 * flag which changes actually occured. This is a small subset of
5777 * all the possible changes. We also have to update things in the
5781 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5782 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
5783 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5784 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5786 notify_printer_comment(snum, printer->info_2->comment);
5789 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5790 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
5791 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5792 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5794 notify_printer_sharename(snum, printer->info_2->sharename);
5797 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5800 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5803 pname = printer->info_2->printername;
5806 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
5807 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5808 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5810 notify_printer_printername( snum, pname );
5813 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5814 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
5815 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5816 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5818 notify_printer_port(snum, printer->info_2->portname);
5821 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5822 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
5823 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5824 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5826 notify_printer_location(snum, printer->info_2->location);
5829 /* here we need to update some more DsSpooler keys */
5830 /* uNCName, serverName, shortServerName */
5832 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
5833 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5834 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5835 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5836 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5838 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5839 global_myname(), printer->info_2->sharename );
5840 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
5841 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5842 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
5844 /* Update printer info */
5845 result = mod_a_printer(printer, 2);
5848 free_a_printer(&printer, 2);
5849 free_a_printer(&old_printer, 2);
5855 /****************************************************************************
5856 ****************************************************************************/
5857 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
5858 struct spoolss_SetPrinterInfo7 *info7)
5862 Printer_entry *Printer;
5864 if ( lp_security() != SEC_ADS ) {
5865 return WERR_UNKNOWN_LEVEL;
5868 Printer = find_printer_index_by_hnd(p, handle);
5870 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5875 if (!get_printer_snum(p, handle, &snum, NULL))
5878 nt_printer_publish(Printer, snum, info7->action);
5882 return WERR_UNKNOWN_LEVEL;
5886 /****************************************************************
5888 ****************************************************************/
5890 WERROR _spoolss_SetPrinter(pipes_struct *p,
5891 struct spoolss_SetPrinter *r)
5893 POLICY_HND *handle = r->in.handle;
5896 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5899 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5900 OUR_HANDLE(handle)));
5904 /* check the level */
5905 switch (r->in.info_ctr->level) {
5907 return control_printer(handle, r->in.command, p);
5909 result = update_printer(p, handle,
5911 r->in.devmode_ctr->devmode);
5912 if (!W_ERROR_IS_OK(result))
5914 if (r->in.secdesc_ctr->sd)
5915 result = update_printer_sec(handle, p,
5919 return update_printer_sec(handle, p,
5922 return publish_or_unpublish_printer(p, handle,
5923 r->in.info_ctr->info.info7);
5925 return WERR_UNKNOWN_LEVEL;
5929 /****************************************************************
5930 _spoolss_FindClosePrinterNotify
5931 ****************************************************************/
5933 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5934 struct spoolss_FindClosePrinterNotify *r)
5936 POLICY_HND *handle = r->in.handle;
5937 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
5940 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5941 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5945 if (Printer->notify.client_connected==True) {
5948 if ( Printer->printer_type == SPLHND_SERVER)
5950 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5951 !get_printer_snum(p, handle, &snum, NULL) )
5954 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5957 Printer->notify.flags=0;
5958 Printer->notify.options=0;
5959 Printer->notify.localmachine[0]='\0';
5960 Printer->notify.printerlocal=0;
5961 TALLOC_FREE(Printer->notify.option);
5962 Printer->notify.client_connected=False;
5967 /****************************************************************
5969 ****************************************************************/
5971 WERROR _spoolss_AddJob(pipes_struct *p,
5972 struct spoolss_AddJob *r)
5974 if (!r->in.buffer && (r->in.offered != 0)) {
5975 return WERR_INVALID_PARAM;
5978 /* this is what a NT server returns for AddJob. AddJob must fail on
5979 * non-local printers */
5981 if (r->in.level != 1) {
5982 return WERR_UNKNOWN_LEVEL;
5985 return WERR_INVALID_PARAM;
5988 /****************************************************************************
5990 ****************************************************************************/
5992 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5993 struct spoolss_JobInfo1 *r,
5994 const print_queue_struct *queue,
5995 int position, int snum,
5996 const NT_PRINTER_INFO_LEVEL *ntprinter)
6000 t = gmtime(&queue->time);
6002 r->job_id = queue->job;
6004 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6005 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6006 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6007 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6008 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6009 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6010 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6011 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6012 r->data_type = talloc_strdup(mem_ctx, "RAW");
6013 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6014 r->text_status = talloc_strdup(mem_ctx, "");
6015 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6017 r->status = nt_printj_status(queue->status);
6018 r->priority = queue->priority;
6019 r->position = position;
6020 r->total_pages = queue->page_count;
6021 r->pages_printed = 0; /* ??? */
6023 init_systemtime(&r->submitted, t);
6028 /****************************************************************************
6030 ****************************************************************************/
6032 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6033 struct spoolss_JobInfo2 *r,
6034 const print_queue_struct *queue,
6035 int position, int snum,
6036 const NT_PRINTER_INFO_LEVEL *ntprinter,
6037 struct spoolss_DeviceMode *devmode)
6041 t = gmtime(&queue->time);
6043 r->job_id = queue->job;
6045 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6046 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6047 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6048 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6049 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6050 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6051 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6052 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6053 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6054 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6055 r->data_type = talloc_strdup(mem_ctx, "RAW");
6056 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6057 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6058 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6059 r->parameters = talloc_strdup(mem_ctx, "");
6060 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6061 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6062 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6064 r->devmode = devmode;
6066 r->text_status = talloc_strdup(mem_ctx, "");
6067 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6071 r->status = nt_printj_status(queue->status);
6072 r->priority = queue->priority;
6073 r->position = position;
6076 r->total_pages = queue->page_count;
6077 r->size = queue->size;
6078 init_systemtime(&r->submitted, t);
6080 r->pages_printed = 0; /* ??? */
6085 /****************************************************************************
6086 Enumjobs at level 1.
6087 ****************************************************************************/
6089 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6090 const print_queue_struct *queue,
6091 uint32_t num_queues, int snum,
6092 const NT_PRINTER_INFO_LEVEL *ntprinter,
6093 union spoolss_JobInfo **info_p,
6096 union spoolss_JobInfo *info;
6098 WERROR result = WERR_OK;
6100 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6101 W_ERROR_HAVE_NO_MEMORY(info);
6103 *count = num_queues;
6105 for (i=0; i<*count; i++) {
6106 result = fill_job_info1(info,
6112 if (!W_ERROR_IS_OK(result)) {
6118 if (!W_ERROR_IS_OK(result)) {
6129 /****************************************************************************
6130 Enumjobs at level 2.
6131 ****************************************************************************/
6133 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6134 const print_queue_struct *queue,
6135 uint32_t num_queues, int snum,
6136 const NT_PRINTER_INFO_LEVEL *ntprinter,
6137 union spoolss_JobInfo **info_p,
6140 union spoolss_JobInfo *info;
6142 WERROR result = WERR_OK;
6144 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6145 W_ERROR_HAVE_NO_MEMORY(info);
6147 *count = num_queues;
6149 for (i=0; i<*count; i++) {
6151 struct spoolss_DeviceMode *devmode;
6153 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6155 result = WERR_NOMEM;
6159 result = fill_job_info2(info,
6166 if (!W_ERROR_IS_OK(result)) {
6172 if (!W_ERROR_IS_OK(result)) {
6183 /****************************************************************
6185 ****************************************************************/
6187 WERROR _spoolss_EnumJobs(pipes_struct *p,
6188 struct spoolss_EnumJobs *r)
6191 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6193 print_status_struct prt_status;
6194 print_queue_struct *queue = NULL;
6197 /* that's an [in out] buffer */
6199 if (!r->in.buffer && (r->in.offered != 0)) {
6200 return WERR_INVALID_PARAM;
6203 DEBUG(4,("_spoolss_EnumJobs\n"));
6207 *r->out.info = NULL;
6209 /* lookup the printer snum and tdb entry */
6211 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6215 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6216 if (!W_ERROR_IS_OK(result)) {
6220 count = print_queue_status(snum, &queue, &prt_status);
6221 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6222 count, prt_status.status, prt_status.message));
6226 free_a_printer(&ntprinter, 2);
6230 switch (r->in.level) {
6232 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6233 ntprinter, r->out.info, r->out.count);
6236 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6237 ntprinter, r->out.info, r->out.count);
6240 result = WERR_UNKNOWN_LEVEL;
6245 free_a_printer(&ntprinter, 2);
6247 if (!W_ERROR_IS_OK(result)) {
6251 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6252 spoolss_EnumJobs, NULL,
6253 *r->out.info, r->in.level,
6255 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6256 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6258 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6261 /****************************************************************
6262 _spoolss_ScheduleJob
6263 ****************************************************************/
6265 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6266 struct spoolss_ScheduleJob *r)
6271 /****************************************************************
6273 ****************************************************************/
6275 WERROR _spoolss_SetJob(pipes_struct *p,
6276 struct spoolss_SetJob *r)
6278 POLICY_HND *handle = r->in.handle;
6279 uint32 jobid = r->in.job_id;
6280 uint32 command = r->in.command;
6283 WERROR errcode = WERR_BADFUNC;
6285 if (!get_printer_snum(p, handle, &snum, NULL)) {
6289 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6290 return WERR_INVALID_PRINTER_NAME;
6294 case SPOOLSS_JOB_CONTROL_CANCEL:
6295 case SPOOLSS_JOB_CONTROL_DELETE:
6296 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6300 case SPOOLSS_JOB_CONTROL_PAUSE:
6301 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6305 case SPOOLSS_JOB_CONTROL_RESTART:
6306 case SPOOLSS_JOB_CONTROL_RESUME:
6307 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6312 return WERR_UNKNOWN_LEVEL;
6318 /****************************************************************************
6319 Enumerates all printer drivers at level 1.
6320 ****************************************************************************/
6322 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6323 const char *servername,
6324 const char *architecture,
6325 union spoolss_DriverInfo **info_p,
6331 fstring *list = NULL;
6332 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6333 union spoolss_DriverInfo *info = NULL;
6334 WERROR result = WERR_OK;
6338 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6340 ndrivers = get_ntdrivers(&list, architecture, version);
6341 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6342 ndrivers, architecture, version));
6344 if (ndrivers == -1) {
6345 result = WERR_NOMEM;
6349 if (ndrivers != 0) {
6350 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6351 union spoolss_DriverInfo,
6354 DEBUG(0,("enumprinterdrivers_level1: "
6355 "failed to enlarge driver info buffer!\n"));
6356 result = WERR_NOMEM;
6361 for (i=0; i<ndrivers; i++) {
6362 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6363 ZERO_STRUCT(driver);
6364 result = get_a_printer_driver(&driver, 3, list[i],
6365 architecture, version);
6366 if (!W_ERROR_IS_OK(result)) {
6369 result = fill_printer_driver_info1(info, &info[*count+i].info1,
6370 &driver, servername,
6372 if (!W_ERROR_IS_OK(result)) {
6373 free_a_printer_driver(driver, 3);
6376 free_a_printer_driver(driver, 3);
6386 if (!W_ERROR_IS_OK(result)) {
6397 /****************************************************************************
6398 Enumerates all printer drivers at level 2.
6399 ****************************************************************************/
6401 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6402 const char *servername,
6403 const char *architecture,
6404 union spoolss_DriverInfo **info_p,
6410 fstring *list = NULL;
6411 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6412 union spoolss_DriverInfo *info = NULL;
6413 WERROR result = WERR_OK;
6417 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6419 ndrivers = get_ntdrivers(&list, architecture, version);
6420 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6421 ndrivers, architecture, version));
6423 if (ndrivers == -1) {
6424 result = WERR_NOMEM;
6428 if (ndrivers != 0) {
6429 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6430 union spoolss_DriverInfo,
6433 DEBUG(0,("enumprinterdrivers_level2: "
6434 "failed to enlarge driver info buffer!\n"));
6435 result = WERR_NOMEM;
6440 for (i=0; i<ndrivers; i++) {
6441 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6442 ZERO_STRUCT(driver);
6443 result = get_a_printer_driver(&driver, 3, list[i],
6444 architecture, version);
6445 if (!W_ERROR_IS_OK(result)) {
6448 result = fill_printer_driver_info2(info, &info[*count+i].info2,
6449 &driver, servername);
6450 if (!W_ERROR_IS_OK(result)) {
6451 free_a_printer_driver(driver, 3);
6454 free_a_printer_driver(driver, 3);
6464 if (!W_ERROR_IS_OK(result)) {
6475 /****************************************************************************
6476 Enumerates all printer drivers at level 3.
6477 ****************************************************************************/
6479 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6480 const char *servername,
6481 const char *architecture,
6482 union spoolss_DriverInfo **info_p,
6488 fstring *list = NULL;
6489 union spoolss_DriverInfo *info = NULL;
6490 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6491 WERROR result = WERR_OK;
6495 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6497 ndrivers = get_ntdrivers(&list, architecture, version);
6498 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6499 ndrivers, architecture, version));
6501 if (ndrivers == -1) {
6502 result = WERR_NOMEM;
6506 if (ndrivers != 0) {
6507 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6508 union spoolss_DriverInfo,
6511 DEBUG(0,("enumprinterdrivers_level3: "
6512 "failed to enlarge driver info buffer!\n"));
6513 result = WERR_NOMEM;
6518 for (i=0; i<ndrivers; i++) {
6519 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6520 ZERO_STRUCT(driver);
6521 result = get_a_printer_driver(&driver, 3, list[i],
6522 architecture, version);
6523 if (!W_ERROR_IS_OK(result)) {
6526 result = fill_printer_driver_info3(info, &info[*count+i].info3,
6527 &driver, servername);
6528 if (!W_ERROR_IS_OK(result)) {
6529 free_a_printer_driver(driver, 3);
6533 free_a_printer_driver(driver, 3);
6543 if (!W_ERROR_IS_OK(result)) {
6554 /****************************************************************
6555 _spoolss_EnumPrinterDrivers
6556 ****************************************************************/
6558 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6559 struct spoolss_EnumPrinterDrivers *r)
6561 const char *cservername;
6564 /* that's an [in out] buffer */
6566 if (!r->in.buffer && (r->in.offered != 0)) {
6567 return WERR_INVALID_PARAM;
6570 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6574 *r->out.info = NULL;
6576 cservername = canon_servername(r->in.server);
6578 if (!is_myname_or_ipaddr(cservername)) {
6579 return WERR_UNKNOWN_PRINTER_DRIVER;
6582 switch (r->in.level) {
6584 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6586 r->out.info, r->out.count);
6589 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6591 r->out.info, r->out.count);
6594 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6596 r->out.info, r->out.count);
6599 return WERR_UNKNOWN_LEVEL;
6602 if (!W_ERROR_IS_OK(result)) {
6606 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6607 spoolss_EnumPrinterDrivers, NULL,
6608 *r->out.info, r->in.level,
6610 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6611 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6613 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6616 /****************************************************************************
6617 ****************************************************************************/
6619 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6620 struct spoolss_FormInfo1 *r,
6621 const nt_forms_struct *form)
6623 r->form_name = talloc_strdup(mem_ctx, form->name);
6624 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6626 r->flags = form->flag;
6627 r->size.width = form->width;
6628 r->size.height = form->length;
6629 r->area.left = form->left;
6630 r->area.top = form->top;
6631 r->area.right = form->right;
6632 r->area.bottom = form->bottom;
6637 /****************************************************************
6638 spoolss_enumforms_level1
6639 ****************************************************************/
6641 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6642 const nt_forms_struct *builtin_forms,
6643 uint32_t num_builtin_forms,
6644 const nt_forms_struct *user_forms,
6645 uint32_t num_user_forms,
6646 union spoolss_FormInfo **info_p,
6649 union spoolss_FormInfo *info;
6650 WERROR result = WERR_OK;
6653 *count = num_builtin_forms + num_user_forms;
6655 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6656 W_ERROR_HAVE_NO_MEMORY(info);
6658 /* construct the list of form structures */
6659 for (i=0; i<num_builtin_forms; i++) {
6660 DEBUGADD(6,("Filling form number [%d]\n",i));
6661 result = fill_form_info_1(info, &info[i].info1,
6663 if (!W_ERROR_IS_OK(result)) {
6668 for (; i<num_user_forms; i++) {
6669 DEBUGADD(6,("Filling form number [%d]\n",i));
6670 result = fill_form_info_1(info, &info[i].info1,
6671 &user_forms[i-num_builtin_forms]);
6672 if (!W_ERROR_IS_OK(result)) {
6678 if (!W_ERROR_IS_OK(result)) {
6689 /****************************************************************
6691 ****************************************************************/
6693 WERROR _spoolss_EnumForms(pipes_struct *p,
6694 struct spoolss_EnumForms *r)
6697 nt_forms_struct *user_forms = NULL;
6698 nt_forms_struct *builtin_forms = NULL;
6699 uint32_t num_user_forms;
6700 uint32_t num_builtin_forms;
6704 *r->out.info = NULL;
6706 /* that's an [in out] buffer */
6708 if (!r->in.buffer && (r->in.offered != 0) ) {
6709 return WERR_INVALID_PARAM;
6712 DEBUG(4,("_spoolss_EnumForms\n"));
6713 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6714 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6716 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6717 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6718 num_user_forms = get_ntforms(&user_forms);
6719 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6721 if (num_user_forms + num_builtin_forms == 0) {
6722 SAFE_FREE(builtin_forms);
6723 SAFE_FREE(user_forms);
6724 return WERR_NO_MORE_ITEMS;
6727 switch (r->in.level) {
6729 result = spoolss_enumforms_level1(p->mem_ctx,
6738 result = WERR_UNKNOWN_LEVEL;
6742 SAFE_FREE(user_forms);
6743 SAFE_FREE(builtin_forms);
6745 if (!W_ERROR_IS_OK(result)) {
6749 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6750 spoolss_EnumForms, NULL,
6751 *r->out.info, r->in.level,
6753 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6754 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6756 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6759 /****************************************************************
6760 ****************************************************************/
6762 static WERROR find_form_byname(const char *name,
6763 nt_forms_struct *form)
6765 nt_forms_struct *list = NULL;
6766 int num_forms = 0, i = 0;
6768 if (get_a_builtin_ntform_by_string(name, form)) {
6772 num_forms = get_ntforms(&list);
6773 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6775 if (num_forms == 0) {
6779 /* Check if the requested name is in the list of form structures */
6780 for (i = 0; i < num_forms; i++) {
6782 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6784 if (strequal(name, list[i].name)) {
6785 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6797 /****************************************************************
6799 ****************************************************************/
6801 WERROR _spoolss_GetForm(pipes_struct *p,
6802 struct spoolss_GetForm *r)
6805 nt_forms_struct form;
6807 /* that's an [in out] buffer */
6809 if (!r->in.buffer && (r->in.offered != 0)) {
6810 return WERR_INVALID_PARAM;
6813 DEBUG(4,("_spoolss_GetForm\n"));
6814 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6815 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6817 result = find_form_byname(r->in.form_name, &form);
6818 if (!W_ERROR_IS_OK(result)) {
6819 TALLOC_FREE(r->out.info);
6823 switch (r->in.level) {
6825 result = fill_form_info_1(p->mem_ctx,
6826 &r->out.info->info1,
6831 result = WERR_UNKNOWN_LEVEL;
6835 if (!W_ERROR_IS_OK(result)) {
6836 TALLOC_FREE(r->out.info);
6840 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6841 r->out.info, r->in.level);
6842 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6844 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6847 /****************************************************************************
6848 ****************************************************************************/
6850 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6851 struct spoolss_PortInfo1 *r,
6854 r->port_name = talloc_strdup(mem_ctx, name);
6855 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6860 /****************************************************************************
6861 TODO: This probably needs distinguish between TCP/IP and Local ports
6863 ****************************************************************************/
6865 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6866 struct spoolss_PortInfo2 *r,
6869 r->port_name = talloc_strdup(mem_ctx, name);
6870 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6872 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6873 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6875 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6876 W_ERROR_HAVE_NO_MEMORY(r->description);
6878 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6885 /****************************************************************************
6886 wrapper around the enumer ports command
6887 ****************************************************************************/
6889 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
6891 char *cmd = lp_enumports_cmd();
6892 char **qlines = NULL;
6893 char *command = NULL;
6901 /* if no hook then just fill in the default port */
6904 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6907 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6908 TALLOC_FREE(qlines);
6915 /* we have a valid enumport command */
6917 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6922 DEBUG(10,("Running [%s]\n", command));
6923 ret = smbrun(command, &fd);
6924 DEBUG(10,("Returned [%d]\n", ret));
6925 TALLOC_FREE(command);
6930 return WERR_ACCESS_DENIED;
6934 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6935 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6945 /****************************************************************************
6947 ****************************************************************************/
6949 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6950 union spoolss_PortInfo **info_p,
6953 union spoolss_PortInfo *info = NULL;
6955 WERROR result = WERR_OK;
6956 char **qlines = NULL;
6959 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6960 if (!W_ERROR_IS_OK(result)) {
6965 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6967 DEBUG(10,("Returning WERR_NOMEM\n"));
6968 result = WERR_NOMEM;
6972 for (i=0; i<numlines; i++) {
6973 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6974 result = fill_port_1(info, &info[i].info1, qlines[i]);
6975 if (!W_ERROR_IS_OK(result)) {
6980 TALLOC_FREE(qlines);
6983 if (!W_ERROR_IS_OK(result)) {
6985 TALLOC_FREE(qlines);
6997 /****************************************************************************
6999 ****************************************************************************/
7001 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7002 union spoolss_PortInfo **info_p,
7005 union spoolss_PortInfo *info = NULL;
7007 WERROR result = WERR_OK;
7008 char **qlines = NULL;
7011 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7012 if (!W_ERROR_IS_OK(result)) {
7017 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7019 DEBUG(10,("Returning WERR_NOMEM\n"));
7020 result = WERR_NOMEM;
7024 for (i=0; i<numlines; i++) {
7025 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7026 result = fill_port_2(info, &info[i].info2, qlines[i]);
7027 if (!W_ERROR_IS_OK(result)) {
7032 TALLOC_FREE(qlines);
7035 if (!W_ERROR_IS_OK(result)) {
7037 TALLOC_FREE(qlines);
7049 /****************************************************************
7051 ****************************************************************/
7053 WERROR _spoolss_EnumPorts(pipes_struct *p,
7054 struct spoolss_EnumPorts *r)
7058 /* that's an [in out] buffer */
7060 if (!r->in.buffer && (r->in.offered != 0)) {
7061 return WERR_INVALID_PARAM;
7064 DEBUG(4,("_spoolss_EnumPorts\n"));
7068 *r->out.info = NULL;
7070 switch (r->in.level) {
7072 result = enumports_level_1(p->mem_ctx, r->out.info,
7076 result = enumports_level_2(p->mem_ctx, r->out.info,
7080 return WERR_UNKNOWN_LEVEL;
7083 if (!W_ERROR_IS_OK(result)) {
7087 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7088 spoolss_EnumPorts, NULL,
7089 *r->out.info, r->in.level,
7091 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7092 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7094 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7097 /****************************************************************************
7098 ****************************************************************************/
7100 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7102 struct spoolss_SetPrinterInfoCtr *info_ctr,
7103 struct spoolss_DeviceMode *devmode,
7104 struct security_descriptor *sec_desc,
7105 struct spoolss_UserLevelCtr *user_ctr,
7108 NT_PRINTER_INFO_LEVEL *printer = NULL;
7111 WERROR err = WERR_OK;
7113 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7114 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7118 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7119 if (!convert_printer_info(info_ctr, printer)) {
7120 free_a_printer(&printer, 2);
7124 /* check to see if the printer already exists */
7126 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7127 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7128 printer->info_2->sharename));
7129 free_a_printer(&printer, 2);
7130 return WERR_PRINTER_ALREADY_EXISTS;
7133 /* FIXME!!! smbd should check to see if the driver is installed before
7134 trying to add a printer like this --jerry */
7136 if (*lp_addprinter_cmd() ) {
7137 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7139 free_a_printer(&printer,2);
7140 return WERR_ACCESS_DENIED;
7143 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7144 "smb.conf parameter \"addprinter command\" is defined. This"
7145 "parameter must exist for this call to succeed\n",
7146 printer->info_2->sharename ));
7149 /* use our primary netbios name since get_a_printer() will convert
7150 it to what the client expects on a case by case basis */
7152 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7153 printer->info_2->sharename);
7156 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7157 free_a_printer(&printer,2);
7158 return WERR_ACCESS_DENIED;
7161 /* you must be a printer admin to add a new printer */
7162 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7163 free_a_printer(&printer,2);
7164 return WERR_ACCESS_DENIED;
7168 * Do sanity check on the requested changes for Samba.
7171 if (!check_printer_ok(printer->info_2, snum)) {
7172 free_a_printer(&printer,2);
7173 return WERR_INVALID_PARAM;
7177 * When a printer is created, the drivername bound to the printer is used
7178 * to lookup previously saved driver initialization info, which is then
7179 * bound to the new printer, simulating what happens in the Windows arch.
7184 set_driver_init(printer, 2);
7188 /* A valid devmode was included, convert and link it
7190 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7192 if (!convert_devicemode(printer->info_2->printername, devmode,
7193 &printer->info_2->devmode)) {
7198 /* write the ASCII on disk */
7199 err = mod_a_printer(printer, 2);
7200 if (!W_ERROR_IS_OK(err)) {
7201 free_a_printer(&printer,2);
7205 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7206 /* Handle open failed - remove addition. */
7207 del_a_printer(printer->info_2->sharename);
7208 free_a_printer(&printer,2);
7209 ZERO_STRUCTP(handle);
7210 return WERR_ACCESS_DENIED;
7213 update_c_setprinter(False);
7214 free_a_printer(&printer,2);
7219 /****************************************************************
7220 _spoolss_AddPrinterEx
7221 ****************************************************************/
7223 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7224 struct spoolss_AddPrinterEx *r)
7226 switch (r->in.info_ctr->level) {
7228 /* we don't handle yet */
7229 /* but I know what to do ... */
7230 return WERR_UNKNOWN_LEVEL;
7232 return spoolss_addprinterex_level_2(p, r->in.server,
7234 r->in.devmode_ctr->devmode,
7235 r->in.secdesc_ctr->sd,
7236 r->in.userlevel_ctr,
7239 return WERR_UNKNOWN_LEVEL;
7243 /****************************************************************
7244 _spoolss_AddPrinterDriver
7245 ****************************************************************/
7247 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7248 struct spoolss_AddPrinterDriver *r)
7250 uint32_t level = r->in.info_ctr->level;
7251 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7252 WERROR err = WERR_OK;
7253 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7254 fstring driver_name;
7258 switch (p->hdr_req.opnum) {
7259 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7260 fn = "_spoolss_AddPrinterDriver";
7262 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7263 fn = "_spoolss_AddPrinterDriverEx";
7266 return WERR_INVALID_PARAM;
7271 if (level != 3 && level != 6) {
7272 /* Clever hack from Martin Zielinski <mz@seh.de>
7273 * to allow downgrade from level 8 (Vista).
7275 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7276 return WERR_UNKNOWN_LEVEL;
7279 ZERO_STRUCT(driver);
7281 if (!convert_printer_driver_info(info, &driver, level)) {
7286 DEBUG(5,("Cleaning driver's information\n"));
7287 err = clean_up_driver_struct(p, driver, level);
7288 if (!W_ERROR_IS_OK(err))
7291 DEBUG(5,("Moving driver to final destination\n"));
7292 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7297 if (add_a_printer_driver(driver, level)!=0) {
7298 err = WERR_ACCESS_DENIED;
7304 fstrcpy(driver_name,
7305 driver.info_3->name ? driver.info_3->name : "");
7308 fstrcpy(driver_name,
7309 driver.info_6->name ? driver.info_6->name : "");
7314 * I think this is where he DrvUpgradePrinter() hook would be
7315 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7316 * server. Right now, we just need to send ourselves a message
7317 * to update each printer bound to this driver. --jerry
7320 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7321 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7326 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7327 * decide if the driver init data should be deleted. The rules are:
7328 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7329 * 2) delete init data only if there is no 2k/Xp driver
7330 * 3) always delete init data
7331 * The generalized rule is always use init data from the highest order driver.
7332 * It is necessary to follow the driver install by an initialization step to
7333 * finish off this process.
7336 version = driver.info_3->cversion;
7337 else if (level == 6)
7338 version = driver.info_6->version;
7343 * 9x printer driver - never delete init data
7346 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7351 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7352 * there is no 2k/Xp driver init data for this driver name.
7356 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7358 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7360 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7362 if (!del_driver_init(driver_name))
7363 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7367 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7369 free_a_printer_driver(driver1,3);
7370 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7377 * 2k or Xp printer driver - always delete init data
7380 if (!del_driver_init(driver_name))
7381 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7386 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7392 free_a_printer_driver(driver, level);
7396 /****************************************************************
7397 _spoolss_AddPrinterDriverEx
7398 ****************************************************************/
7400 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7401 struct spoolss_AddPrinterDriverEx *r)
7403 struct spoolss_AddPrinterDriver a;
7406 * we only support the semantics of AddPrinterDriver()
7407 * i.e. only copy files that are newer than existing ones
7410 if (r->in.flags != APD_COPY_NEW_FILES) {
7411 return WERR_ACCESS_DENIED;
7414 a.in.servername = r->in.servername;
7415 a.in.info_ctr = r->in.info_ctr;
7417 return _spoolss_AddPrinterDriver(p, &a);
7420 /****************************************************************************
7421 ****************************************************************************/
7423 struct _spoolss_paths {
7429 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7431 static const struct _spoolss_paths spoolss_paths[]= {
7432 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7433 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7436 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7437 const char *servername,
7438 const char *environment,
7442 const char *pservername = NULL;
7443 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7444 const char *short_archi;
7448 /* environment may be empty */
7449 if (environment && strlen(environment)) {
7450 long_archi = environment;
7453 /* servername may be empty */
7454 if (servername && strlen(servername)) {
7455 pservername = canon_servername(servername);
7457 if (!is_myname_or_ipaddr(pservername)) {
7458 return WERR_INVALID_PARAM;
7462 if (!(short_archi = get_short_archi(long_archi))) {
7463 return WERR_INVALID_ENVIRONMENT;
7466 switch (component) {
7467 case SPOOLSS_PRTPROCS_PATH:
7468 case SPOOLSS_DRIVER_PATH:
7470 *path = talloc_asprintf(mem_ctx,
7473 spoolss_paths[component].share,
7476 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7477 SPOOLSS_DEFAULT_SERVER_PATH,
7478 spoolss_paths[component].dir,
7483 return WERR_INVALID_PARAM;
7493 /****************************************************************************
7494 ****************************************************************************/
7496 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7497 const char *servername,
7498 const char *environment,
7499 struct spoolss_DriverDirectoryInfo1 *r)
7504 werr = compose_spoolss_server_path(mem_ctx,
7507 SPOOLSS_DRIVER_PATH,
7509 if (!W_ERROR_IS_OK(werr)) {
7513 DEBUG(4,("printer driver directory: [%s]\n", path));
7515 r->directory_name = path;
7520 /****************************************************************
7521 _spoolss_GetPrinterDriverDirectory
7522 ****************************************************************/
7524 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7525 struct spoolss_GetPrinterDriverDirectory *r)
7529 /* that's an [in out] buffer */
7531 if (!r->in.buffer && (r->in.offered != 0)) {
7532 return WERR_INVALID_PARAM;
7535 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7540 /* r->in.level is ignored */
7542 werror = getprinterdriverdir_level_1(p->mem_ctx,
7545 &r->out.info->info1);
7546 if (!W_ERROR_IS_OK(werror)) {
7547 TALLOC_FREE(r->out.info);
7551 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7552 r->out.info, r->in.level);
7553 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7555 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7558 /****************************************************************
7559 _spoolss_EnumPrinterData
7560 ****************************************************************/
7562 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7563 struct spoolss_EnumPrinterData *r)
7565 NT_PRINTER_INFO_LEVEL *printer = NULL;
7566 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7569 REGISTRY_VALUE *val = NULL;
7570 NT_PRINTER_DATA *p_data;
7571 int i, key_index, num_values;
7574 *r->out.value_needed = 0;
7575 *r->out.type = REG_NONE;
7576 *r->out.data_needed = 0;
7578 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7581 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7582 OUR_HANDLE(r->in.handle)));
7586 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7590 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7591 if (!W_ERROR_IS_OK(result)) {
7595 p_data = printer->info_2->data;
7596 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7601 * The NT machine wants to know the biggest size of value and data
7603 * cf: MSDN EnumPrinterData remark section
7606 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7608 uint32_t biggest_valuesize = 0;
7609 uint32_t biggest_datasize = 0;
7611 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7613 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7615 for ( i=0; i<num_values; i++ )
7617 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7619 name_length = strlen(val->valuename);
7620 if ( strlen(val->valuename) > biggest_valuesize )
7621 biggest_valuesize = name_length;
7623 if ( val->size > biggest_datasize )
7624 biggest_datasize = val->size;
7626 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7630 /* the value is an UNICODE string but real_value_size is the length
7631 in bytes including the trailing 0 */
7633 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7634 *r->out.data_needed = biggest_datasize;
7636 DEBUG(6,("final values: [%d], [%d]\n",
7637 *r->out.value_needed, *r->out.data_needed));
7643 * the value len is wrong in NT sp3
7644 * that's the number of bytes not the number of unicode chars
7647 if (key_index != -1) {
7648 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7654 /* out_value should default to "" or else NT4 has
7655 problems unmarshalling the response */
7657 if (r->in.value_offered) {
7658 *r->out.value_needed = 1;
7659 r->out.value_name = talloc_strdup(r, "");
7660 if (!r->out.value_name) {
7661 result = WERR_NOMEM;
7665 r->out.value_name = NULL;
7666 *r->out.value_needed = 0;
7669 /* the data is counted in bytes */
7671 *r->out.data_needed = r->in.data_offered;
7673 result = WERR_NO_MORE_ITEMS;
7677 * - counted in bytes in the request
7678 * - counted in UNICODE chars in the max reply
7679 * - counted in bytes in the real size
7681 * take a pause *before* coding not *during* coding
7685 if (r->in.value_offered) {
7686 r->out.value_name = talloc_strdup(r, regval_name(val));
7687 if (!r->out.value_name) {
7688 result = WERR_NOMEM;
7691 *r->out.value_needed = strlen_m(regval_name(val));
7693 r->out.value_name = NULL;
7694 *r->out.value_needed = 0;
7699 *r->out.type = regval_type(val);
7701 /* data - counted in bytes */
7703 if (r->out.data && regval_size(val)) {
7704 memcpy(r->out.data, regval_data_p(val), regval_size(val));
7707 *r->out.data_needed = regval_size(val);
7711 free_a_printer(&printer, 2);
7715 /****************************************************************
7716 _spoolss_SetPrinterData
7717 ****************************************************************/
7719 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7720 struct spoolss_SetPrinterData *r)
7722 NT_PRINTER_INFO_LEVEL *printer = NULL;
7724 WERROR result = WERR_OK;
7725 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7728 DEBUG(5,("_spoolss_SetPrinterData\n"));
7731 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7732 OUR_HANDLE(r->in.handle)));
7736 if (Printer->printer_type == SPLHND_SERVER) {
7737 DEBUG(10,("_spoolss_SetPrinterData: "
7738 "Not implemented for server handles yet\n"));
7739 return WERR_INVALID_PARAM;
7742 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7747 * Access check : NT returns "access denied" if you make a
7748 * SetPrinterData call without the necessary privildge.
7749 * we were originally returning OK if nothing changed
7750 * which made Win2k issue **a lot** of SetPrinterData
7751 * when connecting to a printer --jerry
7754 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7755 DEBUG(3,("_spoolss_SetPrinterData: "
7756 "change denied by handle access permissions\n"));
7757 result = WERR_ACCESS_DENIED;
7761 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7762 if (!W_ERROR_IS_OK(result)) {
7766 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
7767 r->in.type, &r->in.data);
7768 if (!W_ERROR_IS_OK(result)) {
7773 * When client side code sets a magic printer data key, detect it and save
7774 * the current printer data and the magic key's data (its the DEVMODE) for
7775 * future printer/driver initializations.
7777 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
7778 /* Set devmode and printer initialization info */
7779 result = save_driver_init(printer, 2, blob.data, blob.length);
7781 srv_spoolss_reset_printerdata(printer->info_2->drivername);
7786 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
7787 r->in.value_name, r->in.type,
7788 blob.data, blob.length);
7789 if (W_ERROR_IS_OK(result)) {
7790 result = mod_a_printer(printer, 2);
7794 free_a_printer(&printer, 2);
7799 /****************************************************************
7800 _spoolss_ResetPrinter
7801 ****************************************************************/
7803 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7804 struct spoolss_ResetPrinter *r)
7806 POLICY_HND *handle = r->in.handle;
7807 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7810 DEBUG(5,("_spoolss_ResetPrinter\n"));
7813 * All we do is to check to see if the handle and queue is valid.
7814 * This call really doesn't mean anything to us because we only
7815 * support RAW printing. --jerry
7819 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7820 OUR_HANDLE(handle)));
7824 if (!get_printer_snum(p,handle, &snum, NULL))
7828 /* blindly return success */
7832 /****************************************************************
7833 _spoolss_DeletePrinterData
7834 ****************************************************************/
7836 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7837 struct spoolss_DeletePrinterData *r)
7839 POLICY_HND *handle = r->in.handle;
7840 NT_PRINTER_INFO_LEVEL *printer = NULL;
7842 WERROR status = WERR_OK;
7843 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7845 DEBUG(5,("_spoolss_DeletePrinterData\n"));
7848 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
7849 OUR_HANDLE(handle)));
7853 if (!get_printer_snum(p, handle, &snum, NULL))
7856 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7857 DEBUG(3, ("_spoolss_DeletePrinterData: "
7858 "printer properties change denied by handle\n"));
7859 return WERR_ACCESS_DENIED;
7862 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7863 if (!W_ERROR_IS_OK(status))
7866 if (!r->in.value_name) {
7867 free_a_printer(&printer, 2);
7871 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
7874 if ( W_ERROR_IS_OK(status) )
7875 mod_a_printer( printer, 2 );
7877 free_a_printer(&printer, 2);
7882 /****************************************************************
7884 ****************************************************************/
7886 WERROR _spoolss_AddForm(pipes_struct *p,
7887 struct spoolss_AddForm *r)
7889 POLICY_HND *handle = r->in.handle;
7890 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7891 nt_forms_struct tmpForm;
7893 WERROR status = WERR_OK;
7894 NT_PRINTER_INFO_LEVEL *printer = NULL;
7897 nt_forms_struct *list=NULL;
7898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7900 DEBUG(5,("_spoolss_AddForm\n"));
7903 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7904 OUR_HANDLE(handle)));
7909 /* forms can be added on printer of on the print server handle */
7911 if ( Printer->printer_type == SPLHND_PRINTER )
7913 if (!get_printer_snum(p,handle, &snum, NULL))
7916 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7917 if (!W_ERROR_IS_OK(status))
7921 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7922 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7923 status = WERR_ACCESS_DENIED;
7927 /* can't add if builtin */
7929 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7930 status = WERR_FILE_EXISTS;
7934 count = get_ntforms(&list);
7936 if(!add_a_form(&list, form, &count)) {
7937 status = WERR_NOMEM;
7941 write_ntforms(&list, count);
7944 * ChangeID must always be set if this is a printer
7947 if ( Printer->printer_type == SPLHND_PRINTER )
7948 status = mod_a_printer(printer, 2);
7952 free_a_printer(&printer, 2);
7958 /****************************************************************
7960 ****************************************************************/
7962 WERROR _spoolss_DeleteForm(pipes_struct *p,
7963 struct spoolss_DeleteForm *r)
7965 POLICY_HND *handle = r->in.handle;
7966 const char *form_name = r->in.form_name;
7967 nt_forms_struct tmpForm;
7969 nt_forms_struct *list=NULL;
7970 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7972 WERROR status = WERR_OK;
7973 NT_PRINTER_INFO_LEVEL *printer = NULL;
7975 DEBUG(5,("_spoolss_DeleteForm\n"));
7978 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7979 OUR_HANDLE(handle)));
7983 /* forms can be deleted on printer of on the print server handle */
7985 if ( Printer->printer_type == SPLHND_PRINTER )
7987 if (!get_printer_snum(p,handle, &snum, NULL))
7990 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7991 if (!W_ERROR_IS_OK(status))
7995 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
7996 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
7997 status = WERR_ACCESS_DENIED;
8001 /* can't delete if builtin */
8003 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8004 status = WERR_INVALID_PARAM;
8008 count = get_ntforms(&list);
8010 if ( !delete_a_form(&list, form_name, &count, &status ))
8014 * ChangeID must always be set if this is a printer
8017 if ( Printer->printer_type == SPLHND_PRINTER )
8018 status = mod_a_printer(printer, 2);
8022 free_a_printer(&printer, 2);
8028 /****************************************************************
8030 ****************************************************************/
8032 WERROR _spoolss_SetForm(pipes_struct *p,
8033 struct spoolss_SetForm *r)
8035 POLICY_HND *handle = r->in.handle;
8036 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8037 nt_forms_struct tmpForm;
8039 WERROR status = WERR_OK;
8040 NT_PRINTER_INFO_LEVEL *printer = NULL;
8043 nt_forms_struct *list=NULL;
8044 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8046 DEBUG(5,("_spoolss_SetForm\n"));
8049 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8050 OUR_HANDLE(handle)));
8054 /* forms can be modified on printer of on the print server handle */
8056 if ( Printer->printer_type == SPLHND_PRINTER )
8058 if (!get_printer_snum(p,handle, &snum, NULL))
8061 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8062 if (!W_ERROR_IS_OK(status))
8066 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8067 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8068 status = WERR_ACCESS_DENIED;
8072 /* can't set if builtin */
8073 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8074 status = WERR_INVALID_PARAM;
8078 count = get_ntforms(&list);
8079 update_a_form(&list, form, count);
8080 write_ntforms(&list, count);
8083 * ChangeID must always be set if this is a printer
8086 if ( Printer->printer_type == SPLHND_PRINTER )
8087 status = mod_a_printer(printer, 2);
8092 free_a_printer(&printer, 2);
8098 /****************************************************************************
8099 fill_print_processor1
8100 ****************************************************************************/
8102 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8103 struct spoolss_PrintProcessorInfo1 *r,
8104 const char *print_processor_name)
8106 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8107 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8112 /****************************************************************************
8113 enumprintprocessors level 1.
8114 ****************************************************************************/
8116 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8117 union spoolss_PrintProcessorInfo **info_p,
8120 union spoolss_PrintProcessorInfo *info;
8123 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8124 W_ERROR_HAVE_NO_MEMORY(info);
8128 result = fill_print_processor1(info, &info[0].info1, "winprint");
8129 if (!W_ERROR_IS_OK(result)) {
8134 if (!W_ERROR_IS_OK(result)) {
8145 /****************************************************************
8146 _spoolss_EnumPrintProcessors
8147 ****************************************************************/
8149 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8150 struct spoolss_EnumPrintProcessors *r)
8154 /* that's an [in out] buffer */
8156 if (!r->in.buffer && (r->in.offered != 0)) {
8157 return WERR_INVALID_PARAM;
8160 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8163 * Enumerate the print processors ...
8165 * Just reply with "winprint", to keep NT happy
8166 * and I can use my nice printer checker.
8171 *r->out.info = NULL;
8173 switch (r->in.level) {
8175 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8179 return WERR_UNKNOWN_LEVEL;
8182 if (!W_ERROR_IS_OK(result)) {
8186 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8187 spoolss_EnumPrintProcessors, NULL,
8188 *r->out.info, r->in.level,
8190 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8191 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8193 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8196 /****************************************************************************
8197 fill_printprocdatatype1
8198 ****************************************************************************/
8200 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8201 struct spoolss_PrintProcDataTypesInfo1 *r,
8202 const char *name_array)
8204 r->name_array = talloc_strdup(mem_ctx, name_array);
8205 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8210 /****************************************************************************
8211 enumprintprocdatatypes level 1.
8212 ****************************************************************************/
8214 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8215 union spoolss_PrintProcDataTypesInfo **info_p,
8219 union spoolss_PrintProcDataTypesInfo *info;
8221 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8222 W_ERROR_HAVE_NO_MEMORY(info);
8226 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8227 if (!W_ERROR_IS_OK(result)) {
8232 if (!W_ERROR_IS_OK(result)) {
8243 /****************************************************************
8244 _spoolss_EnumPrintProcDataTypes
8245 ****************************************************************/
8247 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8248 struct spoolss_EnumPrintProcDataTypes *r)
8252 /* that's an [in out] buffer */
8254 if (!r->in.buffer && (r->in.offered != 0)) {
8255 return WERR_INVALID_PARAM;
8258 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8262 *r->out.info = NULL;
8264 switch (r->in.level) {
8266 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8270 return WERR_UNKNOWN_LEVEL;
8273 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8274 spoolss_EnumPrintProcDataTypes, NULL,
8275 *r->out.info, r->in.level,
8277 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8278 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8280 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8283 /****************************************************************************
8285 ****************************************************************************/
8287 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8288 struct spoolss_MonitorInfo1 *r,
8289 const char *monitor_name)
8291 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8292 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8297 /****************************************************************************
8299 ****************************************************************************/
8301 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8302 struct spoolss_MonitorInfo2 *r,
8303 const char *monitor_name,
8304 const char *environment,
8305 const char *dll_name)
8307 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8308 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8309 r->environment = talloc_strdup(mem_ctx, environment);
8310 W_ERROR_HAVE_NO_MEMORY(r->environment);
8311 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8312 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8317 /****************************************************************************
8318 enumprintmonitors level 1.
8319 ****************************************************************************/
8321 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8322 union spoolss_MonitorInfo **info_p,
8325 union spoolss_MonitorInfo *info;
8326 WERROR result = WERR_OK;
8328 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8329 W_ERROR_HAVE_NO_MEMORY(info);
8333 result = fill_monitor_1(info, &info[0].info1,
8335 if (!W_ERROR_IS_OK(result)) {
8339 result = fill_monitor_1(info, &info[1].info1,
8341 if (!W_ERROR_IS_OK(result)) {
8346 if (!W_ERROR_IS_OK(result)) {
8357 /****************************************************************************
8358 enumprintmonitors level 2.
8359 ****************************************************************************/
8361 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8362 union spoolss_MonitorInfo **info_p,
8365 union spoolss_MonitorInfo *info;
8366 WERROR result = WERR_OK;
8368 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8369 W_ERROR_HAVE_NO_MEMORY(info);
8373 result = fill_monitor_2(info, &info[0].info2,
8375 "Windows NT X86", /* FIXME */
8377 if (!W_ERROR_IS_OK(result)) {
8381 result = fill_monitor_2(info, &info[1].info2,
8383 "Windows NT X86", /* FIXME */
8385 if (!W_ERROR_IS_OK(result)) {
8390 if (!W_ERROR_IS_OK(result)) {
8401 /****************************************************************
8402 _spoolss_EnumMonitors
8403 ****************************************************************/
8405 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8406 struct spoolss_EnumMonitors *r)
8410 /* that's an [in out] buffer */
8412 if (!r->in.buffer && (r->in.offered != 0)) {
8413 return WERR_INVALID_PARAM;
8416 DEBUG(5,("_spoolss_EnumMonitors\n"));
8419 * Enumerate the print monitors ...
8421 * Just reply with "Local Port", to keep NT happy
8422 * and I can use my nice printer checker.
8427 *r->out.info = NULL;
8429 switch (r->in.level) {
8431 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8435 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8439 return WERR_UNKNOWN_LEVEL;
8442 if (!W_ERROR_IS_OK(result)) {
8446 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8447 spoolss_EnumMonitors, NULL,
8448 *r->out.info, r->in.level,
8450 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8451 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8453 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8456 /****************************************************************************
8457 ****************************************************************************/
8459 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8460 const print_queue_struct *queue,
8461 int count, int snum,
8462 const NT_PRINTER_INFO_LEVEL *ntprinter,
8464 struct spoolss_JobInfo1 *r)
8469 for (i=0; i<count && found == false; i++) {
8470 if (queue[i].job == (int)jobid) {
8475 if (found == false) {
8476 /* NT treats not found as bad param... yet another bad choice */
8477 return WERR_INVALID_PARAM;
8480 return fill_job_info1(mem_ctx,
8488 /****************************************************************************
8489 ****************************************************************************/
8491 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8492 const print_queue_struct *queue,
8493 int count, int snum,
8494 const NT_PRINTER_INFO_LEVEL *ntprinter,
8496 struct spoolss_JobInfo2 *r)
8500 struct spoolss_DeviceMode *devmode;
8501 NT_DEVICEMODE *nt_devmode;
8504 for (i=0; i<count && found == false; i++) {
8505 if (queue[i].job == (int)jobid) {
8510 if (found == false) {
8511 /* NT treats not found as bad param... yet another bad
8513 return WERR_INVALID_PARAM;
8517 * if the print job does not have a DEVMODE associated with it,
8518 * just use the one for the printer. A NULL devicemode is not
8519 * a failure condition
8522 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8524 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8525 W_ERROR_HAVE_NO_MEMORY(devmode);
8526 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8527 if (!W_ERROR_IS_OK(result)) {
8531 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8532 W_ERROR_HAVE_NO_MEMORY(devmode);
8535 return fill_job_info2(mem_ctx,
8544 /****************************************************************
8546 ****************************************************************/
8548 WERROR _spoolss_GetJob(pipes_struct *p,
8549 struct spoolss_GetJob *r)
8551 WERROR result = WERR_OK;
8552 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8555 print_queue_struct *queue = NULL;
8556 print_status_struct prt_status;
8558 /* that's an [in out] buffer */
8560 if (!r->in.buffer && (r->in.offered != 0)) {
8561 return WERR_INVALID_PARAM;
8564 DEBUG(5,("_spoolss_GetJob\n"));
8568 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8572 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8573 if (!W_ERROR_IS_OK(result)) {
8577 count = print_queue_status(snum, &queue, &prt_status);
8579 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8580 count, prt_status.status, prt_status.message));
8582 switch (r->in.level) {
8584 result = getjob_level_1(p->mem_ctx,
8585 queue, count, snum, ntprinter,
8586 r->in.job_id, &r->out.info->info1);
8589 result = getjob_level_2(p->mem_ctx,
8590 queue, count, snum, ntprinter,
8591 r->in.job_id, &r->out.info->info2);
8594 result = WERR_UNKNOWN_LEVEL;
8599 free_a_printer(&ntprinter, 2);
8601 if (!W_ERROR_IS_OK(result)) {
8602 TALLOC_FREE(r->out.info);
8606 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8607 r->out.info, r->in.level);
8608 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8610 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8613 /****************************************************************
8614 _spoolss_GetPrinterDataEx
8616 From MSDN documentation of GetPrinterDataEx: pass request
8617 to GetPrinterData if key is "PrinterDriverData".
8618 ****************************************************************/
8620 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8621 struct spoolss_GetPrinterDataEx *r)
8624 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8625 REGISTRY_VALUE *val = NULL;
8626 NT_PRINTER_INFO_LEVEL *printer = NULL;
8628 WERROR result = WERR_OK;
8630 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8632 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8633 r->in.key_name, r->in.value_name));
8635 /* in case of problem, return some default values */
8638 *r->out.type = REG_NONE;
8641 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8642 OUR_HANDLE(r->in.handle)));
8643 result = WERR_BADFID;
8647 /* Is the handle to a printer or to the server? */
8649 if (Printer->printer_type == SPLHND_SERVER) {
8650 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8651 "Not implemented for server handles yet\n"));
8652 result = WERR_INVALID_PARAM;
8656 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8660 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8661 if (!W_ERROR_IS_OK(result)) {
8665 /* check to see if the keyname is valid */
8666 if (!strlen(r->in.key_name)) {
8667 result = WERR_INVALID_PARAM;
8671 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8672 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8673 "Invalid keyname [%s]\n", r->in.key_name ));
8674 result = WERR_BADFILE;
8678 /* When given a new keyname, we should just create it */
8680 val = get_printer_data(printer->info_2,
8681 r->in.key_name, r->in.value_name);
8683 result = WERR_BADFILE;
8687 *r->out.needed = regval_size(val);
8689 if (*r->out.needed > r->in.offered) {
8690 result = WERR_MORE_DATA;
8694 *r->out.type = regval_type(val);
8696 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
8700 free_a_printer(&printer, 2);
8706 /****************************************************************
8707 _spoolss_SetPrinterDataEx
8708 ****************************************************************/
8710 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8711 struct spoolss_SetPrinterDataEx *r)
8713 NT_PRINTER_INFO_LEVEL *printer = NULL;
8715 WERROR result = WERR_OK;
8716 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8719 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8721 /* From MSDN documentation of SetPrinterDataEx: pass request to
8722 SetPrinterData if key is "PrinterDriverData" */
8725 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8726 OUR_HANDLE(r->in.handle)));
8730 if (Printer->printer_type == SPLHND_SERVER) {
8731 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8732 "Not implemented for server handles yet\n"));
8733 return WERR_INVALID_PARAM;
8736 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8741 * Access check : NT returns "access denied" if you make a
8742 * SetPrinterData call without the necessary privildge.
8743 * we were originally returning OK if nothing changed
8744 * which made Win2k issue **a lot** of SetPrinterData
8745 * when connecting to a printer --jerry
8748 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8749 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8750 "change denied by handle access permissions\n"));
8751 return WERR_ACCESS_DENIED;
8754 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8755 if (!W_ERROR_IS_OK(result)) {
8759 /* check for OID in valuename */
8761 oid_string = strchr(r->in.value_name, ',');
8767 /* save the registry data */
8769 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8770 r->in.type, r->in.buffer, r->in.offered);
8772 if (W_ERROR_IS_OK(result)) {
8773 /* save the OID if one was specified */
8775 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8776 r->in.key_name, SPOOL_OID_KEY);
8778 result = WERR_NOMEM;
8783 * I'm not checking the status here on purpose. Don't know
8784 * if this is right, but I'm returning the status from the
8785 * previous set_printer_dataex() call. I have no idea if
8786 * this is right. --jerry
8789 set_printer_dataex(printer, str, r->in.value_name,
8790 REG_SZ, (uint8_t *)oid_string,
8791 strlen(oid_string)+1);
8794 result = mod_a_printer(printer, 2);
8798 free_a_printer(&printer, 2);
8803 /****************************************************************
8804 _spoolss_DeletePrinterDataEx
8805 ****************************************************************/
8807 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8808 struct spoolss_DeletePrinterDataEx *r)
8810 POLICY_HND *handle = r->in.handle;
8811 NT_PRINTER_INFO_LEVEL *printer = NULL;
8813 WERROR status = WERR_OK;
8814 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8816 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8819 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8820 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8824 if (!get_printer_snum(p, handle, &snum, NULL))
8827 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8828 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8829 "printer properties change denied by handle\n"));
8830 return WERR_ACCESS_DENIED;
8833 if (!r->in.value_name || !r->in.key_name) {
8837 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8838 if (!W_ERROR_IS_OK(status))
8841 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8843 if ( W_ERROR_IS_OK(status) )
8844 mod_a_printer( printer, 2 );
8846 free_a_printer(&printer, 2);
8851 /****************************************************************
8852 _spoolss_EnumPrinterKey
8853 ****************************************************************/
8855 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8856 struct spoolss_EnumPrinterKey *r)
8858 fstring *keynames = NULL;
8860 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8861 NT_PRINTER_DATA *data;
8862 NT_PRINTER_INFO_LEVEL *printer = NULL;
8864 WERROR result = WERR_BADFILE;
8866 const char **array = NULL;
8869 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8872 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8873 OUR_HANDLE(r->in.handle)));
8877 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8881 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8882 if (!W_ERROR_IS_OK(result)) {
8886 /* get the list of subkey names */
8888 data = printer->info_2->data;
8890 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8891 if (num_keys == -1) {
8892 result = WERR_BADFILE;
8898 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
8900 result = WERR_NOMEM;
8904 for (i=0; i < num_keys; i++) {
8905 array[i] = talloc_strdup(array, keynames[i]);
8907 result = WERR_NOMEM;
8911 *r->out.needed += strlen_m_term(keynames[i]) * 2;
8914 if (r->in.offered < *r->out.needed) {
8915 result = WERR_MORE_DATA;
8921 *r->out.key_buffer = array;
8924 if (!W_ERROR_IS_OK(result)) {
8926 ZERO_STRUCTP(r->out.key_buffer);
8929 free_a_printer(&printer, 2);
8930 SAFE_FREE(keynames);
8935 /****************************************************************
8936 _spoolss_DeletePrinterKey
8937 ****************************************************************/
8939 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8940 struct spoolss_DeletePrinterKey *r)
8942 POLICY_HND *handle = r->in.handle;
8943 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8944 NT_PRINTER_INFO_LEVEL *printer = NULL;
8948 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8951 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8952 OUR_HANDLE(handle)));
8956 /* if keyname == NULL, return error */
8958 if ( !r->in.key_name )
8959 return WERR_INVALID_PARAM;
8961 if (!get_printer_snum(p, handle, &snum, NULL))
8964 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8965 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8966 "printer properties change denied by handle\n"));
8967 return WERR_ACCESS_DENIED;
8970 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8971 if (!W_ERROR_IS_OK(status))
8974 /* delete the key and all subneys */
8976 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8978 if ( W_ERROR_IS_OK(status) )
8979 status = mod_a_printer(printer, 2);
8981 free_a_printer( &printer, 2 );
8986 /****************************************************************
8987 ****************************************************************/
8989 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8991 struct spoolss_PrinterEnumValues *r)
8995 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
8996 W_ERROR_HAVE_NO_MEMORY(r->data);
8998 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
8999 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9001 r->type = regval_type(v);
9002 r->data_length = regval_size(v);
9004 if (r->data_length) {
9005 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9007 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9010 if (!W_ERROR_IS_OK(result)) {
9018 /****************************************************************
9019 _spoolss_EnumPrinterDataEx
9020 ****************************************************************/
9022 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9023 struct spoolss_EnumPrinterDataEx *r)
9026 NT_PRINTER_INFO_LEVEL *printer = NULL;
9027 struct spoolss_PrinterEnumValues *info = NULL;
9028 NT_PRINTER_DATA *p_data;
9029 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9035 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9039 *r->out.info = NULL;
9042 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9043 OUR_HANDLE(r->in.handle)));
9048 * first check for a keyname of NULL or "". Win2k seems to send
9049 * this a lot and we should send back WERR_INVALID_PARAM
9050 * no need to spend time looking up the printer in this case.
9054 if (!strlen(r->in.key_name)) {
9055 result = WERR_INVALID_PARAM;
9059 /* get the printer off of disk */
9061 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9065 ZERO_STRUCT(printer);
9066 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9067 if (!W_ERROR_IS_OK(result)) {
9071 /* now look for a match on the key name */
9073 p_data = printer->info_2->data;
9075 key_index = lookup_printerkey(p_data, r->in.key_name);
9076 if (key_index == -1) {
9077 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9079 result = WERR_INVALID_PARAM;
9083 /* allocate the memory for the array of pointers -- if necessary */
9085 count = regval_ctr_numvals(p_data->keys[key_index].values);
9087 result = WERR_OK; /* ??? */
9091 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9092 struct spoolss_PrinterEnumValues,
9095 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9096 result = WERR_NOMEM;
9101 * loop through all params and build the array to pass
9102 * back to the client
9105 for (i=0; i < count; i++) {
9107 REGISTRY_VALUE *val;
9109 /* lookup the registry value */
9111 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9113 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9117 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9118 if (!W_ERROR_IS_OK(result)) {
9123 #if 0 /* FIXME - gd */
9124 /* housekeeping information in the reply */
9126 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9127 * the hand marshalled container size is a multiple
9128 * of 4 bytes for RPC alignment.
9132 needed += 4-(needed % 4);
9135 *r->out.count = count;
9136 *r->out.info = info;
9141 free_a_printer(&printer, 2);
9144 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9145 spoolss_EnumPrinterDataEx, NULL,
9148 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9149 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9151 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9154 /****************************************************************************
9155 ****************************************************************************/
9157 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9158 const char *servername,
9159 const char *environment,
9160 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9165 werr = compose_spoolss_server_path(mem_ctx,
9168 SPOOLSS_PRTPROCS_PATH,
9170 if (!W_ERROR_IS_OK(werr)) {
9174 DEBUG(4,("print processor directory: [%s]\n", path));
9176 r->directory_name = path;
9181 /****************************************************************
9182 _spoolss_GetPrintProcessorDirectory
9183 ****************************************************************/
9185 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9186 struct spoolss_GetPrintProcessorDirectory *r)
9190 /* that's an [in out] buffer */
9192 if (!r->in.buffer && (r->in.offered != 0)) {
9193 return WERR_INVALID_PARAM;
9196 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9201 /* r->in.level is ignored */
9203 result = getprintprocessordirectory_level_1(p->mem_ctx,
9206 &r->out.info->info1);
9207 if (!W_ERROR_IS_OK(result)) {
9208 TALLOC_FREE(r->out.info);
9212 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9213 r->out.info, r->in.level);
9214 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9216 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9219 /*******************************************************************
9220 ********************************************************************/
9222 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9223 const char *dllname)
9225 enum ndr_err_code ndr_err;
9226 struct spoolss_MonitorUi ui;
9228 ui.dll_name = dllname;
9230 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9231 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9232 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9233 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9235 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9238 /*******************************************************************
9239 Streams the monitor UI DLL name in UNICODE
9240 *******************************************************************/
9242 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9243 NT_USER_TOKEN *token, DATA_BLOB *in,
9244 DATA_BLOB *out, uint32_t *needed)
9246 const char *dllname = "tcpmonui.dll";
9248 *needed = (strlen(dllname)+1) * 2;
9250 if (out->length < *needed) {
9251 return WERR_INSUFFICIENT_BUFFER;
9254 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9261 /*******************************************************************
9262 ********************************************************************/
9264 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9265 struct spoolss_PortData1 *port1,
9266 const DATA_BLOB *buf)
9268 enum ndr_err_code ndr_err;
9269 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9270 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9271 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9272 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9274 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9277 /*******************************************************************
9278 ********************************************************************/
9280 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9281 struct spoolss_PortData2 *port2,
9282 const DATA_BLOB *buf)
9284 enum ndr_err_code ndr_err;
9285 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9286 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9287 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9288 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9290 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9293 /*******************************************************************
9294 Create a new TCP/IP port
9295 *******************************************************************/
9297 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9298 NT_USER_TOKEN *token, DATA_BLOB *in,
9299 DATA_BLOB *out, uint32_t *needed)
9301 struct spoolss_PortData1 port1;
9302 struct spoolss_PortData2 port2;
9303 char *device_uri = NULL;
9306 const char *portname;
9307 const char *hostaddress;
9309 uint32_t port_number;
9312 /* peek for spoolss_PortData version */
9314 if (!in || (in->length < (128 + 4))) {
9315 return WERR_GENERAL_FAILURE;
9318 version = IVAL(in->data, 128);
9324 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9328 portname = port1.portname;
9329 hostaddress = port1.hostaddress;
9330 queue = port1.queue;
9331 protocol = port1.protocol;
9332 port_number = port1.port_number;
9338 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9342 portname = port2.portname;
9343 hostaddress = port2.hostaddress;
9344 queue = port2.queue;
9345 protocol = port2.protocol;
9346 port_number = port2.port_number;
9350 DEBUG(1,("xcvtcp_addport: "
9351 "unknown version of port_data: %d\n", version));
9352 return WERR_UNKNOWN_PORT;
9355 /* create the device URI and call the add_port_hook() */
9358 case PROTOCOL_RAWTCP_TYPE:
9359 device_uri = talloc_asprintf(mem_ctx,
9360 "socket://%s:%d/", hostaddress,
9364 case PROTOCOL_LPR_TYPE:
9365 device_uri = talloc_asprintf(mem_ctx,
9366 "lpr://%s/%s", hostaddress, queue );
9370 return WERR_UNKNOWN_PORT;
9377 return add_port_hook(mem_ctx, token, portname, device_uri);
9380 /*******************************************************************
9381 *******************************************************************/
9383 struct xcv_api_table xcvtcp_cmds[] = {
9384 { "MonitorUI", xcvtcp_monitorui },
9385 { "AddPort", xcvtcp_addport},
9389 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9390 NT_USER_TOKEN *token, const char *command,
9397 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9399 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9400 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9401 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9404 return WERR_BADFUNC;
9407 /*******************************************************************
9408 *******************************************************************/
9409 #if 0 /* don't support management using the "Local Port" monitor */
9411 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9412 NT_USER_TOKEN *token, DATA_BLOB *in,
9413 DATA_BLOB *out, uint32_t *needed)
9415 const char *dllname = "localui.dll";
9417 *needed = (strlen(dllname)+1) * 2;
9419 if (out->length < *needed) {
9420 return WERR_INSUFFICIENT_BUFFER;
9423 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9430 /*******************************************************************
9431 *******************************************************************/
9433 struct xcv_api_table xcvlocal_cmds[] = {
9434 { "MonitorUI", xcvlocal_monitorui },
9438 struct xcv_api_table xcvlocal_cmds[] = {
9445 /*******************************************************************
9446 *******************************************************************/
9448 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9449 NT_USER_TOKEN *token, const char *command,
9450 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9455 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9457 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9458 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9459 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9461 return WERR_BADFUNC;
9464 /****************************************************************
9466 ****************************************************************/
9468 WERROR _spoolss_XcvData(pipes_struct *p,
9469 struct spoolss_XcvData *r)
9471 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9472 DATA_BLOB out_data = data_blob_null;
9476 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9477 OUR_HANDLE(r->in.handle)));
9481 /* Has to be a handle to the TCP/IP port monitor */
9483 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9484 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9488 /* requires administrative access to the server */
9490 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9491 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9492 return WERR_ACCESS_DENIED;
9495 /* Allocate the outgoing buffer */
9497 if (r->in.out_data_size) {
9498 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9499 if (out_data.data == NULL) {
9504 switch ( Printer->printer_type ) {
9505 case SPLHND_PORTMON_TCP:
9506 werror = process_xcvtcp_command(p->mem_ctx,
9507 p->server_info->ptok,
9508 r->in.function_name,
9509 &r->in.in_data, &out_data,
9512 case SPLHND_PORTMON_LOCAL:
9513 werror = process_xcvlocal_command(p->mem_ctx,
9514 p->server_info->ptok,
9515 r->in.function_name,
9516 &r->in.in_data, &out_data,
9520 werror = WERR_INVALID_PRINT_MONITOR;
9523 if (!W_ERROR_IS_OK(werror)) {
9527 *r->out.status_code = 0;
9529 memcpy(r->out.out_data, out_data.data, out_data.length);
9534 /****************************************************************
9535 _spoolss_AddPrintProcessor
9536 ****************************************************************/
9538 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9539 struct spoolss_AddPrintProcessor *r)
9541 /* for now, just indicate success and ignore the add. We'll
9542 automatically set the winprint processor for printer
9543 entries later. Used to debug the LexMark Optra S 1855 PCL
9549 /****************************************************************
9551 ****************************************************************/
9553 WERROR _spoolss_AddPrinter(pipes_struct *p,
9554 struct spoolss_AddPrinter *r)
9556 p->rng_fault_state = true;
9557 return WERR_NOT_SUPPORTED;
9560 /****************************************************************
9561 _spoolss_GetPrinterDriver
9562 ****************************************************************/
9564 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9565 struct spoolss_GetPrinterDriver *r)
9567 p->rng_fault_state = true;
9568 return WERR_NOT_SUPPORTED;
9571 /****************************************************************
9572 _spoolss_ReadPrinter
9573 ****************************************************************/
9575 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9576 struct spoolss_ReadPrinter *r)
9578 p->rng_fault_state = true;
9579 return WERR_NOT_SUPPORTED;
9582 /****************************************************************
9583 _spoolss_WaitForPrinterChange
9584 ****************************************************************/
9586 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9587 struct spoolss_WaitForPrinterChange *r)
9589 p->rng_fault_state = true;
9590 return WERR_NOT_SUPPORTED;
9593 /****************************************************************
9595 ****************************************************************/
9597 WERROR _spoolss_AddPort(pipes_struct *p,
9598 struct spoolss_AddPort *r)
9600 p->rng_fault_state = true;
9601 return WERR_NOT_SUPPORTED;
9604 /****************************************************************
9605 _spoolss_ConfigurePort
9606 ****************************************************************/
9608 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9609 struct spoolss_ConfigurePort *r)
9611 p->rng_fault_state = true;
9612 return WERR_NOT_SUPPORTED;
9615 /****************************************************************
9617 ****************************************************************/
9619 WERROR _spoolss_DeletePort(pipes_struct *p,
9620 struct spoolss_DeletePort *r)
9622 p->rng_fault_state = true;
9623 return WERR_NOT_SUPPORTED;
9626 /****************************************************************
9627 _spoolss_CreatePrinterIC
9628 ****************************************************************/
9630 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9631 struct spoolss_CreatePrinterIC *r)
9633 p->rng_fault_state = true;
9634 return WERR_NOT_SUPPORTED;
9637 /****************************************************************
9638 _spoolss_PlayGDIScriptOnPrinterIC
9639 ****************************************************************/
9641 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9642 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9644 p->rng_fault_state = true;
9645 return WERR_NOT_SUPPORTED;
9648 /****************************************************************
9649 _spoolss_DeletePrinterIC
9650 ****************************************************************/
9652 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9653 struct spoolss_DeletePrinterIC *r)
9655 p->rng_fault_state = true;
9656 return WERR_NOT_SUPPORTED;
9659 /****************************************************************
9660 _spoolss_AddPrinterConnection
9661 ****************************************************************/
9663 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9664 struct spoolss_AddPrinterConnection *r)
9666 p->rng_fault_state = true;
9667 return WERR_NOT_SUPPORTED;
9670 /****************************************************************
9671 _spoolss_DeletePrinterConnection
9672 ****************************************************************/
9674 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9675 struct spoolss_DeletePrinterConnection *r)
9677 p->rng_fault_state = true;
9678 return WERR_NOT_SUPPORTED;
9681 /****************************************************************
9682 _spoolss_PrinterMessageBox
9683 ****************************************************************/
9685 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9686 struct spoolss_PrinterMessageBox *r)
9688 p->rng_fault_state = true;
9689 return WERR_NOT_SUPPORTED;
9692 /****************************************************************
9694 ****************************************************************/
9696 WERROR _spoolss_AddMonitor(pipes_struct *p,
9697 struct spoolss_AddMonitor *r)
9699 p->rng_fault_state = true;
9700 return WERR_NOT_SUPPORTED;
9703 /****************************************************************
9704 _spoolss_DeleteMonitor
9705 ****************************************************************/
9707 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9708 struct spoolss_DeleteMonitor *r)
9710 p->rng_fault_state = true;
9711 return WERR_NOT_SUPPORTED;
9714 /****************************************************************
9715 _spoolss_DeletePrintProcessor
9716 ****************************************************************/
9718 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9719 struct spoolss_DeletePrintProcessor *r)
9721 p->rng_fault_state = true;
9722 return WERR_NOT_SUPPORTED;
9725 /****************************************************************
9726 _spoolss_AddPrintProvidor
9727 ****************************************************************/
9729 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9730 struct spoolss_AddPrintProvidor *r)
9732 p->rng_fault_state = true;
9733 return WERR_NOT_SUPPORTED;
9736 /****************************************************************
9737 _spoolss_DeletePrintProvidor
9738 ****************************************************************/
9740 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9741 struct spoolss_DeletePrintProvidor *r)
9743 p->rng_fault_state = true;
9744 return WERR_NOT_SUPPORTED;
9747 /****************************************************************
9748 _spoolss_FindFirstPrinterChangeNotification
9749 ****************************************************************/
9751 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9752 struct spoolss_FindFirstPrinterChangeNotification *r)
9754 p->rng_fault_state = true;
9755 return WERR_NOT_SUPPORTED;
9758 /****************************************************************
9759 _spoolss_FindNextPrinterChangeNotification
9760 ****************************************************************/
9762 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9763 struct spoolss_FindNextPrinterChangeNotification *r)
9765 p->rng_fault_state = true;
9766 return WERR_NOT_SUPPORTED;
9769 /****************************************************************
9770 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9771 ****************************************************************/
9773 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9774 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9776 p->rng_fault_state = true;
9777 return WERR_NOT_SUPPORTED;
9780 /****************************************************************
9781 _spoolss_ReplyOpenPrinter
9782 ****************************************************************/
9784 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9785 struct spoolss_ReplyOpenPrinter *r)
9787 p->rng_fault_state = true;
9788 return WERR_NOT_SUPPORTED;
9791 /****************************************************************
9792 _spoolss_RouterReplyPrinter
9793 ****************************************************************/
9795 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9796 struct spoolss_RouterReplyPrinter *r)
9798 p->rng_fault_state = true;
9799 return WERR_NOT_SUPPORTED;
9802 /****************************************************************
9803 _spoolss_ReplyClosePrinter
9804 ****************************************************************/
9806 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9807 struct spoolss_ReplyClosePrinter *r)
9809 p->rng_fault_state = true;
9810 return WERR_NOT_SUPPORTED;
9813 /****************************************************************
9815 ****************************************************************/
9817 WERROR _spoolss_AddPortEx(pipes_struct *p,
9818 struct spoolss_AddPortEx *r)
9820 p->rng_fault_state = true;
9821 return WERR_NOT_SUPPORTED;
9824 /****************************************************************
9825 _spoolss_RouterFindFirstPrinterChangeNotification
9826 ****************************************************************/
9828 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9829 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9831 p->rng_fault_state = true;
9832 return WERR_NOT_SUPPORTED;
9835 /****************************************************************
9836 _spoolss_SpoolerInit
9837 ****************************************************************/
9839 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9840 struct spoolss_SpoolerInit *r)
9842 p->rng_fault_state = true;
9843 return WERR_NOT_SUPPORTED;
9846 /****************************************************************
9847 _spoolss_ResetPrinterEx
9848 ****************************************************************/
9850 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9851 struct spoolss_ResetPrinterEx *r)
9853 p->rng_fault_state = true;
9854 return WERR_NOT_SUPPORTED;
9857 /****************************************************************
9858 _spoolss_RouterReplyPrinterEx
9859 ****************************************************************/
9861 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9862 struct spoolss_RouterReplyPrinterEx *r)
9864 p->rng_fault_state = true;
9865 return WERR_NOT_SUPPORTED;
9868 /****************************************************************
9870 ****************************************************************/
9872 WERROR _spoolss_44(pipes_struct *p,
9873 struct spoolss_44 *r)
9875 p->rng_fault_state = true;
9876 return WERR_NOT_SUPPORTED;
9879 /****************************************************************
9881 ****************************************************************/
9883 WERROR _spoolss_47(pipes_struct *p,
9884 struct spoolss_47 *r)
9886 p->rng_fault_state = true;
9887 return WERR_NOT_SUPPORTED;
9890 /****************************************************************
9892 ****************************************************************/
9894 WERROR _spoolss_4a(pipes_struct *p,
9895 struct spoolss_4a *r)
9897 p->rng_fault_state = true;
9898 return WERR_NOT_SUPPORTED;
9901 /****************************************************************
9903 ****************************************************************/
9905 WERROR _spoolss_4b(pipes_struct *p,
9906 struct spoolss_4b *r)
9908 p->rng_fault_state = true;
9909 return WERR_NOT_SUPPORTED;
9912 /****************************************************************
9914 ****************************************************************/
9916 WERROR _spoolss_4c(pipes_struct *p,
9917 struct spoolss_4c *r)
9919 p->rng_fault_state = true;
9920 return WERR_NOT_SUPPORTED;
9923 /****************************************************************
9925 ****************************************************************/
9927 WERROR _spoolss_53(pipes_struct *p,
9928 struct spoolss_53 *r)
9930 p->rng_fault_state = true;
9931 return WERR_NOT_SUPPORTED;
9934 /****************************************************************
9936 ****************************************************************/
9938 WERROR _spoolss_55(pipes_struct *p,
9939 struct spoolss_55 *r)
9941 p->rng_fault_state = true;
9942 return WERR_NOT_SUPPORTED;
9945 /****************************************************************
9947 ****************************************************************/
9949 WERROR _spoolss_56(pipes_struct *p,
9950 struct spoolss_56 *r)
9952 p->rng_fault_state = true;
9953 return WERR_NOT_SUPPORTED;
9956 /****************************************************************
9958 ****************************************************************/
9960 WERROR _spoolss_57(pipes_struct *p,
9961 struct spoolss_57 *r)
9963 p->rng_fault_state = true;
9964 return WERR_NOT_SUPPORTED;
9967 /****************************************************************
9969 ****************************************************************/
9971 WERROR _spoolss_5a(pipes_struct *p,
9972 struct spoolss_5a *r)
9974 p->rng_fault_state = true;
9975 return WERR_NOT_SUPPORTED;
9978 /****************************************************************
9980 ****************************************************************/
9982 WERROR _spoolss_5b(pipes_struct *p,
9983 struct spoolss_5b *r)
9985 p->rng_fault_state = true;
9986 return WERR_NOT_SUPPORTED;
9989 /****************************************************************
9991 ****************************************************************/
9993 WERROR _spoolss_5c(pipes_struct *p,
9994 struct spoolss_5c *r)
9996 p->rng_fault_state = true;
9997 return WERR_NOT_SUPPORTED;
10000 /****************************************************************
10002 ****************************************************************/
10004 WERROR _spoolss_5d(pipes_struct *p,
10005 struct spoolss_5d *r)
10007 p->rng_fault_state = true;
10008 return WERR_NOT_SUPPORTED;
10011 /****************************************************************
10013 ****************************************************************/
10015 WERROR _spoolss_5e(pipes_struct *p,
10016 struct spoolss_5e *r)
10018 p->rng_fault_state = true;
10019 return WERR_NOT_SUPPORTED;
10022 /****************************************************************
10024 ****************************************************************/
10026 WERROR _spoolss_5f(pipes_struct *p,
10027 struct spoolss_5f *r)
10029 p->rng_fault_state = true;
10030 return WERR_NOT_SUPPORTED;