2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
30 /* macros stolen from s4 spoolss server */
31 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
32 ((info)?ndr_size_##fn(info, level, ic, 0):0)
34 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
35 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
37 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
38 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
40 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
43 extern userdom_struct current_user_info
;
46 #define DBGC_CLASS DBGC_RPC_SRV
48 #ifndef MAX_OPEN_PRINTER_EXS
49 #define MAX_OPEN_PRINTER_EXS 50
52 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
53 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
56 const char *long_archi
;
57 const char *short_archi
;
61 static Printer_entry
*printers_list
;
63 typedef struct _counter_printer_0
{
64 struct _counter_printer_0
*next
;
65 struct _counter_printer_0
*prev
;
71 static counter_printer_0
*counter_list
;
73 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
74 static uint32 smb_connections
=0;
77 /* in printing/nt_printing.c */
79 extern struct standard_mapping printer_std_mapping
, printserver_std_mapping
;
81 /* API table for Xcv Monitor functions */
83 struct xcv_api_table
{
85 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, NT_USER_TOKEN
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
88 /********************************************************************
89 * Canonicalize servername.
90 ********************************************************************/
92 static const char *canon_servername(const char *servername
)
94 const char *pservername
= servername
;
95 while (*pservername
== '\\') {
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v
)
108 return JOB_STATUS_PAUSED
;
110 return JOB_STATUS_SPOOLING
;
112 return JOB_STATUS_PRINTING
;
114 return JOB_STATUS_ERROR
;
116 return JOB_STATUS_DELETING
;
118 return JOB_STATUS_OFFLINE
;
120 return JOB_STATUS_PAPEROUT
;
122 return JOB_STATUS_PRINTED
;
124 return JOB_STATUS_DELETED
;
126 return JOB_STATUS_BLOCKED_DEVQ
;
127 case LPQ_USER_INTERVENTION
:
128 return JOB_STATUS_USER_INTERVENTION
;
133 static int nt_printq_status(int v
)
137 return PRINTER_STATUS_PAUSED
;
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum
))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections
==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 status
= rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe
, talloc_tos(),
172 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 win_errstr(result
)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections
==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe
) );
180 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2
, NULL
);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
194 /****************************************************************************
195 Functions to free a printer entry datastruct.
196 ****************************************************************************/
198 static int printer_entry_destructor(Printer_entry
*Printer
)
200 if (Printer
->notify
.client_connected
==True
) {
203 if ( Printer
->printer_type
== SPLHND_SERVER
) {
205 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
206 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
207 snum
= print_queue_snum(Printer
->sharename
);
209 srv_spoolss_replycloseprinter(snum
,
210 &Printer
->notify
.client_hnd
);
214 Printer
->notify
.flags
=0;
215 Printer
->notify
.options
=0;
216 Printer
->notify
.localmachine
[0]='\0';
217 Printer
->notify
.printerlocal
=0;
218 TALLOC_FREE(Printer
->notify
.option
);
219 Printer
->notify
.client_connected
=False
;
221 free_nt_devicemode( &Printer
->nt_devmode
);
222 free_a_printer( &Printer
->printer_info
, 2 );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list
, Printer
);
229 /****************************************************************************
230 find printer index by handle
231 ****************************************************************************/
233 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
235 Printer_entry
*find_printer
= NULL
;
237 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
238 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
245 /****************************************************************************
246 Close printer index by handle.
247 ****************************************************************************/
249 static bool close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
251 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
254 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
258 close_policy_hnd(p
, hnd
);
263 /****************************************************************************
264 Delete a printer given a handle.
265 ****************************************************************************/
267 WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *sharename
)
269 char *cmd
= lp_deleteprinter_cmd();
270 char *command
= NULL
;
272 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
273 bool is_print_op
= False
;
275 /* can't fail if we don't try */
280 command
= talloc_asprintf(ctx
,
287 is_print_op
= user_has_privileges( token
, &se_printop
);
289 DEBUG(10,("Running [%s]\n", command
));
291 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
296 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
297 /* Tell everyone we updated smb.conf. */
298 message_send_all(smbd_messaging_context(),
299 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
305 /********** END SePrintOperatorPrivlege BLOCK **********/
307 DEBUGADD(10,("returned [%d]\n", ret
));
309 TALLOC_FREE(command
);
312 return WERR_BADFID
; /* What to return here? */
314 /* go ahead and re-read the services immediately */
315 reload_services( False
);
317 if ( lp_servicenumber( sharename
) < 0 )
318 return WERR_ACCESS_DENIED
;
323 /****************************************************************************
324 Delete a printer given a handle.
325 ****************************************************************************/
327 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
329 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
332 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
337 * It turns out that Windows allows delete printer on a handle
338 * opened by an admin user, then used on a pipe handle created
339 * by an anonymous user..... but they're working on security.... riiight !
343 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
344 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345 return WERR_ACCESS_DENIED
;
348 /* this does not need a become root since the access check has been
349 done on the handle already */
351 if (del_a_printer( Printer
->sharename
) != 0) {
352 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
356 return delete_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
357 Printer
->sharename
);
360 /****************************************************************************
361 Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
364 static bool get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
,
365 struct share_params
**params
)
367 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
370 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
374 switch (Printer
->printer_type
) {
376 DEBUG(4,("short name:%s\n", Printer
->sharename
));
377 *number
= print_queue_snum(Printer
->sharename
);
378 return (*number
!= -1);
386 /****************************************************************************
387 Set printer handle type.
388 Check if it's \\server or \\server\printer
389 ****************************************************************************/
391 static bool set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
393 DEBUG(3,("Setting printer type=%s\n", handlename
));
395 if ( strlen(handlename
) < 3 ) {
396 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
400 /* it's a print server */
401 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
402 DEBUGADD(4,("Printer is a print server\n"));
403 Printer
->printer_type
= SPLHND_SERVER
;
405 /* it's a printer (set_printer_hnd_name() will handle port monitors */
407 DEBUGADD(4,("Printer is a printer\n"));
408 Printer
->printer_type
= SPLHND_PRINTER
;
414 /****************************************************************************
415 Set printer handle name.. Accept names like \\server, \\server\printer,
416 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
417 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
418 XcvDataPort() interface.
419 ****************************************************************************/
421 static bool set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
424 int n_services
=lp_numservices();
425 char *aprinter
, *printername
;
426 const char *servername
;
429 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
432 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
434 aprinter
= handlename
;
435 if ( *handlename
== '\\' ) {
436 servername
= canon_servername(handlename
);
437 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
445 /* save the servername to fill in replies on this handle */
447 if ( !is_myname_or_ipaddr( servername
) )
450 fstrcpy( Printer
->servername
, servername
);
452 if ( Printer
->printer_type
== SPLHND_SERVER
)
455 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
458 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
460 /* check for the Port Monitor Interface */
462 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
463 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
464 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
467 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
468 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
469 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
473 /* Search all sharenames first as this is easier than pulling
474 the printer_info_2 off of disk. Don't use find_service() since
475 that calls out to map_username() */
477 /* do another loop to look for printernames */
479 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
481 /* no point going on if this is not a printer */
483 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
486 fstrcpy(sname
, lp_servicename(snum
));
487 if ( strequal( aprinter
, sname
) ) {
492 /* no point looking up the printer object if
493 we aren't allowing printername != sharename */
495 if ( lp_force_printername(snum
) )
498 fstrcpy(sname
, lp_servicename(snum
));
502 /* This call doesn't fill in the location or comment from
503 * a CUPS server for efficiency with large numbers of printers.
507 result
= get_a_printer_search( NULL
, &printer
, 2, sname
);
508 if ( !W_ERROR_IS_OK(result
) ) {
509 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
510 sname
, win_errstr(result
)));
514 /* printername is always returned as \\server\printername */
515 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
516 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
517 printer
->info_2
->printername
));
518 free_a_printer( &printer
, 2);
524 if ( strequal(printername
, aprinter
) ) {
525 free_a_printer( &printer
, 2);
530 DEBUGADD(10, ("printername: %s\n", printername
));
532 free_a_printer( &printer
, 2);
535 free_a_printer( &printer
, 2);
538 DEBUGADD(4,("Printer not found\n"));
542 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
544 fstrcpy(Printer
->sharename
, sname
);
549 /****************************************************************************
550 Find first available printer slot. creates a printer handle for you.
551 ****************************************************************************/
553 static bool open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
555 Printer_entry
*new_printer
;
557 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
559 new_printer
= TALLOC_ZERO_P(NULL
, Printer_entry
);
560 if (new_printer
== NULL
) {
563 talloc_set_destructor(new_printer
, printer_entry_destructor
);
565 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
566 TALLOC_FREE(new_printer
);
570 /* Add to the internal list. */
571 DLIST_ADD(printers_list
, new_printer
);
573 new_printer
->notify
.option
=NULL
;
575 if (!set_printer_hnd_printertype(new_printer
, name
)) {
576 close_printer_handle(p
, hnd
);
580 if (!set_printer_hnd_name(new_printer
, name
)) {
581 close_printer_handle(p
, hnd
);
585 new_printer
->access_granted
= access_granted
;
587 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
592 /***************************************************************************
593 check to see if the client motify handle is monitoring the notification
594 given by (notify_type, notify_field).
595 **************************************************************************/
597 static bool is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
603 static bool is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
606 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
610 * Flags should always be zero when the change notify
611 * is registered by the client's spooler. A user Win32 app
612 * might use the flags though instead of the NOTIFY_OPTION_INFO
621 return is_monitoring_event_flags(
622 p
->notify
.flags
, notify_type
, notify_field
);
624 for (i
= 0; i
< option
->count
; i
++) {
626 /* Check match for notify_type */
628 if (option
->types
[i
].type
!= notify_type
)
631 /* Check match for field */
633 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
634 if (option
->types
[i
].fields
[j
] == notify_field
) {
640 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
641 p
->servername
, p
->sharename
, notify_type
, notify_field
));
646 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
647 _data->data.integer[0] = _integer; \
648 _data->data.integer[1] = 0;
651 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
652 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
653 if (!_data->data.string.string) {\
654 _data->data.string.size = 0; \
656 _data->data.string.size = strlen_m_term(_p) * 2;
658 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
659 _data->data.devmode.devmode = _devmode;
661 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
662 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
663 if (!_data->data.sd.sd) { \
664 _data->data.sd.sd_size = 0; \
666 _data->data.sd.sd_size = _size;
668 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
673 struct spoolss_Time st
;
677 if (!init_systemtime(&st
, t
)) {
681 p
= talloc_array(mem_ctx
, char, len
);
687 * Systemtime must be linearized as a set of UINT16's.
688 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
691 SSVAL(p
, 0, st
.year
);
692 SSVAL(p
, 2, st
.month
);
693 SSVAL(p
, 4, st
.day_of_week
);
695 SSVAL(p
, 8, st
.hour
);
696 SSVAL(p
, 10, st
.minute
);
697 SSVAL(p
, 12, st
.second
);
698 SSVAL(p
, 14, st
.millisecond
);
704 /* Convert a notification message to a struct spoolss_Notify */
706 static void notify_one_value(struct spoolss_notify_msg
*msg
,
707 struct spoolss_Notify
*data
,
710 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
713 static void notify_string(struct spoolss_notify_msg
*msg
,
714 struct spoolss_Notify
*data
,
717 /* The length of the message includes the trailing \0 */
719 data
->data
.string
.size
= msg
->len
* 2;
720 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
721 if (!data
->data
.string
.string
) {
722 data
->data
.string
.size
= 0;
727 static void notify_system_time(struct spoolss_notify_msg
*msg
,
728 struct spoolss_Notify
*data
,
731 data
->data
.string
.string
= NULL
;
732 data
->data
.string
.size
= 0;
734 if (msg
->len
!= sizeof(time_t)) {
735 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
740 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
741 &data
->data
.string
.string
,
742 &data
->data
.string
.size
);
745 struct notify2_message_table
{
747 void (*fn
)(struct spoolss_notify_msg
*msg
,
748 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
751 static struct notify2_message_table printer_notify_table
[] = {
752 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
753 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
754 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
755 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
756 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
757 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
758 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
759 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
760 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
761 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
762 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
763 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
764 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
765 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
766 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
767 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
768 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
769 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
770 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
773 static struct notify2_message_table job_notify_table
[] = {
774 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
775 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
776 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
777 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
778 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
779 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
780 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
781 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
782 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
783 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
784 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
785 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
786 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
787 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
788 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
789 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
790 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
791 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
792 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
793 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
794 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
795 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
796 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
797 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
801 /***********************************************************************
802 Allocate talloc context for container object
803 **********************************************************************/
805 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
810 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
815 /***********************************************************************
816 release all allocated memory and zero out structure
817 **********************************************************************/
819 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
825 talloc_destroy(ctr
->ctx
);
832 /***********************************************************************
833 **********************************************************************/
835 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
843 /***********************************************************************
844 **********************************************************************/
846 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
848 if ( !ctr
|| !ctr
->msg_groups
)
851 if ( idx
>= ctr
->num_groups
)
854 return &ctr
->msg_groups
[idx
];
858 /***********************************************************************
859 How many groups of change messages do we have ?
860 **********************************************************************/
862 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
867 return ctr
->num_groups
;
870 /***********************************************************************
871 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
872 **********************************************************************/
874 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
876 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
877 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
878 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
884 /* loop over all groups looking for a matching printer name */
886 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
887 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
891 /* add a new group? */
893 if ( i
== ctr
->num_groups
) {
896 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
897 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
900 ctr
->msg_groups
= groups
;
902 /* clear the new entry and set the printer name */
904 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
905 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
908 /* add the change messages; 'i' is the correct index now regardless */
910 msg_grp
= &ctr
->msg_groups
[i
];
914 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
915 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
918 msg_grp
->msgs
= msg_list
;
920 new_slot
= msg_grp
->num_msgs
-1;
921 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
923 /* need to allocate own copy of data */
926 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
927 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
929 return ctr
->num_groups
;
932 /***********************************************************************
933 Send a change notication message on all handles which have a call
935 **********************************************************************/
937 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
940 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
941 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
942 SPOOLSS_NOTIFY_MSG
*messages
;
943 int sending_msg_count
;
946 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
950 messages
= msg_group
->msgs
;
953 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
957 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
959 /* loop over all printers */
961 for (p
= printers_list
; p
; p
= p
->next
) {
962 struct spoolss_Notify
*notifies
;
967 /* Is there notification on this handle? */
969 if ( !p
->notify
.client_connected
)
972 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
974 /* For this printer? Print servers always receive
977 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
978 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
981 DEBUG(10,("Our printer\n"));
983 /* allocate the max entries possible */
985 notifies
= TALLOC_ZERO_ARRAY(mem_ctx
, struct spoolss_Notify
, msg_group
->num_msgs
);
990 /* build the array of change notifications */
992 sending_msg_count
= 0;
994 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
995 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
997 /* Are we monitoring this event? */
999 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1002 sending_msg_count
++;
1005 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1006 msg
->type
, msg
->field
, p
->sharename
));
1009 * if the is a printer notification handle and not a job notification
1010 * type, then set the id to 0. Other wise just use what was specified
1013 * When registering change notification on a print server handle
1014 * we always need to send back the id (snum) matching the printer
1015 * for which the change took place. For change notify registered
1016 * on a printer handle, this does not matter and the id should be 0.
1021 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1027 /* Convert unix jobid to smb jobid */
1029 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1030 id
= sysjob_to_jobid(msg
->id
);
1033 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1038 construct_info_data( ¬ifies
[count
], msg
->type
, msg
->field
, id
);
1041 case PRINTER_NOTIFY_TYPE
:
1042 if ( printer_notify_table
[msg
->field
].fn
)
1043 printer_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1046 case JOB_NOTIFY_TYPE
:
1047 if ( job_notify_table
[msg
->field
].fn
)
1048 job_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1052 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1059 if ( sending_msg_count
) {
1062 union spoolss_ReplyPrinterInfo info
;
1063 struct spoolss_NotifyInfo info0
;
1064 uint32_t reply_result
;
1066 info0
.version
= 0x2;
1067 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1068 info0
.count
= count
;
1069 info0
.notifies
= notifies
;
1071 info
.info0
= &info0
;
1073 status
= rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe
, mem_ctx
,
1074 &p
->notify
.client_hnd
,
1075 p
->notify
.change
, /* color */
1078 0, /* reply_type, must be 0 */
1081 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
1082 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1083 notify_cli_pipe
->srv_name_slash
,
1086 switch (reply_result
) {
1089 case PRINTER_NOTIFY_INFO_DISCARDED
:
1090 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1091 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1100 DEBUG(8,("send_notify2_changes: Exit...\n"));
1104 /***********************************************************************
1105 **********************************************************************/
1107 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1110 uint32 tv_sec
, tv_usec
;
1113 /* Unpack message */
1115 offset
+= tdb_unpack((uint8
*)buf
+ offset
, len
- offset
, "f",
1118 offset
+= tdb_unpack((uint8
*)buf
+ offset
, len
- offset
, "ddddddd",
1120 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1123 tdb_unpack((uint8
*)buf
+ offset
, len
- offset
, "dd",
1124 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1126 tdb_unpack((uint8
*)buf
+ offset
, len
- offset
, "B",
1127 &msg
->len
, &msg
->notify
.data
);
1129 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1130 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1132 tv
->tv_sec
= tv_sec
;
1133 tv
->tv_usec
= tv_usec
;
1136 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1137 msg
->notify
.value
[1]));
1139 dump_data(3, (uint8
*)msg
->notify
.data
, msg
->len
);
1144 /********************************************************************
1145 Receive a notify2 message list
1146 ********************************************************************/
1148 static void receive_notify2_message_list(struct messaging_context
*msg
,
1151 struct server_id server_id
,
1154 size_t msg_count
, i
;
1155 char *buf
= (char *)data
->data
;
1158 SPOOLSS_NOTIFY_MSG notify
;
1159 SPOOLSS_NOTIFY_MSG_CTR messages
;
1162 if (data
->length
< 4) {
1163 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1167 msg_count
= IVAL(buf
, 0);
1170 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1172 if (msg_count
== 0) {
1173 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1177 /* initialize the container */
1179 ZERO_STRUCT( messages
);
1180 notify_msg_ctr_init( &messages
);
1183 * build message groups for each printer identified
1184 * in a change_notify msg. Remember that a PCN message
1185 * includes the handle returned for the srv_spoolss_replyopenprinter()
1186 * call. Therefore messages are grouped according to printer handle.
1189 for ( i
=0; i
<msg_count
; i
++ ) {
1190 struct timeval msg_tv
;
1192 if (msg_ptr
+ 4 - buf
> data
->length
) {
1193 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1197 msg_len
= IVAL(msg_ptr
,0);
1200 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1201 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1205 /* unpack messages */
1207 ZERO_STRUCT( notify
);
1208 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1211 /* add to correct list in container */
1213 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1215 /* free memory that might have been allocated by notify2_unpack_msg() */
1217 if ( notify
.len
!= 0 )
1218 SAFE_FREE( notify
.notify
.data
);
1221 /* process each group of messages */
1223 num_groups
= notify_msg_ctr_numgroups( &messages
);
1224 for ( i
=0; i
<num_groups
; i
++ )
1225 send_notify2_changes( &messages
, i
);
1230 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1232 notify_msg_ctr_destroy( &messages
);
1237 /********************************************************************
1238 Send a message to ourself about new driver being installed
1239 so we can upgrade the information for each printer bound to this
1241 ********************************************************************/
1243 static bool srv_spoolss_drv_upgrade_printer(char* drivername
)
1245 int len
= strlen(drivername
);
1250 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1253 messaging_send_buf(smbd_messaging_context(), procid_self(),
1254 MSG_PRINTER_DRVUPGRADE
,
1255 (uint8
*)drivername
, len
+1);
1260 /**********************************************************************
1261 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1262 over all printers, upgrading ones as necessary
1263 **********************************************************************/
1265 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1268 struct server_id server_id
,
1273 int n_services
= lp_numservices();
1276 len
= MIN(data
->length
,sizeof(drivername
)-1);
1277 strncpy(drivername
, (const char *)data
->data
, len
);
1279 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1281 /* Iterate the printer list */
1283 for (snum
=0; snum
<n_services
; snum
++)
1285 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1288 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1290 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1291 if (!W_ERROR_IS_OK(result
))
1294 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1296 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1298 /* all we care about currently is the change_id */
1300 result
= mod_a_printer(printer
, 2);
1301 if (!W_ERROR_IS_OK(result
)) {
1302 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1303 win_errstr(result
)));
1307 free_a_printer(&printer
, 2);
1314 /********************************************************************
1315 Update the cache for all printq's with a registered client
1317 ********************************************************************/
1319 void update_monitored_printq_cache( void )
1321 Printer_entry
*printer
= printers_list
;
1324 /* loop through all printers and update the cache where
1325 client_connected == True */
1328 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1329 && printer
->notify
.client_connected
)
1331 snum
= print_queue_snum(printer
->sharename
);
1332 print_queue_status( snum
, NULL
, NULL
);
1335 printer
= printer
->next
;
1340 /********************************************************************
1341 Send a message to ourself about new driver being installed
1342 so we can upgrade the information for each printer bound to this
1344 ********************************************************************/
1346 static bool srv_spoolss_reset_printerdata(char* drivername
)
1348 int len
= strlen(drivername
);
1353 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1356 messaging_send_buf(smbd_messaging_context(), procid_self(),
1357 MSG_PRINTERDATA_INIT_RESET
,
1358 (uint8
*)drivername
, len
+1);
1363 /**********************************************************************
1364 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1365 over all printers, resetting printer data as neessary
1366 **********************************************************************/
1368 void reset_all_printerdata(struct messaging_context
*msg
,
1371 struct server_id server_id
,
1376 int n_services
= lp_numservices();
1379 len
= MIN( data
->length
, sizeof(drivername
)-1 );
1380 strncpy( drivername
, (const char *)data
->data
, len
);
1382 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1384 /* Iterate the printer list */
1386 for ( snum
=0; snum
<n_services
; snum
++ )
1388 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1391 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1393 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1394 if ( !W_ERROR_IS_OK(result
) )
1398 * if the printer is bound to the driver,
1399 * then reset to the new driver initdata
1402 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1404 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1406 if ( !set_driver_init(printer
, 2) ) {
1407 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1408 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1411 result
= mod_a_printer( printer
, 2 );
1412 if ( !W_ERROR_IS_OK(result
) ) {
1413 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1414 get_dos_error_msg(result
)));
1418 free_a_printer( &printer
, 2 );
1427 /****************************************************************
1428 _spoolss_OpenPrinter
1429 ****************************************************************/
1431 WERROR
_spoolss_OpenPrinter(pipes_struct
*p
,
1432 struct spoolss_OpenPrinter
*r
)
1434 struct spoolss_OpenPrinterEx e
;
1437 ZERO_STRUCT(e
.in
.userlevel
);
1439 e
.in
.printername
= r
->in
.printername
;
1440 e
.in
.datatype
= r
->in
.datatype
;
1441 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1442 e
.in
.access_mask
= r
->in
.access_mask
;
1445 e
.out
.handle
= r
->out
.handle
;
1447 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1449 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1450 /* OpenPrinterEx returns this for a bad
1451 * printer name. We must return WERR_INVALID_PRINTER_NAME
1454 werr
= WERR_INVALID_PRINTER_NAME
;
1460 /********************************************************************
1461 ********************************************************************/
1463 bool convert_devicemode(const char *printername
,
1464 const struct spoolss_DeviceMode
*devmode
,
1465 NT_DEVICEMODE
**pp_nt_devmode
)
1467 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1470 * Ensure nt_devmode is a valid pointer
1471 * as we will be overwriting it.
1474 if (nt_devmode
== NULL
) {
1475 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1476 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1480 rpcstr_push(nt_devmode
->devicename
, devmode
->devicename
, 31, 0);
1481 rpcstr_push(nt_devmode
->formname
, devmode
->formname
, 31, 0);
1483 nt_devmode
->specversion
= devmode
->specversion
;
1484 nt_devmode
->driverversion
= devmode
->driverversion
;
1485 nt_devmode
->size
= devmode
->size
;
1486 nt_devmode
->fields
= devmode
->fields
;
1487 nt_devmode
->orientation
= devmode
->orientation
;
1488 nt_devmode
->papersize
= devmode
->papersize
;
1489 nt_devmode
->paperlength
= devmode
->paperlength
;
1490 nt_devmode
->paperwidth
= devmode
->paperwidth
;
1491 nt_devmode
->scale
= devmode
->scale
;
1492 nt_devmode
->copies
= devmode
->copies
;
1493 nt_devmode
->defaultsource
= devmode
->defaultsource
;
1494 nt_devmode
->printquality
= devmode
->printquality
;
1495 nt_devmode
->color
= devmode
->color
;
1496 nt_devmode
->duplex
= devmode
->duplex
;
1497 nt_devmode
->yresolution
= devmode
->yresolution
;
1498 nt_devmode
->ttoption
= devmode
->ttoption
;
1499 nt_devmode
->collate
= devmode
->collate
;
1501 nt_devmode
->logpixels
= devmode
->logpixels
;
1502 nt_devmode
->bitsperpel
= devmode
->bitsperpel
;
1503 nt_devmode
->pelswidth
= devmode
->pelswidth
;
1504 nt_devmode
->pelsheight
= devmode
->pelsheight
;
1505 nt_devmode
->displayflags
= devmode
->displayflags
;
1506 nt_devmode
->displayfrequency
= devmode
->displayfrequency
;
1507 nt_devmode
->icmmethod
= devmode
->icmmethod
;
1508 nt_devmode
->icmintent
= devmode
->icmintent
;
1509 nt_devmode
->mediatype
= devmode
->mediatype
;
1510 nt_devmode
->dithertype
= devmode
->dithertype
;
1511 nt_devmode
->reserved1
= devmode
->reserved1
;
1512 nt_devmode
->reserved2
= devmode
->reserved2
;
1513 nt_devmode
->panningwidth
= devmode
->panningwidth
;
1514 nt_devmode
->panningheight
= devmode
->panningheight
;
1517 * Only change private and driverextra if the incoming devmode
1518 * has a new one. JRA.
1521 if ((devmode
->__driverextra_length
!= 0) && (devmode
->driverextra_data
.data
!= NULL
)) {
1522 SAFE_FREE(nt_devmode
->nt_dev_private
);
1523 nt_devmode
->driverextra
= devmode
->__driverextra_length
;
1524 if((nt_devmode
->nt_dev_private
=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1526 memcpy(nt_devmode
->nt_dev_private
, devmode
->driverextra_data
.data
, nt_devmode
->driverextra
);
1529 *pp_nt_devmode
= nt_devmode
;
1534 /****************************************************************
1535 _spoolss_OpenPrinterEx
1536 ****************************************************************/
1538 WERROR
_spoolss_OpenPrinterEx(pipes_struct
*p
,
1539 struct spoolss_OpenPrinterEx
*r
)
1541 POLICY_HND
*handle
= r
->out
.handle
;
1542 char *name
= CONST_DISCARD(char *, r
->in
.printername
);
1544 Printer_entry
*Printer
=NULL
;
1547 return WERR_INVALID_PARAM
;
1550 /* some sanity check because you can open a printer or a print server */
1551 /* aka: \\server\printer or \\server */
1553 DEBUGADD(3,("checking name: %s\n",name
));
1555 if (!open_printer_hnd(p
, handle
, name
, 0)) {
1556 ZERO_STRUCTP(r
->out
.handle
);
1557 return WERR_INVALID_PARAM
;
1560 Printer
=find_printer_index_by_hnd(p
, handle
);
1562 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1563 "handle we created for printer %s\n", name
));
1564 close_printer_handle(p
,handle
);
1565 ZERO_STRUCTP(r
->out
.handle
);
1566 return WERR_INVALID_PARAM
;
1570 * First case: the user is opening the print server:
1572 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1573 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1575 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1576 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1577 * or if the user is listed in the smb.conf printer admin parameter.
1579 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1580 * client view printer folder, but does not show the MSAPW.
1582 * Note: this test needs code to check access rights here too. Jeremy
1583 * could you look at this?
1585 * Second case: the user is opening a printer:
1586 * NT doesn't let us connect to a printer if the connecting user
1587 * doesn't have print permission.
1589 * Third case: user is opening a Port Monitor
1590 * access checks same as opening a handle to the print server.
1593 switch (Printer
->printer_type
)
1596 case SPLHND_PORTMON_TCP
:
1597 case SPLHND_PORTMON_LOCAL
:
1598 /* Printserver handles use global struct... */
1602 /* Map standard access rights to object specific access rights */
1604 se_map_standard(&r
->in
.access_mask
,
1605 &printserver_std_mapping
);
1607 /* Deny any object specific bits that don't apply to print
1608 servers (i.e printer and job specific bits) */
1610 r
->in
.access_mask
&= SPECIFIC_RIGHTS_MASK
;
1612 if (r
->in
.access_mask
&
1613 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1614 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1615 close_printer_handle(p
, handle
);
1616 ZERO_STRUCTP(r
->out
.handle
);
1617 return WERR_ACCESS_DENIED
;
1620 /* Allow admin access */
1622 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1624 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1626 if (!lp_ms_add_printer_wizard()) {
1627 close_printer_handle(p
, handle
);
1628 ZERO_STRUCTP(r
->out
.handle
);
1629 return WERR_ACCESS_DENIED
;
1632 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1633 and not a printer admin, then fail */
1635 if ((p
->server_info
->utok
.uid
!= 0) &&
1636 !user_has_privileges(p
->server_info
->ptok
,
1638 !token_contains_name_in_list(
1639 uidtoname(p
->server_info
->utok
.uid
),
1641 p
->server_info
->ptok
,
1642 lp_printer_admin(snum
))) {
1643 close_printer_handle(p
, handle
);
1644 ZERO_STRUCTP(r
->out
.handle
);
1645 return WERR_ACCESS_DENIED
;
1648 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1652 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1655 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1656 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1658 /* We fall through to return WERR_OK */
1661 case SPLHND_PRINTER
:
1662 /* NT doesn't let us connect to a printer if the connecting user
1663 doesn't have print permission. */
1665 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
1666 close_printer_handle(p
, handle
);
1667 ZERO_STRUCTP(r
->out
.handle
);
1671 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1673 /* map an empty access mask to the minimum access mask */
1674 if (r
->in
.access_mask
== 0x0)
1675 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1678 * If we are not serving the printer driver for this printer,
1679 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1680 * will keep NT clients happy --jerry
1683 if (lp_use_client_driver(snum
)
1684 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1686 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1689 /* check smb.conf parameters and the the sec_desc */
1691 if ( !check_access(get_client_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1692 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1693 ZERO_STRUCTP(r
->out
.handle
);
1694 return WERR_ACCESS_DENIED
;
1697 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1698 p
->server_info
->ptok
, snum
) ||
1699 !print_access_check(p
->server_info
, snum
,
1700 r
->in
.access_mask
)) {
1701 DEBUG(3, ("access DENIED for printer open\n"));
1702 close_printer_handle(p
, handle
);
1703 ZERO_STRUCTP(r
->out
.handle
);
1704 return WERR_ACCESS_DENIED
;
1707 if ((r
->in
.access_mask
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1708 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1709 close_printer_handle(p
, handle
);
1710 ZERO_STRUCTP(r
->out
.handle
);
1711 return WERR_ACCESS_DENIED
;
1714 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1715 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1717 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1719 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1720 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1725 /* sanity check to prevent programmer error */
1726 ZERO_STRUCTP(r
->out
.handle
);
1730 Printer
->access_granted
= r
->in
.access_mask
;
1733 * If the client sent a devmode in the OpenPrinter() call, then
1734 * save it here in case we get a job submission on this handle
1737 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1738 r
->in
.devmode_ctr
.devmode
) {
1739 convert_devicemode(Printer
->sharename
,
1740 r
->in
.devmode_ctr
.devmode
,
1741 &Printer
->nt_devmode
);
1744 #if 0 /* JERRY -- I'm doubtful this is really effective */
1745 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1746 optimization in Windows 2000 clients --jerry */
1748 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1749 && (RA_WIN2K
== get_remote_arch()) )
1751 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1752 sys_usleep( 500000 );
1759 /****************************************************************************
1760 ****************************************************************************/
1762 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2
*r
,
1763 NT_PRINTER_INFO_LEVEL_2
*d
)
1765 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1771 d
->attributes
= r
->attributes
;
1772 d
->priority
= r
->priority
;
1773 d
->default_priority
= r
->defaultpriority
;
1774 d
->starttime
= r
->starttime
;
1775 d
->untiltime
= r
->untiltime
;
1776 d
->status
= r
->status
;
1777 d
->cjobs
= r
->cjobs
;
1779 fstrcpy(d
->servername
, r
->servername
);
1780 fstrcpy(d
->printername
, r
->printername
);
1781 fstrcpy(d
->sharename
, r
->sharename
);
1782 fstrcpy(d
->portname
, r
->portname
);
1783 fstrcpy(d
->drivername
, r
->drivername
);
1784 slprintf(d
->comment
, sizeof(d
->comment
)-1, "%s", r
->comment
);
1785 fstrcpy(d
->location
, r
->location
);
1786 fstrcpy(d
->sepfile
, r
->sepfile
);
1787 fstrcpy(d
->printprocessor
, r
->printprocessor
);
1788 fstrcpy(d
->datatype
, r
->datatype
);
1789 fstrcpy(d
->parameters
, r
->parameters
);
1794 /****************************************************************************
1795 ****************************************************************************/
1797 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1798 NT_PRINTER_INFO_LEVEL
*printer
)
1802 switch (info_ctr
->level
) {
1804 /* allocate memory if needed. Messy because
1805 convert_printer_info is used to update an existing
1806 printer or build a new one */
1808 if (!printer
->info_2
) {
1809 printer
->info_2
= TALLOC_ZERO_P(printer
, NT_PRINTER_INFO_LEVEL_2
);
1810 if (!printer
->info_2
) {
1811 DEBUG(0,("convert_printer_info: "
1812 "talloc() failed!\n"));
1817 ret
= printer_info2_to_nt_printer_info2(info_ctr
->info
.info2
,
1819 printer
->info_2
->setuptime
= time(NULL
);
1826 /*******************************************************************
1827 ********************************************************************/
1829 static bool string_array_to_fstring_array(const char **sarray
, fstring
**farray
)
1838 *farray
= SMB_MALLOC_ARRAY(fstring
, 1);
1843 for (i
=0; sarray
[i
] != NULL
; i
++) {
1844 *farray
= SMB_REALLOC_ARRAY(*farray
, fstring
, i
+2);
1848 fstrcpy((*farray
)[i
], sarray
[i
]);
1851 fstrcpy((*farray
)[i
], "");
1856 /*******************************************************************
1857 ********************************************************************/
1859 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3
*r
,
1860 NT_PRINTER_DRIVER_INFO_LEVEL_3
**p
)
1862 NT_PRINTER_DRIVER_INFO_LEVEL_3
*d
;
1864 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1867 *p
= SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3
);
1876 d
->cversion
= r
->version
;
1878 fstrcpy(d
->name
, r
->driver_name
);
1879 fstrcpy(d
->environment
, r
->architecture
);
1880 fstrcpy(d
->driverpath
, r
->driver_path
);
1881 fstrcpy(d
->datafile
, r
->data_file
);
1882 fstrcpy(d
->configfile
, r
->config_file
);
1883 fstrcpy(d
->helpfile
, r
->help_file
);
1884 fstrcpy(d
->monitorname
, r
->monitor_name
);
1885 fstrcpy(d
->defaultdatatype
, r
->default_datatype
);
1887 DEBUGADD(8,( "version: %d\n", d
->cversion
));
1888 DEBUGADD(8,( "name: %s\n", d
->name
));
1889 DEBUGADD(8,( "environment: %s\n", d
->environment
));
1890 DEBUGADD(8,( "driverpath: %s\n", d
->driverpath
));
1891 DEBUGADD(8,( "datafile: %s\n", d
->datafile
));
1892 DEBUGADD(8,( "configfile: %s\n", d
->configfile
));
1893 DEBUGADD(8,( "helpfile: %s\n", d
->helpfile
));
1894 DEBUGADD(8,( "monitorname: %s\n", d
->monitorname
));
1895 DEBUGADD(8,( "defaultdatatype: %s\n", d
->defaultdatatype
));
1897 if (r
->dependent_files
) {
1898 if (!string_array_to_fstring_array(r
->dependent_files
->string
,
1899 &d
->dependentfiles
)) {
1908 /*******************************************************************
1909 ********************************************************************/
1911 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6
*r
,
1912 NT_PRINTER_DRIVER_INFO_LEVEL_6
**p
)
1914 NT_PRINTER_DRIVER_INFO_LEVEL_6
*d
;
1916 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1919 *p
= SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6
);
1928 d
->version
= r
->version
;
1930 fstrcpy(d
->name
, r
->driver_name
);
1931 fstrcpy(d
->environment
, r
->architecture
);
1932 fstrcpy(d
->driverpath
, r
->driver_path
);
1933 fstrcpy(d
->datafile
, r
->data_file
);
1934 fstrcpy(d
->configfile
, r
->config_file
);
1935 fstrcpy(d
->helpfile
, r
->help_file
);
1936 fstrcpy(d
->monitorname
, r
->monitor_name
);
1937 fstrcpy(d
->defaultdatatype
, r
->default_datatype
);
1939 DEBUGADD(8,( "version: %d\n", d
->version
));
1940 DEBUGADD(8,( "name: %s\n", d
->name
));
1941 DEBUGADD(8,( "environment: %s\n", d
->environment
));
1942 DEBUGADD(8,( "driverpath: %s\n", d
->driverpath
));
1943 DEBUGADD(8,( "datafile: %s\n", d
->datafile
));
1944 DEBUGADD(8,( "configfile: %s\n", d
->configfile
));
1945 DEBUGADD(8,( "helpfile: %s\n", d
->helpfile
));
1946 DEBUGADD(8,( "monitorname: %s\n", d
->monitorname
));
1947 DEBUGADD(8,( "defaultdatatype: %s\n", d
->defaultdatatype
));
1949 if (r
->dependent_files
) {
1950 if (!string_array_to_fstring_array(r
->dependent_files
->string
,
1951 &d
->dependentfiles
)) {
1956 if (r
->previous_names
) {
1957 if (!string_array_to_fstring_array(r
->previous_names
->string
,
1958 &d
->previousnames
)) {
1970 /********************************************************************
1971 ********************************************************************/
1973 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr
*r
,
1974 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
,
1979 printer
->info_3
= NULL
;
1980 if (!driver_info3_to_nt_driver_info3(r
->info
.info3
, &printer
->info_3
)) {
1985 printer
->info_6
= NULL
;
1986 if (!driver_info6_to_nt_driver_info6(r
->info
.info6
, &printer
->info_6
)) {
1997 /********************************************************************
1998 * _spoolss_enddocprinter_internal.
1999 ********************************************************************/
2001 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
2003 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2007 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
2011 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
2014 Printer
->document_started
=False
;
2015 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
2016 /* error codes unhandled so far ... */
2021 /****************************************************************
2022 _spoolss_ClosePrinter
2023 ****************************************************************/
2025 WERROR
_spoolss_ClosePrinter(pipes_struct
*p
,
2026 struct spoolss_ClosePrinter
*r
)
2028 POLICY_HND
*handle
= r
->in
.handle
;
2030 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2032 if (Printer
&& Printer
->document_started
)
2033 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
2035 if (!close_printer_handle(p
, handle
))
2038 /* clear the returned printer handle. Observed behavior
2039 from Win2k server. Don't think this really matters.
2040 Previous code just copied the value of the closed
2043 ZERO_STRUCTP(r
->out
.handle
);
2048 /****************************************************************
2049 _spoolss_DeletePrinter
2050 ****************************************************************/
2052 WERROR
_spoolss_DeletePrinter(pipes_struct
*p
,
2053 struct spoolss_DeletePrinter
*r
)
2055 POLICY_HND
*handle
= r
->in
.handle
;
2056 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2059 if (Printer
&& Printer
->document_started
)
2060 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
2062 result
= delete_printer_handle(p
, handle
);
2064 update_c_setprinter(False
);
2069 /*******************************************************************
2070 * static function to lookup the version id corresponding to an
2071 * long architecture string
2072 ******************************************************************/
2074 static int get_version_id (char * arch
)
2077 struct table_node archi_table
[]= {
2079 {"Windows 4.0", "WIN40", 0 },
2080 {"Windows NT x86", "W32X86", 2 },
2081 {"Windows NT R4000", "W32MIPS", 2 },
2082 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2083 {"Windows NT PowerPC", "W32PPC", 2 },
2084 {"Windows IA64", "IA64", 3 },
2085 {"Windows x64", "x64", 3 },
2089 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2091 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2092 return (archi_table
[i
].version
);
2098 /****************************************************************
2099 _spoolss_DeletePrinterDriver
2100 ****************************************************************/
2102 WERROR
_spoolss_DeletePrinterDriver(pipes_struct
*p
,
2103 struct spoolss_DeletePrinterDriver
*r
)
2107 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2108 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2111 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2112 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2114 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2115 and not a printer admin, then fail */
2117 if ( (p
->server_info
->utok
.uid
!= 0)
2118 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
2119 && !token_contains_name_in_list(
2120 uidtoname(p
->server_info
->utok
.uid
), NULL
,
2121 NULL
, p
->server_info
->ptok
,
2122 lp_printer_admin(-1)) )
2124 return WERR_ACCESS_DENIED
;
2127 driver
= CONST_DISCARD(char *, r
->in
.driver
);
2128 arch
= CONST_DISCARD(char *, r
->in
.architecture
);
2130 /* check that we have a valid driver name first */
2132 if ((version
=get_version_id(arch
)) == -1)
2133 return WERR_INVALID_ENVIRONMENT
;
2136 ZERO_STRUCT(info_win2k
);
2138 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
2140 /* try for Win2k driver if "Windows NT x86" */
2142 if ( version
== 2 ) {
2144 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2145 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2149 /* otherwise it was a failure */
2151 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2157 if (printer_driver_in_use(info
.info_3
)) {
2158 status
= WERR_PRINTER_DRIVER_IN_USE
;
2164 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2166 /* if we get to here, we now have 2 driver info structures to remove */
2167 /* remove the Win2k driver first*/
2169 status_win2k
= delete_printer_driver(
2170 p
, info_win2k
.info_3
, 3, False
);
2171 free_a_printer_driver( info_win2k
, 3 );
2173 /* this should not have failed---if it did, report to client */
2174 if ( !W_ERROR_IS_OK(status_win2k
) )
2176 status
= status_win2k
;
2182 status
= delete_printer_driver(p
, info
.info_3
, version
, False
);
2184 /* if at least one of the deletes succeeded return OK */
2186 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2190 free_a_printer_driver( info
, 3 );
2195 /****************************************************************
2196 _spoolss_DeletePrinterDriverEx
2197 ****************************************************************/
2199 WERROR
_spoolss_DeletePrinterDriverEx(pipes_struct
*p
,
2200 struct spoolss_DeletePrinterDriverEx
*r
)
2204 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2205 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2207 uint32_t flags
= r
->in
.delete_flags
;
2210 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2211 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2213 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2214 and not a printer admin, then fail */
2216 if ( (p
->server_info
->utok
.uid
!= 0)
2217 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
2218 && !token_contains_name_in_list(
2219 uidtoname(p
->server_info
->utok
.uid
), NULL
, NULL
,
2220 p
->server_info
->ptok
, lp_printer_admin(-1)) )
2222 return WERR_ACCESS_DENIED
;
2225 driver
= CONST_DISCARD(char *, r
->in
.driver
);
2226 arch
= CONST_DISCARD(char *, r
->in
.architecture
);
2228 /* check that we have a valid driver name first */
2229 if ((version
=get_version_id(arch
)) == -1) {
2230 /* this is what NT returns */
2231 return WERR_INVALID_ENVIRONMENT
;
2234 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2235 version
= r
->in
.version
;
2238 ZERO_STRUCT(info_win2k
);
2240 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2242 if ( !W_ERROR_IS_OK(status
) )
2245 * if the client asked for a specific version,
2246 * or this is something other than Windows NT x86,
2250 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2253 /* try for Win2k driver if "Windows NT x86" */
2256 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2257 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2262 if ( printer_driver_in_use(info
.info_3
) ) {
2263 status
= WERR_PRINTER_DRIVER_IN_USE
;
2268 * we have a couple of cases to consider.
2269 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2270 * then the delete should fail if **any** files overlap with
2272 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2273 * non-overlapping files
2274 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2275 * is set, the do not delete any files
2276 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2279 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2281 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2283 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2284 /* no idea of the correct error here */
2285 status
= WERR_ACCESS_DENIED
;
2290 /* also check for W32X86/3 if necessary; maybe we already have? */
2292 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2293 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2296 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2297 /* no idea of the correct error here */
2298 free_a_printer_driver( info_win2k
, 3 );
2299 status
= WERR_ACCESS_DENIED
;
2303 /* if we get to here, we now have 2 driver info structures to remove */
2304 /* remove the Win2k driver first*/
2306 status_win2k
= delete_printer_driver(
2307 p
, info_win2k
.info_3
, 3, delete_files
);
2308 free_a_printer_driver( info_win2k
, 3 );
2310 /* this should not have failed---if it did, report to client */
2312 if ( !W_ERROR_IS_OK(status_win2k
) )
2317 status
= delete_printer_driver(p
, info
.info_3
, version
, delete_files
);
2319 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2322 free_a_printer_driver( info
, 3 );
2328 /****************************************************************************
2329 Internal routine for removing printerdata
2330 ***************************************************************************/
2332 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2334 return delete_printer_data( printer
->info_2
, key
, value
);
2337 /****************************************************************************
2338 Internal routine for storing printerdata
2339 ***************************************************************************/
2341 WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2342 uint32 type
, uint8
*data
, int real_len
)
2344 /* the registry objects enforce uniqueness based on value name */
2346 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2349 /********************************************************************
2350 GetPrinterData on a printer server Handle.
2351 ********************************************************************/
2353 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2355 enum winreg_Type
*type
,
2356 union spoolss_PrinterData
*data
)
2358 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2360 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2366 if (!StrCaseCmp(value
, "BeepEnabled")) {
2372 if (!StrCaseCmp(value
, "EventLog")) {
2374 /* formally was 0x1b */
2379 if (!StrCaseCmp(value
, "NetPopup")) {
2385 if (!StrCaseCmp(value
, "MajorVersion")) {
2388 /* Windows NT 4.0 seems to not allow uploading of drivers
2389 to a server that reports 0x3 as the MajorVersion.
2390 need to investigate more how Win2k gets around this .
2393 if (RA_WINNT
== get_remote_arch()) {
2402 if (!StrCaseCmp(value
, "MinorVersion")) {
2409 * uint32 size = 0x114
2411 * uint32 minor = [0|1]
2412 * uint32 build = [2195|2600]
2413 * extra unicode string = e.g. "Service Pack 3"
2415 if (!StrCaseCmp(value
, "OSVersion")) {
2417 enum ndr_err_code ndr_err
;
2418 struct spoolss_OSVersion os
;
2420 os
.major
= 5; /* Windows 2000 == 5.0 */
2422 os
.build
= 2195; /* build */
2423 os
.extra_string
= ""; /* leave extra string empty */
2425 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, NULL
, &os
,
2426 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2427 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2428 return WERR_GENERAL_FAILURE
;
2432 data
->binary
= blob
;
2438 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2441 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2442 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2447 if (!StrCaseCmp(value
, "Architecture")) {
2450 data
->string
= talloc_strdup(mem_ctx
, "Windows NT x86");
2451 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2456 if (!StrCaseCmp(value
, "DsPresent")) {
2459 /* only show the publish check box if we are a
2460 member of a AD domain */
2462 if (lp_security() == SEC_ADS
) {
2470 if (!StrCaseCmp(value
, "DNSMachineName")) {
2471 const char *hostname
= get_mydnsfullname();
2474 return WERR_BADFILE
;
2478 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2479 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2484 return WERR_BADFILE
;
2487 /****************************************************************
2488 _spoolss_GetPrinterData
2489 ****************************************************************/
2491 WERROR
_spoolss_GetPrinterData(pipes_struct
*p
,
2492 struct spoolss_GetPrinterData
*r
)
2495 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2496 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2500 * Reminder: when it's a string, the length is in BYTES
2501 * even if UNICODE is negociated.
2506 /* in case of problem, return some default values */
2511 DEBUG(4,("_spoolss_GetPrinterData\n"));
2514 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2515 OUR_HANDLE(r
->in
.handle
)));
2516 result
= WERR_BADFID
;
2520 if (Printer
->printer_type
== SPLHND_SERVER
) {
2521 result
= getprinterdata_printer_server(p
->mem_ctx
,
2526 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
2527 result
= WERR_BADFID
;
2531 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2532 if (!W_ERROR_IS_OK(result
)) {
2536 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2538 if (strequal(r
->in
.value_name
, "ChangeId")) {
2539 *r
->out
.type
= REG_DWORD
;
2540 r
->out
.data
->value
= printer
->info_2
->changeid
;
2546 v
= get_printer_data(printer
->info_2
,
2547 SPOOL_PRINTERDATA_KEY
,
2550 result
= WERR_BADFILE
;
2554 *r
->out
.type
= v
->type
;
2556 blob
= data_blob_const(v
->data_p
, v
->size
);
2558 result
= pull_spoolss_PrinterData(p
->mem_ctx
, &blob
,
2565 /* cleanup & exit */
2568 free_a_printer(&printer
, 2);
2571 if (!W_ERROR_IS_OK(result
)) {
2575 *r
->out
.needed
= ndr_size_spoolss_PrinterData(r
->out
.data
, *r
->out
.type
, NULL
, 0);
2576 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
2577 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
2579 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
2582 /*********************************************************
2583 Connect to the client machine.
2584 **********************************************************/
2586 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2587 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2590 struct cli_state
*the_cli
;
2591 struct sockaddr_storage rm_addr
;
2593 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2594 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2595 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2599 if (ismyaddr((struct sockaddr
*)&rm_addr
)) {
2600 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2604 char addr
[INET6_ADDRSTRLEN
];
2605 rm_addr
= *client_ss
;
2606 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2607 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2611 /* setup the connection */
2613 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2614 &rm_addr
, 0, "IPC$", "IPC",
2618 0, lp_client_signing(), NULL
);
2620 if ( !NT_STATUS_IS_OK( ret
) ) {
2621 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2626 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2627 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2628 cli_shutdown(the_cli
);
2633 * Ok - we have an anonymous connection to the IPC$ share.
2634 * Now start the NT Domain stuff :-).
2637 ret
= cli_rpc_pipe_open_noauth(the_cli
, &syntax_spoolss
, pp_pipe
);
2638 if (!NT_STATUS_IS_OK(ret
)) {
2639 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2640 remote_machine
, nt_errstr(ret
)));
2641 cli_shutdown(the_cli
);
2648 /***************************************************************************
2649 Connect to the client.
2650 ****************************************************************************/
2652 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2653 uint32 localprinter
, uint32 type
,
2654 POLICY_HND
*handle
, struct sockaddr_storage
*client_ss
)
2660 * If it's the first connection, contact the client
2661 * and connect to the IPC$ share anonymously
2663 if (smb_connections
==0) {
2664 fstring unix_printer
;
2666 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2668 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2671 messaging_register(smbd_messaging_context(), NULL
,
2672 MSG_PRINTER_NOTIFY2
,
2673 receive_notify2_message_list
);
2674 /* Tell the connections db we're now interested in printer
2675 * notify messages. */
2676 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2680 * Tell the specific printing tdb we want messages for this printer
2681 * by registering our PID.
2684 if (!print_notify_register_pid(snum
))
2685 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2689 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2697 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2698 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2699 win_errstr(result
)));
2701 return (W_ERROR_IS_OK(result
));
2704 /****************************************************************
2705 ****************************************************************/
2707 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2708 const struct spoolss_NotifyOption
*r
)
2710 struct spoolss_NotifyOption
*option
;
2717 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2724 if (!option
->count
) {
2728 option
->types
= talloc_zero_array(option
,
2729 struct spoolss_NotifyOptionType
, option
->count
);
2730 if (!option
->types
) {
2731 talloc_free(option
);
2735 for (i
=0; i
< option
->count
; i
++) {
2736 option
->types
[i
] = r
->types
[i
];
2738 if (option
->types
[i
].count
) {
2739 option
->types
[i
].fields
= talloc_zero_array(option
,
2740 enum spoolss_Field
, option
->types
[i
].count
);
2741 if (!option
->types
[i
].fields
) {
2742 talloc_free(option
);
2745 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2746 option
->types
[i
].fields
[k
] =
2747 r
->types
[i
].fields
[k
];
2755 /****************************************************************
2756 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2758 * before replying OK: status=0 a rpc call is made to the workstation
2759 * asking ReplyOpenPrinter
2761 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2762 * called from api_spoolss_rffpcnex
2763 ****************************************************************/
2765 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct
*p
,
2766 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2768 POLICY_HND
*handle
= r
->in
.handle
;
2770 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2771 struct sockaddr_storage client_ss
;
2773 /* store the notify value in the printer struct */
2775 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2778 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2779 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2783 Printer
->notify
.flags
= r
->in
.flags
;
2784 Printer
->notify
.options
= r
->in
.options
;
2785 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2787 TALLOC_FREE(Printer
->notify
.option
);
2788 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2790 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2792 /* Connect to the client machine and send a ReplyOpenPrinter */
2794 if ( Printer
->printer_type
== SPLHND_SERVER
)
2796 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2797 !get_printer_snum(p
, handle
, &snum
, NULL
) )
2800 if (!interpret_string_addr(&client_ss
, p
->client_address
,
2802 return WERR_SERVER_UNAVAILABLE
;
2805 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2806 Printer
->notify
.printerlocal
, 1,
2807 &Printer
->notify
.client_hnd
, &client_ss
))
2808 return WERR_SERVER_UNAVAILABLE
;
2810 Printer
->notify
.client_connected
=True
;
2815 /*******************************************************************
2816 * fill a notify_info_data with the servername
2817 ********************************************************************/
2819 void spoolss_notify_server_name(int snum
,
2820 struct spoolss_Notify
*data
,
2821 print_queue_struct
*queue
,
2822 NT_PRINTER_INFO_LEVEL
*printer
,
2823 TALLOC_CTX
*mem_ctx
)
2825 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->servername
);
2828 /*******************************************************************
2829 * fill a notify_info_data with the printername (not including the servername).
2830 ********************************************************************/
2832 void spoolss_notify_printer_name(int snum
,
2833 struct spoolss_Notify
*data
,
2834 print_queue_struct
*queue
,
2835 NT_PRINTER_INFO_LEVEL
*printer
,
2836 TALLOC_CTX
*mem_ctx
)
2838 /* the notify name should not contain the \\server\ part */
2839 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2842 p
= printer
->info_2
->printername
;
2847 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2850 /*******************************************************************
2851 * fill a notify_info_data with the servicename
2852 ********************************************************************/
2854 void spoolss_notify_share_name(int snum
,
2855 struct spoolss_Notify
*data
,
2856 print_queue_struct
*queue
,
2857 NT_PRINTER_INFO_LEVEL
*printer
,
2858 TALLOC_CTX
*mem_ctx
)
2860 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2863 /*******************************************************************
2864 * fill a notify_info_data with the port name
2865 ********************************************************************/
2867 void spoolss_notify_port_name(int snum
,
2868 struct spoolss_Notify
*data
,
2869 print_queue_struct
*queue
,
2870 NT_PRINTER_INFO_LEVEL
*printer
,
2871 TALLOC_CTX
*mem_ctx
)
2873 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->portname
);
2876 /*******************************************************************
2877 * fill a notify_info_data with the printername
2878 * but it doesn't exist, have to see what to do
2879 ********************************************************************/
2881 void spoolss_notify_driver_name(int snum
,
2882 struct spoolss_Notify
*data
,
2883 print_queue_struct
*queue
,
2884 NT_PRINTER_INFO_LEVEL
*printer
,
2885 TALLOC_CTX
*mem_ctx
)
2887 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->drivername
);
2890 /*******************************************************************
2891 * fill a notify_info_data with the comment
2892 ********************************************************************/
2894 void spoolss_notify_comment(int snum
,
2895 struct spoolss_Notify
*data
,
2896 print_queue_struct
*queue
,
2897 NT_PRINTER_INFO_LEVEL
*printer
,
2898 TALLOC_CTX
*mem_ctx
)
2902 if (*printer
->info_2
->comment
== '\0') {
2903 p
= lp_comment(snum
);
2905 p
= printer
->info_2
->comment
;
2908 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->comment
);
2911 /*******************************************************************
2912 * fill a notify_info_data with the comment
2913 * location = "Room 1, floor 2, building 3"
2914 ********************************************************************/
2916 void spoolss_notify_location(int snum
,
2917 struct spoolss_Notify
*data
,
2918 print_queue_struct
*queue
,
2919 NT_PRINTER_INFO_LEVEL
*printer
,
2920 TALLOC_CTX
*mem_ctx
)
2922 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->location
);
2925 /*******************************************************************
2926 * fill a notify_info_data with the device mode
2927 * jfm:xxxx don't to it for know but that's a real problem !!!
2928 ********************************************************************/
2930 static void spoolss_notify_devmode(int snum
,
2931 struct spoolss_Notify
*data
,
2932 print_queue_struct
*queue
,
2933 NT_PRINTER_INFO_LEVEL
*printer
,
2934 TALLOC_CTX
*mem_ctx
)
2936 /* for a dummy implementation we have to zero the fields */
2937 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2940 /*******************************************************************
2941 * fill a notify_info_data with the separator file name
2942 ********************************************************************/
2944 void spoolss_notify_sepfile(int snum
,
2945 struct spoolss_Notify
*data
,
2946 print_queue_struct
*queue
,
2947 NT_PRINTER_INFO_LEVEL
*printer
,
2948 TALLOC_CTX
*mem_ctx
)
2950 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->sepfile
);
2953 /*******************************************************************
2954 * fill a notify_info_data with the print processor
2955 * jfm:xxxx return always winprint to indicate we don't do anything to it
2956 ********************************************************************/
2958 void spoolss_notify_print_processor(int snum
,
2959 struct spoolss_Notify
*data
,
2960 print_queue_struct
*queue
,
2961 NT_PRINTER_INFO_LEVEL
*printer
,
2962 TALLOC_CTX
*mem_ctx
)
2964 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->printprocessor
);
2967 /*******************************************************************
2968 * fill a notify_info_data with the print processor options
2969 * jfm:xxxx send an empty string
2970 ********************************************************************/
2972 void spoolss_notify_parameters(int snum
,
2973 struct spoolss_Notify
*data
,
2974 print_queue_struct
*queue
,
2975 NT_PRINTER_INFO_LEVEL
*printer
,
2976 TALLOC_CTX
*mem_ctx
)
2978 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->parameters
);
2981 /*******************************************************************
2982 * fill a notify_info_data with the data type
2983 * jfm:xxxx always send RAW as data type
2984 ********************************************************************/
2986 void spoolss_notify_datatype(int snum
,
2987 struct spoolss_Notify
*data
,
2988 print_queue_struct
*queue
,
2989 NT_PRINTER_INFO_LEVEL
*printer
,
2990 TALLOC_CTX
*mem_ctx
)
2992 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->datatype
);
2995 /*******************************************************************
2996 * fill a notify_info_data with the security descriptor
2997 * jfm:xxxx send an null pointer to say no security desc
2998 * have to implement security before !
2999 ********************************************************************/
3001 static void spoolss_notify_security_desc(int snum
,
3002 struct spoolss_Notify
*data
,
3003 print_queue_struct
*queue
,
3004 NT_PRINTER_INFO_LEVEL
*printer
,
3005 TALLOC_CTX
*mem_ctx
)
3007 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
,
3008 printer
->info_2
->secdesc_buf
->sd_size
,
3009 printer
->info_2
->secdesc_buf
->sd
);
3012 /*******************************************************************
3013 * fill a notify_info_data with the attributes
3014 * jfm:xxxx a samba printer is always shared
3015 ********************************************************************/
3017 void spoolss_notify_attributes(int snum
,
3018 struct spoolss_Notify
*data
,
3019 print_queue_struct
*queue
,
3020 NT_PRINTER_INFO_LEVEL
*printer
,
3021 TALLOC_CTX
*mem_ctx
)
3023 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->attributes
);
3026 /*******************************************************************
3027 * fill a notify_info_data with the priority
3028 ********************************************************************/
3030 static void spoolss_notify_priority(int snum
,
3031 struct spoolss_Notify
*data
,
3032 print_queue_struct
*queue
,
3033 NT_PRINTER_INFO_LEVEL
*printer
,
3034 TALLOC_CTX
*mem_ctx
)
3036 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->priority
);
3039 /*******************************************************************
3040 * fill a notify_info_data with the default priority
3041 ********************************************************************/
3043 static void spoolss_notify_default_priority(int snum
,
3044 struct spoolss_Notify
*data
,
3045 print_queue_struct
*queue
,
3046 NT_PRINTER_INFO_LEVEL
*printer
,
3047 TALLOC_CTX
*mem_ctx
)
3049 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->default_priority
);
3052 /*******************************************************************
3053 * fill a notify_info_data with the start time
3054 ********************************************************************/
3056 static void spoolss_notify_start_time(int snum
,
3057 struct spoolss_Notify
*data
,
3058 print_queue_struct
*queue
,
3059 NT_PRINTER_INFO_LEVEL
*printer
,
3060 TALLOC_CTX
*mem_ctx
)
3062 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->starttime
);
3065 /*******************************************************************
3066 * fill a notify_info_data with the until time
3067 ********************************************************************/
3069 static void spoolss_notify_until_time(int snum
,
3070 struct spoolss_Notify
*data
,
3071 print_queue_struct
*queue
,
3072 NT_PRINTER_INFO_LEVEL
*printer
,
3073 TALLOC_CTX
*mem_ctx
)
3075 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->untiltime
);
3078 /*******************************************************************
3079 * fill a notify_info_data with the status
3080 ********************************************************************/
3082 static void spoolss_notify_status(int snum
,
3083 struct spoolss_Notify
*data
,
3084 print_queue_struct
*queue
,
3085 NT_PRINTER_INFO_LEVEL
*printer
,
3086 TALLOC_CTX
*mem_ctx
)
3088 print_status_struct status
;
3090 print_queue_length(snum
, &status
);
3091 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3094 /*******************************************************************
3095 * fill a notify_info_data with the number of jobs queued
3096 ********************************************************************/
3098 void spoolss_notify_cjobs(int snum
,
3099 struct spoolss_Notify
*data
,
3100 print_queue_struct
*queue
,
3101 NT_PRINTER_INFO_LEVEL
*printer
,
3102 TALLOC_CTX
*mem_ctx
)
3104 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, print_queue_length(snum
, NULL
));
3107 /*******************************************************************
3108 * fill a notify_info_data with the average ppm
3109 ********************************************************************/
3111 static void spoolss_notify_average_ppm(int snum
,
3112 struct spoolss_Notify
*data
,
3113 print_queue_struct
*queue
,
3114 NT_PRINTER_INFO_LEVEL
*printer
,
3115 TALLOC_CTX
*mem_ctx
)
3117 /* always respond 8 pages per minutes */
3118 /* a little hard ! */
3119 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->averageppm
);
3122 /*******************************************************************
3123 * fill a notify_info_data with username
3124 ********************************************************************/
3126 static void spoolss_notify_username(int snum
,
3127 struct spoolss_Notify
*data
,
3128 print_queue_struct
*queue
,
3129 NT_PRINTER_INFO_LEVEL
*printer
,
3130 TALLOC_CTX
*mem_ctx
)
3132 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3135 /*******************************************************************
3136 * fill a notify_info_data with job status
3137 ********************************************************************/
3139 static void spoolss_notify_job_status(int snum
,
3140 struct spoolss_Notify
*data
,
3141 print_queue_struct
*queue
,
3142 NT_PRINTER_INFO_LEVEL
*printer
,
3143 TALLOC_CTX
*mem_ctx
)
3145 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3148 /*******************************************************************
3149 * fill a notify_info_data with job name
3150 ********************************************************************/
3152 static void spoolss_notify_job_name(int snum
,
3153 struct spoolss_Notify
*data
,
3154 print_queue_struct
*queue
,
3155 NT_PRINTER_INFO_LEVEL
*printer
,
3156 TALLOC_CTX
*mem_ctx
)
3158 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3161 /*******************************************************************
3162 * fill a notify_info_data with job status
3163 ********************************************************************/
3165 static void spoolss_notify_job_status_string(int snum
,
3166 struct spoolss_Notify
*data
,
3167 print_queue_struct
*queue
,
3168 NT_PRINTER_INFO_LEVEL
*printer
,
3169 TALLOC_CTX
*mem_ctx
)
3172 * Now we're returning job status codes we just return a "" here. JRA.
3177 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3180 switch (queue
->status
) {
3185 p
= ""; /* NT provides the paused string */
3194 #endif /* NO LONGER NEEDED. */
3196 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3199 /*******************************************************************
3200 * fill a notify_info_data with job time
3201 ********************************************************************/
3203 static void spoolss_notify_job_time(int snum
,
3204 struct spoolss_Notify
*data
,
3205 print_queue_struct
*queue
,
3206 NT_PRINTER_INFO_LEVEL
*printer
,
3207 TALLOC_CTX
*mem_ctx
)
3209 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3212 /*******************************************************************
3213 * fill a notify_info_data with job size
3214 ********************************************************************/
3216 static void spoolss_notify_job_size(int snum
,
3217 struct spoolss_Notify
*data
,
3218 print_queue_struct
*queue
,
3219 NT_PRINTER_INFO_LEVEL
*printer
,
3220 TALLOC_CTX
*mem_ctx
)
3222 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3225 /*******************************************************************
3226 * fill a notify_info_data with page info
3227 ********************************************************************/
3228 static void spoolss_notify_total_pages(int snum
,
3229 struct spoolss_Notify
*data
,
3230 print_queue_struct
*queue
,
3231 NT_PRINTER_INFO_LEVEL
*printer
,
3232 TALLOC_CTX
*mem_ctx
)
3234 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3237 /*******************************************************************
3238 * fill a notify_info_data with pages printed info.
3239 ********************************************************************/
3240 static void spoolss_notify_pages_printed(int snum
,
3241 struct spoolss_Notify
*data
,
3242 print_queue_struct
*queue
,
3243 NT_PRINTER_INFO_LEVEL
*printer
,
3244 TALLOC_CTX
*mem_ctx
)
3246 /* Add code when back-end tracks this */
3247 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3250 /*******************************************************************
3251 Fill a notify_info_data with job position.
3252 ********************************************************************/
3254 static void spoolss_notify_job_position(int snum
,
3255 struct spoolss_Notify
*data
,
3256 print_queue_struct
*queue
,
3257 NT_PRINTER_INFO_LEVEL
*printer
,
3258 TALLOC_CTX
*mem_ctx
)
3260 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
3263 /*******************************************************************
3264 Fill a notify_info_data with submitted time.
3265 ********************************************************************/
3267 static void spoolss_notify_submitted_time(int snum
,
3268 struct spoolss_Notify
*data
,
3269 print_queue_struct
*queue
,
3270 NT_PRINTER_INFO_LEVEL
*printer
,
3271 TALLOC_CTX
*mem_ctx
)
3273 data
->data
.string
.string
= NULL
;
3274 data
->data
.string
.size
= 0;
3276 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3277 &data
->data
.string
.string
,
3278 &data
->data
.string
.size
);
3282 struct s_notify_info_data_table
3284 enum spoolss_NotifyType type
;
3285 enum spoolss_Field field
;
3287 enum spoolss_NotifyTable variable_type
;
3288 void (*fn
) (int snum
, struct spoolss_Notify
*data
,
3289 print_queue_struct
*queue
,
3290 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3293 /* A table describing the various print notification constants and
3294 whether the notification data is a pointer to a variable sized
3295 buffer, a one value uint32 or a two value uint32. */
3297 static const struct s_notify_info_data_table notify_info_data_table
[] =
3299 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3300 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3301 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3302 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3303 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3304 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3305 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3306 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3307 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3308 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3309 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3310 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3311 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3312 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3313 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3314 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3315 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3316 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3317 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3318 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3319 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3320 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3321 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3322 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3323 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3324 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3325 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3326 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3327 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3328 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3329 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3330 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3331 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3332 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3333 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3334 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3335 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3336 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3337 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3338 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3339 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3340 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3341 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3342 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3343 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3344 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3345 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3346 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3347 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3350 /*******************************************************************
3351 Return the variable_type of info_data structure.
3352 ********************************************************************/
3354 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3355 enum spoolss_Field field
)
3359 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3360 if ( (notify_info_data_table
[i
].type
== type
) &&
3361 (notify_info_data_table
[i
].field
== field
) ) {
3362 return notify_info_data_table
[i
].variable_type
;
3366 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3371 /****************************************************************************
3372 ****************************************************************************/
3374 static bool search_notify(enum spoolss_NotifyType type
,
3375 enum spoolss_Field field
,
3380 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3381 if (notify_info_data_table
[i
].type
== type
&&
3382 notify_info_data_table
[i
].field
== field
&&
3383 notify_info_data_table
[i
].fn
!= NULL
) {
3392 /****************************************************************************
3393 ****************************************************************************/
3395 void construct_info_data(struct spoolss_Notify
*info_data
,
3396 enum spoolss_NotifyType type
,
3397 enum spoolss_Field field
,
3400 info_data
->type
= type
;
3401 info_data
->field
= field
;
3402 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3403 info_data
->job_id
= id
;
3406 /*******************************************************************
3408 * fill a notify_info struct with info asked
3410 ********************************************************************/
3412 static bool construct_notify_printer_info(Printer_entry
*print_hnd
,
3413 struct spoolss_NotifyInfo
*info
,
3415 const struct spoolss_NotifyOptionType
*option_type
,
3417 TALLOC_CTX
*mem_ctx
)
3420 enum spoolss_NotifyType type
;
3421 enum spoolss_Field field
;
3423 struct spoolss_Notify
*current_data
;
3424 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3425 print_queue_struct
*queue
=NULL
;
3427 type
= option_type
->type
;
3429 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3430 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3431 option_type
->count
, lp_servicename(snum
)));
3433 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3436 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3437 field
= option_type
->fields
[field_num
];
3439 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3441 if (!search_notify(type
, field
, &j
) )
3444 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3445 struct spoolss_Notify
,
3447 if (info
->notifies
== NULL
) {
3448 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3449 free_a_printer(&printer
, 2);
3453 current_data
= &info
->notifies
[info
->count
];
3455 construct_info_data(current_data
, type
, field
, id
);
3457 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3458 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3460 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3466 free_a_printer(&printer
, 2);
3470 /*******************************************************************
3472 * fill a notify_info struct with info asked
3474 ********************************************************************/
3476 static bool construct_notify_jobs_info(print_queue_struct
*queue
,
3477 struct spoolss_NotifyInfo
*info
,
3478 NT_PRINTER_INFO_LEVEL
*printer
,
3480 const struct spoolss_NotifyOptionType
*option_type
,
3482 TALLOC_CTX
*mem_ctx
)
3485 enum spoolss_NotifyType type
;
3486 enum spoolss_Field field
;
3487 struct spoolss_Notify
*current_data
;
3489 DEBUG(4,("construct_notify_jobs_info\n"));
3491 type
= option_type
->type
;
3493 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3494 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3495 option_type
->count
));
3497 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3498 field
= option_type
->fields
[field_num
];
3500 if (!search_notify(type
, field
, &j
) )
3503 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3504 struct spoolss_Notify
,
3506 if (info
->notifies
== NULL
) {
3507 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3511 current_data
=&(info
->notifies
[info
->count
]);
3513 construct_info_data(current_data
, type
, field
, id
);
3514 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3523 * JFM: The enumeration is not that simple, it's even non obvious.
3525 * let's take an example: I want to monitor the PRINTER SERVER for
3526 * the printer's name and the number of jobs currently queued.
3527 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3528 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3530 * I have 3 printers on the back of my server.
3532 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3535 * 1 printer 1 name 1
3536 * 2 printer 1 cjob 1
3537 * 3 printer 2 name 2
3538 * 4 printer 2 cjob 2
3539 * 5 printer 3 name 3
3540 * 6 printer 3 name 3
3542 * that's the print server case, the printer case is even worse.
3545 /*******************************************************************
3547 * enumerate all printers on the printserver
3548 * fill a notify_info struct with info asked
3550 ********************************************************************/
3552 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3553 struct spoolss_NotifyInfo
*info
,
3554 TALLOC_CTX
*mem_ctx
)
3557 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3558 int n_services
=lp_numservices();
3560 struct spoolss_NotifyOption
*option
;
3561 struct spoolss_NotifyOptionType option_type
;
3563 DEBUG(4,("printserver_notify_info\n"));
3568 option
= Printer
->notify
.option
;
3571 info
->notifies
= NULL
;
3574 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3575 sending a ffpcn() request first */
3580 for (i
=0; i
<option
->count
; i
++) {
3581 option_type
= option
->types
[i
];
3583 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3586 for (snum
=0; snum
<n_services
; snum
++)
3588 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3589 construct_notify_printer_info ( Printer
, info
, snum
, &option_type
, snum
, mem_ctx
);
3595 * Debugging information, don't delete.
3598 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3599 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3600 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3602 for (i
=0; i
<info
->count
; i
++) {
3603 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3604 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3605 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3612 /*******************************************************************
3614 * fill a notify_info struct with info asked
3616 ********************************************************************/
3618 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, struct spoolss_NotifyInfo
*info
,
3619 TALLOC_CTX
*mem_ctx
)
3622 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3625 struct spoolss_NotifyOption
*option
;
3626 struct spoolss_NotifyOptionType option_type
;
3628 print_queue_struct
*queue
=NULL
;
3629 print_status_struct status
;
3631 DEBUG(4,("printer_notify_info\n"));
3636 option
= Printer
->notify
.option
;
3640 info
->notifies
= NULL
;
3643 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3644 sending a ffpcn() request first */
3649 get_printer_snum(p
, hnd
, &snum
, NULL
);
3651 for (i
=0; i
<option
->count
; i
++) {
3652 option_type
= option
->types
[i
];
3654 switch (option_type
.type
) {
3655 case PRINTER_NOTIFY_TYPE
:
3656 if(construct_notify_printer_info(Printer
, info
, snum
,
3662 case JOB_NOTIFY_TYPE
: {
3663 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3665 count
= print_queue_status(snum
, &queue
, &status
);
3667 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3670 for (j
=0; j
<count
; j
++) {
3671 construct_notify_jobs_info(&queue
[j
], info
,
3678 free_a_printer(&printer
, 2);
3688 * Debugging information, don't delete.
3691 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3692 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3693 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3695 for (i=0; i<info->count; i++) {
3696 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3697 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3698 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3704 /****************************************************************
3705 _spoolss_RouterRefreshPrinterChangeNotify
3706 ****************************************************************/
3708 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(pipes_struct
*p
,
3709 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3711 POLICY_HND
*handle
= r
->in
.handle
;
3712 struct spoolss_NotifyInfo
*info
;
3714 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3715 WERROR result
= WERR_BADFID
;
3717 /* we always have a spoolss_NotifyInfo struct */
3718 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3720 result
= WERR_NOMEM
;
3724 *r
->out
.info
= info
;
3727 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3728 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
3732 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3735 * We are now using the change value, and
3736 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3737 * I don't have a global notification system, I'm sending back all the
3738 * informations even when _NOTHING_ has changed.
3741 /* We need to keep track of the change value to send back in
3742 RRPCN replies otherwise our updates are ignored. */
3744 Printer
->notify
.fnpcn
= True
;
3746 if (Printer
->notify
.client_connected
) {
3747 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3748 "Saving change value in request [%x]\n",
3750 Printer
->notify
.change
= r
->in
.change_low
;
3753 /* just ignore the spoolss_NotifyOption */
3755 switch (Printer
->printer_type
) {
3757 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3760 case SPLHND_PRINTER
:
3761 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3765 Printer
->notify
.fnpcn
= False
;
3771 /********************************************************************
3772 * construct_printer_info_0
3773 * fill a printer_info_0 struct
3774 ********************************************************************/
3776 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3777 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3778 struct spoolss_PrinterInfo0
*r
,
3782 counter_printer_0
*session_counter
;
3784 print_status_struct status
;
3786 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3787 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3789 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3790 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3792 count
= print_queue_length(snum
, &status
);
3794 /* check if we already have a counter for this printer */
3795 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3796 if (session_counter
->snum
== snum
)
3800 /* it's the first time, add it to the list */
3801 if (session_counter
== NULL
) {
3802 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3803 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3804 ZERO_STRUCTP(session_counter
);
3805 session_counter
->snum
= snum
;
3806 session_counter
->counter
= 0;
3807 DLIST_ADD(counter_list
, session_counter
);
3811 session_counter
->counter
++;
3817 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3819 init_systemtime(&r
->time
, gmtime(&setuptime
));
3822 * the global_counter should be stored in a TDB as it's common to all the clients
3823 * and should be zeroed on samba startup
3825 r
->global_counter
= session_counter
->counter
;
3827 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3828 r
->version
= 0x0005; /* NT 5 */
3829 r
->free_build
= 0x0893; /* build 2195 */
3831 r
->max_spooling
= 0;
3832 r
->session_counter
= session_counter
->counter
;
3833 r
->num_error_out_of_paper
= 0x0;
3834 r
->num_error_not_ready
= 0x0; /* number of print failure */
3836 r
->number_of_processors
= 0x1;
3837 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3838 r
->high_part_total_bytes
= 0x0;
3839 r
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3840 r
->last_error
= WERR_OK
;
3841 r
->status
= nt_printq_status(status
.status
);
3842 r
->enumerate_network_printers
= 0x0;
3843 r
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3844 r
->processor_architecture
= 0x0;
3845 r
->processor_level
= 0x6; /* 6 ???*/
3853 /****************************************************************************
3854 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3855 should be valid upon entry
3856 ****************************************************************************/
3858 static WERROR
convert_nt_devicemode(TALLOC_CTX
*mem_ctx
,
3859 struct spoolss_DeviceMode
*r
,
3860 const NT_DEVICEMODE
*ntdevmode
)
3862 if (!r
|| !ntdevmode
) {
3863 return WERR_INVALID_PARAM
;
3866 r
->devicename
= talloc_strdup(mem_ctx
, ntdevmode
->devicename
);
3867 W_ERROR_HAVE_NO_MEMORY(r
->devicename
);
3869 r
->specversion
= ntdevmode
->specversion
;
3870 r
->driverversion
= ntdevmode
->driverversion
;
3871 r
->size
= ntdevmode
->size
;
3872 r
->__driverextra_length
= ntdevmode
->driverextra
;
3873 r
->fields
= ntdevmode
->fields
;
3875 r
->orientation
= ntdevmode
->orientation
;
3876 r
->papersize
= ntdevmode
->papersize
;
3877 r
->paperlength
= ntdevmode
->paperlength
;
3878 r
->paperwidth
= ntdevmode
->paperwidth
;
3879 r
->scale
= ntdevmode
->scale
;
3880 r
->copies
= ntdevmode
->copies
;
3881 r
->defaultsource
= ntdevmode
->defaultsource
;
3882 r
->printquality
= ntdevmode
->printquality
;
3883 r
->color
= ntdevmode
->color
;
3884 r
->duplex
= ntdevmode
->duplex
;
3885 r
->yresolution
= ntdevmode
->yresolution
;
3886 r
->ttoption
= ntdevmode
->ttoption
;
3887 r
->collate
= ntdevmode
->collate
;
3889 r
->formname
= talloc_strdup(mem_ctx
, ntdevmode
->formname
);
3890 W_ERROR_HAVE_NO_MEMORY(r
->formname
);
3892 /* all 0 below are values that have not been set in the old parsing/copy
3893 * function, maybe they should... - gd */
3899 r
->displayflags
= 0;
3900 r
->displayfrequency
= 0;
3901 r
->icmmethod
= ntdevmode
->icmmethod
;
3902 r
->icmintent
= ntdevmode
->icmintent
;
3903 r
->mediatype
= ntdevmode
->mediatype
;
3904 r
->dithertype
= ntdevmode
->dithertype
;
3907 r
->panningwidth
= 0;
3908 r
->panningheight
= 0;
3910 if (ntdevmode
->nt_dev_private
!= NULL
) {
3911 r
->driverextra_data
= data_blob_talloc(mem_ctx
,
3912 ntdevmode
->nt_dev_private
,
3913 ntdevmode
->driverextra
);
3914 W_ERROR_HAVE_NO_MEMORY(r
->driverextra_data
.data
);
3921 /****************************************************************************
3922 Create a spoolss_DeviceMode struct. Returns talloced memory.
3923 ****************************************************************************/
3925 struct spoolss_DeviceMode
*construct_dev_mode(TALLOC_CTX
*mem_ctx
,
3926 const char *servicename
)
3929 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3930 struct spoolss_DeviceMode
*devmode
= NULL
;
3932 DEBUG(7,("construct_dev_mode\n"));
3934 DEBUGADD(8,("getting printer characteristics\n"));
3936 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
3939 if (!printer
->info_2
->devmode
) {
3940 DEBUG(5, ("BONG! There was no device mode!\n"));
3944 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
3946 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3950 DEBUGADD(8,("loading DEVICEMODE\n"));
3952 result
= convert_nt_devicemode(mem_ctx
, devmode
, printer
->info_2
->devmode
);
3953 if (!W_ERROR_IS_OK(result
)) {
3954 TALLOC_FREE(devmode
);
3958 free_a_printer(&printer
,2);
3963 /********************************************************************
3964 * construct_printer_info3
3965 * fill a spoolss_PrinterInfo3 struct
3966 ********************************************************************/
3968 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3969 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3970 struct spoolss_PrinterInfo3
*r
,
3973 /* These are the components of the SD we are returning. */
3975 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3976 /* don't use talloc_steal() here unless you do a deep steal of all
3977 the SEC_DESC members */
3979 r
->secdesc
= dup_sec_desc(mem_ctx
,
3980 ntprinter
->info_2
->secdesc_buf
->sd
);
3981 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3987 /********************************************************************
3988 * construct_printer_info4
3989 * fill a spoolss_PrinterInfo4 struct
3990 ********************************************************************/
3992 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
3993 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3994 struct spoolss_PrinterInfo4
*r
,
3997 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3998 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3999 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
4000 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4002 r
->attributes
= ntprinter
->info_2
->attributes
;
4007 /********************************************************************
4008 * construct_printer_info5
4009 * fill a spoolss_PrinterInfo5 struct
4010 ********************************************************************/
4012 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
4013 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4014 struct spoolss_PrinterInfo5
*r
,
4017 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4018 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
4019 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
4020 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4022 r
->attributes
= ntprinter
->info_2
->attributes
;
4024 /* these two are not used by NT+ according to MSDN */
4026 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4027 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4032 /********************************************************************
4033 * construct_printer_info_6
4034 * fill a spoolss_PrinterInfo6 struct
4035 ********************************************************************/
4037 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
4038 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4039 struct spoolss_PrinterInfo6
*r
,
4043 print_status_struct status
;
4045 count
= print_queue_length(snum
, &status
);
4047 r
->status
= nt_printq_status(status
.status
);
4052 /********************************************************************
4053 * construct_printer_info7
4054 * fill a spoolss_PrinterInfo7 struct
4055 ********************************************************************/
4057 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4058 Printer_entry
*print_hnd
,
4059 struct spoolss_PrinterInfo7
*r
,
4064 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4065 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4066 r
->action
= DSPRINT_PUBLISH
;
4068 r
->guid
= talloc_strdup(mem_ctx
, "");
4069 r
->action
= DSPRINT_UNPUBLISH
;
4071 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
4076 /********************************************************************
4077 * construct_printer_info1
4078 * fill a spoolss_PrinterInfo1 struct
4079 ********************************************************************/
4081 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
4082 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4084 struct spoolss_PrinterInfo1
*r
,
4087 char *chaine
= NULL
;
4090 if (*ntprinter
->info_2
->comment
== '\0') {
4091 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4092 chaine
= talloc_asprintf(mem_ctx
,
4093 "%s,%s,%s", ntprinter
->info_2
->printername
,
4094 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4096 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
); /* saved comment */
4097 chaine
= talloc_asprintf(mem_ctx
,
4098 "%s,%s,%s", ntprinter
->info_2
->printername
,
4099 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4101 W_ERROR_HAVE_NO_MEMORY(chaine
);
4102 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4104 r
->description
= talloc_strdup(mem_ctx
, chaine
);
4105 W_ERROR_HAVE_NO_MEMORY(r
->description
);
4106 r
->name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4107 W_ERROR_HAVE_NO_MEMORY(r
->name
);
4112 /********************************************************************
4113 * construct_printer_info2
4114 * fill a spoolss_PrinterInfo2 struct
4115 ********************************************************************/
4117 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
4118 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4119 struct spoolss_PrinterInfo2
*r
,
4124 print_status_struct status
;
4126 count
= print_queue_length(snum
, &status
);
4128 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
4129 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4130 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4131 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
4132 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
4133 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
4134 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
4135 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4136 r
->drivername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
4137 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
4139 if (*ntprinter
->info_2
->comment
== '\0') {
4140 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4142 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
);
4144 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4146 r
->location
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->location
);
4147 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4148 r
->sepfile
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->sepfile
);
4149 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4150 r
->printprocessor
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printprocessor
);
4151 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4152 r
->datatype
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->datatype
);
4153 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4154 r
->parameters
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->parameters
);
4155 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4157 r
->attributes
= ntprinter
->info_2
->attributes
;
4159 r
->priority
= ntprinter
->info_2
->priority
;
4160 r
->defaultpriority
= ntprinter
->info_2
->default_priority
;
4161 r
->starttime
= ntprinter
->info_2
->starttime
;
4162 r
->untiltime
= ntprinter
->info_2
->untiltime
;
4163 r
->status
= nt_printq_status(status
.status
);
4165 r
->averageppm
= ntprinter
->info_2
->averageppm
;
4167 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
4169 DEBUG(8,("Returning NULL Devicemode!\n"));
4174 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
4175 /* don't use talloc_steal() here unless you do a deep steal of all
4176 the SEC_DESC members */
4178 r
->secdesc
= dup_sec_desc(mem_ctx
, ntprinter
->info_2
->secdesc_buf
->sd
);
4184 /********************************************************************
4185 ********************************************************************/
4187 static bool snum_is_shared_printer(int snum
)
4189 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
4192 /********************************************************************
4193 Spoolss_enumprinters.
4194 ********************************************************************/
4196 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4198 union spoolss_PrinterInfo
**info_p
,
4202 int n_services
= lp_numservices();
4203 union spoolss_PrinterInfo
*info
= NULL
;
4204 WERROR result
= WERR_OK
;
4206 DEBUG(4,("enum_all_printers_info_1\n"));
4210 for (snum
=0; snum
<n_services
; snum
++) {
4212 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4213 struct spoolss_PrinterInfo1 info1
;
4215 if (!snum_is_shared_printer(snum
)) {
4219 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4221 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_const_servicename(snum
));
4222 if (!W_ERROR_IS_OK(result
)) {
4226 result
= construct_printer_info1(info
, ntprinter
, flags
, &info1
, snum
);
4227 free_a_printer(&ntprinter
,2);
4228 if (!W_ERROR_IS_OK(result
)) {
4232 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4233 union spoolss_PrinterInfo
,
4236 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4237 result
= WERR_NOMEM
;
4241 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count
));
4243 info
[*count
].info1
= info1
;
4248 if (!W_ERROR_IS_OK(result
)) {
4259 /********************************************************************
4260 enum_all_printers_info_1_local.
4261 *********************************************************************/
4263 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4264 union spoolss_PrinterInfo
**info
,
4267 DEBUG(4,("enum_all_printers_info_1_local\n"));
4269 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4272 /********************************************************************
4273 enum_all_printers_info_1_name.
4274 *********************************************************************/
4276 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4278 union spoolss_PrinterInfo
**info
,
4281 const char *s
= name
;
4283 DEBUG(4,("enum_all_printers_info_1_name\n"));
4285 if ((name
[0] == '\\') && (name
[1] == '\\')) {
4289 if (!is_myname_or_ipaddr(s
)) {
4290 return WERR_INVALID_NAME
;
4293 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4296 /********************************************************************
4297 enum_all_printers_info_1_network.
4298 *********************************************************************/
4300 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4302 union spoolss_PrinterInfo
**info
,
4305 const char *s
= name
;
4307 DEBUG(4,("enum_all_printers_info_1_network\n"));
4309 /* If we respond to a enum_printers level 1 on our name with flags
4310 set to PRINTER_ENUM_REMOTE with a list of printers then these
4311 printers incorrectly appear in the APW browse list.
4312 Specifically the printers for the server appear at the workgroup
4313 level where all the other servers in the domain are
4314 listed. Windows responds to this call with a
4315 WERR_CAN_NOT_COMPLETE so we should do the same. */
4317 if (name
[0] == '\\' && name
[1] == '\\') {
4321 if (is_myname_or_ipaddr(s
)) {
4322 return WERR_CAN_NOT_COMPLETE
;
4325 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_NAME
, info
, count
);
4328 /********************************************************************
4329 * api_spoolss_enumprinters
4331 * called from api_spoolss_enumprinters (see this to understand)
4332 ********************************************************************/
4334 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4335 union spoolss_PrinterInfo
**info_p
,
4339 int n_services
= lp_numservices();
4340 union spoolss_PrinterInfo
*info
= NULL
;
4341 WERROR result
= WERR_OK
;
4345 for (snum
=0; snum
<n_services
; snum
++) {
4347 struct spoolss_PrinterInfo2 info2
;
4348 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4350 if (!snum_is_shared_printer(snum
)) {
4354 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4356 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_const_servicename(snum
));
4357 if (!W_ERROR_IS_OK(result
)) {
4361 result
= construct_printer_info2(info
, ntprinter
, &info2
, snum
);
4362 free_a_printer(&ntprinter
, 2);
4363 if (!W_ERROR_IS_OK(result
)) {
4367 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4368 union spoolss_PrinterInfo
,
4371 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4372 result
= WERR_NOMEM
;
4376 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count
+ 1));
4378 info
[*count
].info2
= info2
;
4384 if (!W_ERROR_IS_OK(result
)) {
4395 /********************************************************************
4396 * handle enumeration of printers at level 1
4397 ********************************************************************/
4399 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4402 union spoolss_PrinterInfo
**info
,
4405 /* Not all the flags are equals */
4407 if (flags
& PRINTER_ENUM_LOCAL
) {
4408 return enum_all_printers_info_1_local(mem_ctx
, info
, count
);
4411 if (flags
& PRINTER_ENUM_NAME
) {
4412 return enum_all_printers_info_1_name(mem_ctx
, name
, info
, count
);
4415 if (flags
& PRINTER_ENUM_NETWORK
) {
4416 return enum_all_printers_info_1_network(mem_ctx
, name
, info
, count
);
4419 return WERR_OK
; /* NT4sp5 does that */
4422 /********************************************************************
4423 * handle enumeration of printers at level 2
4424 ********************************************************************/
4426 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4428 const char *servername
,
4429 union spoolss_PrinterInfo
**info
,
4432 if (flags
& PRINTER_ENUM_LOCAL
) {
4433 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4436 if (flags
& PRINTER_ENUM_NAME
) {
4437 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4438 return WERR_INVALID_NAME
;
4441 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4444 if (flags
& PRINTER_ENUM_REMOTE
) {
4445 return WERR_UNKNOWN_LEVEL
;
4451 /********************************************************************
4452 * handle enumeration of printers at level 5
4453 ********************************************************************/
4455 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4457 const char *servername
,
4458 union spoolss_PrinterInfo
**info
,
4461 /* return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4465 /****************************************************************
4466 _spoolss_EnumPrinters
4467 ****************************************************************/
4469 WERROR
_spoolss_EnumPrinters(pipes_struct
*p
,
4470 struct spoolss_EnumPrinters
*r
)
4475 /* that's an [in out] buffer */
4477 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4478 return WERR_INVALID_PARAM
;
4481 DEBUG(4,("_spoolss_EnumPrinters\n"));
4485 *r
->out
.info
= NULL
;
4489 * flags==PRINTER_ENUM_NAME
4490 * if name=="" then enumerates all printers
4491 * if name!="" then enumerate the printer
4492 * flags==PRINTER_ENUM_REMOTE
4493 * name is NULL, enumerate printers
4494 * Level 2: name!="" enumerates printers, name can't be NULL
4495 * Level 3: doesn't exist
4496 * Level 4: does a local registry lookup
4497 * Level 5: same as Level 2
4500 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4501 W_ERROR_HAVE_NO_MEMORY(name
);
4503 switch (r
->in
.level
) {
4505 result
= enumprinters_level1(p
->mem_ctx
, r
->in
.flags
, name
,
4506 r
->out
.info
, r
->out
.count
);
4509 result
= enumprinters_level2(p
->mem_ctx
, r
->in
.flags
, name
,
4510 r
->out
.info
, r
->out
.count
);
4513 result
= enumprinters_level5(p
->mem_ctx
, r
->in
.flags
, name
,
4514 r
->out
.info
, r
->out
.count
);
4518 result
= WERR_OK
; /* ??? */
4521 return WERR_UNKNOWN_LEVEL
;
4524 if (!W_ERROR_IS_OK(result
)) {
4528 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4529 spoolss_EnumPrinters
, NULL
,
4530 *r
->out
.info
, r
->in
.level
,
4532 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4533 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4535 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4538 /****************************************************************
4540 ****************************************************************/
4542 WERROR
_spoolss_GetPrinter(pipes_struct
*p
,
4543 struct spoolss_GetPrinter
*r
)
4545 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4546 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4547 WERROR result
= WERR_OK
;
4551 /* that's an [in out] buffer */
4553 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4554 return WERR_INVALID_PARAM
;
4559 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4563 result
= get_a_printer(Printer
, &ntprinter
, 2,
4564 lp_const_servicename(snum
));
4565 if (!W_ERROR_IS_OK(result
)) {
4569 switch (r
->in
.level
) {
4571 result
= construct_printer_info0(p
->mem_ctx
, ntprinter
,
4572 &r
->out
.info
->info0
, snum
);
4575 result
= construct_printer_info1(p
->mem_ctx
, ntprinter
,
4577 &r
->out
.info
->info1
, snum
);
4580 result
= construct_printer_info2(p
->mem_ctx
, ntprinter
,
4581 &r
->out
.info
->info2
, snum
);
4584 result
= construct_printer_info3(p
->mem_ctx
, ntprinter
,
4585 &r
->out
.info
->info3
, snum
);
4588 result
= construct_printer_info4(p
->mem_ctx
, ntprinter
,
4589 &r
->out
.info
->info4
, snum
);
4592 result
= construct_printer_info5(p
->mem_ctx
, ntprinter
,
4593 &r
->out
.info
->info5
, snum
);
4596 result
= construct_printer_info6(p
->mem_ctx
, ntprinter
,
4597 &r
->out
.info
->info6
, snum
);
4600 result
= construct_printer_info7(p
->mem_ctx
, Printer
,
4601 &r
->out
.info
->info7
, snum
);
4604 result
= WERR_UNKNOWN_LEVEL
;
4608 free_a_printer(&ntprinter
, 2);
4610 if (!W_ERROR_IS_OK(result
)) {
4611 TALLOC_FREE(r
->out
.info
);
4615 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
, NULL
,
4616 r
->out
.info
, r
->in
.level
);
4617 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4619 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4622 /********************************************************************
4623 ********************************************************************/
4625 static const char **string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4626 fstring
*fstring_array
,
4627 const char *cservername
)
4629 int i
, num_strings
= 0;
4630 const char **array
= NULL
;
4632 for (i
=0; fstring_array
&& fstring_array
[i
][0] != '\0'; i
++) {
4634 const char *str
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4635 cservername
, fstring_array
[i
]);
4642 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4649 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4650 &array
, &num_strings
);
4656 /********************************************************************
4657 * fill a spoolss_DriverInfo1 struct
4658 ********************************************************************/
4660 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4661 struct spoolss_DriverInfo1
*r
,
4662 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4663 const char *servername
,
4664 const char *architecture
)
4666 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4667 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4672 /********************************************************************
4673 * fill a spoolss_DriverInfo2 struct
4674 ********************************************************************/
4676 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4677 struct spoolss_DriverInfo2
*r
,
4678 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4679 const char *servername
)
4682 const char *cservername
= canon_servername(servername
);
4684 r
->version
= driver
->info_3
->cversion
;
4686 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4687 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4688 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4689 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4691 if (strlen(driver
->info_3
->driverpath
)) {
4692 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4693 cservername
, driver
->info_3
->driverpath
);
4695 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4697 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4699 if (strlen(driver
->info_3
->datafile
)) {
4700 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4701 cservername
, driver
->info_3
->datafile
);
4703 r
->data_file
= talloc_strdup(mem_ctx
, "");
4705 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4707 if (strlen(driver
->info_3
->configfile
)) {
4708 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4709 cservername
, driver
->info_3
->configfile
);
4711 r
->config_file
= talloc_strdup(mem_ctx
, "");
4713 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4718 /********************************************************************
4719 * fill a spoolss_DriverInfo3 struct
4720 ********************************************************************/
4722 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4723 struct spoolss_DriverInfo3
*r
,
4724 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4725 const char *servername
)
4727 const char *cservername
= canon_servername(servername
);
4729 r
->version
= driver
->info_3
->cversion
;
4731 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4732 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4733 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4734 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4736 if (strlen(driver
->info_3
->driverpath
)) {
4737 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4738 cservername
, driver
->info_3
->driverpath
);
4740 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4742 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4744 if (strlen(driver
->info_3
->datafile
)) {
4745 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4746 cservername
, driver
->info_3
->datafile
);
4748 r
->data_file
= talloc_strdup(mem_ctx
, "");
4750 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4752 if (strlen(driver
->info_3
->configfile
)) {
4753 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4754 cservername
, driver
->info_3
->configfile
);
4756 r
->config_file
= talloc_strdup(mem_ctx
, "");
4758 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4760 if (strlen(driver
->info_3
->helpfile
)) {
4761 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4762 cservername
, driver
->info_3
->helpfile
);
4764 r
->help_file
= talloc_strdup(mem_ctx
, "");
4766 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4768 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
4769 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
4770 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
4771 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
4773 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4774 driver
->info_3
->dependentfiles
,
4779 /********************************************************************
4780 * fill a spoolss_DriverInfo6 struct
4781 ********************************************************************/
4783 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4784 struct spoolss_DriverInfo6
*r
,
4785 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4786 const char *servername
)
4788 const char *cservername
= canon_servername(servername
);
4790 r
->version
= driver
->info_3
->cversion
;
4792 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4793 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4794 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4795 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4797 if (strlen(driver
->info_3
->driverpath
)) {
4798 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4799 cservername
, driver
->info_3
->driverpath
);
4801 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4803 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4805 if (strlen(driver
->info_3
->datafile
)) {
4806 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4807 cservername
, driver
->info_3
->datafile
);
4809 r
->data_file
= talloc_strdup(mem_ctx
, "");
4811 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4813 if (strlen(driver
->info_3
->configfile
)) {
4814 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4815 cservername
, driver
->info_3
->configfile
);
4817 r
->config_file
= talloc_strdup(mem_ctx
, "");
4819 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4821 if (strlen(driver
->info_3
->helpfile
)) {
4822 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4823 cservername
, driver
->info_3
->helpfile
);
4825 r
->help_file
= talloc_strdup(mem_ctx
, "");
4827 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4829 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
4830 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
4831 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
4832 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
4834 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4835 driver
->info_3
->dependentfiles
,
4837 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4842 r
->driver_version
= 0;
4844 r
->manufacturer_name
= talloc_strdup(mem_ctx
, "");
4845 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_name
);
4846 r
->manufacturer_url
= talloc_strdup(mem_ctx
, "");
4847 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_url
);
4848 r
->hardware_id
= talloc_strdup(mem_ctx
, "");
4849 W_ERROR_HAVE_NO_MEMORY(r
->hardware_id
);
4850 r
->provider
= talloc_strdup(mem_ctx
, "");
4851 W_ERROR_HAVE_NO_MEMORY(r
->provider
);
4856 /********************************************************************
4857 * construct_printer_driver_info_1
4858 ********************************************************************/
4860 static WERROR
construct_printer_driver_info_1(TALLOC_CTX
*mem_ctx
,
4861 struct spoolss_DriverInfo1
*r
,
4863 const char *servername
,
4864 const char *architecture
,
4867 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4868 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4871 ZERO_STRUCT(driver
);
4873 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4874 return WERR_INVALID_PRINTER_NAME
;
4876 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
4877 free_a_printer(&printer
, 2);
4878 return WERR_UNKNOWN_PRINTER_DRIVER
;
4881 result
= fill_printer_driver_info1(mem_ctx
, r
, &driver
, servername
, architecture
);
4883 free_a_printer(&printer
,2);
4888 /********************************************************************
4889 * construct_printer_driver_info_2
4890 * fill a printer_info_2 struct
4891 ********************************************************************/
4893 static WERROR
construct_printer_driver_info_2(TALLOC_CTX
*mem_ctx
,
4894 struct spoolss_DriverInfo2
*r
,
4896 const char *servername
,
4897 const char *architecture
,
4900 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4901 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4904 ZERO_STRUCT(printer
);
4905 ZERO_STRUCT(driver
);
4907 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4908 return WERR_INVALID_PRINTER_NAME
;
4910 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
4911 free_a_printer(&printer
, 2);
4912 return WERR_UNKNOWN_PRINTER_DRIVER
;
4915 result
= fill_printer_driver_info2(mem_ctx
, r
, &driver
, servername
);
4917 free_a_printer(&printer
,2);
4922 /********************************************************************
4923 * construct_printer_info_3
4924 * fill a printer_info_3 struct
4925 ********************************************************************/
4927 static WERROR
construct_printer_driver_info_3(TALLOC_CTX
*mem_ctx
,
4928 struct spoolss_DriverInfo3
*r
,
4930 const char *servername
,
4931 const char *architecture
,
4934 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4935 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4937 ZERO_STRUCT(driver
);
4939 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
4940 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
4941 if (!W_ERROR_IS_OK(status
))
4942 return WERR_INVALID_PRINTER_NAME
;
4944 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4945 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
4950 * I put this code in during testing. Helpful when commenting out the
4951 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4952 * as win2k always queries the driver using an infor level of 6.
4953 * I've left it in (but ifdef'd out) because I'll probably
4954 * use it in experimentation again in the future. --jerry 22/01/2002
4957 if (!W_ERROR_IS_OK(status
)) {
4959 * Is this a W2k client ?
4962 /* Yes - try again with a WinNT driver. */
4964 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4965 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
4969 if (!W_ERROR_IS_OK(status
)) {
4970 free_a_printer(&printer
,2);
4971 return WERR_UNKNOWN_PRINTER_DRIVER
;
4979 status
= fill_printer_driver_info3(mem_ctx
, r
, &driver
, servername
);
4981 free_a_printer(&printer
,2);
4986 /********************************************************************
4987 * construct_printer_info_6
4988 * fill a printer_info_6 struct
4989 ********************************************************************/
4991 static WERROR
construct_printer_driver_info_6(TALLOC_CTX
*mem_ctx
,
4992 struct spoolss_DriverInfo6
*r
,
4994 const char *servername
,
4995 const char *architecture
,
4998 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4999 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5002 ZERO_STRUCT(driver
);
5004 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5006 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5008 if (!W_ERROR_IS_OK(status
))
5009 return WERR_INVALID_PRINTER_NAME
;
5011 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5013 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5015 if (!W_ERROR_IS_OK(status
))
5018 * Is this a W2k client ?
5022 free_a_printer(&printer
,2);
5023 return WERR_UNKNOWN_PRINTER_DRIVER
;
5026 /* Yes - try again with a WinNT driver. */
5028 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5029 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5030 if (!W_ERROR_IS_OK(status
)) {
5031 free_a_printer(&printer
,2);
5032 return WERR_UNKNOWN_PRINTER_DRIVER
;
5036 status
= fill_printer_driver_info6(mem_ctx
, r
, &driver
, servername
);
5038 free_a_printer(&printer
,2);
5039 free_a_printer_driver(driver
, 3);
5044 /****************************************************************
5045 _spoolss_GetPrinterDriver2
5046 ****************************************************************/
5048 WERROR
_spoolss_GetPrinterDriver2(pipes_struct
*p
,
5049 struct spoolss_GetPrinterDriver2
*r
)
5051 Printer_entry
*printer
;
5054 const char *servername
;
5057 /* that's an [in out] buffer */
5059 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5060 return WERR_INVALID_PARAM
;
5063 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5065 if (!(printer
= find_printer_index_by_hnd( p
, r
->in
.handle
))) {
5066 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5067 return WERR_INVALID_PRINTER_NAME
;
5071 *r
->out
.server_major_version
= 0;
5072 *r
->out
.server_minor_version
= 0;
5074 servername
= get_server_name(printer
);
5076 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5080 switch (r
->in
.level
) {
5082 result
= construct_printer_driver_info_1(p
->mem_ctx
,
5083 &r
->out
.info
->info1
,
5087 r
->in
.client_major_version
);
5090 result
= construct_printer_driver_info_2(p
->mem_ctx
,
5091 &r
->out
.info
->info2
,
5095 r
->in
.client_major_version
);
5098 result
= construct_printer_driver_info_3(p
->mem_ctx
,
5099 &r
->out
.info
->info3
,
5103 r
->in
.client_major_version
);
5106 result
= construct_printer_driver_info_6(p
->mem_ctx
,
5107 &r
->out
.info
->info6
,
5111 r
->in
.client_major_version
);
5116 /* apparently this call is the equivalent of
5117 EnumPrinterDataEx() for the DsDriver key */
5120 result
= WERR_UNKNOWN_LEVEL
;
5124 if (!W_ERROR_IS_OK(result
)) {
5125 TALLOC_FREE(r
->out
.info
);
5129 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
, NULL
,
5130 r
->out
.info
, r
->in
.level
);
5131 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5133 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5137 /****************************************************************
5138 _spoolss_StartPagePrinter
5139 ****************************************************************/
5141 WERROR
_spoolss_StartPagePrinter(pipes_struct
*p
,
5142 struct spoolss_StartPagePrinter
*r
)
5144 POLICY_HND
*handle
= r
->in
.handle
;
5146 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5149 DEBUG(3,("_spoolss_StartPagePrinter: "
5150 "Error in startpageprinter printer handle\n"));
5154 Printer
->page_started
=True
;
5158 /****************************************************************
5159 _spoolss_EndPagePrinter
5160 ****************************************************************/
5162 WERROR
_spoolss_EndPagePrinter(pipes_struct
*p
,
5163 struct spoolss_EndPagePrinter
*r
)
5165 POLICY_HND
*handle
= r
->in
.handle
;
5168 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5171 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5172 OUR_HANDLE(handle
)));
5176 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5179 Printer
->page_started
=False
;
5180 print_job_endpage(snum
, Printer
->jobid
);
5185 /****************************************************************
5186 _spoolss_StartDocPrinter
5187 ****************************************************************/
5189 WERROR
_spoolss_StartDocPrinter(pipes_struct
*p
,
5190 struct spoolss_StartDocPrinter
*r
)
5192 POLICY_HND
*handle
= r
->in
.handle
;
5193 uint32_t *jobid
= r
->out
.job_id
;
5194 struct spoolss_DocumentInfo1
*info_1
;
5196 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5199 DEBUG(2,("_spoolss_StartDocPrinter: "
5200 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5204 if (r
->in
.level
!= 1) {
5205 return WERR_UNKNOWN_LEVEL
;
5208 info_1
= r
->in
.info
.info1
;
5211 * a nice thing with NT is it doesn't listen to what you tell it.
5212 * when asked to send _only_ RAW datas, it tries to send datas
5215 * So I add checks like in NT Server ...
5218 if (info_1
->datatype
) {
5219 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5221 return WERR_INVALID_DATATYPE
;
5225 /* get the share number of the printer */
5226 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5230 Printer
->jobid
= print_job_start(p
->server_info
, snum
,
5231 info_1
->document_name
,
5232 Printer
->nt_devmode
);
5234 /* An error occured in print_job_start() so return an appropriate
5237 if (Printer
->jobid
== -1) {
5238 return map_werror_from_unix(errno
);
5241 Printer
->document_started
=True
;
5242 (*jobid
) = Printer
->jobid
;
5247 /****************************************************************
5248 _spoolss_EndDocPrinter
5249 ****************************************************************/
5251 WERROR
_spoolss_EndDocPrinter(pipes_struct
*p
,
5252 struct spoolss_EndDocPrinter
*r
)
5254 POLICY_HND
*handle
= r
->in
.handle
;
5256 return _spoolss_enddocprinter_internal(p
, handle
);
5259 /****************************************************************
5260 _spoolss_WritePrinter
5261 ****************************************************************/
5263 WERROR
_spoolss_WritePrinter(pipes_struct
*p
,
5264 struct spoolss_WritePrinter
*r
)
5266 POLICY_HND
*handle
= r
->in
.handle
;
5267 uint32 buffer_size
= r
->in
._data_size
;
5268 uint8
*buffer
= r
->in
.data
.data
;
5269 uint32
*buffer_written
= &r
->in
._data_size
;
5271 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5274 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5275 OUR_HANDLE(handle
)));
5276 *r
->out
.num_written
= r
->in
._data_size
;
5280 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5283 (*buffer_written
) = (uint32
)print_job_write(snum
, Printer
->jobid
, (const char *)buffer
,
5284 (SMB_OFF_T
)-1, (size_t)buffer_size
);
5285 if (*buffer_written
== (uint32
)-1) {
5286 *r
->out
.num_written
= 0;
5287 if (errno
== ENOSPC
)
5288 return WERR_NO_SPOOL_SPACE
;
5290 return WERR_ACCESS_DENIED
;
5293 *r
->out
.num_written
= r
->in
._data_size
;
5298 /********************************************************************
5299 * api_spoolss_getprinter
5300 * called from the spoolss dispatcher
5302 ********************************************************************/
5304 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5308 WERROR errcode
= WERR_BADFUNC
;
5309 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5312 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5316 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5320 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5321 if (print_queue_pause(p
->server_info
, snum
, &errcode
)) {
5325 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5326 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5327 if (print_queue_resume(p
->server_info
, snum
, &errcode
)) {
5331 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5332 if (print_queue_purge(p
->server_info
, snum
, &errcode
)) {
5337 return WERR_UNKNOWN_LEVEL
;
5344 /****************************************************************
5345 _spoolss_AbortPrinter
5346 * From MSDN: "Deletes printer's spool file if printer is configured
5348 ****************************************************************/
5350 WERROR
_spoolss_AbortPrinter(pipes_struct
*p
,
5351 struct spoolss_AbortPrinter
*r
)
5353 POLICY_HND
*handle
= r
->in
.handle
;
5354 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5356 WERROR errcode
= WERR_OK
;
5359 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5360 OUR_HANDLE(handle
)));
5364 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5367 print_job_delete(p
->server_info
, snum
, Printer
->jobid
, &errcode
);
5372 /********************************************************************
5373 * called by spoolss_api_setprinter
5374 * when updating a printer description
5375 ********************************************************************/
5377 static WERROR
update_printer_sec(POLICY_HND
*handle
,
5378 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5380 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5384 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5386 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5387 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5388 OUR_HANDLE(handle
)));
5390 result
= WERR_BADFID
;
5395 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5396 result
= WERR_INVALID_PARAM
;
5400 /* Check the user has permissions to change the security
5401 descriptor. By experimentation with two NT machines, the user
5402 requires Full Access to the printer to change security
5405 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5406 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5407 result
= WERR_ACCESS_DENIED
;
5411 /* NT seems to like setting the security descriptor even though
5412 nothing may have actually changed. */
5414 if ( !nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
)) {
5415 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5416 result
= WERR_BADFID
;
5420 if (DEBUGLEVEL
>= 10) {
5424 the_acl
= old_secdesc_ctr
->sd
->dacl
;
5425 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5426 PRINTERNAME(snum
), the_acl
->num_aces
));
5428 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5429 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5430 &the_acl
->aces
[i
].trustee
),
5431 the_acl
->aces
[i
].access_mask
));
5434 the_acl
= secdesc_ctr
->sd
->dacl
;
5437 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5438 PRINTERNAME(snum
), the_acl
->num_aces
));
5440 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5441 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5442 &the_acl
->aces
[i
].trustee
),
5443 the_acl
->aces
[i
].access_mask
));
5446 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5450 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5451 if (!new_secdesc_ctr
) {
5452 result
= WERR_NOMEM
;
5456 if (sec_desc_equal(new_secdesc_ctr
->sd
, old_secdesc_ctr
->sd
)) {
5461 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5468 /********************************************************************
5469 Canonicalize printer info from a client
5471 ATTN: It does not matter what we set the servername to hear
5472 since we do the necessary work in get_a_printer() to set it to
5473 the correct value based on what the client sent in the
5474 _spoolss_open_printer_ex().
5475 ********************************************************************/
5477 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5479 fstring printername
;
5482 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5483 "portname=%s drivername=%s comment=%s location=%s\n",
5484 info
->servername
, info
->printername
, info
->sharename
,
5485 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5487 /* we force some elements to "correct" values */
5488 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5489 fstrcpy(info
->sharename
, lp_servicename(snum
));
5491 /* check to see if we allow printername != sharename */
5493 if ( lp_force_printername(snum
) ) {
5494 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5495 global_myname(), info
->sharename
);
5498 /* make sure printername is in \\server\printername format */
5500 fstrcpy( printername
, info
->printername
);
5502 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5503 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5507 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5508 global_myname(), p
);
5511 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5512 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5519 /****************************************************************************
5520 ****************************************************************************/
5522 WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5524 char *cmd
= lp_addport_cmd();
5525 char *command
= NULL
;
5527 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5528 bool is_print_op
= False
;
5531 return WERR_ACCESS_DENIED
;
5534 command
= talloc_asprintf(ctx
,
5535 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5541 is_print_op
= user_has_privileges( token
, &se_printop
);
5543 DEBUG(10,("Running [%s]\n", command
));
5545 /********* BEGIN SePrintOperatorPrivilege **********/
5550 ret
= smbrun(command
, NULL
);
5555 /********* END SePrintOperatorPrivilege **********/
5557 DEBUGADD(10,("returned [%d]\n", ret
));
5559 TALLOC_FREE(command
);
5562 return WERR_ACCESS_DENIED
;
5568 /****************************************************************************
5569 ****************************************************************************/
5571 bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
5573 char *cmd
= lp_addprinter_cmd();
5575 char *command
= NULL
;
5579 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5580 bool is_print_op
= False
;
5581 char *remote_machine
= talloc_strdup(ctx
, "%m");
5583 if (!remote_machine
) {
5586 remote_machine
= talloc_sub_basic(ctx
,
5587 current_user_info
.smb_name
,
5588 current_user_info
.domain
,
5590 if (!remote_machine
) {
5594 command
= talloc_asprintf(ctx
,
5595 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5596 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5597 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5598 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5604 is_print_op
= user_has_privileges( token
, &se_printop
);
5606 DEBUG(10,("Running [%s]\n", command
));
5608 /********* BEGIN SePrintOperatorPrivilege **********/
5613 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5614 /* Tell everyone we updated smb.conf. */
5615 message_send_all(smbd_messaging_context(),
5616 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
5622 /********* END SePrintOperatorPrivilege **********/
5624 DEBUGADD(10,("returned [%d]\n", ret
));
5626 TALLOC_FREE(command
);
5627 TALLOC_FREE(remote_machine
);
5635 /* reload our services immediately */
5636 reload_services( False
);
5639 /* Get lines and convert them back to dos-codepage */
5640 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
5641 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5644 /* Set the portname to what the script says the portname should be. */
5645 /* but don't require anything to be return from the script exit a good error code */
5648 /* Set the portname to what the script says the portname should be. */
5649 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5650 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5653 TALLOC_FREE(qlines
);
5658 /********************************************************************
5659 * Called by spoolss_api_setprinter
5660 * when updating a printer description.
5661 ********************************************************************/
5663 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
,
5664 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
5665 struct spoolss_DeviceMode
*devmode
)
5668 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5669 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5674 DEBUG(8,("update_printer\n"));
5679 result
= WERR_BADFID
;
5683 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5684 result
= WERR_BADFID
;
5688 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
5689 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
5690 result
= WERR_BADFID
;
5694 DEBUGADD(8,("Converting info_2 struct\n"));
5697 * convert_printer_info converts the incoming
5698 * info from the client and overwrites the info
5699 * just read from the tdb in the pointer 'printer'.
5702 if (!convert_printer_info(info_ctr
, printer
)) {
5703 result
= WERR_NOMEM
;
5708 /* we have a valid devmode
5709 convert it and link it*/
5711 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5712 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5713 &printer
->info_2
->devmode
)) {
5714 result
= WERR_NOMEM
;
5719 /* Do sanity check on the requested changes for Samba */
5721 if (!check_printer_ok(printer
->info_2
, snum
)) {
5722 result
= WERR_INVALID_PARAM
;
5726 /* FIXME!!! If the driver has changed we really should verify that
5727 it is installed before doing much else --jerry */
5729 /* Check calling user has permission to update printer description */
5731 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5732 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5733 result
= WERR_ACCESS_DENIED
;
5737 /* Call addprinter hook */
5738 /* Check changes to see if this is really needed */
5740 if ( *lp_addprinter_cmd()
5741 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5742 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5743 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5744 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5746 /* add_printer_hook() will call reload_services() */
5748 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
5750 result
= WERR_ACCESS_DENIED
;
5756 * When a *new* driver is bound to a printer, the drivername is used to
5757 * lookup previously saved driver initialization info, which is then
5758 * bound to the printer, simulating what happens in the Windows arch.
5760 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5762 if (!set_driver_init(printer
, 2))
5764 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5765 printer
->info_2
->drivername
));
5768 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5769 printer
->info_2
->drivername
));
5771 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5775 * flag which changes actually occured. This is a small subset of
5776 * all the possible changes. We also have to update things in the
5780 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
5781 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
5782 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
5783 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5785 notify_printer_comment(snum
, printer
->info_2
->comment
);
5788 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
5789 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
5790 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
5791 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5793 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5796 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
5799 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
5802 pname
= printer
->info_2
->printername
;
5805 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
5806 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
5807 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5809 notify_printer_printername( snum
, pname
);
5812 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
5813 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
5814 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
5815 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5817 notify_printer_port(snum
, printer
->info_2
->portname
);
5820 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
5821 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
5822 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
5823 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5825 notify_printer_location(snum
, printer
->info_2
->location
);
5828 /* here we need to update some more DsSpooler keys */
5829 /* uNCName, serverName, shortServerName */
5831 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
5832 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
5833 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5834 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
5835 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5837 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
5838 global_myname(), printer
->info_2
->sharename
);
5839 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
5840 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
5841 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
5843 /* Update printer info */
5844 result
= mod_a_printer(printer
, 2);
5847 free_a_printer(&printer
, 2);
5848 free_a_printer(&old_printer
, 2);
5854 /****************************************************************************
5855 ****************************************************************************/
5856 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
5857 struct spoolss_SetPrinterInfo7
*info7
)
5861 Printer_entry
*Printer
;
5863 if ( lp_security() != SEC_ADS
) {
5864 return WERR_UNKNOWN_LEVEL
;
5867 Printer
= find_printer_index_by_hnd(p
, handle
);
5869 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
5874 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5877 nt_printer_publish(Printer
, snum
, info7
->action
);
5881 return WERR_UNKNOWN_LEVEL
;
5885 /****************************************************************
5887 ****************************************************************/
5889 WERROR
_spoolss_SetPrinter(pipes_struct
*p
,
5890 struct spoolss_SetPrinter
*r
)
5892 POLICY_HND
*handle
= r
->in
.handle
;
5895 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5898 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5899 OUR_HANDLE(handle
)));
5903 /* check the level */
5904 switch (r
->in
.info_ctr
->level
) {
5906 return control_printer(handle
, r
->in
.command
, p
);
5908 result
= update_printer(p
, handle
,
5910 r
->in
.devmode_ctr
->devmode
);
5911 if (!W_ERROR_IS_OK(result
))
5913 if (r
->in
.secdesc_ctr
->sd
)
5914 result
= update_printer_sec(handle
, p
,
5918 return update_printer_sec(handle
, p
,
5921 return publish_or_unpublish_printer(p
, handle
,
5922 r
->in
.info_ctr
->info
.info7
);
5924 return WERR_UNKNOWN_LEVEL
;
5928 /****************************************************************
5929 _spoolss_FindClosePrinterNotify
5930 ****************************************************************/
5932 WERROR
_spoolss_FindClosePrinterNotify(pipes_struct
*p
,
5933 struct spoolss_FindClosePrinterNotify
*r
)
5935 POLICY_HND
*handle
= r
->in
.handle
;
5936 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5939 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5940 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5944 if (Printer
->notify
.client_connected
==True
) {
5947 if ( Printer
->printer_type
== SPLHND_SERVER
)
5949 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
5950 !get_printer_snum(p
, handle
, &snum
, NULL
) )
5953 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
5956 Printer
->notify
.flags
=0;
5957 Printer
->notify
.options
=0;
5958 Printer
->notify
.localmachine
[0]='\0';
5959 Printer
->notify
.printerlocal
=0;
5960 TALLOC_FREE(Printer
->notify
.option
);
5961 Printer
->notify
.client_connected
=False
;
5966 /****************************************************************
5968 ****************************************************************/
5970 WERROR
_spoolss_AddJob(pipes_struct
*p
,
5971 struct spoolss_AddJob
*r
)
5973 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5974 return WERR_INVALID_PARAM
;
5977 /* this is what a NT server returns for AddJob. AddJob must fail on
5978 * non-local printers */
5980 if (r
->in
.level
!= 1) {
5981 return WERR_UNKNOWN_LEVEL
;
5984 return WERR_INVALID_PARAM
;
5987 /****************************************************************************
5989 ****************************************************************************/
5991 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
5992 struct spoolss_JobInfo1
*r
,
5993 const print_queue_struct
*queue
,
5994 int position
, int snum
,
5995 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
5999 t
= gmtime(&queue
->time
);
6001 r
->job_id
= queue
->job
;
6003 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6004 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6005 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6006 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6007 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6008 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6009 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6010 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6011 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6012 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6013 r
->text_status
= talloc_strdup(mem_ctx
, "");
6014 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6016 r
->status
= nt_printj_status(queue
->status
);
6017 r
->priority
= queue
->priority
;
6018 r
->position
= position
;
6019 r
->total_pages
= queue
->page_count
;
6020 r
->pages_printed
= 0; /* ??? */
6022 init_systemtime(&r
->submitted
, t
);
6027 /****************************************************************************
6029 ****************************************************************************/
6031 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6032 struct spoolss_JobInfo2
*r
,
6033 const print_queue_struct
*queue
,
6034 int position
, int snum
,
6035 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6036 struct spoolss_DeviceMode
*devmode
)
6040 t
= gmtime(&queue
->time
);
6042 r
->job_id
= queue
->job
;
6044 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6045 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6046 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6047 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6048 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6049 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6050 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6051 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6052 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6053 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6054 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6055 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6056 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6057 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6058 r
->parameters
= talloc_strdup(mem_ctx
, "");
6059 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6060 r
->driver_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
6061 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6063 r
->devmode
= devmode
;
6065 r
->text_status
= talloc_strdup(mem_ctx
, "");
6066 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6070 r
->status
= nt_printj_status(queue
->status
);
6071 r
->priority
= queue
->priority
;
6072 r
->position
= position
;
6075 r
->total_pages
= queue
->page_count
;
6076 r
->size
= queue
->size
;
6077 init_systemtime(&r
->submitted
, t
);
6079 r
->pages_printed
= 0; /* ??? */
6084 /****************************************************************************
6085 Enumjobs at level 1.
6086 ****************************************************************************/
6088 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6089 const print_queue_struct
*queue
,
6090 uint32_t num_queues
, int snum
,
6091 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6092 union spoolss_JobInfo
**info_p
,
6095 union spoolss_JobInfo
*info
;
6097 WERROR result
= WERR_OK
;
6099 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6100 W_ERROR_HAVE_NO_MEMORY(info
);
6102 *count
= num_queues
;
6104 for (i
=0; i
<*count
; i
++) {
6105 result
= fill_job_info1(info
,
6111 if (!W_ERROR_IS_OK(result
)) {
6117 if (!W_ERROR_IS_OK(result
)) {
6128 /****************************************************************************
6129 Enumjobs at level 2.
6130 ****************************************************************************/
6132 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6133 const print_queue_struct
*queue
,
6134 uint32_t num_queues
, int snum
,
6135 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6136 union spoolss_JobInfo
**info_p
,
6139 union spoolss_JobInfo
*info
;
6141 WERROR result
= WERR_OK
;
6143 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6144 W_ERROR_HAVE_NO_MEMORY(info
);
6146 *count
= num_queues
;
6148 for (i
=0; i
<*count
; i
++) {
6150 struct spoolss_DeviceMode
*devmode
;
6152 devmode
= construct_dev_mode(info
, lp_const_servicename(snum
));
6154 result
= WERR_NOMEM
;
6158 result
= fill_job_info2(info
,
6165 if (!W_ERROR_IS_OK(result
)) {
6171 if (!W_ERROR_IS_OK(result
)) {
6182 /****************************************************************
6184 ****************************************************************/
6186 WERROR
_spoolss_EnumJobs(pipes_struct
*p
,
6187 struct spoolss_EnumJobs
*r
)
6190 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6192 print_status_struct prt_status
;
6193 print_queue_struct
*queue
= NULL
;
6196 /* that's an [in out] buffer */
6198 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6199 return WERR_INVALID_PARAM
;
6202 DEBUG(4,("_spoolss_EnumJobs\n"));
6206 *r
->out
.info
= NULL
;
6208 /* lookup the printer snum and tdb entry */
6210 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6214 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6215 if (!W_ERROR_IS_OK(result
)) {
6219 count
= print_queue_status(snum
, &queue
, &prt_status
);
6220 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6221 count
, prt_status
.status
, prt_status
.message
));
6225 free_a_printer(&ntprinter
, 2);
6229 switch (r
->in
.level
) {
6231 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6232 ntprinter
, r
->out
.info
, r
->out
.count
);
6235 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6236 ntprinter
, r
->out
.info
, r
->out
.count
);
6239 result
= WERR_UNKNOWN_LEVEL
;
6244 free_a_printer(&ntprinter
, 2);
6246 if (!W_ERROR_IS_OK(result
)) {
6250 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6251 spoolss_EnumJobs
, NULL
,
6252 *r
->out
.info
, r
->in
.level
,
6254 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6255 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6257 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6260 /****************************************************************
6261 _spoolss_ScheduleJob
6262 ****************************************************************/
6264 WERROR
_spoolss_ScheduleJob(pipes_struct
*p
,
6265 struct spoolss_ScheduleJob
*r
)
6270 /****************************************************************
6272 ****************************************************************/
6274 WERROR
_spoolss_SetJob(pipes_struct
*p
,
6275 struct spoolss_SetJob
*r
)
6277 POLICY_HND
*handle
= r
->in
.handle
;
6278 uint32 jobid
= r
->in
.job_id
;
6279 uint32 command
= r
->in
.command
;
6282 WERROR errcode
= WERR_BADFUNC
;
6284 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6288 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6289 return WERR_INVALID_PRINTER_NAME
;
6293 case SPOOLSS_JOB_CONTROL_CANCEL
:
6294 case SPOOLSS_JOB_CONTROL_DELETE
:
6295 if (print_job_delete(p
->server_info
, snum
, jobid
, &errcode
)) {
6299 case SPOOLSS_JOB_CONTROL_PAUSE
:
6300 if (print_job_pause(p
->server_info
, snum
, jobid
, &errcode
)) {
6304 case SPOOLSS_JOB_CONTROL_RESTART
:
6305 case SPOOLSS_JOB_CONTROL_RESUME
:
6306 if (print_job_resume(p
->server_info
, snum
, jobid
, &errcode
)) {
6311 return WERR_UNKNOWN_LEVEL
;
6317 /****************************************************************************
6318 Enumerates all printer drivers at level 1.
6319 ****************************************************************************/
6321 static WERROR
enumprinterdrivers_level1(TALLOC_CTX
*mem_ctx
,
6322 const char *servername
,
6323 const char *architecture
,
6324 union spoolss_DriverInfo
**info_p
,
6330 fstring
*list
= NULL
;
6331 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6332 union spoolss_DriverInfo
*info
= NULL
;
6333 WERROR result
= WERR_OK
;
6337 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6339 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6340 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6341 ndrivers
, architecture
, version
));
6343 if (ndrivers
== -1) {
6344 result
= WERR_NOMEM
;
6348 if (ndrivers
!= 0) {
6349 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6350 union spoolss_DriverInfo
,
6353 DEBUG(0,("enumprinterdrivers_level1: "
6354 "failed to enlarge driver info buffer!\n"));
6355 result
= WERR_NOMEM
;
6360 for (i
=0; i
<ndrivers
; i
++) {
6361 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6362 ZERO_STRUCT(driver
);
6363 result
= get_a_printer_driver(&driver
, 3, list
[i
],
6364 architecture
, version
);
6365 if (!W_ERROR_IS_OK(result
)) {
6368 result
= fill_printer_driver_info1(info
, &info
[*count
+i
].info1
,
6369 &driver
, servername
,
6371 if (!W_ERROR_IS_OK(result
)) {
6372 free_a_printer_driver(driver
, 3);
6375 free_a_printer_driver(driver
, 3);
6385 if (!W_ERROR_IS_OK(result
)) {
6396 /****************************************************************************
6397 Enumerates all printer drivers at level 2.
6398 ****************************************************************************/
6400 static WERROR
enumprinterdrivers_level2(TALLOC_CTX
*mem_ctx
,
6401 const char *servername
,
6402 const char *architecture
,
6403 union spoolss_DriverInfo
**info_p
,
6409 fstring
*list
= NULL
;
6410 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6411 union spoolss_DriverInfo
*info
= NULL
;
6412 WERROR result
= WERR_OK
;
6416 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6418 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6419 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6420 ndrivers
, architecture
, version
));
6422 if (ndrivers
== -1) {
6423 result
= WERR_NOMEM
;
6427 if (ndrivers
!= 0) {
6428 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6429 union spoolss_DriverInfo
,
6432 DEBUG(0,("enumprinterdrivers_level2: "
6433 "failed to enlarge driver info buffer!\n"));
6434 result
= WERR_NOMEM
;
6439 for (i
=0; i
<ndrivers
; i
++) {
6440 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6441 ZERO_STRUCT(driver
);
6442 result
= get_a_printer_driver(&driver
, 3, list
[i
],
6443 architecture
, version
);
6444 if (!W_ERROR_IS_OK(result
)) {
6447 result
= fill_printer_driver_info2(info
, &info
[*count
+i
].info2
,
6448 &driver
, servername
);
6449 if (!W_ERROR_IS_OK(result
)) {
6450 free_a_printer_driver(driver
, 3);
6453 free_a_printer_driver(driver
, 3);
6463 if (!W_ERROR_IS_OK(result
)) {
6474 /****************************************************************************
6475 Enumerates all printer drivers at level 3.
6476 ****************************************************************************/
6478 static WERROR
enumprinterdrivers_level3(TALLOC_CTX
*mem_ctx
,
6479 const char *servername
,
6480 const char *architecture
,
6481 union spoolss_DriverInfo
**info_p
,
6487 fstring
*list
= NULL
;
6488 union spoolss_DriverInfo
*info
= NULL
;
6489 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6490 WERROR result
= WERR_OK
;
6494 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6496 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6497 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6498 ndrivers
, architecture
, version
));
6500 if (ndrivers
== -1) {
6501 result
= WERR_NOMEM
;
6505 if (ndrivers
!= 0) {
6506 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6507 union spoolss_DriverInfo
,
6510 DEBUG(0,("enumprinterdrivers_level3: "
6511 "failed to enlarge driver info buffer!\n"));
6512 result
= WERR_NOMEM
;
6517 for (i
=0; i
<ndrivers
; i
++) {
6518 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6519 ZERO_STRUCT(driver
);
6520 result
= get_a_printer_driver(&driver
, 3, list
[i
],
6521 architecture
, version
);
6522 if (!W_ERROR_IS_OK(result
)) {
6525 result
= fill_printer_driver_info3(info
, &info
[*count
+i
].info3
,
6526 &driver
, servername
);
6527 if (!W_ERROR_IS_OK(result
)) {
6528 free_a_printer_driver(driver
, 3);
6532 free_a_printer_driver(driver
, 3);
6542 if (!W_ERROR_IS_OK(result
)) {
6553 /****************************************************************
6554 _spoolss_EnumPrinterDrivers
6555 ****************************************************************/
6557 WERROR
_spoolss_EnumPrinterDrivers(pipes_struct
*p
,
6558 struct spoolss_EnumPrinterDrivers
*r
)
6560 const char *cservername
;
6563 /* that's an [in out] buffer */
6565 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6566 return WERR_INVALID_PARAM
;
6569 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6573 *r
->out
.info
= NULL
;
6575 cservername
= canon_servername(r
->in
.server
);
6577 if (!is_myname_or_ipaddr(cservername
)) {
6578 return WERR_UNKNOWN_PRINTER_DRIVER
;
6581 switch (r
->in
.level
) {
6583 result
= enumprinterdrivers_level1(p
->mem_ctx
, cservername
,
6585 r
->out
.info
, r
->out
.count
);
6588 result
= enumprinterdrivers_level2(p
->mem_ctx
, cservername
,
6590 r
->out
.info
, r
->out
.count
);
6593 result
= enumprinterdrivers_level3(p
->mem_ctx
, cservername
,
6595 r
->out
.info
, r
->out
.count
);
6598 return WERR_UNKNOWN_LEVEL
;
6601 if (!W_ERROR_IS_OK(result
)) {
6605 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6606 spoolss_EnumPrinterDrivers
, NULL
,
6607 *r
->out
.info
, r
->in
.level
,
6609 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6610 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6612 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6615 /****************************************************************************
6616 ****************************************************************************/
6618 static WERROR
fill_form_info_1(TALLOC_CTX
*mem_ctx
,
6619 struct spoolss_FormInfo1
*r
,
6620 const nt_forms_struct
*form
)
6622 r
->form_name
= talloc_strdup(mem_ctx
, form
->name
);
6623 W_ERROR_HAVE_NO_MEMORY(r
->form_name
);
6625 r
->flags
= form
->flag
;
6626 r
->size
.width
= form
->width
;
6627 r
->size
.height
= form
->length
;
6628 r
->area
.left
= form
->left
;
6629 r
->area
.top
= form
->top
;
6630 r
->area
.right
= form
->right
;
6631 r
->area
.bottom
= form
->bottom
;
6636 /****************************************************************
6637 spoolss_enumforms_level1
6638 ****************************************************************/
6640 static WERROR
spoolss_enumforms_level1(TALLOC_CTX
*mem_ctx
,
6641 const nt_forms_struct
*builtin_forms
,
6642 uint32_t num_builtin_forms
,
6643 const nt_forms_struct
*user_forms
,
6644 uint32_t num_user_forms
,
6645 union spoolss_FormInfo
**info_p
,
6648 union spoolss_FormInfo
*info
;
6649 WERROR result
= WERR_OK
;
6652 *count
= num_builtin_forms
+ num_user_forms
;
6654 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_FormInfo
, *count
);
6655 W_ERROR_HAVE_NO_MEMORY(info
);
6657 /* construct the list of form structures */
6658 for (i
=0; i
<num_builtin_forms
; i
++) {
6659 DEBUGADD(6,("Filling form number [%d]\n",i
));
6660 result
= fill_form_info_1(info
, &info
[i
].info1
,
6662 if (!W_ERROR_IS_OK(result
)) {
6667 for (; i
<num_user_forms
; i
++) {
6668 DEBUGADD(6,("Filling form number [%d]\n",i
));
6669 result
= fill_form_info_1(info
, &info
[i
].info1
,
6670 &user_forms
[i
-num_builtin_forms
]);
6671 if (!W_ERROR_IS_OK(result
)) {
6677 if (!W_ERROR_IS_OK(result
)) {
6688 /****************************************************************
6690 ****************************************************************/
6692 WERROR
_spoolss_EnumForms(pipes_struct
*p
,
6693 struct spoolss_EnumForms
*r
)
6696 nt_forms_struct
*user_forms
= NULL
;
6697 nt_forms_struct
*builtin_forms
= NULL
;
6698 uint32_t num_user_forms
;
6699 uint32_t num_builtin_forms
;
6703 *r
->out
.info
= NULL
;
6705 /* that's an [in out] buffer */
6707 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
6708 return WERR_INVALID_PARAM
;
6711 DEBUG(4,("_spoolss_EnumForms\n"));
6712 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6713 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6715 num_builtin_forms
= get_builtin_ntforms(&builtin_forms
);
6716 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms
));
6717 num_user_forms
= get_ntforms(&user_forms
);
6718 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms
));
6720 if (num_user_forms
+ num_builtin_forms
== 0) {
6721 SAFE_FREE(builtin_forms
);
6722 SAFE_FREE(user_forms
);
6723 return WERR_NO_MORE_ITEMS
;
6726 switch (r
->in
.level
) {
6728 result
= spoolss_enumforms_level1(p
->mem_ctx
,
6737 result
= WERR_UNKNOWN_LEVEL
;
6741 SAFE_FREE(user_forms
);
6742 SAFE_FREE(builtin_forms
);
6744 if (!W_ERROR_IS_OK(result
)) {
6748 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6749 spoolss_EnumForms
, NULL
,
6750 *r
->out
.info
, r
->in
.level
,
6752 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6753 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6755 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6758 /****************************************************************
6759 ****************************************************************/
6761 static WERROR
find_form_byname(const char *name
,
6762 nt_forms_struct
*form
)
6764 nt_forms_struct
*list
= NULL
;
6765 int num_forms
= 0, i
= 0;
6767 if (get_a_builtin_ntform_by_string(name
, form
)) {
6771 num_forms
= get_ntforms(&list
);
6772 DEBUGADD(5,("Number of forms [%d]\n", num_forms
));
6774 if (num_forms
== 0) {
6778 /* Check if the requested name is in the list of form structures */
6779 for (i
= 0; i
< num_forms
; i
++) {
6781 DEBUG(4,("checking form %s (want %s)\n", list
[i
].name
, name
));
6783 if (strequal(name
, list
[i
].name
)) {
6784 DEBUGADD(6,("Found form %s number [%d]\n", name
, i
));
6796 /****************************************************************
6798 ****************************************************************/
6800 WERROR
_spoolss_GetForm(pipes_struct
*p
,
6801 struct spoolss_GetForm
*r
)
6804 nt_forms_struct form
;
6806 /* that's an [in out] buffer */
6808 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6809 return WERR_INVALID_PARAM
;
6812 DEBUG(4,("_spoolss_GetForm\n"));
6813 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6814 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6816 result
= find_form_byname(r
->in
.form_name
, &form
);
6817 if (!W_ERROR_IS_OK(result
)) {
6818 TALLOC_FREE(r
->out
.info
);
6822 switch (r
->in
.level
) {
6824 result
= fill_form_info_1(p
->mem_ctx
,
6825 &r
->out
.info
->info1
,
6830 result
= WERR_UNKNOWN_LEVEL
;
6834 if (!W_ERROR_IS_OK(result
)) {
6835 TALLOC_FREE(r
->out
.info
);
6839 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
, NULL
,
6840 r
->out
.info
, r
->in
.level
);
6841 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
6843 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6846 /****************************************************************************
6847 ****************************************************************************/
6849 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
6850 struct spoolss_PortInfo1
*r
,
6853 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6854 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6859 /****************************************************************************
6860 TODO: This probably needs distinguish between TCP/IP and Local ports
6862 ****************************************************************************/
6864 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
6865 struct spoolss_PortInfo2
*r
,
6868 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6869 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6871 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
6872 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
6874 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
6875 W_ERROR_HAVE_NO_MEMORY(r
->description
);
6877 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
6884 /****************************************************************************
6885 wrapper around the enumer ports command
6886 ****************************************************************************/
6888 WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
6890 char *cmd
= lp_enumports_cmd();
6891 char **qlines
= NULL
;
6892 char *command
= NULL
;
6900 /* if no hook then just fill in the default port */
6903 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
6906 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
6907 TALLOC_FREE(qlines
);
6914 /* we have a valid enumport command */
6916 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
6921 DEBUG(10,("Running [%s]\n", command
));
6922 ret
= smbrun(command
, &fd
);
6923 DEBUG(10,("Returned [%d]\n", ret
));
6924 TALLOC_FREE(command
);
6929 return WERR_ACCESS_DENIED
;
6933 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6934 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6944 /****************************************************************************
6946 ****************************************************************************/
6948 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
6949 union spoolss_PortInfo
**info_p
,
6952 union spoolss_PortInfo
*info
= NULL
;
6954 WERROR result
= WERR_OK
;
6955 char **qlines
= NULL
;
6958 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
6959 if (!W_ERROR_IS_OK(result
)) {
6964 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
6966 DEBUG(10,("Returning WERR_NOMEM\n"));
6967 result
= WERR_NOMEM
;
6971 for (i
=0; i
<numlines
; i
++) {
6972 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6973 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
6974 if (!W_ERROR_IS_OK(result
)) {
6979 TALLOC_FREE(qlines
);
6982 if (!W_ERROR_IS_OK(result
)) {
6984 TALLOC_FREE(qlines
);
6996 /****************************************************************************
6998 ****************************************************************************/
7000 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7001 union spoolss_PortInfo
**info_p
,
7004 union spoolss_PortInfo
*info
= NULL
;
7006 WERROR result
= WERR_OK
;
7007 char **qlines
= NULL
;
7010 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7011 if (!W_ERROR_IS_OK(result
)) {
7016 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7018 DEBUG(10,("Returning WERR_NOMEM\n"));
7019 result
= WERR_NOMEM
;
7023 for (i
=0; i
<numlines
; i
++) {
7024 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7025 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7026 if (!W_ERROR_IS_OK(result
)) {
7031 TALLOC_FREE(qlines
);
7034 if (!W_ERROR_IS_OK(result
)) {
7036 TALLOC_FREE(qlines
);
7048 /****************************************************************
7050 ****************************************************************/
7052 WERROR
_spoolss_EnumPorts(pipes_struct
*p
,
7053 struct spoolss_EnumPorts
*r
)
7057 /* that's an [in out] buffer */
7059 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7060 return WERR_INVALID_PARAM
;
7063 DEBUG(4,("_spoolss_EnumPorts\n"));
7067 *r
->out
.info
= NULL
;
7069 switch (r
->in
.level
) {
7071 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7075 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7079 return WERR_UNKNOWN_LEVEL
;
7082 if (!W_ERROR_IS_OK(result
)) {
7086 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7087 spoolss_EnumPorts
, NULL
,
7088 *r
->out
.info
, r
->in
.level
,
7090 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7091 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7093 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7096 /****************************************************************************
7097 ****************************************************************************/
7099 static WERROR
spoolss_addprinterex_level_2(pipes_struct
*p
,
7101 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7102 struct spoolss_DeviceMode
*devmode
,
7103 struct security_descriptor
*sec_desc
,
7104 struct spoolss_UserLevelCtr
*user_ctr
,
7107 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7110 WERROR err
= WERR_OK
;
7112 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7113 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7117 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7118 if (!convert_printer_info(info_ctr
, printer
)) {
7119 free_a_printer(&printer
, 2);
7123 /* check to see if the printer already exists */
7125 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7126 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7127 printer
->info_2
->sharename
));
7128 free_a_printer(&printer
, 2);
7129 return WERR_PRINTER_ALREADY_EXISTS
;
7132 /* FIXME!!! smbd should check to see if the driver is installed before
7133 trying to add a printer like this --jerry */
7135 if (*lp_addprinter_cmd() ) {
7136 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7138 free_a_printer(&printer
,2);
7139 return WERR_ACCESS_DENIED
;
7142 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7143 "smb.conf parameter \"addprinter command\" is defined. This"
7144 "parameter must exist for this call to succeed\n",
7145 printer
->info_2
->sharename
));
7148 /* use our primary netbios name since get_a_printer() will convert
7149 it to what the client expects on a case by case basis */
7151 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7152 printer
->info_2
->sharename
);
7155 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7156 free_a_printer(&printer
,2);
7157 return WERR_ACCESS_DENIED
;
7160 /* you must be a printer admin to add a new printer */
7161 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7162 free_a_printer(&printer
,2);
7163 return WERR_ACCESS_DENIED
;
7167 * Do sanity check on the requested changes for Samba.
7170 if (!check_printer_ok(printer
->info_2
, snum
)) {
7171 free_a_printer(&printer
,2);
7172 return WERR_INVALID_PARAM
;
7176 * When a printer is created, the drivername bound to the printer is used
7177 * to lookup previously saved driver initialization info, which is then
7178 * bound to the new printer, simulating what happens in the Windows arch.
7183 set_driver_init(printer
, 2);
7187 /* A valid devmode was included, convert and link it
7189 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7191 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7192 &printer
->info_2
->devmode
)) {
7197 /* write the ASCII on disk */
7198 err
= mod_a_printer(printer
, 2);
7199 if (!W_ERROR_IS_OK(err
)) {
7200 free_a_printer(&printer
,2);
7204 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7205 /* Handle open failed - remove addition. */
7206 del_a_printer(printer
->info_2
->sharename
);
7207 free_a_printer(&printer
,2);
7208 ZERO_STRUCTP(handle
);
7209 return WERR_ACCESS_DENIED
;
7212 update_c_setprinter(False
);
7213 free_a_printer(&printer
,2);
7218 /****************************************************************
7219 _spoolss_AddPrinterEx
7220 ****************************************************************/
7222 WERROR
_spoolss_AddPrinterEx(pipes_struct
*p
,
7223 struct spoolss_AddPrinterEx
*r
)
7225 switch (r
->in
.info_ctr
->level
) {
7227 /* we don't handle yet */
7228 /* but I know what to do ... */
7229 return WERR_UNKNOWN_LEVEL
;
7231 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7233 r
->in
.devmode_ctr
->devmode
,
7234 r
->in
.secdesc_ctr
->sd
,
7235 r
->in
.userlevel_ctr
,
7238 return WERR_UNKNOWN_LEVEL
;
7242 /****************************************************************
7243 _spoolss_AddPrinterDriver
7244 ****************************************************************/
7246 WERROR
_spoolss_AddPrinterDriver(pipes_struct
*p
,
7247 struct spoolss_AddPrinterDriver
*r
)
7249 uint32_t level
= r
->in
.info_ctr
->level
;
7250 struct spoolss_AddDriverInfoCtr
*info
= r
->in
.info_ctr
;
7251 WERROR err
= WERR_OK
;
7252 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7253 fstring driver_name
;
7257 switch (p
->hdr_req
.opnum
) {
7258 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7259 fn
= "_spoolss_AddPrinterDriver";
7261 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7262 fn
= "_spoolss_AddPrinterDriverEx";
7265 return WERR_INVALID_PARAM
;
7270 if (level
!= 3 && level
!= 6) {
7271 /* Clever hack from Martin Zielinski <mz@seh.de>
7272 * to allow downgrade from level 8 (Vista).
7274 DEBUG(0,("%s: level %d not yet implemented\n", fn
, level
));
7275 return WERR_UNKNOWN_LEVEL
;
7278 ZERO_STRUCT(driver
);
7280 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7285 DEBUG(5,("Cleaning driver's information\n"));
7286 err
= clean_up_driver_struct(p
, driver
, level
);
7287 if (!W_ERROR_IS_OK(err
))
7290 DEBUG(5,("Moving driver to final destination\n"));
7291 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, driver
, level
,
7296 if (add_a_printer_driver(driver
, level
)!=0) {
7297 err
= WERR_ACCESS_DENIED
;
7303 fstrcpy(driver_name
,
7304 driver
.info_3
->name
? driver
.info_3
->name
: "");
7307 fstrcpy(driver_name
,
7308 driver
.info_6
->name
? driver
.info_6
->name
: "");
7313 * I think this is where he DrvUpgradePrinter() hook would be
7314 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7315 * server. Right now, we just need to send ourselves a message
7316 * to update each printer bound to this driver. --jerry
7319 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7320 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7325 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7326 * decide if the driver init data should be deleted. The rules are:
7327 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7328 * 2) delete init data only if there is no 2k/Xp driver
7329 * 3) always delete init data
7330 * The generalized rule is always use init data from the highest order driver.
7331 * It is necessary to follow the driver install by an initialization step to
7332 * finish off this process.
7335 version
= driver
.info_3
->cversion
;
7336 else if (level
== 6)
7337 version
= driver
.info_6
->version
;
7342 * 9x printer driver - never delete init data
7345 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7350 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7351 * there is no 2k/Xp driver init data for this driver name.
7355 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7357 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7359 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7361 if (!del_driver_init(driver_name
))
7362 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7366 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7368 free_a_printer_driver(driver1
,3);
7369 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7376 * 2k or Xp printer driver - always delete init data
7379 if (!del_driver_init(driver_name
))
7380 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7385 DEBUG(0,("%s: invalid level=%d\n", fn
, level
));
7391 free_a_printer_driver(driver
, level
);
7395 /****************************************************************
7396 _spoolss_AddPrinterDriverEx
7397 ****************************************************************/
7399 WERROR
_spoolss_AddPrinterDriverEx(pipes_struct
*p
,
7400 struct spoolss_AddPrinterDriverEx
*r
)
7402 struct spoolss_AddPrinterDriver a
;
7405 * we only support the semantics of AddPrinterDriver()
7406 * i.e. only copy files that are newer than existing ones
7409 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7410 return WERR_ACCESS_DENIED
;
7413 a
.in
.servername
= r
->in
.servername
;
7414 a
.in
.info_ctr
= r
->in
.info_ctr
;
7416 return _spoolss_AddPrinterDriver(p
, &a
);
7419 /****************************************************************************
7420 ****************************************************************************/
7422 struct _spoolss_paths
{
7428 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7430 static const struct _spoolss_paths spoolss_paths
[]= {
7431 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7432 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7435 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7436 const char *servername
,
7437 const char *environment
,
7441 const char *pservername
= NULL
;
7442 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7443 const char *short_archi
;
7447 /* environment may be empty */
7448 if (environment
&& strlen(environment
)) {
7449 long_archi
= environment
;
7452 /* servername may be empty */
7453 if (servername
&& strlen(servername
)) {
7454 pservername
= canon_servername(servername
);
7456 if (!is_myname_or_ipaddr(pservername
)) {
7457 return WERR_INVALID_PARAM
;
7461 if (!(short_archi
= get_short_archi(long_archi
))) {
7462 return WERR_INVALID_ENVIRONMENT
;
7465 switch (component
) {
7466 case SPOOLSS_PRTPROCS_PATH
:
7467 case SPOOLSS_DRIVER_PATH
:
7469 *path
= talloc_asprintf(mem_ctx
,
7472 spoolss_paths
[component
].share
,
7475 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7476 SPOOLSS_DEFAULT_SERVER_PATH
,
7477 spoolss_paths
[component
].dir
,
7482 return WERR_INVALID_PARAM
;
7492 /****************************************************************************
7493 ****************************************************************************/
7495 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7496 const char *servername
,
7497 const char *environment
,
7498 struct spoolss_DriverDirectoryInfo1
*r
)
7503 werr
= compose_spoolss_server_path(mem_ctx
,
7506 SPOOLSS_DRIVER_PATH
,
7508 if (!W_ERROR_IS_OK(werr
)) {
7512 DEBUG(4,("printer driver directory: [%s]\n", path
));
7514 r
->directory_name
= path
;
7519 /****************************************************************
7520 _spoolss_GetPrinterDriverDirectory
7521 ****************************************************************/
7523 WERROR
_spoolss_GetPrinterDriverDirectory(pipes_struct
*p
,
7524 struct spoolss_GetPrinterDriverDirectory
*r
)
7528 /* that's an [in out] buffer */
7530 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7531 return WERR_INVALID_PARAM
;
7534 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7539 /* r->in.level is ignored */
7541 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7544 &r
->out
.info
->info1
);
7545 if (!W_ERROR_IS_OK(werror
)) {
7546 TALLOC_FREE(r
->out
.info
);
7550 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
, NULL
,
7551 r
->out
.info
, r
->in
.level
);
7552 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7554 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7557 /****************************************************************
7558 _spoolss_EnumPrinterData
7559 ****************************************************************/
7561 WERROR
_spoolss_EnumPrinterData(pipes_struct
*p
,
7562 struct spoolss_EnumPrinterData
*r
)
7564 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7565 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7568 REGISTRY_VALUE
*val
= NULL
;
7569 NT_PRINTER_DATA
*p_data
;
7570 int i
, key_index
, num_values
;
7573 *r
->out
.value_needed
= 0;
7574 *r
->out
.type
= REG_NONE
;
7575 *r
->out
.data_needed
= 0;
7577 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7580 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7581 OUR_HANDLE(r
->in
.handle
)));
7585 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7589 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7590 if (!W_ERROR_IS_OK(result
)) {
7594 p_data
= printer
->info_2
->data
;
7595 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7600 * The NT machine wants to know the biggest size of value and data
7602 * cf: MSDN EnumPrinterData remark section
7605 if (!r
->in
.value_offered
&& !r
->in
.data_offered
&& (key_index
!= -1)) {
7607 uint32_t biggest_valuesize
= 0;
7608 uint32_t biggest_datasize
= 0;
7610 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7612 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
7614 for ( i
=0; i
<num_values
; i
++ )
7616 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
7618 name_length
= strlen(val
->valuename
);
7619 if ( strlen(val
->valuename
) > biggest_valuesize
)
7620 biggest_valuesize
= name_length
;
7622 if ( val
->size
> biggest_datasize
)
7623 biggest_datasize
= val
->size
;
7625 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7629 /* the value is an UNICODE string but real_value_size is the length
7630 in bytes including the trailing 0 */
7632 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
7633 *r
->out
.data_needed
= biggest_datasize
;
7635 DEBUG(6,("final values: [%d], [%d]\n",
7636 *r
->out
.value_needed
, *r
->out
.data_needed
));
7642 * the value len is wrong in NT sp3
7643 * that's the number of bytes not the number of unicode chars
7646 if (key_index
!= -1) {
7647 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
,
7653 /* out_value should default to "" or else NT4 has
7654 problems unmarshalling the response */
7656 if (r
->in
.value_offered
) {
7657 *r
->out
.value_needed
= 1;
7658 r
->out
.value_name
= talloc_strdup(r
, "");
7659 if (!r
->out
.value_name
) {
7660 result
= WERR_NOMEM
;
7664 r
->out
.value_name
= NULL
;
7665 *r
->out
.value_needed
= 0;
7668 /* the data is counted in bytes */
7670 *r
->out
.data_needed
= r
->in
.data_offered
;
7672 result
= WERR_NO_MORE_ITEMS
;
7676 * - counted in bytes in the request
7677 * - counted in UNICODE chars in the max reply
7678 * - counted in bytes in the real size
7680 * take a pause *before* coding not *during* coding
7684 if (r
->in
.value_offered
) {
7685 r
->out
.value_name
= talloc_strdup(r
, regval_name(val
));
7686 if (!r
->out
.value_name
) {
7687 result
= WERR_NOMEM
;
7690 *r
->out
.value_needed
= strlen_m(regval_name(val
));
7692 r
->out
.value_name
= NULL
;
7693 *r
->out
.value_needed
= 0;
7698 *r
->out
.type
= regval_type(val
);
7700 /* data - counted in bytes */
7702 if (r
->out
.data
&& regval_size(val
)) {
7703 memcpy(r
->out
.data
, regval_data_p(val
), regval_size(val
));
7706 *r
->out
.data_needed
= regval_size(val
);
7710 free_a_printer(&printer
, 2);
7714 /****************************************************************
7715 _spoolss_SetPrinterData
7716 ****************************************************************/
7718 WERROR
_spoolss_SetPrinterData(pipes_struct
*p
,
7719 struct spoolss_SetPrinterData
*r
)
7721 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7723 WERROR result
= WERR_OK
;
7724 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7727 DEBUG(5,("_spoolss_SetPrinterData\n"));
7730 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7731 OUR_HANDLE(r
->in
.handle
)));
7735 if (Printer
->printer_type
== SPLHND_SERVER
) {
7736 DEBUG(10,("_spoolss_SetPrinterData: "
7737 "Not implemented for server handles yet\n"));
7738 return WERR_INVALID_PARAM
;
7741 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7746 * Access check : NT returns "access denied" if you make a
7747 * SetPrinterData call without the necessary privildge.
7748 * we were originally returning OK if nothing changed
7749 * which made Win2k issue **a lot** of SetPrinterData
7750 * when connecting to a printer --jerry
7753 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7754 DEBUG(3,("_spoolss_SetPrinterData: "
7755 "change denied by handle access permissions\n"));
7756 result
= WERR_ACCESS_DENIED
;
7760 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7761 if (!W_ERROR_IS_OK(result
)) {
7765 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
7766 r
->in
.type
, &r
->in
.data
);
7767 if (!W_ERROR_IS_OK(result
)) {
7772 * When client side code sets a magic printer data key, detect it and save
7773 * the current printer data and the magic key's data (its the DEVMODE) for
7774 * future printer/driver initializations.
7776 if ((r
->in
.type
== REG_BINARY
) && strequal(r
->in
.value_name
, PHANTOM_DEVMODE_KEY
)) {
7777 /* Set devmode and printer initialization info */
7778 result
= save_driver_init(printer
, 2, blob
.data
, blob
.length
);
7780 srv_spoolss_reset_printerdata(printer
->info_2
->drivername
);
7785 result
= set_printer_dataex(printer
, SPOOL_PRINTERDATA_KEY
,
7786 r
->in
.value_name
, r
->in
.type
,
7787 blob
.data
, blob
.length
);
7788 if (W_ERROR_IS_OK(result
)) {
7789 result
= mod_a_printer(printer
, 2);
7793 free_a_printer(&printer
, 2);
7798 /****************************************************************
7799 _spoolss_ResetPrinter
7800 ****************************************************************/
7802 WERROR
_spoolss_ResetPrinter(pipes_struct
*p
,
7803 struct spoolss_ResetPrinter
*r
)
7805 POLICY_HND
*handle
= r
->in
.handle
;
7806 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7809 DEBUG(5,("_spoolss_ResetPrinter\n"));
7812 * All we do is to check to see if the handle and queue is valid.
7813 * This call really doesn't mean anything to us because we only
7814 * support RAW printing. --jerry
7818 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7819 OUR_HANDLE(handle
)));
7823 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
7827 /* blindly return success */
7831 /****************************************************************
7832 _spoolss_DeletePrinterData
7833 ****************************************************************/
7835 WERROR
_spoolss_DeletePrinterData(pipes_struct
*p
,
7836 struct spoolss_DeletePrinterData
*r
)
7838 POLICY_HND
*handle
= r
->in
.handle
;
7839 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7841 WERROR status
= WERR_OK
;
7842 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7844 DEBUG(5,("_spoolss_DeletePrinterData\n"));
7847 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
7848 OUR_HANDLE(handle
)));
7852 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
7855 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7856 DEBUG(3, ("_spoolss_DeletePrinterData: "
7857 "printer properties change denied by handle\n"));
7858 return WERR_ACCESS_DENIED
;
7861 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7862 if (!W_ERROR_IS_OK(status
))
7865 if (!r
->in
.value_name
) {
7866 free_a_printer(&printer
, 2);
7870 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
,
7873 if ( W_ERROR_IS_OK(status
) )
7874 mod_a_printer( printer
, 2 );
7876 free_a_printer(&printer
, 2);
7881 /****************************************************************
7883 ****************************************************************/
7885 WERROR
_spoolss_AddForm(pipes_struct
*p
,
7886 struct spoolss_AddForm
*r
)
7888 POLICY_HND
*handle
= r
->in
.handle
;
7889 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7890 nt_forms_struct tmpForm
;
7892 WERROR status
= WERR_OK
;
7893 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7896 nt_forms_struct
*list
=NULL
;
7897 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7899 DEBUG(5,("_spoolss_AddForm\n"));
7902 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7903 OUR_HANDLE(handle
)));
7908 /* forms can be added on printer of on the print server handle */
7910 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7912 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
7915 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7916 if (!W_ERROR_IS_OK(status
))
7920 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7921 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7922 status
= WERR_ACCESS_DENIED
;
7926 /* can't add if builtin */
7928 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
7929 status
= WERR_FILE_EXISTS
;
7933 count
= get_ntforms(&list
);
7935 if(!add_a_form(&list
, form
, &count
)) {
7936 status
= WERR_NOMEM
;
7940 write_ntforms(&list
, count
);
7943 * ChangeID must always be set if this is a printer
7946 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7947 status
= mod_a_printer(printer
, 2);
7951 free_a_printer(&printer
, 2);
7957 /****************************************************************
7959 ****************************************************************/
7961 WERROR
_spoolss_DeleteForm(pipes_struct
*p
,
7962 struct spoolss_DeleteForm
*r
)
7964 POLICY_HND
*handle
= r
->in
.handle
;
7965 const char *form_name
= r
->in
.form_name
;
7966 nt_forms_struct tmpForm
;
7968 nt_forms_struct
*list
=NULL
;
7969 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7971 WERROR status
= WERR_OK
;
7972 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7974 DEBUG(5,("_spoolss_DeleteForm\n"));
7977 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7978 OUR_HANDLE(handle
)));
7982 /* forms can be deleted on printer of on the print server handle */
7984 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7986 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
7989 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7990 if (!W_ERROR_IS_OK(status
))
7994 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7995 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
7996 status
= WERR_ACCESS_DENIED
;
8000 /* can't delete if builtin */
8002 if (get_a_builtin_ntform_by_string(form_name
,&tmpForm
)) {
8003 status
= WERR_INVALID_PARAM
;
8007 count
= get_ntforms(&list
);
8009 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8013 * ChangeID must always be set if this is a printer
8016 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8017 status
= mod_a_printer(printer
, 2);
8021 free_a_printer(&printer
, 2);
8027 /****************************************************************
8029 ****************************************************************/
8031 WERROR
_spoolss_SetForm(pipes_struct
*p
,
8032 struct spoolss_SetForm
*r
)
8034 POLICY_HND
*handle
= r
->in
.handle
;
8035 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8036 nt_forms_struct tmpForm
;
8038 WERROR status
= WERR_OK
;
8039 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8042 nt_forms_struct
*list
=NULL
;
8043 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8045 DEBUG(5,("_spoolss_SetForm\n"));
8048 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8049 OUR_HANDLE(handle
)));
8053 /* forms can be modified on printer of on the print server handle */
8055 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8057 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
8060 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8061 if (!W_ERROR_IS_OK(status
))
8065 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8066 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8067 status
= WERR_ACCESS_DENIED
;
8071 /* can't set if builtin */
8072 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8073 status
= WERR_INVALID_PARAM
;
8077 count
= get_ntforms(&list
);
8078 update_a_form(&list
, form
, count
);
8079 write_ntforms(&list
, count
);
8082 * ChangeID must always be set if this is a printer
8085 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8086 status
= mod_a_printer(printer
, 2);
8091 free_a_printer(&printer
, 2);
8097 /****************************************************************************
8098 fill_print_processor1
8099 ****************************************************************************/
8101 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8102 struct spoolss_PrintProcessorInfo1
*r
,
8103 const char *print_processor_name
)
8105 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8106 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8111 /****************************************************************************
8112 enumprintprocessors level 1.
8113 ****************************************************************************/
8115 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8116 union spoolss_PrintProcessorInfo
**info_p
,
8119 union spoolss_PrintProcessorInfo
*info
;
8122 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8123 W_ERROR_HAVE_NO_MEMORY(info
);
8127 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8128 if (!W_ERROR_IS_OK(result
)) {
8133 if (!W_ERROR_IS_OK(result
)) {
8144 /****************************************************************
8145 _spoolss_EnumPrintProcessors
8146 ****************************************************************/
8148 WERROR
_spoolss_EnumPrintProcessors(pipes_struct
*p
,
8149 struct spoolss_EnumPrintProcessors
*r
)
8153 /* that's an [in out] buffer */
8155 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8156 return WERR_INVALID_PARAM
;
8159 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8162 * Enumerate the print processors ...
8164 * Just reply with "winprint", to keep NT happy
8165 * and I can use my nice printer checker.
8170 *r
->out
.info
= NULL
;
8172 switch (r
->in
.level
) {
8174 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8178 return WERR_UNKNOWN_LEVEL
;
8181 if (!W_ERROR_IS_OK(result
)) {
8185 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8186 spoolss_EnumPrintProcessors
, NULL
,
8187 *r
->out
.info
, r
->in
.level
,
8189 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8190 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8192 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8195 /****************************************************************************
8196 fill_printprocdatatype1
8197 ****************************************************************************/
8199 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8200 struct spoolss_PrintProcDataTypesInfo1
*r
,
8201 const char *name_array
)
8203 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8204 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8209 /****************************************************************************
8210 enumprintprocdatatypes level 1.
8211 ****************************************************************************/
8213 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8214 union spoolss_PrintProcDataTypesInfo
**info_p
,
8218 union spoolss_PrintProcDataTypesInfo
*info
;
8220 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8221 W_ERROR_HAVE_NO_MEMORY(info
);
8225 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8226 if (!W_ERROR_IS_OK(result
)) {
8231 if (!W_ERROR_IS_OK(result
)) {
8242 /****************************************************************
8243 _spoolss_EnumPrintProcDataTypes
8244 ****************************************************************/
8246 WERROR
_spoolss_EnumPrintProcDataTypes(pipes_struct
*p
,
8247 struct spoolss_EnumPrintProcDataTypes
*r
)
8251 /* that's an [in out] buffer */
8253 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8254 return WERR_INVALID_PARAM
;
8257 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8261 *r
->out
.info
= NULL
;
8263 switch (r
->in
.level
) {
8265 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8269 return WERR_UNKNOWN_LEVEL
;
8272 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8273 spoolss_EnumPrintProcDataTypes
, NULL
,
8274 *r
->out
.info
, r
->in
.level
,
8276 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8277 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8279 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8282 /****************************************************************************
8284 ****************************************************************************/
8286 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8287 struct spoolss_MonitorInfo1
*r
,
8288 const char *monitor_name
)
8290 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8291 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8296 /****************************************************************************
8298 ****************************************************************************/
8300 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8301 struct spoolss_MonitorInfo2
*r
,
8302 const char *monitor_name
,
8303 const char *environment
,
8304 const char *dll_name
)
8306 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8307 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8308 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8309 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8310 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8311 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8316 /****************************************************************************
8317 enumprintmonitors level 1.
8318 ****************************************************************************/
8320 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8321 union spoolss_MonitorInfo
**info_p
,
8324 union spoolss_MonitorInfo
*info
;
8325 WERROR result
= WERR_OK
;
8327 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8328 W_ERROR_HAVE_NO_MEMORY(info
);
8332 result
= fill_monitor_1(info
, &info
[0].info1
,
8334 if (!W_ERROR_IS_OK(result
)) {
8338 result
= fill_monitor_1(info
, &info
[1].info1
,
8340 if (!W_ERROR_IS_OK(result
)) {
8345 if (!W_ERROR_IS_OK(result
)) {
8356 /****************************************************************************
8357 enumprintmonitors level 2.
8358 ****************************************************************************/
8360 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8361 union spoolss_MonitorInfo
**info_p
,
8364 union spoolss_MonitorInfo
*info
;
8365 WERROR result
= WERR_OK
;
8367 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8368 W_ERROR_HAVE_NO_MEMORY(info
);
8372 result
= fill_monitor_2(info
, &info
[0].info2
,
8374 "Windows NT X86", /* FIXME */
8376 if (!W_ERROR_IS_OK(result
)) {
8380 result
= fill_monitor_2(info
, &info
[1].info2
,
8382 "Windows NT X86", /* FIXME */
8384 if (!W_ERROR_IS_OK(result
)) {
8389 if (!W_ERROR_IS_OK(result
)) {
8400 /****************************************************************
8401 _spoolss_EnumMonitors
8402 ****************************************************************/
8404 WERROR
_spoolss_EnumMonitors(pipes_struct
*p
,
8405 struct spoolss_EnumMonitors
*r
)
8409 /* that's an [in out] buffer */
8411 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8412 return WERR_INVALID_PARAM
;
8415 DEBUG(5,("_spoolss_EnumMonitors\n"));
8418 * Enumerate the print monitors ...
8420 * Just reply with "Local Port", to keep NT happy
8421 * and I can use my nice printer checker.
8426 *r
->out
.info
= NULL
;
8428 switch (r
->in
.level
) {
8430 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8434 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8438 return WERR_UNKNOWN_LEVEL
;
8441 if (!W_ERROR_IS_OK(result
)) {
8445 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8446 spoolss_EnumMonitors
, NULL
,
8447 *r
->out
.info
, r
->in
.level
,
8449 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8450 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8452 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8455 /****************************************************************************
8456 ****************************************************************************/
8458 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8459 const print_queue_struct
*queue
,
8460 int count
, int snum
,
8461 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8463 struct spoolss_JobInfo1
*r
)
8468 for (i
=0; i
<count
&& found
== false; i
++) {
8469 if (queue
[i
].job
== (int)jobid
) {
8474 if (found
== false) {
8475 /* NT treats not found as bad param... yet another bad choice */
8476 return WERR_INVALID_PARAM
;
8479 return fill_job_info1(mem_ctx
,
8487 /****************************************************************************
8488 ****************************************************************************/
8490 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8491 const print_queue_struct
*queue
,
8492 int count
, int snum
,
8493 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8495 struct spoolss_JobInfo2
*r
)
8499 struct spoolss_DeviceMode
*devmode
;
8500 NT_DEVICEMODE
*nt_devmode
;
8503 for (i
=0; i
<count
&& found
== false; i
++) {
8504 if (queue
[i
].job
== (int)jobid
) {
8509 if (found
== false) {
8510 /* NT treats not found as bad param... yet another bad
8512 return WERR_INVALID_PARAM
;
8516 * if the print job does not have a DEVMODE associated with it,
8517 * just use the one for the printer. A NULL devicemode is not
8518 * a failure condition
8521 nt_devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8523 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
8524 W_ERROR_HAVE_NO_MEMORY(devmode
);
8525 result
= convert_nt_devicemode(devmode
, devmode
, nt_devmode
);
8526 if (!W_ERROR_IS_OK(result
)) {
8530 devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
8531 W_ERROR_HAVE_NO_MEMORY(devmode
);
8534 return fill_job_info2(mem_ctx
,
8543 /****************************************************************
8545 ****************************************************************/
8547 WERROR
_spoolss_GetJob(pipes_struct
*p
,
8548 struct spoolss_GetJob
*r
)
8550 WERROR result
= WERR_OK
;
8551 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8554 print_queue_struct
*queue
= NULL
;
8555 print_status_struct prt_status
;
8557 /* that's an [in out] buffer */
8559 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8560 return WERR_INVALID_PARAM
;
8563 DEBUG(5,("_spoolss_GetJob\n"));
8567 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8571 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8572 if (!W_ERROR_IS_OK(result
)) {
8576 count
= print_queue_status(snum
, &queue
, &prt_status
);
8578 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8579 count
, prt_status
.status
, prt_status
.message
));
8581 switch (r
->in
.level
) {
8583 result
= getjob_level_1(p
->mem_ctx
,
8584 queue
, count
, snum
, ntprinter
,
8585 r
->in
.job_id
, &r
->out
.info
->info1
);
8588 result
= getjob_level_2(p
->mem_ctx
,
8589 queue
, count
, snum
, ntprinter
,
8590 r
->in
.job_id
, &r
->out
.info
->info2
);
8593 result
= WERR_UNKNOWN_LEVEL
;
8598 free_a_printer(&ntprinter
, 2);
8600 if (!W_ERROR_IS_OK(result
)) {
8601 TALLOC_FREE(r
->out
.info
);
8605 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, NULL
,
8606 r
->out
.info
, r
->in
.level
);
8607 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8609 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8612 /****************************************************************
8613 _spoolss_GetPrinterDataEx
8615 From MSDN documentation of GetPrinterDataEx: pass request
8616 to GetPrinterData if key is "PrinterDriverData".
8617 ****************************************************************/
8619 WERROR
_spoolss_GetPrinterDataEx(pipes_struct
*p
,
8620 struct spoolss_GetPrinterDataEx
*r
)
8623 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8624 REGISTRY_VALUE
*val
= NULL
;
8625 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8627 WERROR result
= WERR_OK
;
8629 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8631 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8632 r
->in
.key_name
, r
->in
.value_name
));
8634 /* in case of problem, return some default values */
8637 *r
->out
.type
= REG_NONE
;
8640 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8641 OUR_HANDLE(r
->in
.handle
)));
8642 result
= WERR_BADFID
;
8646 /* Is the handle to a printer or to the server? */
8648 if (Printer
->printer_type
== SPLHND_SERVER
) {
8649 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8650 "Not implemented for server handles yet\n"));
8651 result
= WERR_INVALID_PARAM
;
8655 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8659 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8660 if (!W_ERROR_IS_OK(result
)) {
8664 /* check to see if the keyname is valid */
8665 if (!strlen(r
->in
.key_name
)) {
8666 result
= WERR_INVALID_PARAM
;
8670 if (lookup_printerkey(printer
->info_2
->data
, r
->in
.key_name
) == -1) {
8671 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8672 "Invalid keyname [%s]\n", r
->in
.key_name
));
8673 result
= WERR_BADFILE
;
8677 /* When given a new keyname, we should just create it */
8679 val
= get_printer_data(printer
->info_2
,
8680 r
->in
.key_name
, r
->in
.value_name
);
8682 result
= WERR_BADFILE
;
8686 *r
->out
.needed
= regval_size(val
);
8688 if (*r
->out
.needed
> r
->in
.offered
) {
8689 result
= WERR_MORE_DATA
;
8693 *r
->out
.type
= regval_type(val
);
8695 memcpy(r
->out
.buffer
, regval_data_p(val
), regval_size(val
));
8699 free_a_printer(&printer
, 2);
8705 /****************************************************************
8706 _spoolss_SetPrinterDataEx
8707 ****************************************************************/
8709 WERROR
_spoolss_SetPrinterDataEx(pipes_struct
*p
,
8710 struct spoolss_SetPrinterDataEx
*r
)
8712 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8714 WERROR result
= WERR_OK
;
8715 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8718 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8720 /* From MSDN documentation of SetPrinterDataEx: pass request to
8721 SetPrinterData if key is "PrinterDriverData" */
8724 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8725 OUR_HANDLE(r
->in
.handle
)));
8729 if (Printer
->printer_type
== SPLHND_SERVER
) {
8730 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8731 "Not implemented for server handles yet\n"));
8732 return WERR_INVALID_PARAM
;
8735 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8740 * Access check : NT returns "access denied" if you make a
8741 * SetPrinterData call without the necessary privildge.
8742 * we were originally returning OK if nothing changed
8743 * which made Win2k issue **a lot** of SetPrinterData
8744 * when connecting to a printer --jerry
8747 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8748 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8749 "change denied by handle access permissions\n"));
8750 return WERR_ACCESS_DENIED
;
8753 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8754 if (!W_ERROR_IS_OK(result
)) {
8758 /* check for OID in valuename */
8760 oid_string
= strchr(r
->in
.value_name
, ',');
8766 /* save the registry data */
8768 result
= set_printer_dataex(printer
, r
->in
.key_name
, r
->in
.value_name
,
8769 r
->in
.type
, r
->in
.buffer
, r
->in
.offered
);
8771 if (W_ERROR_IS_OK(result
)) {
8772 /* save the OID if one was specified */
8774 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
8775 r
->in
.key_name
, SPOOL_OID_KEY
);
8777 result
= WERR_NOMEM
;
8782 * I'm not checking the status here on purpose. Don't know
8783 * if this is right, but I'm returning the status from the
8784 * previous set_printer_dataex() call. I have no idea if
8785 * this is right. --jerry
8788 set_printer_dataex(printer
, str
, r
->in
.value_name
,
8789 REG_SZ
, (uint8_t *)oid_string
,
8790 strlen(oid_string
)+1);
8793 result
= mod_a_printer(printer
, 2);
8797 free_a_printer(&printer
, 2);
8802 /****************************************************************
8803 _spoolss_DeletePrinterDataEx
8804 ****************************************************************/
8806 WERROR
_spoolss_DeletePrinterDataEx(pipes_struct
*p
,
8807 struct spoolss_DeletePrinterDataEx
*r
)
8809 POLICY_HND
*handle
= r
->in
.handle
;
8810 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8812 WERROR status
= WERR_OK
;
8813 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8815 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8818 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8819 "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8823 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
8826 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8827 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8828 "printer properties change denied by handle\n"));
8829 return WERR_ACCESS_DENIED
;
8832 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
8836 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8837 if (!W_ERROR_IS_OK(status
))
8840 status
= delete_printer_dataex( printer
, r
->in
.key_name
, r
->in
.value_name
);
8842 if ( W_ERROR_IS_OK(status
) )
8843 mod_a_printer( printer
, 2 );
8845 free_a_printer(&printer
, 2);
8850 /****************************************************************
8851 _spoolss_EnumPrinterKey
8852 ****************************************************************/
8854 WERROR
_spoolss_EnumPrinterKey(pipes_struct
*p
,
8855 struct spoolss_EnumPrinterKey
*r
)
8857 fstring
*keynames
= NULL
;
8859 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8860 NT_PRINTER_DATA
*data
;
8861 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8863 WERROR result
= WERR_BADFILE
;
8865 const char **array
= NULL
;
8868 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8871 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8872 OUR_HANDLE(r
->in
.handle
)));
8876 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8880 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8881 if (!W_ERROR_IS_OK(result
)) {
8885 /* get the list of subkey names */
8887 data
= printer
->info_2
->data
;
8889 num_keys
= get_printer_subkeys(data
, r
->in
.key_name
, &keynames
);
8890 if (num_keys
== -1) {
8891 result
= WERR_BADFILE
;
8897 array
= talloc_zero_array(r
->out
.key_buffer
, const char *, num_keys
+ 1);
8899 result
= WERR_NOMEM
;
8903 for (i
=0; i
< num_keys
; i
++) {
8904 array
[i
] = talloc_strdup(array
, keynames
[i
]);
8906 result
= WERR_NOMEM
;
8910 *r
->out
.needed
+= strlen_m_term(keynames
[i
]) * 2;
8913 if (r
->in
.offered
< *r
->out
.needed
) {
8914 result
= WERR_MORE_DATA
;
8920 *r
->out
.key_buffer
= array
;
8923 if (!W_ERROR_IS_OK(result
)) {
8925 ZERO_STRUCTP(r
->out
.key_buffer
);
8928 free_a_printer(&printer
, 2);
8929 SAFE_FREE(keynames
);
8934 /****************************************************************
8935 _spoolss_DeletePrinterKey
8936 ****************************************************************/
8938 WERROR
_spoolss_DeletePrinterKey(pipes_struct
*p
,
8939 struct spoolss_DeletePrinterKey
*r
)
8941 POLICY_HND
*handle
= r
->in
.handle
;
8942 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8943 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8947 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8950 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8951 OUR_HANDLE(handle
)));
8955 /* if keyname == NULL, return error */
8957 if ( !r
->in
.key_name
)
8958 return WERR_INVALID_PARAM
;
8960 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
8963 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8964 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8965 "printer properties change denied by handle\n"));
8966 return WERR_ACCESS_DENIED
;
8969 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8970 if (!W_ERROR_IS_OK(status
))
8973 /* delete the key and all subneys */
8975 status
= delete_all_printer_data( printer
->info_2
, r
->in
.key_name
);
8977 if ( W_ERROR_IS_OK(status
) )
8978 status
= mod_a_printer(printer
, 2);
8980 free_a_printer( &printer
, 2 );
8985 /****************************************************************
8986 ****************************************************************/
8988 static WERROR
registry_value_to_printer_enum_value(TALLOC_CTX
*mem_ctx
,
8990 struct spoolss_PrinterEnumValues
*r
)
8994 r
->data
= TALLOC_ZERO_P(mem_ctx
, union spoolss_PrinterData
);
8995 W_ERROR_HAVE_NO_MEMORY(r
->data
);
8997 r
->value_name
= talloc_strdup(mem_ctx
, regval_name(v
));
8998 W_ERROR_HAVE_NO_MEMORY(r
->value_name
);
9000 r
->type
= regval_type(v
);
9001 r
->data_length
= regval_size(v
);
9003 if (r
->data_length
) {
9004 DATA_BLOB blob
= data_blob_const(regval_data_p(v
),
9006 result
= pull_spoolss_PrinterData(mem_ctx
, &blob
,
9009 if (!W_ERROR_IS_OK(result
)) {
9017 /********************************************************************
9018 * spoolss_enumprinterdataex
9019 ********************************************************************/
9021 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9023 POLICY_HND
*handle
= &q_u
->handle
;
9024 uint32 in_size
= q_u
->size
;
9027 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9028 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9029 NT_PRINTER_DATA
*p_data
;
9031 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9036 REGISTRY_VALUE
*val
;
9041 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9044 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9049 * first check for a keyname of NULL or "". Win2k seems to send
9050 * this a lot and we should send back WERR_INVALID_PARAM
9051 * no need to spend time looking up the printer in this case.
9055 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
));
9056 if ( !strlen(key
) ) {
9057 result
= WERR_INVALID_PARAM
;
9061 /* get the printer off of disk */
9063 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
9066 ZERO_STRUCT(printer
);
9067 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9068 if (!W_ERROR_IS_OK(result
))
9071 /* now look for a match on the key name */
9073 p_data
= printer
->info_2
->data
;
9075 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
));
9076 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9078 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9079 result
= WERR_INVALID_PARAM
;
9086 /* allocate the memory for the array of pointers -- if necessary */
9088 num_entries
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
9091 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9093 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9094 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9095 result
= WERR_NOMEM
;
9099 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9103 * loop through all params and build the array to pass
9104 * back to the client
9107 for ( i
=0; i
<num_entries
; i
++ )
9109 /* lookup the registry value */
9111 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
9112 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9116 value_name
= regval_name( val
);
9117 init_unistr( &enum_values
[i
].valuename
, value_name
);
9118 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9119 enum_values
[i
].type
= regval_type( val
);
9121 data_len
= regval_size( val
);
9123 if ( !(enum_values
[i
].data
= (uint8
*)TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9125 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9127 result
= WERR_NOMEM
;
9131 enum_values
[i
].data_len
= data_len
;
9133 /* keep track of the size of the array in bytes */
9135 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9138 /* housekeeping information in the reply */
9140 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9141 * the hand marshalled container size is a multiple
9142 * of 4 bytes for RPC alignment.
9146 needed
+= 4-(needed
% 4);
9149 r_u
->needed
= needed
;
9150 r_u
->returned
= num_entries
;
9152 if (needed
> in_size
) {
9153 result
= WERR_MORE_DATA
;
9157 /* copy data into the reply */
9159 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9160 response buffer size is != the offered buffer size
9162 r_u->ctr.size = r_u->needed;
9164 r_u
->ctr
.size
= in_size
;
9166 r_u
->ctr
.size_of_array
= r_u
->returned
;
9167 r_u
->ctr
.values
= enum_values
;
9171 free_a_printer(&printer
, 2);
9176 /****************************************************************************
9177 ****************************************************************************/
9179 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9180 const char *servername
,
9181 const char *environment
,
9182 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9187 werr
= compose_spoolss_server_path(mem_ctx
,
9190 SPOOLSS_PRTPROCS_PATH
,
9192 if (!W_ERROR_IS_OK(werr
)) {
9196 DEBUG(4,("print processor directory: [%s]\n", path
));
9198 r
->directory_name
= path
;
9203 /****************************************************************
9204 _spoolss_GetPrintProcessorDirectory
9205 ****************************************************************/
9207 WERROR
_spoolss_GetPrintProcessorDirectory(pipes_struct
*p
,
9208 struct spoolss_GetPrintProcessorDirectory
*r
)
9212 /* that's an [in out] buffer */
9214 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9215 return WERR_INVALID_PARAM
;
9218 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9223 /* r->in.level is ignored */
9225 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9228 &r
->out
.info
->info1
);
9229 if (!W_ERROR_IS_OK(result
)) {
9230 TALLOC_FREE(r
->out
.info
);
9234 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
, NULL
,
9235 r
->out
.info
, r
->in
.level
);
9236 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9238 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9241 /*******************************************************************
9242 ********************************************************************/
9244 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9245 const char *dllname
)
9247 enum ndr_err_code ndr_err
;
9248 struct spoolss_MonitorUi ui
;
9250 ui
.dll_name
= dllname
;
9252 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, NULL
, &ui
,
9253 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9254 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9255 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9257 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9260 /*******************************************************************
9261 Streams the monitor UI DLL name in UNICODE
9262 *******************************************************************/
9264 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9265 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9266 DATA_BLOB
*out
, uint32_t *needed
)
9268 const char *dllname
= "tcpmonui.dll";
9270 *needed
= (strlen(dllname
)+1) * 2;
9272 if (out
->length
< *needed
) {
9273 return WERR_INSUFFICIENT_BUFFER
;
9276 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9283 /*******************************************************************
9284 ********************************************************************/
9286 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9287 struct spoolss_PortData1
*port1
,
9288 const DATA_BLOB
*buf
)
9290 enum ndr_err_code ndr_err
;
9291 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, NULL
, port1
,
9292 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9293 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9294 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9296 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9299 /*******************************************************************
9300 ********************************************************************/
9302 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9303 struct spoolss_PortData2
*port2
,
9304 const DATA_BLOB
*buf
)
9306 enum ndr_err_code ndr_err
;
9307 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, NULL
, port2
,
9308 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9309 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9310 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9312 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9315 /*******************************************************************
9316 Create a new TCP/IP port
9317 *******************************************************************/
9319 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9320 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9321 DATA_BLOB
*out
, uint32_t *needed
)
9323 struct spoolss_PortData1 port1
;
9324 struct spoolss_PortData2 port2
;
9325 char *device_uri
= NULL
;
9328 const char *portname
;
9329 const char *hostaddress
;
9331 uint32_t port_number
;
9334 /* peek for spoolss_PortData version */
9336 if (!in
|| (in
->length
< (128 + 4))) {
9337 return WERR_GENERAL_FAILURE
;
9340 version
= IVAL(in
->data
, 128);
9346 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9350 portname
= port1
.portname
;
9351 hostaddress
= port1
.hostaddress
;
9352 queue
= port1
.queue
;
9353 protocol
= port1
.protocol
;
9354 port_number
= port1
.port_number
;
9360 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9364 portname
= port2
.portname
;
9365 hostaddress
= port2
.hostaddress
;
9366 queue
= port2
.queue
;
9367 protocol
= port2
.protocol
;
9368 port_number
= port2
.port_number
;
9372 DEBUG(1,("xcvtcp_addport: "
9373 "unknown version of port_data: %d\n", version
));
9374 return WERR_UNKNOWN_PORT
;
9377 /* create the device URI and call the add_port_hook() */
9380 case PROTOCOL_RAWTCP_TYPE
:
9381 device_uri
= talloc_asprintf(mem_ctx
,
9382 "socket://%s:%d/", hostaddress
,
9386 case PROTOCOL_LPR_TYPE
:
9387 device_uri
= talloc_asprintf(mem_ctx
,
9388 "lpr://%s/%s", hostaddress
, queue
);
9392 return WERR_UNKNOWN_PORT
;
9399 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9402 /*******************************************************************
9403 *******************************************************************/
9405 struct xcv_api_table xcvtcp_cmds
[] = {
9406 { "MonitorUI", xcvtcp_monitorui
},
9407 { "AddPort", xcvtcp_addport
},
9411 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9412 NT_USER_TOKEN
*token
, const char *command
,
9419 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9421 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9422 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9423 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9426 return WERR_BADFUNC
;
9429 /*******************************************************************
9430 *******************************************************************/
9431 #if 0 /* don't support management using the "Local Port" monitor */
9433 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9434 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9435 DATA_BLOB
*out
, uint32_t *needed
)
9437 const char *dllname
= "localui.dll";
9439 *needed
= (strlen(dllname
)+1) * 2;
9441 if (out
->length
< *needed
) {
9442 return WERR_INSUFFICIENT_BUFFER
;
9445 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9452 /*******************************************************************
9453 *******************************************************************/
9455 struct xcv_api_table xcvlocal_cmds
[] = {
9456 { "MonitorUI", xcvlocal_monitorui
},
9460 struct xcv_api_table xcvlocal_cmds
[] = {
9467 /*******************************************************************
9468 *******************************************************************/
9470 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9471 NT_USER_TOKEN
*token
, const char *command
,
9472 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9477 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9479 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9480 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9481 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9483 return WERR_BADFUNC
;
9486 /****************************************************************
9488 ****************************************************************/
9490 WERROR
_spoolss_XcvData(pipes_struct
*p
,
9491 struct spoolss_XcvData
*r
)
9493 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9494 DATA_BLOB out_data
= data_blob_null
;
9498 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9499 OUR_HANDLE(r
->in
.handle
)));
9503 /* Has to be a handle to the TCP/IP port monitor */
9505 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9506 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9510 /* requires administrative access to the server */
9512 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9513 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9514 return WERR_ACCESS_DENIED
;
9517 /* Allocate the outgoing buffer */
9519 if (r
->in
.out_data_size
) {
9520 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9521 if (out_data
.data
== NULL
) {
9526 switch ( Printer
->printer_type
) {
9527 case SPLHND_PORTMON_TCP
:
9528 werror
= process_xcvtcp_command(p
->mem_ctx
,
9529 p
->server_info
->ptok
,
9530 r
->in
.function_name
,
9531 &r
->in
.in_data
, &out_data
,
9534 case SPLHND_PORTMON_LOCAL
:
9535 werror
= process_xcvlocal_command(p
->mem_ctx
,
9536 p
->server_info
->ptok
,
9537 r
->in
.function_name
,
9538 &r
->in
.in_data
, &out_data
,
9542 werror
= WERR_INVALID_PRINT_MONITOR
;
9545 if (!W_ERROR_IS_OK(werror
)) {
9549 *r
->out
.status_code
= 0;
9551 memcpy(r
->out
.out_data
, out_data
.data
, out_data
.length
);
9556 /****************************************************************
9557 _spoolss_AddPrintProcessor
9558 ****************************************************************/
9560 WERROR
_spoolss_AddPrintProcessor(pipes_struct
*p
,
9561 struct spoolss_AddPrintProcessor
*r
)
9563 /* for now, just indicate success and ignore the add. We'll
9564 automatically set the winprint processor for printer
9565 entries later. Used to debug the LexMark Optra S 1855 PCL
9571 /****************************************************************
9573 ****************************************************************/
9575 WERROR
_spoolss_AddPrinter(pipes_struct
*p
,
9576 struct spoolss_AddPrinter
*r
)
9578 p
->rng_fault_state
= true;
9579 return WERR_NOT_SUPPORTED
;
9582 /****************************************************************
9583 _spoolss_GetPrinterDriver
9584 ****************************************************************/
9586 WERROR
_spoolss_GetPrinterDriver(pipes_struct
*p
,
9587 struct spoolss_GetPrinterDriver
*r
)
9589 p
->rng_fault_state
= true;
9590 return WERR_NOT_SUPPORTED
;
9593 /****************************************************************
9594 _spoolss_ReadPrinter
9595 ****************************************************************/
9597 WERROR
_spoolss_ReadPrinter(pipes_struct
*p
,
9598 struct spoolss_ReadPrinter
*r
)
9600 p
->rng_fault_state
= true;
9601 return WERR_NOT_SUPPORTED
;
9604 /****************************************************************
9605 _spoolss_WaitForPrinterChange
9606 ****************************************************************/
9608 WERROR
_spoolss_WaitForPrinterChange(pipes_struct
*p
,
9609 struct spoolss_WaitForPrinterChange
*r
)
9611 p
->rng_fault_state
= true;
9612 return WERR_NOT_SUPPORTED
;
9615 /****************************************************************
9617 ****************************************************************/
9619 WERROR
_spoolss_AddPort(pipes_struct
*p
,
9620 struct spoolss_AddPort
*r
)
9622 p
->rng_fault_state
= true;
9623 return WERR_NOT_SUPPORTED
;
9626 /****************************************************************
9627 _spoolss_ConfigurePort
9628 ****************************************************************/
9630 WERROR
_spoolss_ConfigurePort(pipes_struct
*p
,
9631 struct spoolss_ConfigurePort
*r
)
9633 p
->rng_fault_state
= true;
9634 return WERR_NOT_SUPPORTED
;
9637 /****************************************************************
9639 ****************************************************************/
9641 WERROR
_spoolss_DeletePort(pipes_struct
*p
,
9642 struct spoolss_DeletePort
*r
)
9644 p
->rng_fault_state
= true;
9645 return WERR_NOT_SUPPORTED
;
9648 /****************************************************************
9649 _spoolss_CreatePrinterIC
9650 ****************************************************************/
9652 WERROR
_spoolss_CreatePrinterIC(pipes_struct
*p
,
9653 struct spoolss_CreatePrinterIC
*r
)
9655 p
->rng_fault_state
= true;
9656 return WERR_NOT_SUPPORTED
;
9659 /****************************************************************
9660 _spoolss_PlayGDIScriptOnPrinterIC
9661 ****************************************************************/
9663 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(pipes_struct
*p
,
9664 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
9666 p
->rng_fault_state
= true;
9667 return WERR_NOT_SUPPORTED
;
9670 /****************************************************************
9671 _spoolss_DeletePrinterIC
9672 ****************************************************************/
9674 WERROR
_spoolss_DeletePrinterIC(pipes_struct
*p
,
9675 struct spoolss_DeletePrinterIC
*r
)
9677 p
->rng_fault_state
= true;
9678 return WERR_NOT_SUPPORTED
;
9681 /****************************************************************
9682 _spoolss_AddPrinterConnection
9683 ****************************************************************/
9685 WERROR
_spoolss_AddPrinterConnection(pipes_struct
*p
,
9686 struct spoolss_AddPrinterConnection
*r
)
9688 p
->rng_fault_state
= true;
9689 return WERR_NOT_SUPPORTED
;
9692 /****************************************************************
9693 _spoolss_DeletePrinterConnection
9694 ****************************************************************/
9696 WERROR
_spoolss_DeletePrinterConnection(pipes_struct
*p
,
9697 struct spoolss_DeletePrinterConnection
*r
)
9699 p
->rng_fault_state
= true;
9700 return WERR_NOT_SUPPORTED
;
9703 /****************************************************************
9704 _spoolss_PrinterMessageBox
9705 ****************************************************************/
9707 WERROR
_spoolss_PrinterMessageBox(pipes_struct
*p
,
9708 struct spoolss_PrinterMessageBox
*r
)
9710 p
->rng_fault_state
= true;
9711 return WERR_NOT_SUPPORTED
;
9714 /****************************************************************
9716 ****************************************************************/
9718 WERROR
_spoolss_AddMonitor(pipes_struct
*p
,
9719 struct spoolss_AddMonitor
*r
)
9721 p
->rng_fault_state
= true;
9722 return WERR_NOT_SUPPORTED
;
9725 /****************************************************************
9726 _spoolss_DeleteMonitor
9727 ****************************************************************/
9729 WERROR
_spoolss_DeleteMonitor(pipes_struct
*p
,
9730 struct spoolss_DeleteMonitor
*r
)
9732 p
->rng_fault_state
= true;
9733 return WERR_NOT_SUPPORTED
;
9736 /****************************************************************
9737 _spoolss_DeletePrintProcessor
9738 ****************************************************************/
9740 WERROR
_spoolss_DeletePrintProcessor(pipes_struct
*p
,
9741 struct spoolss_DeletePrintProcessor
*r
)
9743 p
->rng_fault_state
= true;
9744 return WERR_NOT_SUPPORTED
;
9747 /****************************************************************
9748 _spoolss_AddPrintProvidor
9749 ****************************************************************/
9751 WERROR
_spoolss_AddPrintProvidor(pipes_struct
*p
,
9752 struct spoolss_AddPrintProvidor
*r
)
9754 p
->rng_fault_state
= true;
9755 return WERR_NOT_SUPPORTED
;
9758 /****************************************************************
9759 _spoolss_DeletePrintProvidor
9760 ****************************************************************/
9762 WERROR
_spoolss_DeletePrintProvidor(pipes_struct
*p
,
9763 struct spoolss_DeletePrintProvidor
*r
)
9765 p
->rng_fault_state
= true;
9766 return WERR_NOT_SUPPORTED
;
9769 /****************************************************************
9770 _spoolss_FindFirstPrinterChangeNotification
9771 ****************************************************************/
9773 WERROR
_spoolss_FindFirstPrinterChangeNotification(pipes_struct
*p
,
9774 struct spoolss_FindFirstPrinterChangeNotification
*r
)
9776 p
->rng_fault_state
= true;
9777 return WERR_NOT_SUPPORTED
;
9780 /****************************************************************
9781 _spoolss_FindNextPrinterChangeNotification
9782 ****************************************************************/
9784 WERROR
_spoolss_FindNextPrinterChangeNotification(pipes_struct
*p
,
9785 struct spoolss_FindNextPrinterChangeNotification
*r
)
9787 p
->rng_fault_state
= true;
9788 return WERR_NOT_SUPPORTED
;
9791 /****************************************************************
9792 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9793 ****************************************************************/
9795 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct
*p
,
9796 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
9798 p
->rng_fault_state
= true;
9799 return WERR_NOT_SUPPORTED
;
9802 /****************************************************************
9803 _spoolss_ReplyOpenPrinter
9804 ****************************************************************/
9806 WERROR
_spoolss_ReplyOpenPrinter(pipes_struct
*p
,
9807 struct spoolss_ReplyOpenPrinter
*r
)
9809 p
->rng_fault_state
= true;
9810 return WERR_NOT_SUPPORTED
;
9813 /****************************************************************
9814 _spoolss_RouterReplyPrinter
9815 ****************************************************************/
9817 WERROR
_spoolss_RouterReplyPrinter(pipes_struct
*p
,
9818 struct spoolss_RouterReplyPrinter
*r
)
9820 p
->rng_fault_state
= true;
9821 return WERR_NOT_SUPPORTED
;
9824 /****************************************************************
9825 _spoolss_ReplyClosePrinter
9826 ****************************************************************/
9828 WERROR
_spoolss_ReplyClosePrinter(pipes_struct
*p
,
9829 struct spoolss_ReplyClosePrinter
*r
)
9831 p
->rng_fault_state
= true;
9832 return WERR_NOT_SUPPORTED
;
9835 /****************************************************************
9837 ****************************************************************/
9839 WERROR
_spoolss_AddPortEx(pipes_struct
*p
,
9840 struct spoolss_AddPortEx
*r
)
9842 p
->rng_fault_state
= true;
9843 return WERR_NOT_SUPPORTED
;
9846 /****************************************************************
9847 _spoolss_RouterFindFirstPrinterChangeNotification
9848 ****************************************************************/
9850 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct
*p
,
9851 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
9853 p
->rng_fault_state
= true;
9854 return WERR_NOT_SUPPORTED
;
9857 /****************************************************************
9858 _spoolss_SpoolerInit
9859 ****************************************************************/
9861 WERROR
_spoolss_SpoolerInit(pipes_struct
*p
,
9862 struct spoolss_SpoolerInit
*r
)
9864 p
->rng_fault_state
= true;
9865 return WERR_NOT_SUPPORTED
;
9868 /****************************************************************
9869 _spoolss_ResetPrinterEx
9870 ****************************************************************/
9872 WERROR
_spoolss_ResetPrinterEx(pipes_struct
*p
,
9873 struct spoolss_ResetPrinterEx
*r
)
9875 p
->rng_fault_state
= true;
9876 return WERR_NOT_SUPPORTED
;
9879 /****************************************************************
9880 _spoolss_RouterReplyPrinterEx
9881 ****************************************************************/
9883 WERROR
_spoolss_RouterReplyPrinterEx(pipes_struct
*p
,
9884 struct spoolss_RouterReplyPrinterEx
*r
)
9886 p
->rng_fault_state
= true;
9887 return WERR_NOT_SUPPORTED
;
9890 /****************************************************************
9892 ****************************************************************/
9894 WERROR
_spoolss_44(pipes_struct
*p
,
9895 struct spoolss_44
*r
)
9897 p
->rng_fault_state
= true;
9898 return WERR_NOT_SUPPORTED
;
9901 /****************************************************************
9903 ****************************************************************/
9905 WERROR
_spoolss_47(pipes_struct
*p
,
9906 struct spoolss_47
*r
)
9908 p
->rng_fault_state
= true;
9909 return WERR_NOT_SUPPORTED
;
9912 /****************************************************************
9914 ****************************************************************/
9916 WERROR
_spoolss_4a(pipes_struct
*p
,
9917 struct spoolss_4a
*r
)
9919 p
->rng_fault_state
= true;
9920 return WERR_NOT_SUPPORTED
;
9923 /****************************************************************
9925 ****************************************************************/
9927 WERROR
_spoolss_4b(pipes_struct
*p
,
9928 struct spoolss_4b
*r
)
9930 p
->rng_fault_state
= true;
9931 return WERR_NOT_SUPPORTED
;
9934 /****************************************************************
9936 ****************************************************************/
9938 WERROR
_spoolss_4c(pipes_struct
*p
,
9939 struct spoolss_4c
*r
)
9941 p
->rng_fault_state
= true;
9942 return WERR_NOT_SUPPORTED
;
9945 /****************************************************************
9946 _spoolss_EnumPrinterDataEx
9947 ****************************************************************/
9949 WERROR
_spoolss_EnumPrinterDataEx(pipes_struct
*p
,
9950 struct spoolss_EnumPrinterDataEx
*r
)
9952 p
->rng_fault_state
= true;
9953 return WERR_NOT_SUPPORTED
;
9956 /****************************************************************
9958 ****************************************************************/
9960 WERROR
_spoolss_53(pipes_struct
*p
,
9961 struct spoolss_53
*r
)
9963 p
->rng_fault_state
= true;
9964 return WERR_NOT_SUPPORTED
;
9967 /****************************************************************
9969 ****************************************************************/
9971 WERROR
_spoolss_55(pipes_struct
*p
,
9972 struct spoolss_55
*r
)
9974 p
->rng_fault_state
= true;
9975 return WERR_NOT_SUPPORTED
;
9978 /****************************************************************
9980 ****************************************************************/
9982 WERROR
_spoolss_56(pipes_struct
*p
,
9983 struct spoolss_56
*r
)
9985 p
->rng_fault_state
= true;
9986 return WERR_NOT_SUPPORTED
;
9989 /****************************************************************
9991 ****************************************************************/
9993 WERROR
_spoolss_57(pipes_struct
*p
,
9994 struct spoolss_57
*r
)
9996 p
->rng_fault_state
= true;
9997 return WERR_NOT_SUPPORTED
;
10000 /****************************************************************
10002 ****************************************************************/
10004 WERROR
_spoolss_5a(pipes_struct
*p
,
10005 struct spoolss_5a
*r
)
10007 p
->rng_fault_state
= true;
10008 return WERR_NOT_SUPPORTED
;
10011 /****************************************************************
10013 ****************************************************************/
10015 WERROR
_spoolss_5b(pipes_struct
*p
,
10016 struct spoolss_5b
*r
)
10018 p
->rng_fault_state
= true;
10019 return WERR_NOT_SUPPORTED
;
10022 /****************************************************************
10024 ****************************************************************/
10026 WERROR
_spoolss_5c(pipes_struct
*p
,
10027 struct spoolss_5c
*r
)
10029 p
->rng_fault_state
= true;
10030 return WERR_NOT_SUPPORTED
;
10033 /****************************************************************
10035 ****************************************************************/
10037 WERROR
_spoolss_5d(pipes_struct
*p
,
10038 struct spoolss_5d
*r
)
10040 p
->rng_fault_state
= true;
10041 return WERR_NOT_SUPPORTED
;
10044 /****************************************************************
10046 ****************************************************************/
10048 WERROR
_spoolss_5e(pipes_struct
*p
,
10049 struct spoolss_5e
*r
)
10051 p
->rng_fault_state
= true;
10052 return WERR_NOT_SUPPORTED
;
10055 /****************************************************************
10057 ****************************************************************/
10059 WERROR
_spoolss_5f(pipes_struct
*p
,
10060 struct spoolss_5f
*r
)
10062 p
->rng_fault_state
= true;
10063 return WERR_NOT_SUPPORTED
;