2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33 ((info)?ndr_size_##fn(info, level, ic, 0):0)
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44 extern userdom_struct current_user_info
;
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
56 static Printer_entry
*printers_list
;
58 typedef struct _counter_printer_0
{
59 struct _counter_printer_0
*next
;
60 struct _counter_printer_0
*prev
;
66 static counter_printer_0
*counter_list
;
68 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections
= 0;
72 /* in printing/nt_printing.c */
74 extern struct standard_mapping printer_std_mapping
, printserver_std_mapping
;
76 /* API table for Xcv Monitor functions */
78 struct xcv_api_table
{
80 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, NT_USER_TOKEN
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
83 /********************************************************************
84 * Canonicalize servername.
85 ********************************************************************/
87 static const char *canon_servername(const char *servername
)
89 const char *pservername
= servername
;
90 while (*pservername
== '\\') {
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v
)
103 return JOB_STATUS_PAUSED
;
105 return JOB_STATUS_SPOOLING
;
107 return JOB_STATUS_PRINTING
;
109 return JOB_STATUS_ERROR
;
111 return JOB_STATUS_DELETING
;
113 return JOB_STATUS_OFFLINE
;
115 return JOB_STATUS_PAPEROUT
;
117 return JOB_STATUS_PRINTED
;
119 return JOB_STATUS_DELETED
;
121 return JOB_STATUS_BLOCKED_DEVQ
;
122 case LPQ_USER_INTERVENTION
:
123 return JOB_STATUS_USER_INTERVENTION
;
128 static int nt_printq_status(int v
)
132 return PRINTER_STATUS_PAUSED
;
141 /***************************************************************************
142 Disconnect from the client
143 ****************************************************************************/
145 static void srv_spoolss_replycloseprinter(int snum
, struct policy_handle
*handle
)
151 * Tell the specific printing tdb we no longer want messages for this printer
152 * by deregistering our PID.
155 if (!print_notify_deregister_pid(snum
))
156 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
158 /* weird if the test succeds !!! */
159 if (smb_connections
==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 status
= rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe
, talloc_tos(),
167 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
168 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169 win_errstr(result
)));
171 /* if it's the last connection, deconnect the IPC$ share */
172 if (smb_connections
==1) {
174 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe
) );
175 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
177 messaging_deregister(smbd_messaging_context(),
178 MSG_PRINTER_NOTIFY2
, NULL
);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY
);
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static int printer_entry_destructor(Printer_entry
*Printer
)
195 if (Printer
->notify
.client_connected
== true) {
198 if ( Printer
->printer_type
== SPLHND_SERVER
) {
200 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
201 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
202 snum
= print_queue_snum(Printer
->sharename
);
204 srv_spoolss_replycloseprinter(snum
,
205 &Printer
->notify
.client_hnd
);
209 Printer
->notify
.flags
=0;
210 Printer
->notify
.options
=0;
211 Printer
->notify
.localmachine
[0]='\0';
212 Printer
->notify
.printerlocal
=0;
213 TALLOC_FREE(Printer
->notify
.option
);
214 Printer
->notify
.client_connected
= false;
216 free_nt_devicemode( &Printer
->nt_devmode
);
217 free_a_printer( &Printer
->printer_info
, 2 );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list
, Printer
);
224 /****************************************************************************
225 find printer index by handle
226 ****************************************************************************/
228 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
,
229 struct policy_handle
*hnd
)
231 Printer_entry
*find_printer
= NULL
;
233 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
234 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
241 /****************************************************************************
242 Close printer index by handle.
243 ****************************************************************************/
245 static bool close_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
247 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
250 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
255 close_policy_hnd(p
, hnd
);
260 /****************************************************************************
261 Delete a printer given a handle.
262 ****************************************************************************/
264 WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *sharename
)
266 char *cmd
= lp_deleteprinter_cmd();
267 char *command
= NULL
;
269 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
270 bool is_print_op
= false;
272 /* can't fail if we don't try */
277 command
= talloc_asprintf(ctx
,
284 is_print_op
= user_has_privileges( token
, &se_printop
);
286 DEBUG(10,("Running [%s]\n", command
));
288 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
293 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
294 /* Tell everyone we updated smb.conf. */
295 message_send_all(smbd_messaging_context(),
296 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
302 /********** END SePrintOperatorPrivlege BLOCK **********/
304 DEBUGADD(10,("returned [%d]\n", ret
));
306 TALLOC_FREE(command
);
309 return WERR_BADFID
; /* What to return here? */
311 /* go ahead and re-read the services immediately */
313 reload_services(false);
316 if ( lp_servicenumber( sharename
) < 0 )
317 return WERR_ACCESS_DENIED
;
322 /****************************************************************************
323 Delete a printer given a handle.
324 ****************************************************************************/
326 static WERROR
delete_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
328 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
331 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
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
, struct policy_handle
*hnd
,
365 int *number
, 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",
375 switch (Printer
->printer_type
) {
377 DEBUG(4,("short name:%s\n", Printer
->sharename
));
378 *number
= print_queue_snum(Printer
->sharename
);
379 return (*number
!= -1);
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static bool set_printer_hnd_printertype(Printer_entry
*Printer
, const char *handlename
)
394 DEBUG(3,("Setting printer type=%s\n", handlename
));
396 if ( strlen(handlename
) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
401 /* it's a print server */
402 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer
->printer_type
= SPLHND_SERVER
;
406 /* it's a printer (set_printer_hnd_name() will handle port monitors */
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer
->printer_type
= SPLHND_PRINTER
;
415 /****************************************************************************
416 Set printer handle name.. Accept names like \\server, \\server\printer,
417 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
418 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
419 XcvDataPort() interface.
420 ****************************************************************************/
422 static bool set_printer_hnd_name(Printer_entry
*Printer
, const char *handlename
)
425 int n_services
=lp_numservices();
426 char *aprinter
, *printername
;
427 const char *servername
;
430 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
433 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
434 (unsigned long)strlen(handlename
)));
436 aprinter
= CONST_DISCARD(char *, handlename
);
437 if ( *handlename
== '\\' ) {
438 servername
= canon_servername(handlename
);
439 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
444 servername
= global_myname();
447 /* save the servername to fill in replies on this handle */
449 if ( !is_myname_or_ipaddr( servername
) )
452 fstrcpy( Printer
->servername
, servername
);
454 if ( Printer
->printer_type
== SPLHND_SERVER
)
457 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
460 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
462 /* check for the Port Monitor Interface */
464 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
465 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
466 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
469 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
470 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
471 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
475 /* Search all sharenames first as this is easier than pulling
476 the printer_info_2 off of disk. Don't use find_service() since
477 that calls out to map_username() */
479 /* do another loop to look for printernames */
481 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
483 /* no point going on if this is not a printer */
485 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
488 fstrcpy(sname
, lp_servicename(snum
));
489 if ( strequal( aprinter
, sname
) ) {
494 /* no point looking up the printer object if
495 we aren't allowing printername != sharename */
497 if ( lp_force_printername(snum
) )
500 fstrcpy(sname
, lp_servicename(snum
));
504 /* This call doesn't fill in the location or comment from
505 * a CUPS server for efficiency with large numbers of printers.
509 result
= get_a_printer_search( NULL
, &printer
, 2, sname
);
510 if ( !W_ERROR_IS_OK(result
) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname
, win_errstr(result
)));
516 /* printername is always returned as \\server\printername */
517 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer
->info_2
->printername
));
520 free_a_printer( &printer
, 2);
526 if ( strequal(printername
, aprinter
) ) {
527 free_a_printer( &printer
, 2);
532 DEBUGADD(10, ("printername: %s\n", printername
));
534 free_a_printer( &printer
, 2);
537 free_a_printer( &printer
, 2);
540 DEBUGADD(4,("Printer not found\n"));
544 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
546 fstrcpy(Printer
->sharename
, sname
);
551 /****************************************************************************
552 Find first available printer slot. creates a printer handle for you.
553 ****************************************************************************/
555 static bool open_printer_hnd(pipes_struct
*p
, struct policy_handle
*hnd
,
556 const char *name
, uint32_t access_granted
)
558 Printer_entry
*new_printer
;
560 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
562 new_printer
= TALLOC_ZERO_P(NULL
, Printer_entry
);
563 if (new_printer
== NULL
) {
566 talloc_set_destructor(new_printer
, printer_entry_destructor
);
568 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
569 TALLOC_FREE(new_printer
);
573 /* Add to the internal list. */
574 DLIST_ADD(printers_list
, new_printer
);
576 new_printer
->notify
.option
=NULL
;
578 if (!set_printer_hnd_printertype(new_printer
, name
)) {
579 close_printer_handle(p
, hnd
);
583 if (!set_printer_hnd_name(new_printer
, name
)) {
584 close_printer_handle(p
, hnd
);
588 new_printer
->access_granted
= access_granted
;
590 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
595 /***************************************************************************
596 check to see if the client motify handle is monitoring the notification
597 given by (notify_type, notify_field).
598 **************************************************************************/
600 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
601 uint16_t notify_field
)
606 static bool is_monitoring_event(Printer_entry
*p
, uint16_t notify_type
,
607 uint16_t notify_field
)
609 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
613 * Flags should always be zero when the change notify
614 * is registered by the client's spooler. A user Win32 app
615 * might use the flags though instead of the NOTIFY_OPTION_INFO
624 return is_monitoring_event_flags(
625 p
->notify
.flags
, notify_type
, notify_field
);
627 for (i
= 0; i
< option
->count
; i
++) {
629 /* Check match for notify_type */
631 if (option
->types
[i
].type
!= notify_type
)
634 /* Check match for field */
636 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
637 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
643 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
644 p
->servername
, p
->sharename
, notify_type
, notify_field
));
649 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
650 _data->data.integer[0] = _integer; \
651 _data->data.integer[1] = 0;
654 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
655 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
656 if (!_data->data.string.string) {\
657 _data->data.string.size = 0; \
659 _data->data.string.size = strlen_m_term(_p) * 2;
661 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
662 _data->data.devmode.devmode = _devmode;
664 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
665 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
666 if (!_data->data.sd.sd) { \
667 _data->data.sd.sd_size = 0; \
669 _data->data.sd.sd_size = _size;
671 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
676 struct spoolss_Time st
;
680 if (!init_systemtime(&st
, t
)) {
684 p
= talloc_array(mem_ctx
, char, len
);
690 * Systemtime must be linearized as a set of UINT16's.
691 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
694 SSVAL(p
, 0, st
.year
);
695 SSVAL(p
, 2, st
.month
);
696 SSVAL(p
, 4, st
.day_of_week
);
698 SSVAL(p
, 8, st
.hour
);
699 SSVAL(p
, 10, st
.minute
);
700 SSVAL(p
, 12, st
.second
);
701 SSVAL(p
, 14, st
.millisecond
);
707 /* Convert a notification message to a struct spoolss_Notify */
709 static void notify_one_value(struct spoolss_notify_msg
*msg
,
710 struct spoolss_Notify
*data
,
713 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
716 static void notify_string(struct spoolss_notify_msg
*msg
,
717 struct spoolss_Notify
*data
,
720 /* The length of the message includes the trailing \0 */
722 data
->data
.string
.size
= msg
->len
* 2;
723 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
724 if (!data
->data
.string
.string
) {
725 data
->data
.string
.size
= 0;
730 static void notify_system_time(struct spoolss_notify_msg
*msg
,
731 struct spoolss_Notify
*data
,
734 data
->data
.string
.string
= NULL
;
735 data
->data
.string
.size
= 0;
737 if (msg
->len
!= sizeof(time_t)) {
738 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
743 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
744 &data
->data
.string
.string
,
745 &data
->data
.string
.size
);
748 struct notify2_message_table
{
750 void (*fn
)(struct spoolss_notify_msg
*msg
,
751 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
754 static struct notify2_message_table printer_notify_table
[] = {
755 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
756 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
757 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
758 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
759 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
760 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
761 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
762 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
763 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
764 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
765 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
766 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
767 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
768 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
769 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
770 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
771 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
772 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
773 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
776 static struct notify2_message_table job_notify_table
[] = {
777 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
778 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
779 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
780 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
781 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
782 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
783 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
784 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
785 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
786 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
787 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
788 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
789 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
790 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
791 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
792 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
793 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
794 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
795 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
796 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
797 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
798 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
799 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
800 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
804 /***********************************************************************
805 Allocate talloc context for container object
806 **********************************************************************/
808 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
813 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
818 /***********************************************************************
819 release all allocated memory and zero out structure
820 **********************************************************************/
822 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
828 talloc_destroy(ctr
->ctx
);
835 /***********************************************************************
836 **********************************************************************/
838 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
846 /***********************************************************************
847 **********************************************************************/
849 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
851 if ( !ctr
|| !ctr
->msg_groups
)
854 if ( idx
>= ctr
->num_groups
)
857 return &ctr
->msg_groups
[idx
];
861 /***********************************************************************
862 How many groups of change messages do we have ?
863 **********************************************************************/
865 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
870 return ctr
->num_groups
;
873 /***********************************************************************
874 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
875 **********************************************************************/
877 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
879 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
880 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
881 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
887 /* loop over all groups looking for a matching printer name */
889 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
890 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
894 /* add a new group? */
896 if ( i
== ctr
->num_groups
) {
899 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
900 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
903 ctr
->msg_groups
= groups
;
905 /* clear the new entry and set the printer name */
907 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
908 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
911 /* add the change messages; 'i' is the correct index now regardless */
913 msg_grp
= &ctr
->msg_groups
[i
];
917 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
918 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
921 msg_grp
->msgs
= msg_list
;
923 new_slot
= msg_grp
->num_msgs
-1;
924 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
926 /* need to allocate own copy of data */
929 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
930 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
932 return ctr
->num_groups
;
935 /***********************************************************************
936 Send a change notication message on all handles which have a call
938 **********************************************************************/
940 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
943 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
944 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
945 SPOOLSS_NOTIFY_MSG
*messages
;
946 int sending_msg_count
;
949 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953 messages
= msg_group
->msgs
;
956 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
962 /* loop over all printers */
964 for (p
= printers_list
; p
; p
= p
->next
) {
965 struct spoolss_Notify
*notifies
;
970 /* Is there notification on this handle? */
972 if ( !p
->notify
.client_connected
)
975 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
977 /* For this printer? Print servers always receive
980 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
981 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
984 DEBUG(10,("Our printer\n"));
986 /* allocate the max entries possible */
988 notifies
= TALLOC_ZERO_ARRAY(mem_ctx
, struct spoolss_Notify
, msg_group
->num_msgs
);
993 /* build the array of change notifications */
995 sending_msg_count
= 0;
997 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
998 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1000 /* Are we monitoring this event? */
1002 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1005 sending_msg_count
++;
1008 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1009 msg
->type
, msg
->field
, p
->sharename
));
1012 * if the is a printer notification handle and not a job notification
1013 * type, then set the id to 0. Other wise just use what was specified
1016 * When registering change notification on a print server handle
1017 * we always need to send back the id (snum) matching the printer
1018 * for which the change took place. For change notify registered
1019 * on a printer handle, this does not matter and the id should be 0.
1024 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1030 /* Convert unix jobid to smb jobid */
1032 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1033 id
= sysjob_to_jobid(msg
->id
);
1036 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1041 construct_info_data( ¬ifies
[count
], msg
->type
, msg
->field
, id
);
1044 case PRINTER_NOTIFY_TYPE
:
1045 if ( printer_notify_table
[msg
->field
].fn
)
1046 printer_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1049 case JOB_NOTIFY_TYPE
:
1050 if ( job_notify_table
[msg
->field
].fn
)
1051 job_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1055 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1062 if ( sending_msg_count
) {
1065 union spoolss_ReplyPrinterInfo info
;
1066 struct spoolss_NotifyInfo info0
;
1067 uint32_t reply_result
;
1069 info0
.version
= 0x2;
1070 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1071 info0
.count
= count
;
1072 info0
.notifies
= notifies
;
1074 info
.info0
= &info0
;
1076 status
= rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe
, mem_ctx
,
1077 &p
->notify
.client_hnd
,
1078 p
->notify
.change
, /* color */
1081 0, /* reply_type, must be 0 */
1084 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
1085 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1086 notify_cli_pipe
->srv_name_slash
,
1089 switch (reply_result
) {
1092 case PRINTER_NOTIFY_INFO_DISCARDED
:
1093 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1094 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1103 DEBUG(8,("send_notify2_changes: Exit...\n"));
1107 /***********************************************************************
1108 **********************************************************************/
1110 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1113 uint32_t tv_sec
, tv_usec
;
1116 /* Unpack message */
1118 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1121 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1123 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1126 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1127 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1129 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1130 &msg
->len
, &msg
->notify
.data
);
1132 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1133 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1135 tv
->tv_sec
= tv_sec
;
1136 tv
->tv_usec
= tv_usec
;
1139 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1140 msg
->notify
.value
[1]));
1142 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1147 /********************************************************************
1148 Receive a notify2 message list
1149 ********************************************************************/
1151 static void receive_notify2_message_list(struct messaging_context
*msg
,
1154 struct server_id server_id
,
1157 size_t msg_count
, i
;
1158 char *buf
= (char *)data
->data
;
1161 SPOOLSS_NOTIFY_MSG notify
;
1162 SPOOLSS_NOTIFY_MSG_CTR messages
;
1165 if (data
->length
< 4) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170 msg_count
= IVAL(buf
, 0);
1173 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1175 if (msg_count
== 0) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180 /* initialize the container */
1182 ZERO_STRUCT( messages
);
1183 notify_msg_ctr_init( &messages
);
1186 * build message groups for each printer identified
1187 * in a change_notify msg. Remember that a PCN message
1188 * includes the handle returned for the srv_spoolss_replyopenprinter()
1189 * call. Therefore messages are grouped according to printer handle.
1192 for ( i
=0; i
<msg_count
; i
++ ) {
1193 struct timeval msg_tv
;
1195 if (msg_ptr
+ 4 - buf
> data
->length
) {
1196 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200 msg_len
= IVAL(msg_ptr
,0);
1203 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1204 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208 /* unpack messages */
1210 ZERO_STRUCT( notify
);
1211 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1214 /* add to correct list in container */
1216 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1218 /* free memory that might have been allocated by notify2_unpack_msg() */
1220 if ( notify
.len
!= 0 )
1221 SAFE_FREE( notify
.notify
.data
);
1224 /* process each group of messages */
1226 num_groups
= notify_msg_ctr_numgroups( &messages
);
1227 for ( i
=0; i
<num_groups
; i
++ )
1228 send_notify2_changes( &messages
, i
);
1233 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1234 (uint32_t)msg_count
));
1236 notify_msg_ctr_destroy( &messages
);
1241 /********************************************************************
1242 Send a message to ourself about new driver being installed
1243 so we can upgrade the information for each printer bound to this
1245 ********************************************************************/
1247 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
)
1249 int len
= strlen(drivername
);
1254 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1257 messaging_send_buf(smbd_messaging_context(), procid_self(),
1258 MSG_PRINTER_DRVUPGRADE
,
1259 (uint8_t *)drivername
, len
+1);
1264 /**********************************************************************
1265 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1266 over all printers, upgrading ones as necessary
1267 **********************************************************************/
1269 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1272 struct server_id server_id
,
1277 int n_services
= lp_numservices();
1280 len
= MIN(data
->length
,sizeof(drivername
)-1);
1281 strncpy(drivername
, (const char *)data
->data
, len
);
1283 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1285 /* Iterate the printer list */
1287 for (snum
=0; snum
<n_services
; snum
++)
1289 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1292 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1294 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1295 if (!W_ERROR_IS_OK(result
))
1298 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1300 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1302 /* all we care about currently is the change_id */
1304 result
= mod_a_printer(printer
, 2);
1305 if (!W_ERROR_IS_OK(result
)) {
1306 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1307 win_errstr(result
)));
1311 free_a_printer(&printer
, 2);
1318 /********************************************************************
1319 Update the cache for all printq's with a registered client
1321 ********************************************************************/
1323 void update_monitored_printq_cache( void )
1325 Printer_entry
*printer
= printers_list
;
1328 /* loop through all printers and update the cache where
1329 client_connected == true */
1332 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1333 && printer
->notify
.client_connected
)
1335 snum
= print_queue_snum(printer
->sharename
);
1336 print_queue_status( snum
, NULL
, NULL
);
1339 printer
= printer
->next
;
1344 /********************************************************************
1345 Send a message to ourself about new driver being installed
1346 so we can upgrade the information for each printer bound to this
1348 ********************************************************************/
1350 static bool srv_spoolss_reset_printerdata(char* drivername
)
1352 int len
= strlen(drivername
);
1357 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1360 messaging_send_buf(smbd_messaging_context(), procid_self(),
1361 MSG_PRINTERDATA_INIT_RESET
,
1362 (uint8_t *)drivername
, len
+1);
1367 /**********************************************************************
1368 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1369 over all printers, resetting printer data as neessary
1370 **********************************************************************/
1372 void reset_all_printerdata(struct messaging_context
*msg
,
1375 struct server_id server_id
,
1380 int n_services
= lp_numservices();
1383 len
= MIN( data
->length
, sizeof(drivername
)-1 );
1384 strncpy( drivername
, (const char *)data
->data
, len
);
1386 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1388 /* Iterate the printer list */
1390 for ( snum
=0; snum
<n_services
; snum
++ )
1392 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1395 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1397 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1398 if ( !W_ERROR_IS_OK(result
) )
1402 * if the printer is bound to the driver,
1403 * then reset to the new driver initdata
1406 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1408 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1410 if ( !set_driver_init(printer
, 2) ) {
1411 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1412 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1415 result
= mod_a_printer( printer
, 2 );
1416 if ( !W_ERROR_IS_OK(result
) ) {
1417 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1418 get_dos_error_msg(result
)));
1422 free_a_printer( &printer
, 2 );
1431 /****************************************************************
1432 _spoolss_OpenPrinter
1433 ****************************************************************/
1435 WERROR
_spoolss_OpenPrinter(pipes_struct
*p
,
1436 struct spoolss_OpenPrinter
*r
)
1438 struct spoolss_OpenPrinterEx e
;
1441 ZERO_STRUCT(e
.in
.userlevel
);
1443 e
.in
.printername
= r
->in
.printername
;
1444 e
.in
.datatype
= r
->in
.datatype
;
1445 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1446 e
.in
.access_mask
= r
->in
.access_mask
;
1449 e
.out
.handle
= r
->out
.handle
;
1451 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1453 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1454 /* OpenPrinterEx returns this for a bad
1455 * printer name. We must return WERR_INVALID_PRINTER_NAME
1458 werr
= WERR_INVALID_PRINTER_NAME
;
1464 /********************************************************************
1465 ********************************************************************/
1467 bool convert_devicemode(const char *printername
,
1468 const struct spoolss_DeviceMode
*devmode
,
1469 NT_DEVICEMODE
**pp_nt_devmode
)
1471 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1474 * Ensure nt_devmode is a valid pointer
1475 * as we will be overwriting it.
1478 if (nt_devmode
== NULL
) {
1479 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1480 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1484 fstrcpy(nt_devmode
->devicename
, devmode
->devicename
);
1485 fstrcpy(nt_devmode
->formname
, devmode
->formname
);
1487 nt_devmode
->devicename
[31] = '\0';
1488 nt_devmode
->formname
[31] = '\0';
1490 nt_devmode
->specversion
= devmode
->specversion
;
1491 nt_devmode
->driverversion
= devmode
->driverversion
;
1492 nt_devmode
->size
= devmode
->size
;
1493 nt_devmode
->fields
= devmode
->fields
;
1494 nt_devmode
->orientation
= devmode
->orientation
;
1495 nt_devmode
->papersize
= devmode
->papersize
;
1496 nt_devmode
->paperlength
= devmode
->paperlength
;
1497 nt_devmode
->paperwidth
= devmode
->paperwidth
;
1498 nt_devmode
->scale
= devmode
->scale
;
1499 nt_devmode
->copies
= devmode
->copies
;
1500 nt_devmode
->defaultsource
= devmode
->defaultsource
;
1501 nt_devmode
->printquality
= devmode
->printquality
;
1502 nt_devmode
->color
= devmode
->color
;
1503 nt_devmode
->duplex
= devmode
->duplex
;
1504 nt_devmode
->yresolution
= devmode
->yresolution
;
1505 nt_devmode
->ttoption
= devmode
->ttoption
;
1506 nt_devmode
->collate
= devmode
->collate
;
1508 nt_devmode
->logpixels
= devmode
->logpixels
;
1509 nt_devmode
->bitsperpel
= devmode
->bitsperpel
;
1510 nt_devmode
->pelswidth
= devmode
->pelswidth
;
1511 nt_devmode
->pelsheight
= devmode
->pelsheight
;
1512 nt_devmode
->displayflags
= devmode
->displayflags
;
1513 nt_devmode
->displayfrequency
= devmode
->displayfrequency
;
1514 nt_devmode
->icmmethod
= devmode
->icmmethod
;
1515 nt_devmode
->icmintent
= devmode
->icmintent
;
1516 nt_devmode
->mediatype
= devmode
->mediatype
;
1517 nt_devmode
->dithertype
= devmode
->dithertype
;
1518 nt_devmode
->reserved1
= devmode
->reserved1
;
1519 nt_devmode
->reserved2
= devmode
->reserved2
;
1520 nt_devmode
->panningwidth
= devmode
->panningwidth
;
1521 nt_devmode
->panningheight
= devmode
->panningheight
;
1524 * Only change private and driverextra if the incoming devmode
1525 * has a new one. JRA.
1528 if ((devmode
->__driverextra_length
!= 0) && (devmode
->driverextra_data
.data
!= NULL
)) {
1529 SAFE_FREE(nt_devmode
->nt_dev_private
);
1530 nt_devmode
->driverextra
= devmode
->__driverextra_length
;
1531 if((nt_devmode
->nt_dev_private
= SMB_MALLOC_ARRAY(uint8_t, nt_devmode
->driverextra
)) == NULL
)
1533 memcpy(nt_devmode
->nt_dev_private
, devmode
->driverextra_data
.data
, nt_devmode
->driverextra
);
1536 *pp_nt_devmode
= nt_devmode
;
1541 /****************************************************************
1542 _spoolss_OpenPrinterEx
1543 ****************************************************************/
1545 WERROR
_spoolss_OpenPrinterEx(pipes_struct
*p
,
1546 struct spoolss_OpenPrinterEx
*r
)
1549 Printer_entry
*Printer
=NULL
;
1551 if (!r
->in
.printername
) {
1552 return WERR_INVALID_PARAM
;
1555 /* some sanity check because you can open a printer or a print server */
1556 /* aka: \\server\printer or \\server */
1558 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1560 if (!open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0)) {
1561 ZERO_STRUCTP(r
->out
.handle
);
1562 return WERR_INVALID_PARAM
;
1565 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1567 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1568 "handle we created for printer %s\n", r
->in
.printername
));
1569 close_printer_handle(p
, r
->out
.handle
);
1570 ZERO_STRUCTP(r
->out
.handle
);
1571 return WERR_INVALID_PARAM
;
1575 * First case: the user is opening the print server:
1577 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1578 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1580 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1581 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1582 * or if the user is listed in the smb.conf printer admin parameter.
1584 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1585 * client view printer folder, but does not show the MSAPW.
1587 * Note: this test needs code to check access rights here too. Jeremy
1588 * could you look at this?
1590 * Second case: the user is opening a printer:
1591 * NT doesn't let us connect to a printer if the connecting user
1592 * doesn't have print permission.
1594 * Third case: user is opening a Port Monitor
1595 * access checks same as opening a handle to the print server.
1598 switch (Printer
->printer_type
)
1601 case SPLHND_PORTMON_TCP
:
1602 case SPLHND_PORTMON_LOCAL
:
1603 /* Printserver handles use global struct... */
1607 /* Map standard access rights to object specific access rights */
1609 se_map_standard(&r
->in
.access_mask
,
1610 &printserver_std_mapping
);
1612 /* Deny any object specific bits that don't apply to print
1613 servers (i.e printer and job specific bits) */
1615 r
->in
.access_mask
&= SPECIFIC_RIGHTS_MASK
;
1617 if (r
->in
.access_mask
&
1618 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1619 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1620 close_printer_handle(p
, r
->out
.handle
);
1621 ZERO_STRUCTP(r
->out
.handle
);
1622 return WERR_ACCESS_DENIED
;
1625 /* Allow admin access */
1627 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1629 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1631 if (!lp_ms_add_printer_wizard()) {
1632 close_printer_handle(p
, r
->out
.handle
);
1633 ZERO_STRUCTP(r
->out
.handle
);
1634 return WERR_ACCESS_DENIED
;
1637 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1638 and not a printer admin, then fail */
1640 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
1641 !user_has_privileges(p
->server_info
->ptok
,
1643 !token_contains_name_in_list(
1644 uidtoname(p
->server_info
->utok
.uid
),
1645 pdb_get_domain(p
->server_info
->sam_account
),
1647 p
->server_info
->ptok
,
1648 lp_printer_admin(snum
))) {
1649 close_printer_handle(p
, r
->out
.handle
);
1650 ZERO_STRUCTP(r
->out
.handle
);
1651 return WERR_ACCESS_DENIED
;
1654 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1658 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1661 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1662 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1664 /* We fall through to return WERR_OK */
1667 case SPLHND_PRINTER
:
1668 /* NT doesn't let us connect to a printer if the connecting user
1669 doesn't have print permission. */
1671 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1672 close_printer_handle(p
, r
->out
.handle
);
1673 ZERO_STRUCTP(r
->out
.handle
);
1677 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1678 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1681 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1683 /* map an empty access mask to the minimum access mask */
1684 if (r
->in
.access_mask
== 0x0)
1685 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1688 * If we are not serving the printer driver for this printer,
1689 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1690 * will keep NT clients happy --jerry
1693 if (lp_use_client_driver(snum
)
1694 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1696 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1699 /* check smb.conf parameters and the the sec_desc */
1701 if ( !check_access(get_client_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1702 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1703 ZERO_STRUCTP(r
->out
.handle
);
1704 return WERR_ACCESS_DENIED
;
1707 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1708 p
->server_info
->ptok
, snum
) ||
1709 !print_access_check(p
->server_info
, snum
,
1710 r
->in
.access_mask
)) {
1711 DEBUG(3, ("access DENIED for printer open\n"));
1712 close_printer_handle(p
, r
->out
.handle
);
1713 ZERO_STRUCTP(r
->out
.handle
);
1714 return WERR_ACCESS_DENIED
;
1717 if ((r
->in
.access_mask
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1718 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1719 close_printer_handle(p
, r
->out
.handle
);
1720 ZERO_STRUCTP(r
->out
.handle
);
1721 return WERR_ACCESS_DENIED
;
1724 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1725 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1727 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1729 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1730 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1735 /* sanity check to prevent programmer error */
1736 ZERO_STRUCTP(r
->out
.handle
);
1740 Printer
->access_granted
= r
->in
.access_mask
;
1743 * If the client sent a devmode in the OpenPrinter() call, then
1744 * save it here in case we get a job submission on this handle
1747 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1748 r
->in
.devmode_ctr
.devmode
) {
1749 convert_devicemode(Printer
->sharename
,
1750 r
->in
.devmode_ctr
.devmode
,
1751 &Printer
->nt_devmode
);
1754 #if 0 /* JERRY -- I'm doubtful this is really effective */
1755 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1756 optimization in Windows 2000 clients --jerry */
1758 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1759 && (RA_WIN2K
== get_remote_arch()) )
1761 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1762 sys_usleep( 500000 );
1769 /****************************************************************************
1770 ****************************************************************************/
1772 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2
*r
,
1773 NT_PRINTER_INFO_LEVEL_2
*d
)
1775 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1781 d
->attributes
= r
->attributes
;
1782 d
->priority
= r
->priority
;
1783 d
->default_priority
= r
->defaultpriority
;
1784 d
->starttime
= r
->starttime
;
1785 d
->untiltime
= r
->untiltime
;
1786 d
->status
= r
->status
;
1787 d
->cjobs
= r
->cjobs
;
1789 fstrcpy(d
->servername
, r
->servername
);
1790 fstrcpy(d
->printername
, r
->printername
);
1791 fstrcpy(d
->sharename
, r
->sharename
);
1792 fstrcpy(d
->portname
, r
->portname
);
1793 fstrcpy(d
->drivername
, r
->drivername
);
1794 slprintf(d
->comment
, sizeof(d
->comment
)-1, "%s", r
->comment
);
1795 fstrcpy(d
->location
, r
->location
);
1796 fstrcpy(d
->sepfile
, r
->sepfile
);
1797 fstrcpy(d
->printprocessor
, r
->printprocessor
);
1798 fstrcpy(d
->datatype
, r
->datatype
);
1799 fstrcpy(d
->parameters
, r
->parameters
);
1804 /****************************************************************************
1805 ****************************************************************************/
1807 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1808 NT_PRINTER_INFO_LEVEL
*printer
)
1812 switch (info_ctr
->level
) {
1814 /* allocate memory if needed. Messy because
1815 convert_printer_info is used to update an existing
1816 printer or build a new one */
1818 if (!printer
->info_2
) {
1819 printer
->info_2
= TALLOC_ZERO_P(printer
, NT_PRINTER_INFO_LEVEL_2
);
1820 if (!printer
->info_2
) {
1821 DEBUG(0,("convert_printer_info: "
1822 "talloc() failed!\n"));
1827 ret
= printer_info2_to_nt_printer_info2(info_ctr
->info
.info2
,
1829 printer
->info_2
->setuptime
= time(NULL
);
1836 /*******************************************************************
1837 ********************************************************************/
1839 static bool string_array_to_fstring_array(const char **sarray
, fstring
**farray
)
1848 *farray
= SMB_MALLOC_ARRAY(fstring
, 1);
1853 for (i
=0; sarray
[i
] != NULL
; i
++) {
1854 *farray
= SMB_REALLOC_ARRAY(*farray
, fstring
, i
+2);
1858 fstrcpy((*farray
)[i
], sarray
[i
]);
1861 fstrcpy((*farray
)[i
], "");
1866 /*******************************************************************
1867 ********************************************************************/
1869 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3
*r
,
1870 NT_PRINTER_DRIVER_INFO_LEVEL_3
**p
)
1872 NT_PRINTER_DRIVER_INFO_LEVEL_3
*d
;
1874 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1877 *p
= SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3
);
1886 d
->cversion
= r
->version
;
1888 fstrcpy(d
->name
, r
->driver_name
);
1889 fstrcpy(d
->environment
, r
->architecture
);
1890 fstrcpy(d
->driverpath
, r
->driver_path
);
1891 fstrcpy(d
->datafile
, r
->data_file
);
1892 fstrcpy(d
->configfile
, r
->config_file
);
1893 fstrcpy(d
->helpfile
, r
->help_file
);
1894 fstrcpy(d
->monitorname
, r
->monitor_name
);
1895 fstrcpy(d
->defaultdatatype
, r
->default_datatype
);
1897 DEBUGADD(8,( "version: %d\n", d
->cversion
));
1898 DEBUGADD(8,( "name: %s\n", d
->name
));
1899 DEBUGADD(8,( "environment: %s\n", d
->environment
));
1900 DEBUGADD(8,( "driverpath: %s\n", d
->driverpath
));
1901 DEBUGADD(8,( "datafile: %s\n", d
->datafile
));
1902 DEBUGADD(8,( "configfile: %s\n", d
->configfile
));
1903 DEBUGADD(8,( "helpfile: %s\n", d
->helpfile
));
1904 DEBUGADD(8,( "monitorname: %s\n", d
->monitorname
));
1905 DEBUGADD(8,( "defaultdatatype: %s\n", d
->defaultdatatype
));
1907 if (r
->dependent_files
) {
1908 if (!string_array_to_fstring_array(r
->dependent_files
->string
,
1909 &d
->dependentfiles
)) {
1918 /*******************************************************************
1919 ********************************************************************/
1921 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6
*r
,
1922 NT_PRINTER_DRIVER_INFO_LEVEL_6
**p
)
1924 NT_PRINTER_DRIVER_INFO_LEVEL_6
*d
;
1926 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1929 *p
= SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6
);
1938 d
->version
= r
->version
;
1940 fstrcpy(d
->name
, r
->driver_name
);
1941 fstrcpy(d
->environment
, r
->architecture
);
1942 fstrcpy(d
->driverpath
, r
->driver_path
);
1943 fstrcpy(d
->datafile
, r
->data_file
);
1944 fstrcpy(d
->configfile
, r
->config_file
);
1945 fstrcpy(d
->helpfile
, r
->help_file
);
1946 fstrcpy(d
->monitorname
, r
->monitor_name
);
1947 fstrcpy(d
->defaultdatatype
, r
->default_datatype
);
1949 DEBUGADD(8,( "version: %d\n", d
->version
));
1950 DEBUGADD(8,( "name: %s\n", d
->name
));
1951 DEBUGADD(8,( "environment: %s\n", d
->environment
));
1952 DEBUGADD(8,( "driverpath: %s\n", d
->driverpath
));
1953 DEBUGADD(8,( "datafile: %s\n", d
->datafile
));
1954 DEBUGADD(8,( "configfile: %s\n", d
->configfile
));
1955 DEBUGADD(8,( "helpfile: %s\n", d
->helpfile
));
1956 DEBUGADD(8,( "monitorname: %s\n", d
->monitorname
));
1957 DEBUGADD(8,( "defaultdatatype: %s\n", d
->defaultdatatype
));
1959 if (r
->dependent_files
) {
1960 if (!string_array_to_fstring_array(r
->dependent_files
->string
,
1961 &d
->dependentfiles
)) {
1966 if (r
->previous_names
) {
1967 if (!string_array_to_fstring_array(r
->previous_names
->string
,
1968 &d
->previousnames
)) {
1980 /********************************************************************
1981 ********************************************************************/
1983 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr
*r
,
1984 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
,
1989 printer
->info_3
= NULL
;
1990 if (!driver_info3_to_nt_driver_info3(r
->info
.info3
, &printer
->info_3
)) {
1995 printer
->info_6
= NULL
;
1996 if (!driver_info6_to_nt_driver_info6(r
->info
.info6
, &printer
->info_6
)) {
2007 /********************************************************************
2008 * _spoolss_enddocprinter_internal.
2009 ********************************************************************/
2011 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
,
2012 struct policy_handle
*handle
)
2014 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2018 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
2022 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
2025 Printer
->document_started
= false;
2026 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
2027 /* error codes unhandled so far ... */
2032 /****************************************************************
2033 _spoolss_ClosePrinter
2034 ****************************************************************/
2036 WERROR
_spoolss_ClosePrinter(pipes_struct
*p
,
2037 struct spoolss_ClosePrinter
*r
)
2039 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2041 if (Printer
&& Printer
->document_started
)
2042 _spoolss_enddocprinter_internal(p
, r
->in
.handle
); /* print job was not closed */
2044 if (!close_printer_handle(p
, r
->in
.handle
))
2047 /* clear the returned printer handle. Observed behavior
2048 from Win2k server. Don't think this really matters.
2049 Previous code just copied the value of the closed
2052 ZERO_STRUCTP(r
->out
.handle
);
2057 /****************************************************************
2058 _spoolss_DeletePrinter
2059 ****************************************************************/
2061 WERROR
_spoolss_DeletePrinter(pipes_struct
*p
,
2062 struct spoolss_DeletePrinter
*r
)
2064 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2067 if (Printer
&& Printer
->document_started
)
2068 _spoolss_enddocprinter_internal(p
, r
->in
.handle
); /* print job was not closed */
2070 result
= delete_printer_handle(p
, r
->in
.handle
);
2072 update_c_setprinter(false);
2077 /*******************************************************************
2078 * static function to lookup the version id corresponding to an
2079 * long architecture string
2080 ******************************************************************/
2082 static int get_version_id(const char *arch
)
2085 struct print_architecture_table_node archi_table
[]= {
2087 {"Windows 4.0", "WIN40", 0 },
2088 {"Windows NT x86", "W32X86", 2 },
2089 {"Windows NT R4000", "W32MIPS", 2 },
2090 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2091 {"Windows NT PowerPC", "W32PPC", 2 },
2092 {"Windows IA64", "IA64", 3 },
2093 {"Windows x64", "x64", 3 },
2097 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2099 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2100 return (archi_table
[i
].version
);
2106 /****************************************************************
2107 _spoolss_DeletePrinterDriver
2108 ****************************************************************/
2110 WERROR
_spoolss_DeletePrinterDriver(pipes_struct
*p
,
2111 struct spoolss_DeletePrinterDriver
*r
)
2113 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2114 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2117 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2118 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2120 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2121 and not a printer admin, then fail */
2123 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
2124 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
2125 && !token_contains_name_in_list(
2126 uidtoname(p
->server_info
->utok
.uid
),
2127 pdb_get_domain(p
->server_info
->sam_account
),
2129 p
->server_info
->ptok
,
2130 lp_printer_admin(-1)) )
2132 return WERR_ACCESS_DENIED
;
2135 /* check that we have a valid driver name first */
2137 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
2138 return WERR_INVALID_ENVIRONMENT
;
2141 ZERO_STRUCT(info_win2k
);
2143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, r
->in
.driver
,
2147 /* try for Win2k driver if "Windows NT x86" */
2149 if ( version
== 2 ) {
2151 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3,
2155 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2159 /* otherwise it was a failure */
2161 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2167 if (printer_driver_in_use(info
.info_3
)) {
2168 status
= WERR_PRINTER_DRIVER_IN_USE
;
2174 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3,
2176 r
->in
.architecture
, 3)))
2178 /* if we get to here, we now have 2 driver info structures to remove */
2179 /* remove the Win2k driver first*/
2181 status_win2k
= delete_printer_driver(
2182 p
, info_win2k
.info_3
, 3, false);
2183 free_a_printer_driver( info_win2k
, 3 );
2185 /* this should not have failed---if it did, report to client */
2186 if ( !W_ERROR_IS_OK(status_win2k
) )
2188 status
= status_win2k
;
2194 status
= delete_printer_driver(p
, info
.info_3
, version
, false);
2196 /* if at least one of the deletes succeeded return OK */
2198 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2202 free_a_printer_driver( info
, 3 );
2207 /****************************************************************
2208 _spoolss_DeletePrinterDriverEx
2209 ****************************************************************/
2211 WERROR
_spoolss_DeletePrinterDriverEx(pipes_struct
*p
,
2212 struct spoolss_DeletePrinterDriverEx
*r
)
2214 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2215 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2219 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2220 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2222 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2223 and not a printer admin, then fail */
2225 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
2226 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
2227 && !token_contains_name_in_list(
2228 uidtoname(p
->server_info
->utok
.uid
),
2229 pdb_get_domain(p
->server_info
->sam_account
),
2231 p
->server_info
->ptok
, lp_printer_admin(-1)) )
2233 return WERR_ACCESS_DENIED
;
2236 /* check that we have a valid driver name first */
2237 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
2238 /* this is what NT returns */
2239 return WERR_INVALID_ENVIRONMENT
;
2242 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2243 version
= r
->in
.version
;
2246 ZERO_STRUCT(info_win2k
);
2248 status
= get_a_printer_driver(&info
, 3, r
->in
.driver
,
2249 r
->in
.architecture
, version
);
2251 if ( !W_ERROR_IS_OK(status
) )
2254 * if the client asked for a specific version,
2255 * or this is something other than Windows NT x86,
2259 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2262 /* try for Win2k driver if "Windows NT x86" */
2265 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, r
->in
.driver
,
2268 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2273 if ( printer_driver_in_use(info
.info_3
) ) {
2274 status
= WERR_PRINTER_DRIVER_IN_USE
;
2279 * we have a couple of cases to consider.
2280 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2281 * then the delete should fail if **any** files overlap with
2283 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2284 * non-overlapping files
2285 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2286 * is set, the do not delete any files
2287 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2290 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2292 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2294 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) ) {
2295 /* no idea of the correct error here */
2296 status
= WERR_ACCESS_DENIED
;
2301 /* also check for W32X86/3 if necessary; maybe we already have? */
2303 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2304 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3,
2306 r
->in
.architecture
, 3)))
2309 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) ) {
2310 /* no idea of the correct error here */
2311 free_a_printer_driver( info_win2k
, 3 );
2312 status
= WERR_ACCESS_DENIED
;
2316 /* if we get to here, we now have 2 driver info structures to remove */
2317 /* remove the Win2k driver first*/
2319 status_win2k
= delete_printer_driver(
2320 p
, info_win2k
.info_3
, 3, delete_files
);
2321 free_a_printer_driver( info_win2k
, 3 );
2323 /* this should not have failed---if it did, report to client */
2325 if ( !W_ERROR_IS_OK(status_win2k
) )
2330 status
= delete_printer_driver(p
, info
.info_3
, version
, delete_files
);
2332 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2335 free_a_printer_driver( info
, 3 );
2341 /****************************************************************************
2342 Internal routine for removing printerdata
2343 ***************************************************************************/
2345 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2347 return delete_printer_data( printer
->info_2
, key
, value
);
2350 /****************************************************************************
2351 Internal routine for storing printerdata
2352 ***************************************************************************/
2354 WERROR
set_printer_dataex(NT_PRINTER_INFO_LEVEL
*printer
,
2355 const char *key
, const char *value
,
2356 uint32_t type
, uint8_t *data
, int real_len
)
2358 /* the registry objects enforce uniqueness based on value name */
2360 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2363 /********************************************************************
2364 GetPrinterData on a printer server Handle.
2365 ********************************************************************/
2367 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2369 enum winreg_Type
*type
,
2370 union spoolss_PrinterData
*data
)
2372 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2374 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2380 if (!StrCaseCmp(value
, "BeepEnabled")) {
2386 if (!StrCaseCmp(value
, "EventLog")) {
2388 /* formally was 0x1b */
2393 if (!StrCaseCmp(value
, "NetPopup")) {
2399 if (!StrCaseCmp(value
, "MajorVersion")) {
2402 /* Windows NT 4.0 seems to not allow uploading of drivers
2403 to a server that reports 0x3 as the MajorVersion.
2404 need to investigate more how Win2k gets around this .
2407 if (RA_WINNT
== get_remote_arch()) {
2416 if (!StrCaseCmp(value
, "MinorVersion")) {
2423 * uint32_t size = 0x114
2424 * uint32_t major = 5
2425 * uint32_t minor = [0|1]
2426 * uint32_t build = [2195|2600]
2427 * extra unicode string = e.g. "Service Pack 3"
2429 if (!StrCaseCmp(value
, "OSVersion")) {
2431 enum ndr_err_code ndr_err
;
2432 struct spoolss_OSVersion os
;
2434 os
.major
= 5; /* Windows 2000 == 5.0 */
2436 os
.build
= 2195; /* build */
2437 os
.extra_string
= ""; /* leave extra string empty */
2439 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, NULL
, &os
,
2440 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2441 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2442 return WERR_GENERAL_FAILURE
;
2446 data
->binary
= blob
;
2452 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2455 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2456 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2461 if (!StrCaseCmp(value
, "Architecture")) {
2464 data
->string
= talloc_strdup(mem_ctx
, "Windows NT x86");
2465 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2470 if (!StrCaseCmp(value
, "DsPresent")) {
2473 /* only show the publish check box if we are a
2474 member of a AD domain */
2476 if (lp_security() == SEC_ADS
) {
2484 if (!StrCaseCmp(value
, "DNSMachineName")) {
2485 const char *hostname
= get_mydnsfullname();
2488 return WERR_BADFILE
;
2492 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2493 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2500 return WERR_INVALID_PARAM
;
2503 /****************************************************************
2504 _spoolss_GetPrinterData
2505 ****************************************************************/
2507 WERROR
_spoolss_GetPrinterData(pipes_struct
*p
,
2508 struct spoolss_GetPrinterData
*r
)
2510 struct spoolss_GetPrinterDataEx r2
;
2512 r2
.in
.handle
= r
->in
.handle
;
2513 r2
.in
.key_name
= "PrinterDriverData";
2514 r2
.in
.value_name
= r
->in
.value_name
;
2515 r2
.in
.offered
= r
->in
.offered
;
2516 r2
.out
.type
= r
->out
.type
;
2517 r2
.out
.data
= r
->out
.data
;
2518 r2
.out
.needed
= r
->out
.needed
;
2520 return _spoolss_GetPrinterDataEx(p
, &r2
);
2523 /*********************************************************
2524 Connect to the client machine.
2525 **********************************************************/
2527 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2528 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2531 struct cli_state
*the_cli
;
2532 struct sockaddr_storage rm_addr
;
2534 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2535 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2536 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2540 if (ismyaddr((struct sockaddr
*)&rm_addr
)) {
2541 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2545 char addr
[INET6_ADDRSTRLEN
];
2546 rm_addr
= *client_ss
;
2547 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2548 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2552 /* setup the connection */
2554 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2555 &rm_addr
, 0, "IPC$", "IPC",
2559 0, lp_client_signing(), NULL
);
2561 if ( !NT_STATUS_IS_OK( ret
) ) {
2562 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2567 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2568 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2569 cli_shutdown(the_cli
);
2574 * Ok - we have an anonymous connection to the IPC$ share.
2575 * Now start the NT Domain stuff :-).
2578 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2579 if (!NT_STATUS_IS_OK(ret
)) {
2580 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2581 remote_machine
, nt_errstr(ret
)));
2582 cli_shutdown(the_cli
);
2589 /***************************************************************************
2590 Connect to the client.
2591 ****************************************************************************/
2593 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2594 uint32_t localprinter
, uint32_t type
,
2595 struct policy_handle
*handle
,
2596 struct sockaddr_storage
*client_ss
)
2602 * If it's the first connection, contact the client
2603 * and connect to the IPC$ share anonymously
2605 if (smb_connections
==0) {
2606 fstring unix_printer
;
2608 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2610 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2613 messaging_register(smbd_messaging_context(), NULL
,
2614 MSG_PRINTER_NOTIFY2
,
2615 receive_notify2_message_list
);
2616 /* Tell the connections db we're now interested in printer
2617 * notify messages. */
2618 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY
);
2622 * Tell the specific printing tdb we want messages for this printer
2623 * by registering our PID.
2626 if (!print_notify_register_pid(snum
))
2627 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2631 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2639 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2640 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2641 win_errstr(result
)));
2643 return (W_ERROR_IS_OK(result
));
2646 /****************************************************************
2647 ****************************************************************/
2649 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2650 const struct spoolss_NotifyOption
*r
)
2652 struct spoolss_NotifyOption
*option
;
2659 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2666 if (!option
->count
) {
2670 option
->types
= talloc_zero_array(option
,
2671 struct spoolss_NotifyOptionType
, option
->count
);
2672 if (!option
->types
) {
2673 talloc_free(option
);
2677 for (i
=0; i
< option
->count
; i
++) {
2678 option
->types
[i
] = r
->types
[i
];
2680 if (option
->types
[i
].count
) {
2681 option
->types
[i
].fields
= talloc_zero_array(option
,
2682 union spoolss_Field
, option
->types
[i
].count
);
2683 if (!option
->types
[i
].fields
) {
2684 talloc_free(option
);
2687 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2688 option
->types
[i
].fields
[k
] =
2689 r
->types
[i
].fields
[k
];
2697 /****************************************************************
2698 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2700 * before replying OK: status=0 a rpc call is made to the workstation
2701 * asking ReplyOpenPrinter
2703 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2704 * called from api_spoolss_rffpcnex
2705 ****************************************************************/
2707 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct
*p
,
2708 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2711 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2712 struct sockaddr_storage client_ss
;
2714 /* store the notify value in the printer struct */
2716 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2719 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720 "Invalid handle (%s:%u:%u).\n",
2721 OUR_HANDLE(r
->in
.handle
)));
2725 Printer
->notify
.flags
= r
->in
.flags
;
2726 Printer
->notify
.options
= r
->in
.options
;
2727 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2729 TALLOC_FREE(Printer
->notify
.option
);
2730 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2732 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2734 /* Connect to the client machine and send a ReplyOpenPrinter */
2736 if ( Printer
->printer_type
== SPLHND_SERVER
)
2738 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2739 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2742 if (!interpret_string_addr(&client_ss
, p
->client_address
,
2744 return WERR_SERVER_UNAVAILABLE
;
2747 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2748 Printer
->notify
.printerlocal
, 1,
2749 &Printer
->notify
.client_hnd
, &client_ss
))
2750 return WERR_SERVER_UNAVAILABLE
;
2752 Printer
->notify
.client_connected
= true;
2757 /*******************************************************************
2758 * fill a notify_info_data with the servername
2759 ********************************************************************/
2761 void spoolss_notify_server_name(int snum
,
2762 struct spoolss_Notify
*data
,
2763 print_queue_struct
*queue
,
2764 NT_PRINTER_INFO_LEVEL
*printer
,
2765 TALLOC_CTX
*mem_ctx
)
2767 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->servername
);
2770 /*******************************************************************
2771 * fill a notify_info_data with the printername (not including the servername).
2772 ********************************************************************/
2774 void spoolss_notify_printer_name(int snum
,
2775 struct spoolss_Notify
*data
,
2776 print_queue_struct
*queue
,
2777 NT_PRINTER_INFO_LEVEL
*printer
,
2778 TALLOC_CTX
*mem_ctx
)
2780 /* the notify name should not contain the \\server\ part */
2781 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2784 p
= printer
->info_2
->printername
;
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2792 /*******************************************************************
2793 * fill a notify_info_data with the servicename
2794 ********************************************************************/
2796 void spoolss_notify_share_name(int snum
,
2797 struct spoolss_Notify
*data
,
2798 print_queue_struct
*queue
,
2799 NT_PRINTER_INFO_LEVEL
*printer
,
2800 TALLOC_CTX
*mem_ctx
)
2802 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2805 /*******************************************************************
2806 * fill a notify_info_data with the port name
2807 ********************************************************************/
2809 void spoolss_notify_port_name(int snum
,
2810 struct spoolss_Notify
*data
,
2811 print_queue_struct
*queue
,
2812 NT_PRINTER_INFO_LEVEL
*printer
,
2813 TALLOC_CTX
*mem_ctx
)
2815 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->portname
);
2818 /*******************************************************************
2819 * fill a notify_info_data with the printername
2820 * but it doesn't exist, have to see what to do
2821 ********************************************************************/
2823 void spoolss_notify_driver_name(int snum
,
2824 struct spoolss_Notify
*data
,
2825 print_queue_struct
*queue
,
2826 NT_PRINTER_INFO_LEVEL
*printer
,
2827 TALLOC_CTX
*mem_ctx
)
2829 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->drivername
);
2832 /*******************************************************************
2833 * fill a notify_info_data with the comment
2834 ********************************************************************/
2836 void spoolss_notify_comment(int snum
,
2837 struct spoolss_Notify
*data
,
2838 print_queue_struct
*queue
,
2839 NT_PRINTER_INFO_LEVEL
*printer
,
2840 TALLOC_CTX
*mem_ctx
)
2844 if (*printer
->info_2
->comment
== '\0') {
2845 p
= lp_comment(snum
);
2847 p
= printer
->info_2
->comment
;
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->comment
);
2853 /*******************************************************************
2854 * fill a notify_info_data with the comment
2855 * location = "Room 1, floor 2, building 3"
2856 ********************************************************************/
2858 void spoolss_notify_location(int snum
,
2859 struct spoolss_Notify
*data
,
2860 print_queue_struct
*queue
,
2861 NT_PRINTER_INFO_LEVEL
*printer
,
2862 TALLOC_CTX
*mem_ctx
)
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->location
);
2867 /*******************************************************************
2868 * fill a notify_info_data with the device mode
2869 * jfm:xxxx don't to it for know but that's a real problem !!!
2870 ********************************************************************/
2872 static void spoolss_notify_devmode(int snum
,
2873 struct spoolss_Notify
*data
,
2874 print_queue_struct
*queue
,
2875 NT_PRINTER_INFO_LEVEL
*printer
,
2876 TALLOC_CTX
*mem_ctx
)
2878 /* for a dummy implementation we have to zero the fields */
2879 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2882 /*******************************************************************
2883 * fill a notify_info_data with the separator file name
2884 ********************************************************************/
2886 void spoolss_notify_sepfile(int snum
,
2887 struct spoolss_Notify
*data
,
2888 print_queue_struct
*queue
,
2889 NT_PRINTER_INFO_LEVEL
*printer
,
2890 TALLOC_CTX
*mem_ctx
)
2892 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->sepfile
);
2895 /*******************************************************************
2896 * fill a notify_info_data with the print processor
2897 * jfm:xxxx return always winprint to indicate we don't do anything to it
2898 ********************************************************************/
2900 void spoolss_notify_print_processor(int snum
,
2901 struct spoolss_Notify
*data
,
2902 print_queue_struct
*queue
,
2903 NT_PRINTER_INFO_LEVEL
*printer
,
2904 TALLOC_CTX
*mem_ctx
)
2906 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->printprocessor
);
2909 /*******************************************************************
2910 * fill a notify_info_data with the print processor options
2911 * jfm:xxxx send an empty string
2912 ********************************************************************/
2914 void spoolss_notify_parameters(int snum
,
2915 struct spoolss_Notify
*data
,
2916 print_queue_struct
*queue
,
2917 NT_PRINTER_INFO_LEVEL
*printer
,
2918 TALLOC_CTX
*mem_ctx
)
2920 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->parameters
);
2923 /*******************************************************************
2924 * fill a notify_info_data with the data type
2925 * jfm:xxxx always send RAW as data type
2926 ********************************************************************/
2928 void spoolss_notify_datatype(int snum
,
2929 struct spoolss_Notify
*data
,
2930 print_queue_struct
*queue
,
2931 NT_PRINTER_INFO_LEVEL
*printer
,
2932 TALLOC_CTX
*mem_ctx
)
2934 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->datatype
);
2937 /*******************************************************************
2938 * fill a notify_info_data with the security descriptor
2939 * jfm:xxxx send an null pointer to say no security desc
2940 * have to implement security before !
2941 ********************************************************************/
2943 static void spoolss_notify_security_desc(int snum
,
2944 struct spoolss_Notify
*data
,
2945 print_queue_struct
*queue
,
2946 NT_PRINTER_INFO_LEVEL
*printer
,
2947 TALLOC_CTX
*mem_ctx
)
2949 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
,
2950 printer
->info_2
->secdesc_buf
->sd_size
,
2951 printer
->info_2
->secdesc_buf
->sd
);
2954 /*******************************************************************
2955 * fill a notify_info_data with the attributes
2956 * jfm:xxxx a samba printer is always shared
2957 ********************************************************************/
2959 void spoolss_notify_attributes(int snum
,
2960 struct spoolss_Notify
*data
,
2961 print_queue_struct
*queue
,
2962 NT_PRINTER_INFO_LEVEL
*printer
,
2963 TALLOC_CTX
*mem_ctx
)
2965 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->attributes
);
2968 /*******************************************************************
2969 * fill a notify_info_data with the priority
2970 ********************************************************************/
2972 static void spoolss_notify_priority(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_INTEGER(data
, printer
->info_2
->priority
);
2981 /*******************************************************************
2982 * fill a notify_info_data with the default priority
2983 ********************************************************************/
2985 static void spoolss_notify_default_priority(int snum
,
2986 struct spoolss_Notify
*data
,
2987 print_queue_struct
*queue
,
2988 NT_PRINTER_INFO_LEVEL
*printer
,
2989 TALLOC_CTX
*mem_ctx
)
2991 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->default_priority
);
2994 /*******************************************************************
2995 * fill a notify_info_data with the start time
2996 ********************************************************************/
2998 static void spoolss_notify_start_time(int snum
,
2999 struct spoolss_Notify
*data
,
3000 print_queue_struct
*queue
,
3001 NT_PRINTER_INFO_LEVEL
*printer
,
3002 TALLOC_CTX
*mem_ctx
)
3004 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->starttime
);
3007 /*******************************************************************
3008 * fill a notify_info_data with the until time
3009 ********************************************************************/
3011 static void spoolss_notify_until_time(int snum
,
3012 struct spoolss_Notify
*data
,
3013 print_queue_struct
*queue
,
3014 NT_PRINTER_INFO_LEVEL
*printer
,
3015 TALLOC_CTX
*mem_ctx
)
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->untiltime
);
3020 /*******************************************************************
3021 * fill a notify_info_data with the status
3022 ********************************************************************/
3024 static void spoolss_notify_status(int snum
,
3025 struct spoolss_Notify
*data
,
3026 print_queue_struct
*queue
,
3027 NT_PRINTER_INFO_LEVEL
*printer
,
3028 TALLOC_CTX
*mem_ctx
)
3030 print_status_struct status
;
3032 print_queue_length(snum
, &status
);
3033 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3036 /*******************************************************************
3037 * fill a notify_info_data with the number of jobs queued
3038 ********************************************************************/
3040 void spoolss_notify_cjobs(int snum
,
3041 struct spoolss_Notify
*data
,
3042 print_queue_struct
*queue
,
3043 NT_PRINTER_INFO_LEVEL
*printer
,
3044 TALLOC_CTX
*mem_ctx
)
3046 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, print_queue_length(snum
, NULL
));
3049 /*******************************************************************
3050 * fill a notify_info_data with the average ppm
3051 ********************************************************************/
3053 static void spoolss_notify_average_ppm(int snum
,
3054 struct spoolss_Notify
*data
,
3055 print_queue_struct
*queue
,
3056 NT_PRINTER_INFO_LEVEL
*printer
,
3057 TALLOC_CTX
*mem_ctx
)
3059 /* always respond 8 pages per minutes */
3060 /* a little hard ! */
3061 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->averageppm
);
3064 /*******************************************************************
3065 * fill a notify_info_data with username
3066 ********************************************************************/
3068 static void spoolss_notify_username(int snum
,
3069 struct spoolss_Notify
*data
,
3070 print_queue_struct
*queue
,
3071 NT_PRINTER_INFO_LEVEL
*printer
,
3072 TALLOC_CTX
*mem_ctx
)
3074 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(int snum
,
3082 struct spoolss_Notify
*data
,
3083 print_queue_struct
*queue
,
3084 NT_PRINTER_INFO_LEVEL
*printer
,
3085 TALLOC_CTX
*mem_ctx
)
3087 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3090 /*******************************************************************
3091 * fill a notify_info_data with job name
3092 ********************************************************************/
3094 static void spoolss_notify_job_name(int snum
,
3095 struct spoolss_Notify
*data
,
3096 print_queue_struct
*queue
,
3097 NT_PRINTER_INFO_LEVEL
*printer
,
3098 TALLOC_CTX
*mem_ctx
)
3100 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3103 /*******************************************************************
3104 * fill a notify_info_data with job status
3105 ********************************************************************/
3107 static void spoolss_notify_job_status_string(int snum
,
3108 struct spoolss_Notify
*data
,
3109 print_queue_struct
*queue
,
3110 NT_PRINTER_INFO_LEVEL
*printer
,
3111 TALLOC_CTX
*mem_ctx
)
3114 * Now we're returning job status codes we just return a "" here. JRA.
3119 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3122 switch (queue
->status
) {
3127 p
= ""; /* NT provides the paused string */
3136 #endif /* NO LONGER NEEDED. */
3138 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3141 /*******************************************************************
3142 * fill a notify_info_data with job time
3143 ********************************************************************/
3145 static void spoolss_notify_job_time(int snum
,
3146 struct spoolss_Notify
*data
,
3147 print_queue_struct
*queue
,
3148 NT_PRINTER_INFO_LEVEL
*printer
,
3149 TALLOC_CTX
*mem_ctx
)
3151 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3154 /*******************************************************************
3155 * fill a notify_info_data with job size
3156 ********************************************************************/
3158 static void spoolss_notify_job_size(int snum
,
3159 struct spoolss_Notify
*data
,
3160 print_queue_struct
*queue
,
3161 NT_PRINTER_INFO_LEVEL
*printer
,
3162 TALLOC_CTX
*mem_ctx
)
3164 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3167 /*******************************************************************
3168 * fill a notify_info_data with page info
3169 ********************************************************************/
3170 static void spoolss_notify_total_pages(int snum
,
3171 struct spoolss_Notify
*data
,
3172 print_queue_struct
*queue
,
3173 NT_PRINTER_INFO_LEVEL
*printer
,
3174 TALLOC_CTX
*mem_ctx
)
3176 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3179 /*******************************************************************
3180 * fill a notify_info_data with pages printed info.
3181 ********************************************************************/
3182 static void spoolss_notify_pages_printed(int snum
,
3183 struct spoolss_Notify
*data
,
3184 print_queue_struct
*queue
,
3185 NT_PRINTER_INFO_LEVEL
*printer
,
3186 TALLOC_CTX
*mem_ctx
)
3188 /* Add code when back-end tracks this */
3189 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3192 /*******************************************************************
3193 Fill a notify_info_data with job position.
3194 ********************************************************************/
3196 static void spoolss_notify_job_position(int snum
,
3197 struct spoolss_Notify
*data
,
3198 print_queue_struct
*queue
,
3199 NT_PRINTER_INFO_LEVEL
*printer
,
3200 TALLOC_CTX
*mem_ctx
)
3202 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
3205 /*******************************************************************
3206 Fill a notify_info_data with submitted time.
3207 ********************************************************************/
3209 static void spoolss_notify_submitted_time(int snum
,
3210 struct spoolss_Notify
*data
,
3211 print_queue_struct
*queue
,
3212 NT_PRINTER_INFO_LEVEL
*printer
,
3213 TALLOC_CTX
*mem_ctx
)
3215 data
->data
.string
.string
= NULL
;
3216 data
->data
.string
.size
= 0;
3218 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3219 &data
->data
.string
.string
,
3220 &data
->data
.string
.size
);
3224 struct s_notify_info_data_table
3226 enum spoolss_NotifyType type
;
3229 enum spoolss_NotifyTable variable_type
;
3230 void (*fn
) (int snum
, struct spoolss_Notify
*data
,
3231 print_queue_struct
*queue
,
3232 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3235 /* A table describing the various print notification constants and
3236 whether the notification data is a pointer to a variable sized
3237 buffer, a one value uint32_t or a two value uint32_t. */
3239 static const struct s_notify_info_data_table notify_info_data_table
[] =
3241 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3242 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3243 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3244 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3245 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3246 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3247 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3248 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3249 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3250 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3251 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3252 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3253 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3254 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3255 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3256 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3257 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3258 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3259 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3260 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3261 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3262 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3263 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3264 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3265 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3266 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3267 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3268 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3269 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3270 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3271 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3272 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3273 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3274 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3275 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3276 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3277 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3278 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3279 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3280 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3281 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3282 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3283 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3284 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3285 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3286 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3287 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3288 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3289 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3292 /*******************************************************************
3293 Return the variable_type of info_data structure.
3294 ********************************************************************/
3296 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3301 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3302 if ( (notify_info_data_table
[i
].type
== type
) &&
3303 (notify_info_data_table
[i
].field
== field
) ) {
3304 return notify_info_data_table
[i
].variable_type
;
3308 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3313 /****************************************************************************
3314 ****************************************************************************/
3316 static bool search_notify(enum spoolss_NotifyType type
,
3322 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3323 if (notify_info_data_table
[i
].type
== type
&&
3324 notify_info_data_table
[i
].field
== field
&&
3325 notify_info_data_table
[i
].fn
!= NULL
) {
3334 /****************************************************************************
3335 ****************************************************************************/
3337 void construct_info_data(struct spoolss_Notify
*info_data
,
3338 enum spoolss_NotifyType type
,
3342 info_data
->type
= type
;
3343 info_data
->field
.field
= field
;
3344 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3345 info_data
->job_id
= id
;
3348 /*******************************************************************
3350 * fill a notify_info struct with info asked
3352 ********************************************************************/
3354 static bool construct_notify_printer_info(Printer_entry
*print_hnd
,
3355 struct spoolss_NotifyInfo
*info
,
3357 const struct spoolss_NotifyOptionType
*option_type
,
3359 TALLOC_CTX
*mem_ctx
)
3362 enum spoolss_NotifyType type
;
3365 struct spoolss_Notify
*current_data
;
3366 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3367 print_queue_struct
*queue
=NULL
;
3369 type
= option_type
->type
;
3371 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3372 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3373 option_type
->count
, lp_servicename(snum
)));
3375 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3378 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3379 field
= option_type
->fields
[field_num
].field
;
3381 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3383 if (!search_notify(type
, field
, &j
) )
3386 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3387 struct spoolss_Notify
,
3389 if (info
->notifies
== NULL
) {
3390 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3391 free_a_printer(&printer
, 2);
3395 current_data
= &info
->notifies
[info
->count
];
3397 construct_info_data(current_data
, type
, field
, id
);
3399 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3400 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3402 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3408 free_a_printer(&printer
, 2);
3412 /*******************************************************************
3414 * fill a notify_info struct with info asked
3416 ********************************************************************/
3418 static bool construct_notify_jobs_info(print_queue_struct
*queue
,
3419 struct spoolss_NotifyInfo
*info
,
3420 NT_PRINTER_INFO_LEVEL
*printer
,
3422 const struct spoolss_NotifyOptionType
*option_type
,
3424 TALLOC_CTX
*mem_ctx
)
3427 enum spoolss_NotifyType type
;
3429 struct spoolss_Notify
*current_data
;
3431 DEBUG(4,("construct_notify_jobs_info\n"));
3433 type
= option_type
->type
;
3435 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3436 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3437 option_type
->count
));
3439 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3440 field
= option_type
->fields
[field_num
].field
;
3442 if (!search_notify(type
, field
, &j
) )
3445 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3446 struct spoolss_Notify
,
3448 if (info
->notifies
== NULL
) {
3449 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3453 current_data
=&(info
->notifies
[info
->count
]);
3455 construct_info_data(current_data
, type
, field
, id
);
3456 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3465 * JFM: The enumeration is not that simple, it's even non obvious.
3467 * let's take an example: I want to monitor the PRINTER SERVER for
3468 * the printer's name and the number of jobs currently queued.
3469 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3470 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3472 * I have 3 printers on the back of my server.
3474 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3477 * 1 printer 1 name 1
3478 * 2 printer 1 cjob 1
3479 * 3 printer 2 name 2
3480 * 4 printer 2 cjob 2
3481 * 5 printer 3 name 3
3482 * 6 printer 3 name 3
3484 * that's the print server case, the printer case is even worse.
3487 /*******************************************************************
3489 * enumerate all printers on the printserver
3490 * fill a notify_info struct with info asked
3492 ********************************************************************/
3494 static WERROR
printserver_notify_info(pipes_struct
*p
,
3495 struct policy_handle
*hnd
,
3496 struct spoolss_NotifyInfo
*info
,
3497 TALLOC_CTX
*mem_ctx
)
3500 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3501 int n_services
=lp_numservices();
3503 struct spoolss_NotifyOption
*option
;
3504 struct spoolss_NotifyOptionType option_type
;
3506 DEBUG(4,("printserver_notify_info\n"));
3511 option
= Printer
->notify
.option
;
3514 info
->notifies
= NULL
;
3517 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3518 sending a ffpcn() request first */
3523 for (i
=0; i
<option
->count
; i
++) {
3524 option_type
= option
->types
[i
];
3526 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3529 for (snum
=0; snum
<n_services
; snum
++)
3531 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3532 construct_notify_printer_info ( Printer
, info
, snum
, &option_type
, snum
, mem_ctx
);
3538 * Debugging information, don't delete.
3541 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3542 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3543 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3545 for (i
=0; i
<info
->count
; i
++) {
3546 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3547 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3548 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3555 /*******************************************************************
3557 * fill a notify_info struct with info asked
3559 ********************************************************************/
3561 static WERROR
printer_notify_info(pipes_struct
*p
, struct policy_handle
*hnd
,
3562 struct spoolss_NotifyInfo
*info
,
3563 TALLOC_CTX
*mem_ctx
)
3566 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3569 struct spoolss_NotifyOption
*option
;
3570 struct spoolss_NotifyOptionType option_type
;
3572 print_queue_struct
*queue
=NULL
;
3573 print_status_struct status
;
3575 DEBUG(4,("printer_notify_info\n"));
3580 option
= Printer
->notify
.option
;
3584 info
->notifies
= NULL
;
3587 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3588 sending a ffpcn() request first */
3593 get_printer_snum(p
, hnd
, &snum
, NULL
);
3595 for (i
=0; i
<option
->count
; i
++) {
3596 option_type
= option
->types
[i
];
3598 switch (option_type
.type
) {
3599 case PRINTER_NOTIFY_TYPE
:
3600 if(construct_notify_printer_info(Printer
, info
, snum
,
3606 case JOB_NOTIFY_TYPE
: {
3607 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3609 count
= print_queue_status(snum
, &queue
, &status
);
3611 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3614 for (j
=0; j
<count
; j
++) {
3615 construct_notify_jobs_info(&queue
[j
], info
,
3622 free_a_printer(&printer
, 2);
3632 * Debugging information, don't delete.
3635 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3636 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3637 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3639 for (i=0; i<info->count; i++) {
3640 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3641 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3642 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3648 /****************************************************************
3649 _spoolss_RouterRefreshPrinterChangeNotify
3650 ****************************************************************/
3652 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(pipes_struct
*p
,
3653 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3655 struct spoolss_NotifyInfo
*info
;
3657 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3658 WERROR result
= WERR_BADFID
;
3660 /* we always have a spoolss_NotifyInfo struct */
3661 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3663 result
= WERR_NOMEM
;
3667 *r
->out
.info
= info
;
3670 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3671 "Invalid handle (%s:%u:%u).\n",
3672 OUR_HANDLE(r
->in
.handle
)));
3676 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3679 * We are now using the change value, and
3680 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3681 * I don't have a global notification system, I'm sending back all the
3682 * informations even when _NOTHING_ has changed.
3685 /* We need to keep track of the change value to send back in
3686 RRPCN replies otherwise our updates are ignored. */
3688 Printer
->notify
.fnpcn
= true;
3690 if (Printer
->notify
.client_connected
) {
3691 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3692 "Saving change value in request [%x]\n",
3694 Printer
->notify
.change
= r
->in
.change_low
;
3697 /* just ignore the spoolss_NotifyOption */
3699 switch (Printer
->printer_type
) {
3701 result
= printserver_notify_info(p
, r
->in
.handle
,
3705 case SPLHND_PRINTER
:
3706 result
= printer_notify_info(p
, r
->in
.handle
,
3711 Printer
->notify
.fnpcn
= false;
3717 /********************************************************************
3718 * construct_printer_info_0
3719 * fill a printer_info_0 struct
3720 ********************************************************************/
3722 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3723 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3724 struct spoolss_PrinterInfo0
*r
,
3728 counter_printer_0
*session_counter
;
3730 print_status_struct status
;
3732 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3733 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3735 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3736 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3738 count
= print_queue_length(snum
, &status
);
3740 /* check if we already have a counter for this printer */
3741 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3742 if (session_counter
->snum
== snum
)
3746 /* it's the first time, add it to the list */
3747 if (session_counter
== NULL
) {
3748 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3749 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3750 ZERO_STRUCTP(session_counter
);
3751 session_counter
->snum
= snum
;
3752 session_counter
->counter
= 0;
3753 DLIST_ADD(counter_list
, session_counter
);
3757 session_counter
->counter
++;
3763 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3765 init_systemtime(&r
->time
, gmtime(&setuptime
));
3768 * the global_counter should be stored in a TDB as it's common to all the clients
3769 * and should be zeroed on samba startup
3771 r
->global_counter
= session_counter
->counter
;
3773 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3774 r
->version
= 0x0005; /* NT 5 */
3775 r
->free_build
= 0x0893; /* build 2195 */
3777 r
->max_spooling
= 0;
3778 r
->session_counter
= session_counter
->counter
;
3779 r
->num_error_out_of_paper
= 0x0;
3780 r
->num_error_not_ready
= 0x0; /* number of print failure */
3782 r
->number_of_processors
= 0x1;
3783 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3784 r
->high_part_total_bytes
= 0x0;
3785 r
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3786 r
->last_error
= WERR_OK
;
3787 r
->status
= nt_printq_status(status
.status
);
3788 r
->enumerate_network_printers
= 0x0;
3789 r
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3790 r
->processor_architecture
= 0x0;
3791 r
->processor_level
= 0x6; /* 6 ???*/
3799 /****************************************************************************
3800 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3801 should be valid upon entry
3802 ****************************************************************************/
3804 static WERROR
convert_nt_devicemode(TALLOC_CTX
*mem_ctx
,
3805 struct spoolss_DeviceMode
*r
,
3806 const NT_DEVICEMODE
*ntdevmode
)
3808 if (!r
|| !ntdevmode
) {
3809 return WERR_INVALID_PARAM
;
3812 r
->devicename
= talloc_strdup(mem_ctx
, ntdevmode
->devicename
);
3813 W_ERROR_HAVE_NO_MEMORY(r
->devicename
);
3815 r
->specversion
= ntdevmode
->specversion
;
3816 r
->driverversion
= ntdevmode
->driverversion
;
3817 r
->size
= ntdevmode
->size
;
3818 r
->__driverextra_length
= ntdevmode
->driverextra
;
3819 r
->fields
= ntdevmode
->fields
;
3821 r
->orientation
= ntdevmode
->orientation
;
3822 r
->papersize
= ntdevmode
->papersize
;
3823 r
->paperlength
= ntdevmode
->paperlength
;
3824 r
->paperwidth
= ntdevmode
->paperwidth
;
3825 r
->scale
= ntdevmode
->scale
;
3826 r
->copies
= ntdevmode
->copies
;
3827 r
->defaultsource
= ntdevmode
->defaultsource
;
3828 r
->printquality
= ntdevmode
->printquality
;
3829 r
->color
= ntdevmode
->color
;
3830 r
->duplex
= ntdevmode
->duplex
;
3831 r
->yresolution
= ntdevmode
->yresolution
;
3832 r
->ttoption
= ntdevmode
->ttoption
;
3833 r
->collate
= ntdevmode
->collate
;
3835 r
->formname
= talloc_strdup(mem_ctx
, ntdevmode
->formname
);
3836 W_ERROR_HAVE_NO_MEMORY(r
->formname
);
3838 /* all 0 below are values that have not been set in the old parsing/copy
3839 * function, maybe they should... - gd */
3845 r
->displayflags
= 0;
3846 r
->displayfrequency
= 0;
3847 r
->icmmethod
= ntdevmode
->icmmethod
;
3848 r
->icmintent
= ntdevmode
->icmintent
;
3849 r
->mediatype
= ntdevmode
->mediatype
;
3850 r
->dithertype
= ntdevmode
->dithertype
;
3853 r
->panningwidth
= 0;
3854 r
->panningheight
= 0;
3856 if (ntdevmode
->nt_dev_private
!= NULL
) {
3857 r
->driverextra_data
= data_blob_talloc(mem_ctx
,
3858 ntdevmode
->nt_dev_private
,
3859 ntdevmode
->driverextra
);
3860 W_ERROR_HAVE_NO_MEMORY(r
->driverextra_data
.data
);
3867 /****************************************************************************
3868 Create a spoolss_DeviceMode struct. Returns talloced memory.
3869 ****************************************************************************/
3871 struct spoolss_DeviceMode
*construct_dev_mode(TALLOC_CTX
*mem_ctx
,
3872 const char *servicename
)
3875 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3876 struct spoolss_DeviceMode
*devmode
= NULL
;
3878 DEBUG(7,("construct_dev_mode\n"));
3880 DEBUGADD(8,("getting printer characteristics\n"));
3882 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
3885 if (!printer
->info_2
->devmode
) {
3886 DEBUG(5, ("BONG! There was no device mode!\n"));
3890 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
3892 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3896 DEBUGADD(8,("loading DEVICEMODE\n"));
3898 result
= convert_nt_devicemode(mem_ctx
, devmode
, printer
->info_2
->devmode
);
3899 if (!W_ERROR_IS_OK(result
)) {
3900 TALLOC_FREE(devmode
);
3904 free_a_printer(&printer
,2);
3909 /********************************************************************
3910 * construct_printer_info3
3911 * fill a spoolss_PrinterInfo3 struct
3912 ********************************************************************/
3914 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3915 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3916 struct spoolss_PrinterInfo3
*r
,
3919 /* These are the components of the SD we are returning. */
3921 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3922 /* don't use talloc_steal() here unless you do a deep steal of all
3923 the SEC_DESC members */
3925 r
->secdesc
= dup_sec_desc(mem_ctx
,
3926 ntprinter
->info_2
->secdesc_buf
->sd
);
3927 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3933 /********************************************************************
3934 * construct_printer_info4
3935 * fill a spoolss_PrinterInfo4 struct
3936 ********************************************************************/
3938 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
3939 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3940 struct spoolss_PrinterInfo4
*r
,
3943 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3944 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3945 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3946 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3948 r
->attributes
= ntprinter
->info_2
->attributes
;
3953 /********************************************************************
3954 * construct_printer_info5
3955 * fill a spoolss_PrinterInfo5 struct
3956 ********************************************************************/
3958 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
3959 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3960 struct spoolss_PrinterInfo5
*r
,
3963 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3964 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3965 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
3966 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3968 r
->attributes
= ntprinter
->info_2
->attributes
;
3970 /* these two are not used by NT+ according to MSDN */
3972 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
3973 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
3978 /********************************************************************
3979 * construct_printer_info_6
3980 * fill a spoolss_PrinterInfo6 struct
3981 ********************************************************************/
3983 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
3984 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3985 struct spoolss_PrinterInfo6
*r
,
3989 print_status_struct status
;
3991 count
= print_queue_length(snum
, &status
);
3993 r
->status
= nt_printq_status(status
.status
);
3998 /********************************************************************
3999 * construct_printer_info7
4000 * fill a spoolss_PrinterInfo7 struct
4001 ********************************************************************/
4003 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4004 Printer_entry
*print_hnd
,
4005 struct spoolss_PrinterInfo7
*r
,
4010 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4011 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4012 r
->action
= DSPRINT_PUBLISH
;
4014 r
->guid
= talloc_strdup(mem_ctx
, "");
4015 r
->action
= DSPRINT_UNPUBLISH
;
4017 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
4022 /********************************************************************
4023 * construct_printer_info8
4024 * fill a spoolss_PrinterInfo8 struct
4025 ********************************************************************/
4027 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
4028 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4029 struct spoolss_DeviceModeInfo
*r
,
4032 struct spoolss_DeviceMode
*devmode
;
4035 if (!ntprinter
->info_2
->devmode
) {
4040 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
4041 W_ERROR_HAVE_NO_MEMORY(devmode
);
4043 result
= convert_nt_devicemode(mem_ctx
, devmode
, ntprinter
->info_2
->devmode
);
4044 if (!W_ERROR_IS_OK(result
)) {
4045 TALLOC_FREE(devmode
);
4049 r
->devmode
= devmode
;
4055 /********************************************************************
4056 * construct_printer_info1
4057 * fill a spoolss_PrinterInfo1 struct
4058 ********************************************************************/
4060 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
4061 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4063 struct spoolss_PrinterInfo1
*r
,
4068 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
4069 ntprinter
->info_2
->printername
,
4070 ntprinter
->info_2
->drivername
,
4071 ntprinter
->info_2
->location
);
4072 W_ERROR_HAVE_NO_MEMORY(r
->description
);
4074 if (*ntprinter
->info_2
->comment
== '\0') {
4075 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4077 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
); /* saved comment */
4079 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4081 r
->name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4082 W_ERROR_HAVE_NO_MEMORY(r
->name
);
4087 /********************************************************************
4088 * construct_printer_info2
4089 * fill a spoolss_PrinterInfo2 struct
4090 ********************************************************************/
4092 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
4093 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4094 struct spoolss_PrinterInfo2
*r
,
4099 print_status_struct status
;
4101 count
= print_queue_length(snum
, &status
);
4103 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
4104 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4105 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4106 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
4107 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
4108 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
4109 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
4110 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4111 r
->drivername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
4112 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
4114 if (*ntprinter
->info_2
->comment
== '\0') {
4115 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4117 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
);
4119 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4121 r
->location
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->location
);
4122 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4123 r
->sepfile
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->sepfile
);
4124 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4125 r
->printprocessor
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printprocessor
);
4126 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4127 r
->datatype
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->datatype
);
4128 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4129 r
->parameters
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->parameters
);
4130 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4132 r
->attributes
= ntprinter
->info_2
->attributes
;
4134 r
->priority
= ntprinter
->info_2
->priority
;
4135 r
->defaultpriority
= ntprinter
->info_2
->default_priority
;
4136 r
->starttime
= ntprinter
->info_2
->starttime
;
4137 r
->untiltime
= ntprinter
->info_2
->untiltime
;
4138 r
->status
= nt_printq_status(status
.status
);
4140 r
->averageppm
= ntprinter
->info_2
->averageppm
;
4142 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
4144 DEBUG(8,("Returning NULL Devicemode!\n"));
4149 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
4150 /* don't use talloc_steal() here unless you do a deep steal of all
4151 the SEC_DESC members */
4153 r
->secdesc
= dup_sec_desc(mem_ctx
, ntprinter
->info_2
->secdesc_buf
->sd
);
4159 /********************************************************************
4160 ********************************************************************/
4162 static bool snum_is_shared_printer(int snum
)
4164 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
4167 /********************************************************************
4168 Spoolss_enumprinters.
4169 ********************************************************************/
4171 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
4174 union spoolss_PrinterInfo
**info_p
,
4178 int n_services
= lp_numservices();
4179 union spoolss_PrinterInfo
*info
= NULL
;
4181 WERROR result
= WERR_OK
;
4186 for (snum
= 0; snum
< n_services
; snum
++) {
4188 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4190 if (!snum_is_shared_printer(snum
)) {
4194 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4195 lp_servicename(snum
), snum
));
4197 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4198 union spoolss_PrinterInfo
,
4201 result
= WERR_NOMEM
;
4205 result
= get_a_printer(NULL
, &ntprinter
, 2,
4206 lp_const_servicename(snum
));
4207 if (!W_ERROR_IS_OK(result
)) {
4213 result
= construct_printer_info0(info
, ntprinter
,
4214 &info
[count
].info0
, snum
);
4217 result
= construct_printer_info1(info
, ntprinter
, flags
,
4218 &info
[count
].info1
, snum
);
4221 result
= construct_printer_info2(info
, ntprinter
,
4222 &info
[count
].info2
, snum
);
4225 result
= construct_printer_info4(info
, ntprinter
,
4226 &info
[count
].info4
, snum
);
4229 result
= construct_printer_info5(info
, ntprinter
,
4230 &info
[count
].info5
, snum
);
4234 result
= WERR_UNKNOWN_LEVEL
;
4235 free_a_printer(&ntprinter
, 2);
4239 free_a_printer(&ntprinter
, 2);
4240 if (!W_ERROR_IS_OK(result
)) {
4251 if (!W_ERROR_IS_OK(result
)) {
4261 /********************************************************************
4262 * handle enumeration of printers at level 0
4263 ********************************************************************/
4265 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4267 const char *servername
,
4268 union spoolss_PrinterInfo
**info
,
4271 DEBUG(4,("enum_all_printers_info_0\n"));
4273 return enum_all_printers_info_level(mem_ctx
, 0, flags
, info
, count
);
4277 /********************************************************************
4278 ********************************************************************/
4280 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4282 union spoolss_PrinterInfo
**info
,
4285 DEBUG(4,("enum_all_printers_info_1\n"));
4287 return enum_all_printers_info_level(mem_ctx
, 1, flags
, info
, count
);
4290 /********************************************************************
4291 enum_all_printers_info_1_local.
4292 *********************************************************************/
4294 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4295 union spoolss_PrinterInfo
**info
,
4298 DEBUG(4,("enum_all_printers_info_1_local\n"));
4300 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4303 /********************************************************************
4304 enum_all_printers_info_1_name.
4305 *********************************************************************/
4307 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4309 union spoolss_PrinterInfo
**info
,
4312 const char *s
= name
;
4314 DEBUG(4,("enum_all_printers_info_1_name\n"));
4316 if ((name
[0] == '\\') && (name
[1] == '\\')) {
4320 if (!is_myname_or_ipaddr(s
)) {
4321 return WERR_INVALID_NAME
;
4324 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4327 /********************************************************************
4328 enum_all_printers_info_1_network.
4329 *********************************************************************/
4331 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4333 union spoolss_PrinterInfo
**info
,
4336 const char *s
= name
;
4338 DEBUG(4,("enum_all_printers_info_1_network\n"));
4340 /* If we respond to a enum_printers level 1 on our name with flags
4341 set to PRINTER_ENUM_REMOTE with a list of printers then these
4342 printers incorrectly appear in the APW browse list.
4343 Specifically the printers for the server appear at the workgroup
4344 level where all the other servers in the domain are
4345 listed. Windows responds to this call with a
4346 WERR_CAN_NOT_COMPLETE so we should do the same. */
4348 if (name
[0] == '\\' && name
[1] == '\\') {
4352 if (is_myname_or_ipaddr(s
)) {
4353 return WERR_CAN_NOT_COMPLETE
;
4356 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_NAME
, info
, count
);
4359 /********************************************************************
4360 * api_spoolss_enumprinters
4362 * called from api_spoolss_enumprinters (see this to understand)
4363 ********************************************************************/
4365 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4366 union spoolss_PrinterInfo
**info
,
4369 DEBUG(4,("enum_all_printers_info_2\n"));
4371 return enum_all_printers_info_level(mem_ctx
, 2, 0, info
, count
);
4374 /********************************************************************
4375 * handle enumeration of printers at level 1
4376 ********************************************************************/
4378 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4381 union spoolss_PrinterInfo
**info
,
4384 /* Not all the flags are equals */
4386 if (flags
& PRINTER_ENUM_LOCAL
) {
4387 return enum_all_printers_info_1_local(mem_ctx
, info
, count
);
4390 if (flags
& PRINTER_ENUM_NAME
) {
4391 return enum_all_printers_info_1_name(mem_ctx
, name
, info
, count
);
4394 if (flags
& PRINTER_ENUM_NETWORK
) {
4395 return enum_all_printers_info_1_network(mem_ctx
, name
, info
, count
);
4398 return WERR_OK
; /* NT4sp5 does that */
4401 /********************************************************************
4402 * handle enumeration of printers at level 2
4403 ********************************************************************/
4405 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4407 const char *servername
,
4408 union spoolss_PrinterInfo
**info
,
4411 if (flags
& PRINTER_ENUM_LOCAL
) {
4412 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4415 if (flags
& PRINTER_ENUM_NAME
) {
4416 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4417 return WERR_INVALID_NAME
;
4420 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4423 if (flags
& PRINTER_ENUM_REMOTE
) {
4424 return WERR_UNKNOWN_LEVEL
;
4430 /********************************************************************
4431 * handle enumeration of printers at level 4
4432 ********************************************************************/
4434 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4436 const char *servername
,
4437 union spoolss_PrinterInfo
**info
,
4440 DEBUG(4,("enum_all_printers_info_4\n"));
4442 return enum_all_printers_info_level(mem_ctx
, 4, flags
, info
, count
);
4446 /********************************************************************
4447 * handle enumeration of printers at level 5
4448 ********************************************************************/
4450 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4452 const char *servername
,
4453 union spoolss_PrinterInfo
**info
,
4456 DEBUG(4,("enum_all_printers_info_5\n"));
4458 return enum_all_printers_info_level(mem_ctx
, 5, flags
, info
, count
);
4461 /****************************************************************
4462 _spoolss_EnumPrinters
4463 ****************************************************************/
4465 WERROR
_spoolss_EnumPrinters(pipes_struct
*p
,
4466 struct spoolss_EnumPrinters
*r
)
4468 const char *name
= NULL
;
4471 /* that's an [in out] buffer */
4473 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4474 return WERR_INVALID_PARAM
;
4477 DEBUG(4,("_spoolss_EnumPrinters\n"));
4481 *r
->out
.info
= NULL
;
4485 * flags==PRINTER_ENUM_NAME
4486 * if name=="" then enumerates all printers
4487 * if name!="" then enumerate the printer
4488 * flags==PRINTER_ENUM_REMOTE
4489 * name is NULL, enumerate printers
4490 * Level 2: name!="" enumerates printers, name can't be NULL
4491 * Level 3: doesn't exist
4492 * Level 4: does a local registry lookup
4493 * Level 5: same as Level 2
4497 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4498 W_ERROR_HAVE_NO_MEMORY(name
);
4501 switch (r
->in
.level
) {
4503 result
= enumprinters_level0(p
->mem_ctx
, r
->in
.flags
, name
,
4504 r
->out
.info
, r
->out
.count
);
4507 result
= enumprinters_level1(p
->mem_ctx
, r
->in
.flags
, name
,
4508 r
->out
.info
, r
->out
.count
);
4511 result
= enumprinters_level2(p
->mem_ctx
, r
->in
.flags
, name
,
4512 r
->out
.info
, r
->out
.count
);
4515 result
= enumprinters_level4(p
->mem_ctx
, r
->in
.flags
, name
,
4516 r
->out
.info
, r
->out
.count
);
4519 result
= enumprinters_level5(p
->mem_ctx
, r
->in
.flags
, name
,
4520 r
->out
.info
, r
->out
.count
);
4523 return WERR_UNKNOWN_LEVEL
;
4526 if (!W_ERROR_IS_OK(result
)) {
4530 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4531 spoolss_EnumPrinters
, NULL
,
4532 *r
->out
.info
, r
->in
.level
,
4534 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4535 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4537 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4540 /****************************************************************
4542 ****************************************************************/
4544 WERROR
_spoolss_GetPrinter(pipes_struct
*p
,
4545 struct spoolss_GetPrinter
*r
)
4547 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4548 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4549 WERROR result
= WERR_OK
;
4553 /* that's an [in out] buffer */
4555 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4556 return WERR_INVALID_PARAM
;
4561 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4565 result
= get_a_printer(Printer
, &ntprinter
, 2,
4566 lp_const_servicename(snum
));
4567 if (!W_ERROR_IS_OK(result
)) {
4571 switch (r
->in
.level
) {
4573 result
= construct_printer_info0(p
->mem_ctx
, ntprinter
,
4574 &r
->out
.info
->info0
, snum
);
4577 result
= construct_printer_info1(p
->mem_ctx
, ntprinter
,
4579 &r
->out
.info
->info1
, snum
);
4582 result
= construct_printer_info2(p
->mem_ctx
, ntprinter
,
4583 &r
->out
.info
->info2
, snum
);
4586 result
= construct_printer_info3(p
->mem_ctx
, ntprinter
,
4587 &r
->out
.info
->info3
, snum
);
4590 result
= construct_printer_info4(p
->mem_ctx
, ntprinter
,
4591 &r
->out
.info
->info4
, snum
);
4594 result
= construct_printer_info5(p
->mem_ctx
, ntprinter
,
4595 &r
->out
.info
->info5
, snum
);
4598 result
= construct_printer_info6(p
->mem_ctx
, ntprinter
,
4599 &r
->out
.info
->info6
, snum
);
4602 result
= construct_printer_info7(p
->mem_ctx
, Printer
,
4603 &r
->out
.info
->info7
, snum
);
4606 result
= construct_printer_info8(p
->mem_ctx
, ntprinter
,
4607 &r
->out
.info
->info8
, snum
);
4610 result
= WERR_UNKNOWN_LEVEL
;
4614 free_a_printer(&ntprinter
, 2);
4616 if (!W_ERROR_IS_OK(result
)) {
4617 TALLOC_FREE(r
->out
.info
);
4621 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
, NULL
,
4622 r
->out
.info
, r
->in
.level
);
4623 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4625 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4628 /********************************************************************
4629 ********************************************************************/
4631 static const char **string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4632 fstring
*fstring_array
,
4633 const char *cservername
)
4635 int i
, num_strings
= 0;
4636 const char **array
= NULL
;
4638 for (i
=0; fstring_array
&& fstring_array
[i
][0] != '\0'; i
++) {
4640 const char *str
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4641 cservername
, fstring_array
[i
]);
4648 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4655 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4656 &array
, &num_strings
);
4662 /********************************************************************
4663 * fill a spoolss_DriverInfo1 struct
4664 ********************************************************************/
4666 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4667 struct spoolss_DriverInfo1
*r
,
4668 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4669 const char *servername
,
4670 const char *architecture
)
4672 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4673 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4678 /********************************************************************
4679 * fill a spoolss_DriverInfo2 struct
4680 ********************************************************************/
4682 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4683 struct spoolss_DriverInfo2
*r
,
4684 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4685 const char *servername
)
4688 const char *cservername
= canon_servername(servername
);
4690 r
->version
= driver
->info_3
->cversion
;
4692 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4693 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4694 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4695 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4697 if (strlen(driver
->info_3
->driverpath
)) {
4698 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4699 cservername
, driver
->info_3
->driverpath
);
4701 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4703 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4705 if (strlen(driver
->info_3
->datafile
)) {
4706 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4707 cservername
, driver
->info_3
->datafile
);
4709 r
->data_file
= talloc_strdup(mem_ctx
, "");
4711 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4713 if (strlen(driver
->info_3
->configfile
)) {
4714 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4715 cservername
, driver
->info_3
->configfile
);
4717 r
->config_file
= talloc_strdup(mem_ctx
, "");
4719 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4724 /********************************************************************
4725 * fill a spoolss_DriverInfo3 struct
4726 ********************************************************************/
4728 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4729 struct spoolss_DriverInfo3
*r
,
4730 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4731 const char *servername
)
4733 const char *cservername
= canon_servername(servername
);
4735 r
->version
= driver
->info_3
->cversion
;
4737 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4738 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4739 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4740 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4742 if (strlen(driver
->info_3
->driverpath
)) {
4743 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4744 cservername
, driver
->info_3
->driverpath
);
4746 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4748 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4750 if (strlen(driver
->info_3
->datafile
)) {
4751 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4752 cservername
, driver
->info_3
->datafile
);
4754 r
->data_file
= talloc_strdup(mem_ctx
, "");
4756 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4758 if (strlen(driver
->info_3
->configfile
)) {
4759 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4760 cservername
, driver
->info_3
->configfile
);
4762 r
->config_file
= talloc_strdup(mem_ctx
, "");
4764 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4766 if (strlen(driver
->info_3
->helpfile
)) {
4767 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4768 cservername
, driver
->info_3
->helpfile
);
4770 r
->help_file
= talloc_strdup(mem_ctx
, "");
4772 W_ERROR_HAVE_NO_MEMORY(r
->help_file
);
4774 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
4775 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
4776 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
4777 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
4779 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4780 driver
->info_3
->dependentfiles
,
4785 /********************************************************************
4786 * fill a spoolss_DriverInfo4 struct
4787 ********************************************************************/
4789 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4790 struct spoolss_DriverInfo4
*r
,
4791 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4792 const char *servername
)
4794 const char *cservername
= canon_servername(servername
);
4796 r
->version
= driver
->info_3
->cversion
;
4798 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4799 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4800 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4801 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4803 if (strlen(driver
->info_3
->driverpath
)) {
4804 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4805 cservername
, driver
->info_3
->driverpath
);
4807 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4809 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4811 if (strlen(driver
->info_3
->datafile
)) {
4812 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4813 cservername
, driver
->info_3
->datafile
);
4815 r
->data_file
= talloc_strdup(mem_ctx
, "");
4817 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4819 if (strlen(driver
->info_3
->configfile
)) {
4820 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4821 cservername
, driver
->info_3
->configfile
);
4823 r
->config_file
= talloc_strdup(mem_ctx
, "");
4825 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4827 if (strlen(driver
->info_3
->helpfile
)) {
4828 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4829 cservername
, driver
->info_3
->helpfile
);
4831 r
->help_file
= talloc_strdup(mem_ctx
, "");
4833 W_ERROR_HAVE_NO_MEMORY(r
->help_file
);
4835 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4836 driver
->info_3
->dependentfiles
,
4840 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
4841 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
4842 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
4843 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
4845 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4852 /********************************************************************
4853 * fill a spoolss_DriverInfo5 struct
4854 ********************************************************************/
4856 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
4857 struct spoolss_DriverInfo5
*r
,
4858 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4859 const char *servername
)
4861 const char *cservername
= canon_servername(servername
);
4863 r
->version
= driver
->info_3
->cversion
;
4865 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4866 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4867 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4868 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4870 if (strlen(driver
->info_3
->driverpath
)) {
4871 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4872 cservername
, driver
->info_3
->driverpath
);
4874 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4876 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4878 if (strlen(driver
->info_3
->datafile
)) {
4879 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4880 cservername
, driver
->info_3
->datafile
);
4882 r
->data_file
= talloc_strdup(mem_ctx
, "");
4884 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4886 if (strlen(driver
->info_3
->configfile
)) {
4887 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4888 cservername
, driver
->info_3
->configfile
);
4890 r
->config_file
= talloc_strdup(mem_ctx
, "");
4892 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4894 r
->driver_attributes
= 0;
4895 r
->config_version
= 0;
4896 r
->driver_version
= 0;
4900 /********************************************************************
4901 * fill a spoolss_DriverInfo6 struct
4902 ********************************************************************/
4904 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4905 struct spoolss_DriverInfo6
*r
,
4906 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4907 const char *servername
)
4909 const char *cservername
= canon_servername(servername
);
4911 r
->version
= driver
->info_3
->cversion
;
4913 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4914 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4915 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4916 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4918 if (strlen(driver
->info_3
->driverpath
)) {
4919 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4920 cservername
, driver
->info_3
->driverpath
);
4922 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4924 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4926 if (strlen(driver
->info_3
->datafile
)) {
4927 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4928 cservername
, driver
->info_3
->datafile
);
4930 r
->data_file
= talloc_strdup(mem_ctx
, "");
4932 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4934 if (strlen(driver
->info_3
->configfile
)) {
4935 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4936 cservername
, driver
->info_3
->configfile
);
4938 r
->config_file
= talloc_strdup(mem_ctx
, "");
4940 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4942 if (strlen(driver
->info_3
->helpfile
)) {
4943 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4944 cservername
, driver
->info_3
->helpfile
);
4946 r
->help_file
= talloc_strdup(mem_ctx
, "");
4948 W_ERROR_HAVE_NO_MEMORY(r
->help_file
);
4950 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
4951 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
4952 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
4953 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
4955 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4956 driver
->info_3
->dependentfiles
,
4958 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4963 r
->driver_version
= 0;
4965 r
->manufacturer_name
= talloc_strdup(mem_ctx
, "");
4966 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_name
);
4967 r
->manufacturer_url
= talloc_strdup(mem_ctx
, "");
4968 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_url
);
4969 r
->hardware_id
= talloc_strdup(mem_ctx
, "");
4970 W_ERROR_HAVE_NO_MEMORY(r
->hardware_id
);
4971 r
->provider
= talloc_strdup(mem_ctx
, "");
4972 W_ERROR_HAVE_NO_MEMORY(r
->provider
);
4977 /********************************************************************
4978 ********************************************************************/
4979 #if 0 /* disabled until marshalling issues are resolved - gd */
4980 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
4981 struct spoolss_DriverFileInfo
*r
,
4982 const char *cservername
,
4983 const char *file_name
,
4984 enum spoolss_DriverFileType file_type
,
4985 uint32_t file_version
)
4987 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4988 cservername
, file_name
);
4989 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
4990 r
->file_type
= file_type
;
4991 r
->file_version
= file_version
;
4996 /********************************************************************
4997 ********************************************************************/
4999 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
5000 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
5001 const char *cservername
,
5002 struct spoolss_DriverFileInfo
**info_p
,
5005 struct spoolss_DriverFileInfo
*info
= NULL
;
5013 if (strlen(driver
->info_3
->driverpath
)) {
5014 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5015 struct spoolss_DriverFileInfo
,
5017 W_ERROR_HAVE_NO_MEMORY(info
);
5018 result
= fill_spoolss_DriverFileInfo(info
,
5021 driver
->info_3
->driverpath
,
5022 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
5024 W_ERROR_NOT_OK_RETURN(result
);
5028 if (strlen(driver
->info_3
->configfile
)) {
5029 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5030 struct spoolss_DriverFileInfo
,
5032 W_ERROR_HAVE_NO_MEMORY(info
);
5033 result
= fill_spoolss_DriverFileInfo(info
,
5036 driver
->info_3
->configfile
,
5037 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
5039 W_ERROR_NOT_OK_RETURN(result
);
5043 if (strlen(driver
->info_3
->datafile
)) {
5044 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5045 struct spoolss_DriverFileInfo
,
5047 W_ERROR_HAVE_NO_MEMORY(info
);
5048 result
= fill_spoolss_DriverFileInfo(info
,
5051 driver
->info_3
->datafile
,
5052 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5054 W_ERROR_NOT_OK_RETURN(result
);
5058 if (strlen(driver
->info_3
->helpfile
)) {
5059 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5060 struct spoolss_DriverFileInfo
,
5062 W_ERROR_HAVE_NO_MEMORY(info
);
5063 result
= fill_spoolss_DriverFileInfo(info
,
5066 driver
->info_3
->helpfile
,
5067 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5069 W_ERROR_NOT_OK_RETURN(result
);
5073 for (i
=0; driver
->info_3
->dependentfiles
[i
][0] != '\0'; i
++) {
5074 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5075 struct spoolss_DriverFileInfo
,
5077 W_ERROR_HAVE_NO_MEMORY(info
);
5078 result
= fill_spoolss_DriverFileInfo(info
,
5081 driver
->info_3
->dependentfiles
[i
],
5082 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5084 W_ERROR_NOT_OK_RETURN(result
);
5094 /********************************************************************
5095 * fill a spoolss_DriverInfo101 struct
5096 ********************************************************************/
5098 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5099 struct spoolss_DriverInfo101
*r
,
5100 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
5101 const char *servername
)
5103 const char *cservername
= canon_servername(servername
);
5106 r
->version
= driver
->info_3
->cversion
;
5108 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
5109 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5110 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
5111 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5113 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5117 if (!W_ERROR_IS_OK(result
)) {
5121 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
5122 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
5124 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
5125 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
5127 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
5131 r
->driver_version
= 0;
5133 r
->manufacturer_name
= talloc_strdup(mem_ctx
, "");
5134 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_name
);
5135 r
->manufacturer_url
= talloc_strdup(mem_ctx
, "");
5136 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_url
);
5137 r
->hardware_id
= talloc_strdup(mem_ctx
, "");
5138 W_ERROR_HAVE_NO_MEMORY(r
->hardware_id
);
5139 r
->provider
= talloc_strdup(mem_ctx
, "");
5140 W_ERROR_HAVE_NO_MEMORY(r
->provider
);
5145 /********************************************************************
5146 * construct_printer_driver_info_1
5147 ********************************************************************/
5149 static WERROR
construct_printer_driver_info_1(TALLOC_CTX
*mem_ctx
,
5150 struct spoolss_DriverInfo1
*r
,
5152 const char *servername
,
5153 const char *architecture
,
5156 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5157 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5160 ZERO_STRUCT(driver
);
5162 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5163 return WERR_INVALID_PRINTER_NAME
;
5165 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5166 free_a_printer(&printer
, 2);
5167 return WERR_UNKNOWN_PRINTER_DRIVER
;
5170 result
= fill_printer_driver_info1(mem_ctx
, r
, &driver
, servername
, architecture
);
5172 free_a_printer(&printer
,2);
5177 /********************************************************************
5178 * construct_printer_driver_info_2
5179 * fill a printer_info_2 struct
5180 ********************************************************************/
5182 static WERROR
construct_printer_driver_info_2(TALLOC_CTX
*mem_ctx
,
5183 struct spoolss_DriverInfo2
*r
,
5185 const char *servername
,
5186 const char *architecture
,
5189 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5190 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5193 ZERO_STRUCT(printer
);
5194 ZERO_STRUCT(driver
);
5196 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5197 return WERR_INVALID_PRINTER_NAME
;
5199 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5200 free_a_printer(&printer
, 2);
5201 return WERR_UNKNOWN_PRINTER_DRIVER
;
5204 result
= fill_printer_driver_info2(mem_ctx
, r
, &driver
, servername
);
5206 free_a_printer(&printer
,2);
5211 /********************************************************************
5212 * construct_printer_info_3
5213 * fill a printer_info_3 struct
5214 ********************************************************************/
5216 static WERROR
construct_printer_driver_info_3(TALLOC_CTX
*mem_ctx
,
5217 struct spoolss_DriverInfo3
*r
,
5219 const char *servername
,
5220 const char *architecture
,
5223 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5224 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5226 ZERO_STRUCT(driver
);
5228 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
5230 if (!W_ERROR_IS_OK(status
))
5231 return WERR_INVALID_PRINTER_NAME
;
5233 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5234 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
5239 * I put this code in during testing. Helpful when commenting out the
5240 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5241 * as win2k always queries the driver using an infor level of 6.
5242 * I've left it in (but ifdef'd out) because I'll probably
5243 * use it in experimentation again in the future. --jerry 22/01/2002
5246 if (!W_ERROR_IS_OK(status
)) {
5248 * Is this a W2k client ?
5251 /* Yes - try again with a WinNT driver. */
5253 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5254 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
5258 if (!W_ERROR_IS_OK(status
)) {
5259 free_a_printer(&printer
,2);
5260 return WERR_UNKNOWN_PRINTER_DRIVER
;
5268 status
= fill_printer_driver_info3(mem_ctx
, r
, &driver
, servername
);
5270 free_a_printer(&printer
,2);
5275 /********************************************************************
5276 * construct_printer_info_6
5277 * fill a printer_info_6 struct
5278 ********************************************************************/
5280 static WERROR
construct_printer_driver_info_6(TALLOC_CTX
*mem_ctx
,
5281 struct spoolss_DriverInfo6
*r
,
5283 const char *servername
,
5284 const char *architecture
,
5287 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5288 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5291 ZERO_STRUCT(driver
);
5293 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5295 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5297 if (!W_ERROR_IS_OK(status
))
5298 return WERR_INVALID_PRINTER_NAME
;
5300 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5302 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5304 if (!W_ERROR_IS_OK(status
))
5307 * Is this a W2k client ?
5311 free_a_printer(&printer
,2);
5312 return WERR_UNKNOWN_PRINTER_DRIVER
;
5315 /* Yes - try again with a WinNT driver. */
5317 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5318 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5319 if (!W_ERROR_IS_OK(status
)) {
5320 free_a_printer(&printer
,2);
5321 return WERR_UNKNOWN_PRINTER_DRIVER
;
5325 status
= fill_printer_driver_info6(mem_ctx
, r
, &driver
, servername
);
5327 free_a_printer(&printer
,2);
5328 free_a_printer_driver(driver
, 3);
5332 #if 0 /* disabled until marshalling issues are resolved - gd */
5333 /********************************************************************
5334 * construct_printer_info_101
5335 * fill a printer_info_101 struct
5336 ********************************************************************/
5338 static WERROR
construct_printer_driver_info_101(TALLOC_CTX
*mem_ctx
,
5339 struct spoolss_DriverInfo101
*r
,
5341 const char *servername
,
5342 const char *architecture
,
5345 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5346 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5349 ZERO_STRUCT(driver
);
5351 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
5353 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5354 win_errstr(result
)));
5356 if (!W_ERROR_IS_OK(result
)) {
5357 return WERR_INVALID_PRINTER_NAME
;
5360 result
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
5361 architecture
, version
);
5363 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5364 win_errstr(result
)));
5366 if (!W_ERROR_IS_OK(result
)) {
5368 * Is this a W2k client ?
5372 free_a_printer(&printer
, 2);
5373 return WERR_UNKNOWN_PRINTER_DRIVER
;
5376 /* Yes - try again with a WinNT driver. */
5378 result
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
5379 architecture
, version
);
5380 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5381 win_errstr(result
)));
5382 if (!W_ERROR_IS_OK(result
)) {
5383 free_a_printer(&printer
, 2);
5384 return WERR_UNKNOWN_PRINTER_DRIVER
;
5388 result
= fill_printer_driver_info101(mem_ctx
, r
, &driver
, servername
);
5390 free_a_printer(&printer
, 2);
5391 free_a_printer_driver(driver
, 3);
5396 /****************************************************************
5397 _spoolss_GetPrinterDriver2
5398 ****************************************************************/
5400 WERROR
_spoolss_GetPrinterDriver2(pipes_struct
*p
,
5401 struct spoolss_GetPrinterDriver2
*r
)
5403 Printer_entry
*printer
;
5406 const char *servername
;
5409 /* that's an [in out] buffer */
5411 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5412 return WERR_INVALID_PARAM
;
5415 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5417 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5418 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5419 return WERR_INVALID_PRINTER_NAME
;
5423 *r
->out
.server_major_version
= 0;
5424 *r
->out
.server_minor_version
= 0;
5426 servername
= get_server_name(printer
);
5428 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5432 switch (r
->in
.level
) {
5434 result
= construct_printer_driver_info_1(p
->mem_ctx
,
5435 &r
->out
.info
->info1
,
5439 r
->in
.client_major_version
);
5442 result
= construct_printer_driver_info_2(p
->mem_ctx
,
5443 &r
->out
.info
->info2
,
5447 r
->in
.client_major_version
);
5450 result
= construct_printer_driver_info_3(p
->mem_ctx
,
5451 &r
->out
.info
->info3
,
5455 r
->in
.client_major_version
);
5458 result
= construct_printer_driver_info_6(p
->mem_ctx
,
5459 &r
->out
.info
->info6
,
5463 r
->in
.client_major_version
);
5465 #if 0 /* disabled until marshalling issues are resolved - gd */
5467 result
= construct_printer_driver_info_101(p
->mem_ctx
,
5468 &r
->out
.info
->info101
,
5472 r
->in
.client_major_version
);
5476 result
= WERR_UNKNOWN_LEVEL
;
5480 if (!W_ERROR_IS_OK(result
)) {
5481 TALLOC_FREE(r
->out
.info
);
5485 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
, NULL
,
5486 r
->out
.info
, r
->in
.level
);
5487 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5489 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5493 /****************************************************************
5494 _spoolss_StartPagePrinter
5495 ****************************************************************/
5497 WERROR
_spoolss_StartPagePrinter(pipes_struct
*p
,
5498 struct spoolss_StartPagePrinter
*r
)
5500 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5503 DEBUG(3,("_spoolss_StartPagePrinter: "
5504 "Error in startpageprinter printer handle\n"));
5508 Printer
->page_started
= true;
5512 /****************************************************************
5513 _spoolss_EndPagePrinter
5514 ****************************************************************/
5516 WERROR
_spoolss_EndPagePrinter(pipes_struct
*p
,
5517 struct spoolss_EndPagePrinter
*r
)
5521 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5524 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5525 OUR_HANDLE(r
->in
.handle
)));
5529 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5532 Printer
->page_started
= false;
5533 print_job_endpage(snum
, Printer
->jobid
);
5538 /****************************************************************
5539 _spoolss_StartDocPrinter
5540 ****************************************************************/
5542 WERROR
_spoolss_StartDocPrinter(pipes_struct
*p
,
5543 struct spoolss_StartDocPrinter
*r
)
5545 struct spoolss_DocumentInfo1
*info_1
;
5547 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5550 DEBUG(2,("_spoolss_StartDocPrinter: "
5551 "Invalid handle (%s:%u:%u)\n",
5552 OUR_HANDLE(r
->in
.handle
)));
5556 if (r
->in
.level
!= 1) {
5557 return WERR_UNKNOWN_LEVEL
;
5560 info_1
= r
->in
.info
.info1
;
5563 * a nice thing with NT is it doesn't listen to what you tell it.
5564 * when asked to send _only_ RAW datas, it tries to send datas
5567 * So I add checks like in NT Server ...
5570 if (info_1
->datatype
) {
5571 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5573 return WERR_INVALID_DATATYPE
;
5577 /* get the share number of the printer */
5578 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5582 Printer
->jobid
= print_job_start(p
->server_info
, snum
,
5583 info_1
->document_name
,
5584 Printer
->nt_devmode
);
5586 /* An error occured in print_job_start() so return an appropriate
5589 if (Printer
->jobid
== -1) {
5590 return map_werror_from_unix(errno
);
5593 Printer
->document_started
= true;
5594 *r
->out
.job_id
= Printer
->jobid
;
5599 /****************************************************************
5600 _spoolss_EndDocPrinter
5601 ****************************************************************/
5603 WERROR
_spoolss_EndDocPrinter(pipes_struct
*p
,
5604 struct spoolss_EndDocPrinter
*r
)
5606 return _spoolss_enddocprinter_internal(p
, r
->in
.handle
);
5609 /****************************************************************
5610 _spoolss_WritePrinter
5611 ****************************************************************/
5613 WERROR
_spoolss_WritePrinter(pipes_struct
*p
,
5614 struct spoolss_WritePrinter
*r
)
5616 uint32_t buffer_written
;
5618 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5621 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5622 OUR_HANDLE(r
->in
.handle
)));
5623 *r
->out
.num_written
= r
->in
._data_size
;
5627 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5630 buffer_written
= (uint32_t)print_job_write(snum
, Printer
->jobid
,
5631 (const char *)r
->in
.data
.data
,
5633 (size_t)r
->in
._data_size
);
5634 if (buffer_written
== (uint32_t)-1) {
5635 *r
->out
.num_written
= 0;
5636 if (errno
== ENOSPC
)
5637 return WERR_NO_SPOOL_SPACE
;
5639 return WERR_ACCESS_DENIED
;
5642 *r
->out
.num_written
= r
->in
._data_size
;
5647 /********************************************************************
5648 * api_spoolss_getprinter
5649 * called from the spoolss dispatcher
5651 ********************************************************************/
5653 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5657 WERROR errcode
= WERR_BADFUNC
;
5658 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5661 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5662 OUR_HANDLE(handle
)));
5666 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5670 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5671 errcode
= print_queue_pause(p
->server_info
, snum
);
5673 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5674 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5675 errcode
= print_queue_resume(p
->server_info
, snum
);
5677 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5678 errcode
= print_queue_purge(p
->server_info
, snum
);
5681 return WERR_UNKNOWN_LEVEL
;
5688 /****************************************************************
5689 _spoolss_AbortPrinter
5690 * From MSDN: "Deletes printer's spool file if printer is configured
5692 ****************************************************************/
5694 WERROR
_spoolss_AbortPrinter(pipes_struct
*p
,
5695 struct spoolss_AbortPrinter
*r
)
5697 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5699 WERROR errcode
= WERR_OK
;
5702 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5703 OUR_HANDLE(r
->in
.handle
)));
5707 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5710 print_job_delete(p
->server_info
, snum
, Printer
->jobid
, &errcode
);
5715 /********************************************************************
5716 * called by spoolss_api_setprinter
5717 * when updating a printer description
5718 ********************************************************************/
5720 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5721 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5723 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5727 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5729 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5730 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5731 OUR_HANDLE(handle
)));
5733 result
= WERR_BADFID
;
5738 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5739 result
= WERR_INVALID_PARAM
;
5743 /* Check the user has permissions to change the security
5744 descriptor. By experimentation with two NT machines, the user
5745 requires Full Access to the printer to change security
5748 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5749 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5750 result
= WERR_ACCESS_DENIED
;
5754 /* NT seems to like setting the security descriptor even though
5755 nothing may have actually changed. */
5757 if ( !nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
)) {
5758 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5759 result
= WERR_BADFID
;
5763 if (DEBUGLEVEL
>= 10) {
5767 the_acl
= old_secdesc_ctr
->sd
->dacl
;
5768 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5769 PRINTERNAME(snum
), the_acl
->num_aces
));
5771 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5772 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5773 &the_acl
->aces
[i
].trustee
),
5774 the_acl
->aces
[i
].access_mask
));
5777 the_acl
= secdesc_ctr
->sd
->dacl
;
5780 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5781 PRINTERNAME(snum
), the_acl
->num_aces
));
5783 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5784 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5785 &the_acl
->aces
[i
].trustee
),
5786 the_acl
->aces
[i
].access_mask
));
5789 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5793 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5794 if (!new_secdesc_ctr
) {
5795 result
= WERR_NOMEM
;
5799 if (sec_desc_equal(new_secdesc_ctr
->sd
, old_secdesc_ctr
->sd
)) {
5804 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5811 /********************************************************************
5812 Canonicalize printer info from a client
5814 ATTN: It does not matter what we set the servername to hear
5815 since we do the necessary work in get_a_printer() to set it to
5816 the correct value based on what the client sent in the
5817 _spoolss_open_printer_ex().
5818 ********************************************************************/
5820 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5822 fstring printername
;
5825 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5826 "portname=%s drivername=%s comment=%s location=%s\n",
5827 info
->servername
, info
->printername
, info
->sharename
,
5828 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5830 /* we force some elements to "correct" values */
5831 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5832 fstrcpy(info
->sharename
, lp_servicename(snum
));
5834 /* check to see if we allow printername != sharename */
5836 if ( lp_force_printername(snum
) ) {
5837 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5838 global_myname(), info
->sharename
);
5841 /* make sure printername is in \\server\printername format */
5843 fstrcpy( printername
, info
->printername
);
5845 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5846 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5850 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5851 global_myname(), p
);
5854 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5855 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5862 /****************************************************************************
5863 ****************************************************************************/
5865 WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5867 char *cmd
= lp_addport_cmd();
5868 char *command
= NULL
;
5870 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5871 bool is_print_op
= false;
5874 return WERR_ACCESS_DENIED
;
5877 command
= talloc_asprintf(ctx
,
5878 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5884 is_print_op
= user_has_privileges( token
, &se_printop
);
5886 DEBUG(10,("Running [%s]\n", command
));
5888 /********* BEGIN SePrintOperatorPrivilege **********/
5893 ret
= smbrun(command
, NULL
);
5898 /********* END SePrintOperatorPrivilege **********/
5900 DEBUGADD(10,("returned [%d]\n", ret
));
5902 TALLOC_FREE(command
);
5905 return WERR_ACCESS_DENIED
;
5911 /****************************************************************************
5912 ****************************************************************************/
5914 bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
5916 char *cmd
= lp_addprinter_cmd();
5918 char *command
= NULL
;
5922 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5923 bool is_print_op
= false;
5924 char *remote_machine
= talloc_strdup(ctx
, "%m");
5926 if (!remote_machine
) {
5929 remote_machine
= talloc_sub_basic(ctx
,
5930 current_user_info
.smb_name
,
5931 current_user_info
.domain
,
5933 if (!remote_machine
) {
5937 command
= talloc_asprintf(ctx
,
5938 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5939 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5940 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5941 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5947 is_print_op
= user_has_privileges( token
, &se_printop
);
5949 DEBUG(10,("Running [%s]\n", command
));
5951 /********* BEGIN SePrintOperatorPrivilege **********/
5956 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5957 /* Tell everyone we updated smb.conf. */
5958 message_send_all(smbd_messaging_context(),
5959 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
5965 /********* END SePrintOperatorPrivilege **********/
5967 DEBUGADD(10,("returned [%d]\n", ret
));
5969 TALLOC_FREE(command
);
5970 TALLOC_FREE(remote_machine
);
5978 /* reload our services immediately */
5980 reload_services(false);
5984 /* Get lines and convert them back to dos-codepage */
5985 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
5986 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5989 /* Set the portname to what the script says the portname should be. */
5990 /* but don't require anything to be return from the script exit a good error code */
5993 /* Set the portname to what the script says the portname should be. */
5994 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5995 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5998 TALLOC_FREE(qlines
);
6003 /********************************************************************
6004 * Called by spoolss_api_setprinter
6005 * when updating a printer description.
6006 ********************************************************************/
6008 static WERROR
update_printer(pipes_struct
*p
, struct policy_handle
*handle
,
6009 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6010 struct spoolss_DeviceMode
*devmode
)
6013 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6014 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6019 DEBUG(8,("update_printer\n"));
6024 result
= WERR_BADFID
;
6028 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6029 result
= WERR_BADFID
;
6033 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6034 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6035 result
= WERR_BADFID
;
6039 DEBUGADD(8,("Converting info_2 struct\n"));
6042 * convert_printer_info converts the incoming
6043 * info from the client and overwrites the info
6044 * just read from the tdb in the pointer 'printer'.
6047 if (!convert_printer_info(info_ctr
, printer
)) {
6048 result
= WERR_NOMEM
;
6053 /* we have a valid devmode
6054 convert it and link it*/
6056 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6057 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6058 &printer
->info_2
->devmode
)) {
6059 result
= WERR_NOMEM
;
6064 /* Do sanity check on the requested changes for Samba */
6066 if (!check_printer_ok(printer
->info_2
, snum
)) {
6067 result
= WERR_INVALID_PARAM
;
6071 /* FIXME!!! If the driver has changed we really should verify that
6072 it is installed before doing much else --jerry */
6074 /* Check calling user has permission to update printer description */
6076 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6077 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6078 result
= WERR_ACCESS_DENIED
;
6082 /* Call addprinter hook */
6083 /* Check changes to see if this is really needed */
6085 if ( *lp_addprinter_cmd()
6086 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6087 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6088 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6089 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6091 /* add_printer_hook() will call reload_services() */
6093 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
6095 result
= WERR_ACCESS_DENIED
;
6101 * When a *new* driver is bound to a printer, the drivername is used to
6102 * lookup previously saved driver initialization info, which is then
6103 * bound to the printer, simulating what happens in the Windows arch.
6105 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6107 if (!set_driver_init(printer
, 2))
6109 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6110 printer
->info_2
->drivername
));
6113 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6114 printer
->info_2
->drivername
));
6116 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6120 * flag which changes actually occured. This is a small subset of
6121 * all the possible changes. We also have to update things in the
6125 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6126 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6127 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6128 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6130 notify_printer_comment(snum
, printer
->info_2
->comment
);
6133 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6134 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6135 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6136 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6138 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6141 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6144 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6147 pname
= printer
->info_2
->printername
;
6150 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6151 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6152 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6154 notify_printer_printername( snum
, pname
);
6157 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6158 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6159 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6160 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6162 notify_printer_port(snum
, printer
->info_2
->portname
);
6165 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6166 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6167 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6168 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6170 notify_printer_location(snum
, printer
->info_2
->location
);
6173 /* here we need to update some more DsSpooler keys */
6174 /* uNCName, serverName, shortServerName */
6176 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6177 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6178 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6179 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6180 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6182 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6183 global_myname(), printer
->info_2
->sharename
);
6184 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6185 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6186 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6188 /* Update printer info */
6189 result
= mod_a_printer(printer
, 2);
6192 free_a_printer(&printer
, 2);
6193 free_a_printer(&old_printer
, 2);
6199 /****************************************************************************
6200 ****************************************************************************/
6201 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
,
6202 struct policy_handle
*handle
,
6203 struct spoolss_SetPrinterInfo7
*info7
)
6207 Printer_entry
*Printer
;
6209 if ( lp_security() != SEC_ADS
) {
6210 return WERR_UNKNOWN_LEVEL
;
6213 Printer
= find_printer_index_by_hnd(p
, handle
);
6215 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6220 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6223 nt_printer_publish(Printer
, snum
, info7
->action
);
6227 return WERR_UNKNOWN_LEVEL
;
6231 /****************************************************************
6233 ****************************************************************/
6235 WERROR
_spoolss_SetPrinter(pipes_struct
*p
,
6236 struct spoolss_SetPrinter
*r
)
6240 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6243 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6244 OUR_HANDLE(r
->in
.handle
)));
6248 /* check the level */
6249 switch (r
->in
.info_ctr
->level
) {
6251 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6253 result
= update_printer(p
, r
->in
.handle
,
6255 r
->in
.devmode_ctr
->devmode
);
6256 if (!W_ERROR_IS_OK(result
))
6258 if (r
->in
.secdesc_ctr
->sd
)
6259 result
= update_printer_sec(r
->in
.handle
, p
,
6263 return update_printer_sec(r
->in
.handle
, p
,
6266 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6267 r
->in
.info_ctr
->info
.info7
);
6269 return WERR_UNKNOWN_LEVEL
;
6273 /****************************************************************
6274 _spoolss_FindClosePrinterNotify
6275 ****************************************************************/
6277 WERROR
_spoolss_FindClosePrinterNotify(pipes_struct
*p
,
6278 struct spoolss_FindClosePrinterNotify
*r
)
6280 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6283 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6284 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6288 if (Printer
->notify
.client_connected
== true) {
6291 if ( Printer
->printer_type
== SPLHND_SERVER
)
6293 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6294 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
6297 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6300 Printer
->notify
.flags
=0;
6301 Printer
->notify
.options
=0;
6302 Printer
->notify
.localmachine
[0]='\0';
6303 Printer
->notify
.printerlocal
=0;
6304 TALLOC_FREE(Printer
->notify
.option
);
6305 Printer
->notify
.client_connected
= false;
6310 /****************************************************************
6312 ****************************************************************/
6314 WERROR
_spoolss_AddJob(pipes_struct
*p
,
6315 struct spoolss_AddJob
*r
)
6317 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6318 return WERR_INVALID_PARAM
;
6321 /* this is what a NT server returns for AddJob. AddJob must fail on
6322 * non-local printers */
6324 if (r
->in
.level
!= 1) {
6325 return WERR_UNKNOWN_LEVEL
;
6328 return WERR_INVALID_PARAM
;
6331 /****************************************************************************
6333 ****************************************************************************/
6335 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
6336 struct spoolss_JobInfo1
*r
,
6337 const print_queue_struct
*queue
,
6338 int position
, int snum
,
6339 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6343 t
= gmtime(&queue
->time
);
6345 r
->job_id
= queue
->job
;
6347 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6348 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6349 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6350 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6351 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6352 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6353 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6354 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6355 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6356 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6357 r
->text_status
= talloc_strdup(mem_ctx
, "");
6358 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6360 r
->status
= nt_printj_status(queue
->status
);
6361 r
->priority
= queue
->priority
;
6362 r
->position
= position
;
6363 r
->total_pages
= queue
->page_count
;
6364 r
->pages_printed
= 0; /* ??? */
6366 init_systemtime(&r
->submitted
, t
);
6371 /****************************************************************************
6373 ****************************************************************************/
6375 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6376 struct spoolss_JobInfo2
*r
,
6377 const print_queue_struct
*queue
,
6378 int position
, int snum
,
6379 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6380 struct spoolss_DeviceMode
*devmode
)
6384 t
= gmtime(&queue
->time
);
6386 r
->job_id
= queue
->job
;
6388 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6389 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6390 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6391 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6392 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6393 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6394 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6395 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6396 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6397 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6398 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6399 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6400 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6401 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6402 r
->parameters
= talloc_strdup(mem_ctx
, "");
6403 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6404 r
->driver_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
6405 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6407 r
->devmode
= devmode
;
6409 r
->text_status
= talloc_strdup(mem_ctx
, "");
6410 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6414 r
->status
= nt_printj_status(queue
->status
);
6415 r
->priority
= queue
->priority
;
6416 r
->position
= position
;
6419 r
->total_pages
= queue
->page_count
;
6420 r
->size
= queue
->size
;
6421 init_systemtime(&r
->submitted
, t
);
6423 r
->pages_printed
= 0; /* ??? */
6428 /****************************************************************************
6430 ****************************************************************************/
6432 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6433 struct spoolss_JobInfo3
*r
,
6434 const print_queue_struct
*queue
,
6435 const print_queue_struct
*next_queue
,
6436 int position
, int snum
,
6437 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6439 r
->job_id
= queue
->job
;
6442 r
->next_job_id
= next_queue
->job
;
6449 /****************************************************************************
6450 Enumjobs at level 1.
6451 ****************************************************************************/
6453 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6454 const print_queue_struct
*queue
,
6455 uint32_t num_queues
, int snum
,
6456 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6457 union spoolss_JobInfo
**info_p
,
6460 union spoolss_JobInfo
*info
;
6462 WERROR result
= WERR_OK
;
6464 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6465 W_ERROR_HAVE_NO_MEMORY(info
);
6467 *count
= num_queues
;
6469 for (i
=0; i
<*count
; i
++) {
6470 result
= fill_job_info1(info
,
6476 if (!W_ERROR_IS_OK(result
)) {
6482 if (!W_ERROR_IS_OK(result
)) {
6493 /****************************************************************************
6494 Enumjobs at level 2.
6495 ****************************************************************************/
6497 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6498 const print_queue_struct
*queue
,
6499 uint32_t num_queues
, int snum
,
6500 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6501 union spoolss_JobInfo
**info_p
,
6504 union spoolss_JobInfo
*info
;
6506 WERROR result
= WERR_OK
;
6508 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6509 W_ERROR_HAVE_NO_MEMORY(info
);
6511 *count
= num_queues
;
6513 for (i
=0; i
<*count
; i
++) {
6515 struct spoolss_DeviceMode
*devmode
;
6517 devmode
= construct_dev_mode(info
, lp_const_servicename(snum
));
6519 result
= WERR_NOMEM
;
6523 result
= fill_job_info2(info
,
6530 if (!W_ERROR_IS_OK(result
)) {
6536 if (!W_ERROR_IS_OK(result
)) {
6547 /****************************************************************************
6548 Enumjobs at level 3.
6549 ****************************************************************************/
6551 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
6552 const print_queue_struct
*queue
,
6553 uint32_t num_queues
, int snum
,
6554 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6555 union spoolss_JobInfo
**info_p
,
6558 union spoolss_JobInfo
*info
;
6560 WERROR result
= WERR_OK
;
6562 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6563 W_ERROR_HAVE_NO_MEMORY(info
);
6565 *count
= num_queues
;
6567 for (i
=0; i
<*count
; i
++) {
6568 const print_queue_struct
*next_queue
= NULL
;
6571 next_queue
= &queue
[i
+1];
6574 result
= fill_job_info3(info
,
6581 if (!W_ERROR_IS_OK(result
)) {
6587 if (!W_ERROR_IS_OK(result
)) {
6598 /****************************************************************
6600 ****************************************************************/
6602 WERROR
_spoolss_EnumJobs(pipes_struct
*p
,
6603 struct spoolss_EnumJobs
*r
)
6606 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6608 print_status_struct prt_status
;
6609 print_queue_struct
*queue
= NULL
;
6612 /* that's an [in out] buffer */
6614 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6615 return WERR_INVALID_PARAM
;
6618 DEBUG(4,("_spoolss_EnumJobs\n"));
6622 *r
->out
.info
= NULL
;
6624 /* lookup the printer snum and tdb entry */
6626 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6630 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6631 if (!W_ERROR_IS_OK(result
)) {
6635 count
= print_queue_status(snum
, &queue
, &prt_status
);
6636 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6637 count
, prt_status
.status
, prt_status
.message
));
6641 free_a_printer(&ntprinter
, 2);
6645 switch (r
->in
.level
) {
6647 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6648 ntprinter
, r
->out
.info
, r
->out
.count
);
6651 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6652 ntprinter
, r
->out
.info
, r
->out
.count
);
6655 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
6656 ntprinter
, r
->out
.info
, r
->out
.count
);
6659 result
= WERR_UNKNOWN_LEVEL
;
6664 free_a_printer(&ntprinter
, 2);
6666 if (!W_ERROR_IS_OK(result
)) {
6670 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6671 spoolss_EnumJobs
, NULL
,
6672 *r
->out
.info
, r
->in
.level
,
6674 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6675 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6677 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6680 /****************************************************************
6681 _spoolss_ScheduleJob
6682 ****************************************************************/
6684 WERROR
_spoolss_ScheduleJob(pipes_struct
*p
,
6685 struct spoolss_ScheduleJob
*r
)
6690 /****************************************************************
6692 ****************************************************************/
6694 WERROR
_spoolss_SetJob(pipes_struct
*p
,
6695 struct spoolss_SetJob
*r
)
6698 WERROR errcode
= WERR_BADFUNC
;
6700 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6704 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
6705 return WERR_INVALID_PRINTER_NAME
;
6708 switch (r
->in
.command
) {
6709 case SPOOLSS_JOB_CONTROL_CANCEL
:
6710 case SPOOLSS_JOB_CONTROL_DELETE
:
6711 if (print_job_delete(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6715 case SPOOLSS_JOB_CONTROL_PAUSE
:
6716 if (print_job_pause(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6720 case SPOOLSS_JOB_CONTROL_RESTART
:
6721 case SPOOLSS_JOB_CONTROL_RESUME
:
6722 if (print_job_resume(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6727 return WERR_UNKNOWN_LEVEL
;
6733 /****************************************************************************
6734 Enumerates all printer drivers by level.
6735 ****************************************************************************/
6737 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
6738 const char *servername
,
6739 const char *architecture
,
6741 union spoolss_DriverInfo
**info_p
,
6747 fstring
*list
= NULL
;
6748 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6749 union spoolss_DriverInfo
*info
= NULL
;
6751 WERROR result
= WERR_OK
;
6756 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6758 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6759 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6760 ndrivers
, architecture
, version
));
6762 if (ndrivers
== -1) {
6763 result
= WERR_NOMEM
;
6767 if (ndrivers
!= 0) {
6768 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6769 union spoolss_DriverInfo
,
6772 DEBUG(0,("enumprinterdrivers_level1: "
6773 "failed to enlarge driver info buffer!\n"));
6774 result
= WERR_NOMEM
;
6779 for (i
=0; i
<ndrivers
; i
++) {
6780 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6781 ZERO_STRUCT(driver
);
6782 result
= get_a_printer_driver(&driver
, 3, list
[i
],
6783 architecture
, version
);
6784 if (!W_ERROR_IS_OK(result
)) {
6790 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
6791 &driver
, servername
,
6795 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
6796 &driver
, servername
);
6799 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
6800 &driver
, servername
);
6803 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
6804 &driver
, servername
);
6807 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
6808 &driver
, servername
);
6811 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
6812 &driver
, servername
);
6815 result
= WERR_UNKNOWN_LEVEL
;
6819 if (!W_ERROR_IS_OK(result
)) {
6820 free_a_printer_driver(driver
, 3);
6823 free_a_printer_driver(driver
, 3);
6833 if (!W_ERROR_IS_OK(result
)) {
6844 /****************************************************************************
6845 Enumerates all printer drivers at level 1.
6846 ****************************************************************************/
6848 static WERROR
enumprinterdrivers_level1(TALLOC_CTX
*mem_ctx
,
6849 const char *servername
,
6850 const char *architecture
,
6851 union spoolss_DriverInfo
**info_p
,
6854 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 1,
6858 /****************************************************************************
6859 Enumerates all printer drivers at level 2.
6860 ****************************************************************************/
6862 static WERROR
enumprinterdrivers_level2(TALLOC_CTX
*mem_ctx
,
6863 const char *servername
,
6864 const char *architecture
,
6865 union spoolss_DriverInfo
**info_p
,
6868 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 2,
6872 /****************************************************************************
6873 Enumerates all printer drivers at level 3.
6874 ****************************************************************************/
6876 static WERROR
enumprinterdrivers_level3(TALLOC_CTX
*mem_ctx
,
6877 const char *servername
,
6878 const char *architecture
,
6879 union spoolss_DriverInfo
**info_p
,
6882 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 3,
6886 /****************************************************************************
6887 Enumerates all printer drivers at level 4.
6888 ****************************************************************************/
6890 static WERROR
enumprinterdrivers_level4(TALLOC_CTX
*mem_ctx
,
6891 const char *servername
,
6892 const char *architecture
,
6893 union spoolss_DriverInfo
**info_p
,
6896 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 4,
6900 /****************************************************************************
6901 Enumerates all printer drivers at level 5.
6902 ****************************************************************************/
6904 static WERROR
enumprinterdrivers_level5(TALLOC_CTX
*mem_ctx
,
6905 const char *servername
,
6906 const char *architecture
,
6907 union spoolss_DriverInfo
**info_p
,
6910 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 5,
6914 /****************************************************************************
6915 Enumerates all printer drivers at level 6.
6916 ****************************************************************************/
6918 static WERROR
enumprinterdrivers_level6(TALLOC_CTX
*mem_ctx
,
6919 const char *servername
,
6920 const char *architecture
,
6921 union spoolss_DriverInfo
**info_p
,
6924 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 6,
6929 /****************************************************************
6930 _spoolss_EnumPrinterDrivers
6931 ****************************************************************/
6933 WERROR
_spoolss_EnumPrinterDrivers(pipes_struct
*p
,
6934 struct spoolss_EnumPrinterDrivers
*r
)
6936 const char *cservername
;
6939 /* that's an [in out] buffer */
6941 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6942 return WERR_INVALID_PARAM
;
6945 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6949 *r
->out
.info
= NULL
;
6951 cservername
= canon_servername(r
->in
.server
);
6953 if (!is_myname_or_ipaddr(cservername
)) {
6954 return WERR_UNKNOWN_PRINTER_DRIVER
;
6957 switch (r
->in
.level
) {
6959 result
= enumprinterdrivers_level1(p
->mem_ctx
, cservername
,
6961 r
->out
.info
, r
->out
.count
);
6964 result
= enumprinterdrivers_level2(p
->mem_ctx
, cservername
,
6966 r
->out
.info
, r
->out
.count
);
6969 result
= enumprinterdrivers_level3(p
->mem_ctx
, cservername
,
6971 r
->out
.info
, r
->out
.count
);
6974 result
= enumprinterdrivers_level4(p
->mem_ctx
, cservername
,
6976 r
->out
.info
, r
->out
.count
);
6979 result
= enumprinterdrivers_level5(p
->mem_ctx
, cservername
,
6981 r
->out
.info
, r
->out
.count
);
6984 result
= enumprinterdrivers_level6(p
->mem_ctx
, cservername
,
6986 r
->out
.info
, r
->out
.count
);
6989 return WERR_UNKNOWN_LEVEL
;
6992 if (!W_ERROR_IS_OK(result
)) {
6996 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6997 spoolss_EnumPrinterDrivers
, NULL
,
6998 *r
->out
.info
, r
->in
.level
,
7000 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7001 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7003 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7006 /****************************************************************************
7007 ****************************************************************************/
7009 static WERROR
fill_form_info_1(TALLOC_CTX
*mem_ctx
,
7010 struct spoolss_FormInfo1
*r
,
7011 const nt_forms_struct
*form
)
7013 r
->form_name
= talloc_strdup(mem_ctx
, form
->name
);
7014 W_ERROR_HAVE_NO_MEMORY(r
->form_name
);
7016 r
->flags
= form
->flag
;
7017 r
->size
.width
= form
->width
;
7018 r
->size
.height
= form
->length
;
7019 r
->area
.left
= form
->left
;
7020 r
->area
.top
= form
->top
;
7021 r
->area
.right
= form
->right
;
7022 r
->area
.bottom
= form
->bottom
;
7027 /****************************************************************
7028 spoolss_enumforms_level1
7029 ****************************************************************/
7031 static WERROR
spoolss_enumforms_level1(TALLOC_CTX
*mem_ctx
,
7032 const nt_forms_struct
*builtin_forms
,
7033 uint32_t num_builtin_forms
,
7034 const nt_forms_struct
*user_forms
,
7035 uint32_t num_user_forms
,
7036 union spoolss_FormInfo
**info_p
,
7039 union spoolss_FormInfo
*info
;
7040 WERROR result
= WERR_OK
;
7043 *count
= num_builtin_forms
+ num_user_forms
;
7045 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_FormInfo
, *count
);
7046 W_ERROR_HAVE_NO_MEMORY(info
);
7048 /* construct the list of form structures */
7049 for (i
=0; i
<num_builtin_forms
; i
++) {
7050 DEBUGADD(6,("Filling builtin form number [%d]\n",i
));
7051 result
= fill_form_info_1(info
, &info
[i
].info1
,
7053 if (!W_ERROR_IS_OK(result
)) {
7058 for (i
=0; i
<num_user_forms
; i
++) {
7059 DEBUGADD(6,("Filling user form number [%d]\n",i
));
7060 result
= fill_form_info_1(info
, &info
[i
+num_builtin_forms
].info1
,
7062 if (!W_ERROR_IS_OK(result
)) {
7068 if (!W_ERROR_IS_OK(result
)) {
7079 /****************************************************************
7081 ****************************************************************/
7083 WERROR
_spoolss_EnumForms(pipes_struct
*p
,
7084 struct spoolss_EnumForms
*r
)
7087 nt_forms_struct
*user_forms
= NULL
;
7088 nt_forms_struct
*builtin_forms
= NULL
;
7089 uint32_t num_user_forms
;
7090 uint32_t num_builtin_forms
;
7094 *r
->out
.info
= NULL
;
7096 /* that's an [in out] buffer */
7098 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7099 return WERR_INVALID_PARAM
;
7102 DEBUG(4,("_spoolss_EnumForms\n"));
7103 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7104 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7106 num_builtin_forms
= get_builtin_ntforms(&builtin_forms
);
7107 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms
));
7108 num_user_forms
= get_ntforms(&user_forms
);
7109 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms
));
7111 if (num_user_forms
+ num_builtin_forms
== 0) {
7112 SAFE_FREE(builtin_forms
);
7113 SAFE_FREE(user_forms
);
7114 return WERR_NO_MORE_ITEMS
;
7117 switch (r
->in
.level
) {
7119 result
= spoolss_enumforms_level1(p
->mem_ctx
,
7128 result
= WERR_UNKNOWN_LEVEL
;
7132 SAFE_FREE(user_forms
);
7133 SAFE_FREE(builtin_forms
);
7135 if (!W_ERROR_IS_OK(result
)) {
7139 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7140 spoolss_EnumForms
, NULL
,
7141 *r
->out
.info
, r
->in
.level
,
7143 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7144 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7146 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7149 /****************************************************************
7150 ****************************************************************/
7152 static WERROR
find_form_byname(const char *name
,
7153 nt_forms_struct
*form
)
7155 nt_forms_struct
*list
= NULL
;
7156 int num_forms
= 0, i
= 0;
7158 if (get_a_builtin_ntform_by_string(name
, form
)) {
7162 num_forms
= get_ntforms(&list
);
7163 DEBUGADD(5,("Number of forms [%d]\n", num_forms
));
7165 if (num_forms
== 0) {
7169 /* Check if the requested name is in the list of form structures */
7170 for (i
= 0; i
< num_forms
; i
++) {
7172 DEBUG(4,("checking form %s (want %s)\n", list
[i
].name
, name
));
7174 if (strequal(name
, list
[i
].name
)) {
7175 DEBUGADD(6,("Found form %s number [%d]\n", name
, i
));
7187 /****************************************************************
7189 ****************************************************************/
7191 WERROR
_spoolss_GetForm(pipes_struct
*p
,
7192 struct spoolss_GetForm
*r
)
7195 nt_forms_struct form
;
7197 /* that's an [in out] buffer */
7199 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7200 return WERR_INVALID_PARAM
;
7203 DEBUG(4,("_spoolss_GetForm\n"));
7204 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7205 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7207 result
= find_form_byname(r
->in
.form_name
, &form
);
7208 if (!W_ERROR_IS_OK(result
)) {
7209 TALLOC_FREE(r
->out
.info
);
7213 switch (r
->in
.level
) {
7215 result
= fill_form_info_1(p
->mem_ctx
,
7216 &r
->out
.info
->info1
,
7221 result
= WERR_UNKNOWN_LEVEL
;
7225 if (!W_ERROR_IS_OK(result
)) {
7226 TALLOC_FREE(r
->out
.info
);
7230 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
, NULL
,
7231 r
->out
.info
, r
->in
.level
);
7232 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7234 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7237 /****************************************************************************
7238 ****************************************************************************/
7240 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7241 struct spoolss_PortInfo1
*r
,
7244 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7245 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7250 /****************************************************************************
7251 TODO: This probably needs distinguish between TCP/IP and Local ports
7253 ****************************************************************************/
7255 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7256 struct spoolss_PortInfo2
*r
,
7259 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7260 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7262 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7263 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7265 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7266 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7268 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7275 /****************************************************************************
7276 wrapper around the enumer ports command
7277 ****************************************************************************/
7279 WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7281 char *cmd
= lp_enumports_cmd();
7282 char **qlines
= NULL
;
7283 char *command
= NULL
;
7291 /* if no hook then just fill in the default port */
7294 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
7297 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7298 TALLOC_FREE(qlines
);
7305 /* we have a valid enumport command */
7307 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7312 DEBUG(10,("Running [%s]\n", command
));
7313 ret
= smbrun(command
, &fd
);
7314 DEBUG(10,("Returned [%d]\n", ret
));
7315 TALLOC_FREE(command
);
7320 return WERR_ACCESS_DENIED
;
7324 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7325 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7335 /****************************************************************************
7337 ****************************************************************************/
7339 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7340 union spoolss_PortInfo
**info_p
,
7343 union spoolss_PortInfo
*info
= NULL
;
7345 WERROR result
= WERR_OK
;
7346 char **qlines
= NULL
;
7349 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7350 if (!W_ERROR_IS_OK(result
)) {
7355 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7357 DEBUG(10,("Returning WERR_NOMEM\n"));
7358 result
= WERR_NOMEM
;
7362 for (i
=0; i
<numlines
; i
++) {
7363 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7364 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7365 if (!W_ERROR_IS_OK(result
)) {
7370 TALLOC_FREE(qlines
);
7373 if (!W_ERROR_IS_OK(result
)) {
7375 TALLOC_FREE(qlines
);
7387 /****************************************************************************
7389 ****************************************************************************/
7391 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7392 union spoolss_PortInfo
**info_p
,
7395 union spoolss_PortInfo
*info
= NULL
;
7397 WERROR result
= WERR_OK
;
7398 char **qlines
= NULL
;
7401 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7402 if (!W_ERROR_IS_OK(result
)) {
7407 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7409 DEBUG(10,("Returning WERR_NOMEM\n"));
7410 result
= WERR_NOMEM
;
7414 for (i
=0; i
<numlines
; i
++) {
7415 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7416 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7417 if (!W_ERROR_IS_OK(result
)) {
7422 TALLOC_FREE(qlines
);
7425 if (!W_ERROR_IS_OK(result
)) {
7427 TALLOC_FREE(qlines
);
7439 /****************************************************************
7441 ****************************************************************/
7443 WERROR
_spoolss_EnumPorts(pipes_struct
*p
,
7444 struct spoolss_EnumPorts
*r
)
7448 /* that's an [in out] buffer */
7450 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7451 return WERR_INVALID_PARAM
;
7454 DEBUG(4,("_spoolss_EnumPorts\n"));
7458 *r
->out
.info
= NULL
;
7460 switch (r
->in
.level
) {
7462 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7466 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7470 return WERR_UNKNOWN_LEVEL
;
7473 if (!W_ERROR_IS_OK(result
)) {
7477 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7478 spoolss_EnumPorts
, NULL
,
7479 *r
->out
.info
, r
->in
.level
,
7481 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7482 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7484 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7487 /****************************************************************************
7488 ****************************************************************************/
7490 static WERROR
spoolss_addprinterex_level_2(pipes_struct
*p
,
7492 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7493 struct spoolss_DeviceMode
*devmode
,
7494 struct security_descriptor
*sec_desc
,
7495 struct spoolss_UserLevelCtr
*user_ctr
,
7496 struct policy_handle
*handle
)
7498 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7501 WERROR err
= WERR_OK
;
7503 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7504 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7508 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7509 if (!convert_printer_info(info_ctr
, printer
)) {
7510 free_a_printer(&printer
, 2);
7514 /* check to see if the printer already exists */
7516 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7517 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7518 printer
->info_2
->sharename
));
7519 free_a_printer(&printer
, 2);
7520 return WERR_PRINTER_ALREADY_EXISTS
;
7523 /* FIXME!!! smbd should check to see if the driver is installed before
7524 trying to add a printer like this --jerry */
7526 if (*lp_addprinter_cmd() ) {
7527 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7529 free_a_printer(&printer
,2);
7530 return WERR_ACCESS_DENIED
;
7533 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7534 "smb.conf parameter \"addprinter command\" is defined. This"
7535 "parameter must exist for this call to succeed\n",
7536 printer
->info_2
->sharename
));
7539 /* use our primary netbios name since get_a_printer() will convert
7540 it to what the client expects on a case by case basis */
7542 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7543 printer
->info_2
->sharename
);
7546 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7547 free_a_printer(&printer
,2);
7548 return WERR_ACCESS_DENIED
;
7551 /* you must be a printer admin to add a new printer */
7552 if (!print_access_check(p
->server_info
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7553 free_a_printer(&printer
,2);
7554 return WERR_ACCESS_DENIED
;
7558 * Do sanity check on the requested changes for Samba.
7561 if (!check_printer_ok(printer
->info_2
, snum
)) {
7562 free_a_printer(&printer
,2);
7563 return WERR_INVALID_PARAM
;
7567 * When a printer is created, the drivername bound to the printer is used
7568 * to lookup previously saved driver initialization info, which is then
7569 * bound to the new printer, simulating what happens in the Windows arch.
7574 set_driver_init(printer
, 2);
7578 /* A valid devmode was included, convert and link it
7580 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7582 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7583 &printer
->info_2
->devmode
)) {
7588 /* write the ASCII on disk */
7589 err
= mod_a_printer(printer
, 2);
7590 if (!W_ERROR_IS_OK(err
)) {
7591 free_a_printer(&printer
,2);
7595 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7596 /* Handle open failed - remove addition. */
7597 del_a_printer(printer
->info_2
->sharename
);
7598 free_a_printer(&printer
,2);
7599 ZERO_STRUCTP(handle
);
7600 return WERR_ACCESS_DENIED
;
7603 update_c_setprinter(false);
7604 free_a_printer(&printer
,2);
7609 /****************************************************************
7610 _spoolss_AddPrinterEx
7611 ****************************************************************/
7613 WERROR
_spoolss_AddPrinterEx(pipes_struct
*p
,
7614 struct spoolss_AddPrinterEx
*r
)
7616 switch (r
->in
.info_ctr
->level
) {
7618 /* we don't handle yet */
7619 /* but I know what to do ... */
7620 return WERR_UNKNOWN_LEVEL
;
7622 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7624 r
->in
.devmode_ctr
->devmode
,
7625 r
->in
.secdesc_ctr
->sd
,
7626 r
->in
.userlevel_ctr
,
7629 return WERR_UNKNOWN_LEVEL
;
7633 /****************************************************************
7634 _spoolss_AddPrinterDriver
7635 ****************************************************************/
7637 WERROR
_spoolss_AddPrinterDriver(pipes_struct
*p
,
7638 struct spoolss_AddPrinterDriver
*r
)
7640 uint32_t level
= r
->in
.info_ctr
->level
;
7641 struct spoolss_AddDriverInfoCtr
*info
= r
->in
.info_ctr
;
7642 WERROR err
= WERR_OK
;
7643 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7644 const char *driver_name
= NULL
;
7648 switch (p
->hdr_req
.opnum
) {
7649 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7650 fn
= "_spoolss_AddPrinterDriver";
7652 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7653 fn
= "_spoolss_AddPrinterDriverEx";
7656 return WERR_INVALID_PARAM
;
7661 if (level
!= 3 && level
!= 6) {
7662 /* Clever hack from Martin Zielinski <mz@seh.de>
7663 * to allow downgrade from level 8 (Vista).
7665 DEBUG(0,("%s: level %d not yet implemented\n", fn
, level
));
7666 return WERR_UNKNOWN_LEVEL
;
7669 ZERO_STRUCT(driver
);
7671 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7676 DEBUG(5,("Cleaning driver's information\n"));
7677 err
= clean_up_driver_struct(p
, driver
, level
);
7678 if (!W_ERROR_IS_OK(err
))
7681 DEBUG(5,("Moving driver to final destination\n"));
7682 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, driver
, level
,
7687 if (add_a_printer_driver(driver
, level
)!=0) {
7688 err
= WERR_ACCESS_DENIED
;
7694 driver_name
= driver
.info_3
->name
? driver
.info_3
->name
: "";
7697 driver_name
= driver
.info_6
->name
? driver
.info_6
->name
: "";
7702 * I think this is where he DrvUpgradePrinter() hook would be
7703 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7704 * server. Right now, we just need to send ourselves a message
7705 * to update each printer bound to this driver. --jerry
7708 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7709 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7714 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7715 * decide if the driver init data should be deleted. The rules are:
7716 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7717 * 2) delete init data only if there is no 2k/Xp driver
7718 * 3) always delete init data
7719 * The generalized rule is always use init data from the highest order driver.
7720 * It is necessary to follow the driver install by an initialization step to
7721 * finish off this process.
7724 version
= driver
.info_3
->cversion
;
7725 else if (level
== 6)
7726 version
= driver
.info_6
->version
;
7731 * 9x printer driver - never delete init data
7734 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7739 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7740 * there is no 2k/Xp driver init data for this driver name.
7744 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7746 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7748 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7750 if (!del_driver_init(driver_name
))
7751 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7755 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7757 free_a_printer_driver(driver1
,3);
7758 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7765 * 2k or Xp printer driver - always delete init data
7768 if (!del_driver_init(driver_name
))
7769 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7774 DEBUG(0,("%s: invalid level=%d\n", fn
, level
));
7780 free_a_printer_driver(driver
, level
);
7784 /****************************************************************
7785 _spoolss_AddPrinterDriverEx
7786 ****************************************************************/
7788 WERROR
_spoolss_AddPrinterDriverEx(pipes_struct
*p
,
7789 struct spoolss_AddPrinterDriverEx
*r
)
7791 struct spoolss_AddPrinterDriver a
;
7794 * we only support the semantics of AddPrinterDriver()
7795 * i.e. only copy files that are newer than existing ones
7798 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7799 return WERR_ACCESS_DENIED
;
7802 a
.in
.servername
= r
->in
.servername
;
7803 a
.in
.info_ctr
= r
->in
.info_ctr
;
7805 return _spoolss_AddPrinterDriver(p
, &a
);
7808 /****************************************************************************
7809 ****************************************************************************/
7811 struct _spoolss_paths
{
7817 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7819 static const struct _spoolss_paths spoolss_paths
[]= {
7820 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7821 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7824 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7825 const char *servername
,
7826 const char *environment
,
7830 const char *pservername
= NULL
;
7831 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7832 const char *short_archi
;
7836 /* environment may be empty */
7837 if (environment
&& strlen(environment
)) {
7838 long_archi
= environment
;
7841 /* servername may be empty */
7842 if (servername
&& strlen(servername
)) {
7843 pservername
= canon_servername(servername
);
7845 if (!is_myname_or_ipaddr(pservername
)) {
7846 return WERR_INVALID_PARAM
;
7850 if (!(short_archi
= get_short_archi(long_archi
))) {
7851 return WERR_INVALID_ENVIRONMENT
;
7854 switch (component
) {
7855 case SPOOLSS_PRTPROCS_PATH
:
7856 case SPOOLSS_DRIVER_PATH
:
7858 *path
= talloc_asprintf(mem_ctx
,
7861 spoolss_paths
[component
].share
,
7864 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7865 SPOOLSS_DEFAULT_SERVER_PATH
,
7866 spoolss_paths
[component
].dir
,
7871 return WERR_INVALID_PARAM
;
7881 /****************************************************************************
7882 ****************************************************************************/
7884 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7885 const char *servername
,
7886 const char *environment
,
7887 struct spoolss_DriverDirectoryInfo1
*r
)
7892 werr
= compose_spoolss_server_path(mem_ctx
,
7895 SPOOLSS_DRIVER_PATH
,
7897 if (!W_ERROR_IS_OK(werr
)) {
7901 DEBUG(4,("printer driver directory: [%s]\n", path
));
7903 r
->directory_name
= path
;
7908 /****************************************************************
7909 _spoolss_GetPrinterDriverDirectory
7910 ****************************************************************/
7912 WERROR
_spoolss_GetPrinterDriverDirectory(pipes_struct
*p
,
7913 struct spoolss_GetPrinterDriverDirectory
*r
)
7917 /* that's an [in out] buffer */
7919 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7920 return WERR_INVALID_PARAM
;
7923 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7928 /* r->in.level is ignored */
7930 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7933 &r
->out
.info
->info1
);
7934 if (!W_ERROR_IS_OK(werror
)) {
7935 TALLOC_FREE(r
->out
.info
);
7939 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
, NULL
,
7940 r
->out
.info
, r
->in
.level
);
7941 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7943 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7946 /****************************************************************
7947 _spoolss_EnumPrinterData
7948 ****************************************************************/
7950 WERROR
_spoolss_EnumPrinterData(pipes_struct
*p
,
7951 struct spoolss_EnumPrinterData
*r
)
7953 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7954 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7957 REGISTRY_VALUE
*val
= NULL
;
7958 NT_PRINTER_DATA
*p_data
;
7959 int i
, key_index
, num_values
;
7962 *r
->out
.value_needed
= 0;
7963 *r
->out
.type
= REG_NONE
;
7964 *r
->out
.data_needed
= 0;
7966 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7969 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7970 OUR_HANDLE(r
->in
.handle
)));
7974 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7978 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7979 if (!W_ERROR_IS_OK(result
)) {
7983 p_data
= printer
->info_2
->data
;
7984 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7989 * The NT machine wants to know the biggest size of value and data
7991 * cf: MSDN EnumPrinterData remark section
7994 if (!r
->in
.value_offered
&& !r
->in
.data_offered
&& (key_index
!= -1)) {
7996 uint32_t biggest_valuesize
= 0;
7997 uint32_t biggest_datasize
= 0;
7999 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8001 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
8003 for ( i
=0; i
<num_values
; i
++ )
8005 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
8007 name_length
= strlen(val
->valuename
);
8008 if ( strlen(val
->valuename
) > biggest_valuesize
)
8009 biggest_valuesize
= name_length
;
8011 if ( val
->size
> biggest_datasize
)
8012 biggest_datasize
= val
->size
;
8014 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8018 /* the value is an UNICODE string but real_value_size is the length
8019 in bytes including the trailing 0 */
8021 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
8022 *r
->out
.data_needed
= biggest_datasize
;
8024 DEBUG(6,("final values: [%d], [%d]\n",
8025 *r
->out
.value_needed
, *r
->out
.data_needed
));
8031 * the value len is wrong in NT sp3
8032 * that's the number of bytes not the number of unicode chars
8035 if (key_index
!= -1) {
8036 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
,
8042 /* out_value should default to "" or else NT4 has
8043 problems unmarshalling the response */
8045 if (r
->in
.value_offered
) {
8046 *r
->out
.value_needed
= 1;
8047 r
->out
.value_name
= talloc_strdup(r
, "");
8048 if (!r
->out
.value_name
) {
8049 result
= WERR_NOMEM
;
8053 r
->out
.value_name
= NULL
;
8054 *r
->out
.value_needed
= 0;
8057 /* the data is counted in bytes */
8059 *r
->out
.data_needed
= r
->in
.data_offered
;
8061 result
= WERR_NO_MORE_ITEMS
;
8065 * - counted in bytes in the request
8066 * - counted in UNICODE chars in the max reply
8067 * - counted in bytes in the real size
8069 * take a pause *before* coding not *during* coding
8073 if (r
->in
.value_offered
) {
8074 r
->out
.value_name
= talloc_strdup(r
, regval_name(val
));
8075 if (!r
->out
.value_name
) {
8076 result
= WERR_NOMEM
;
8079 *r
->out
.value_needed
= strlen_m_term(regval_name(val
)) * 2;
8081 r
->out
.value_name
= NULL
;
8082 *r
->out
.value_needed
= 0;
8087 *r
->out
.type
= regval_type(val
);
8089 /* data - counted in bytes */
8092 * See the section "Dynamically Typed Query Parameters"
8096 if (r
->out
.data
&& regval_data_p(val
) &&
8097 regval_size(val
) && r
->in
.data_offered
) {
8098 memcpy(r
->out
.data
, regval_data_p(val
),
8099 MIN(regval_size(val
),r
->in
.data_offered
));
8102 *r
->out
.data_needed
= regval_size(val
);
8106 free_a_printer(&printer
, 2);
8110 /****************************************************************
8111 _spoolss_SetPrinterData
8112 ****************************************************************/
8114 WERROR
_spoolss_SetPrinterData(pipes_struct
*p
,
8115 struct spoolss_SetPrinterData
*r
)
8117 struct spoolss_SetPrinterDataEx r2
;
8119 r2
.in
.handle
= r
->in
.handle
;
8120 r2
.in
.key_name
= "PrinterDriverData";
8121 r2
.in
.value_name
= r
->in
.value_name
;
8122 r2
.in
.type
= r
->in
.type
;
8123 r2
.in
.data
= r
->in
.data
;
8124 r2
.in
.offered
= r
->in
.offered
;
8126 return _spoolss_SetPrinterDataEx(p
, &r2
);
8129 /****************************************************************
8130 _spoolss_ResetPrinter
8131 ****************************************************************/
8133 WERROR
_spoolss_ResetPrinter(pipes_struct
*p
,
8134 struct spoolss_ResetPrinter
*r
)
8136 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8139 DEBUG(5,("_spoolss_ResetPrinter\n"));
8142 * All we do is to check to see if the handle and queue is valid.
8143 * This call really doesn't mean anything to us because we only
8144 * support RAW printing. --jerry
8148 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8149 OUR_HANDLE(r
->in
.handle
)));
8153 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8157 /* blindly return success */
8161 /****************************************************************
8162 _spoolss_DeletePrinterData
8163 ****************************************************************/
8165 WERROR
_spoolss_DeletePrinterData(pipes_struct
*p
,
8166 struct spoolss_DeletePrinterData
*r
)
8168 struct spoolss_DeletePrinterDataEx r2
;
8170 r2
.in
.handle
= r
->in
.handle
;
8171 r2
.in
.key_name
= "PrinterDriverData";
8172 r2
.in
.value_name
= r
->in
.value_name
;
8174 return _spoolss_DeletePrinterDataEx(p
, &r2
);
8177 /****************************************************************
8179 ****************************************************************/
8181 WERROR
_spoolss_AddForm(pipes_struct
*p
,
8182 struct spoolss_AddForm
*r
)
8184 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8185 nt_forms_struct tmpForm
;
8187 WERROR status
= WERR_OK
;
8188 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8189 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8192 nt_forms_struct
*list
=NULL
;
8193 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8195 DEBUG(5,("_spoolss_AddForm\n"));
8198 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8199 OUR_HANDLE(r
->in
.handle
)));
8204 /* forms can be added on printer of on the print server handle */
8206 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8208 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8211 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8212 if (!W_ERROR_IS_OK(status
))
8216 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8217 and not a printer admin, then fail */
8219 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8220 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8221 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8222 pdb_get_domain(p
->server_info
->sam_account
),
8224 p
->server_info
->ptok
,
8225 lp_printer_admin(snum
))) {
8226 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8227 return WERR_ACCESS_DENIED
;
8230 /* can't add if builtin */
8232 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8233 status
= WERR_FILE_EXISTS
;
8237 count
= get_ntforms(&list
);
8239 if(!add_a_form(&list
, form
, &count
)) {
8240 status
= WERR_NOMEM
;
8245 write_ntforms(&list
, count
);
8249 * ChangeID must always be set if this is a printer
8252 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8253 status
= mod_a_printer(printer
, 2);
8257 free_a_printer(&printer
, 2);
8263 /****************************************************************
8265 ****************************************************************/
8267 WERROR
_spoolss_DeleteForm(pipes_struct
*p
,
8268 struct spoolss_DeleteForm
*r
)
8270 const char *form_name
= r
->in
.form_name
;
8271 nt_forms_struct tmpForm
;
8273 nt_forms_struct
*list
=NULL
;
8274 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8276 WERROR status
= WERR_OK
;
8277 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8278 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8281 DEBUG(5,("_spoolss_DeleteForm\n"));
8284 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8285 OUR_HANDLE(r
->in
.handle
)));
8289 /* forms can be deleted on printer of on the print server handle */
8291 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8293 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8296 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8297 if (!W_ERROR_IS_OK(status
))
8301 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8302 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8303 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8304 pdb_get_domain(p
->server_info
->sam_account
),
8306 p
->server_info
->ptok
,
8307 lp_printer_admin(snum
))) {
8308 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8309 return WERR_ACCESS_DENIED
;
8313 /* can't delete if builtin */
8315 if (get_a_builtin_ntform_by_string(form_name
,&tmpForm
)) {
8316 status
= WERR_INVALID_PARAM
;
8320 count
= get_ntforms(&list
);
8323 ret
= delete_a_form(&list
, form_name
, &count
, &status
);
8330 * ChangeID must always be set if this is a printer
8333 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8334 status
= mod_a_printer(printer
, 2);
8338 free_a_printer(&printer
, 2);
8344 /****************************************************************
8346 ****************************************************************/
8348 WERROR
_spoolss_SetForm(pipes_struct
*p
,
8349 struct spoolss_SetForm
*r
)
8351 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8352 nt_forms_struct tmpForm
;
8354 WERROR status
= WERR_OK
;
8355 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8356 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8359 nt_forms_struct
*list
=NULL
;
8360 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8362 DEBUG(5,("_spoolss_SetForm\n"));
8365 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8366 OUR_HANDLE(r
->in
.handle
)));
8370 /* forms can be modified on printer of on the print server handle */
8372 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8374 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8377 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8378 if (!W_ERROR_IS_OK(status
))
8382 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8383 and not a printer admin, then fail */
8385 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8386 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8387 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8388 pdb_get_domain(p
->server_info
->sam_account
),
8390 p
->server_info
->ptok
,
8391 lp_printer_admin(snum
))) {
8392 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8393 return WERR_ACCESS_DENIED
;
8396 /* can't set if builtin */
8397 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8398 status
= WERR_INVALID_PARAM
;
8402 count
= get_ntforms(&list
);
8403 update_a_form(&list
, form
, count
);
8405 write_ntforms(&list
, count
);
8409 * ChangeID must always be set if this is a printer
8412 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8413 status
= mod_a_printer(printer
, 2);
8418 free_a_printer(&printer
, 2);
8424 /****************************************************************************
8425 fill_print_processor1
8426 ****************************************************************************/
8428 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8429 struct spoolss_PrintProcessorInfo1
*r
,
8430 const char *print_processor_name
)
8432 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8433 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8438 /****************************************************************************
8439 enumprintprocessors level 1.
8440 ****************************************************************************/
8442 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8443 union spoolss_PrintProcessorInfo
**info_p
,
8446 union spoolss_PrintProcessorInfo
*info
;
8449 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8450 W_ERROR_HAVE_NO_MEMORY(info
);
8454 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8455 if (!W_ERROR_IS_OK(result
)) {
8460 if (!W_ERROR_IS_OK(result
)) {
8471 /****************************************************************
8472 _spoolss_EnumPrintProcessors
8473 ****************************************************************/
8475 WERROR
_spoolss_EnumPrintProcessors(pipes_struct
*p
,
8476 struct spoolss_EnumPrintProcessors
*r
)
8480 /* that's an [in out] buffer */
8482 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8483 return WERR_INVALID_PARAM
;
8486 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8489 * Enumerate the print processors ...
8491 * Just reply with "winprint", to keep NT happy
8492 * and I can use my nice printer checker.
8497 *r
->out
.info
= NULL
;
8499 switch (r
->in
.level
) {
8501 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8505 return WERR_UNKNOWN_LEVEL
;
8508 if (!W_ERROR_IS_OK(result
)) {
8512 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8513 spoolss_EnumPrintProcessors
, NULL
,
8514 *r
->out
.info
, r
->in
.level
,
8516 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8517 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8519 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8522 /****************************************************************************
8523 fill_printprocdatatype1
8524 ****************************************************************************/
8526 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8527 struct spoolss_PrintProcDataTypesInfo1
*r
,
8528 const char *name_array
)
8530 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8531 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8536 /****************************************************************************
8537 enumprintprocdatatypes level 1.
8538 ****************************************************************************/
8540 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8541 union spoolss_PrintProcDataTypesInfo
**info_p
,
8545 union spoolss_PrintProcDataTypesInfo
*info
;
8547 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8548 W_ERROR_HAVE_NO_MEMORY(info
);
8552 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8553 if (!W_ERROR_IS_OK(result
)) {
8558 if (!W_ERROR_IS_OK(result
)) {
8569 /****************************************************************
8570 _spoolss_EnumPrintProcDataTypes
8571 ****************************************************************/
8573 WERROR
_spoolss_EnumPrintProcDataTypes(pipes_struct
*p
,
8574 struct spoolss_EnumPrintProcDataTypes
*r
)
8578 /* that's an [in out] buffer */
8580 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8581 return WERR_INVALID_PARAM
;
8584 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8588 *r
->out
.info
= NULL
;
8590 switch (r
->in
.level
) {
8592 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8596 return WERR_UNKNOWN_LEVEL
;
8599 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8600 spoolss_EnumPrintProcDataTypes
, NULL
,
8601 *r
->out
.info
, r
->in
.level
,
8603 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8604 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8606 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8609 /****************************************************************************
8611 ****************************************************************************/
8613 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8614 struct spoolss_MonitorInfo1
*r
,
8615 const char *monitor_name
)
8617 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8618 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8623 /****************************************************************************
8625 ****************************************************************************/
8627 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8628 struct spoolss_MonitorInfo2
*r
,
8629 const char *monitor_name
,
8630 const char *environment
,
8631 const char *dll_name
)
8633 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8634 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8635 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8636 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8637 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8638 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8643 /****************************************************************************
8644 enumprintmonitors level 1.
8645 ****************************************************************************/
8647 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8648 union spoolss_MonitorInfo
**info_p
,
8651 union spoolss_MonitorInfo
*info
;
8652 WERROR result
= WERR_OK
;
8654 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8655 W_ERROR_HAVE_NO_MEMORY(info
);
8659 result
= fill_monitor_1(info
, &info
[0].info1
,
8661 if (!W_ERROR_IS_OK(result
)) {
8665 result
= fill_monitor_1(info
, &info
[1].info1
,
8667 if (!W_ERROR_IS_OK(result
)) {
8672 if (!W_ERROR_IS_OK(result
)) {
8683 /****************************************************************************
8684 enumprintmonitors level 2.
8685 ****************************************************************************/
8687 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8688 union spoolss_MonitorInfo
**info_p
,
8691 union spoolss_MonitorInfo
*info
;
8692 WERROR result
= WERR_OK
;
8694 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8695 W_ERROR_HAVE_NO_MEMORY(info
);
8699 result
= fill_monitor_2(info
, &info
[0].info2
,
8701 "Windows NT X86", /* FIXME */
8703 if (!W_ERROR_IS_OK(result
)) {
8707 result
= fill_monitor_2(info
, &info
[1].info2
,
8709 "Windows NT X86", /* FIXME */
8711 if (!W_ERROR_IS_OK(result
)) {
8716 if (!W_ERROR_IS_OK(result
)) {
8727 /****************************************************************
8728 _spoolss_EnumMonitors
8729 ****************************************************************/
8731 WERROR
_spoolss_EnumMonitors(pipes_struct
*p
,
8732 struct spoolss_EnumMonitors
*r
)
8736 /* that's an [in out] buffer */
8738 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8739 return WERR_INVALID_PARAM
;
8742 DEBUG(5,("_spoolss_EnumMonitors\n"));
8745 * Enumerate the print monitors ...
8747 * Just reply with "Local Port", to keep NT happy
8748 * and I can use my nice printer checker.
8753 *r
->out
.info
= NULL
;
8755 switch (r
->in
.level
) {
8757 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8761 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8765 return WERR_UNKNOWN_LEVEL
;
8768 if (!W_ERROR_IS_OK(result
)) {
8772 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8773 spoolss_EnumMonitors
, NULL
,
8774 *r
->out
.info
, r
->in
.level
,
8776 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8777 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8779 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8782 /****************************************************************************
8783 ****************************************************************************/
8785 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8786 const print_queue_struct
*queue
,
8787 int count
, int snum
,
8788 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8790 struct spoolss_JobInfo1
*r
)
8795 for (i
=0; i
<count
&& found
== false; i
++) {
8796 if (queue
[i
].job
== (int)jobid
) {
8801 if (found
== false) {
8802 /* NT treats not found as bad param... yet another bad choice */
8803 return WERR_INVALID_PARAM
;
8806 return fill_job_info1(mem_ctx
,
8814 /****************************************************************************
8815 ****************************************************************************/
8817 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8818 const print_queue_struct
*queue
,
8819 int count
, int snum
,
8820 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8822 struct spoolss_JobInfo2
*r
)
8826 struct spoolss_DeviceMode
*devmode
;
8827 NT_DEVICEMODE
*nt_devmode
;
8830 for (i
=0; i
<count
&& found
== false; i
++) {
8831 if (queue
[i
].job
== (int)jobid
) {
8836 if (found
== false) {
8837 /* NT treats not found as bad param... yet another bad
8839 return WERR_INVALID_PARAM
;
8843 * if the print job does not have a DEVMODE associated with it,
8844 * just use the one for the printer. A NULL devicemode is not
8845 * a failure condition
8848 nt_devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8850 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
8851 W_ERROR_HAVE_NO_MEMORY(devmode
);
8852 result
= convert_nt_devicemode(devmode
, devmode
, nt_devmode
);
8853 if (!W_ERROR_IS_OK(result
)) {
8857 devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
8858 W_ERROR_HAVE_NO_MEMORY(devmode
);
8861 return fill_job_info2(mem_ctx
,
8870 /****************************************************************
8872 ****************************************************************/
8874 WERROR
_spoolss_GetJob(pipes_struct
*p
,
8875 struct spoolss_GetJob
*r
)
8877 WERROR result
= WERR_OK
;
8878 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8881 print_queue_struct
*queue
= NULL
;
8882 print_status_struct prt_status
;
8884 /* that's an [in out] buffer */
8886 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8887 return WERR_INVALID_PARAM
;
8890 DEBUG(5,("_spoolss_GetJob\n"));
8894 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8898 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8899 if (!W_ERROR_IS_OK(result
)) {
8903 count
= print_queue_status(snum
, &queue
, &prt_status
);
8905 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8906 count
, prt_status
.status
, prt_status
.message
));
8908 switch (r
->in
.level
) {
8910 result
= getjob_level_1(p
->mem_ctx
,
8911 queue
, count
, snum
, ntprinter
,
8912 r
->in
.job_id
, &r
->out
.info
->info1
);
8915 result
= getjob_level_2(p
->mem_ctx
,
8916 queue
, count
, snum
, ntprinter
,
8917 r
->in
.job_id
, &r
->out
.info
->info2
);
8920 result
= WERR_UNKNOWN_LEVEL
;
8925 free_a_printer(&ntprinter
, 2);
8927 if (!W_ERROR_IS_OK(result
)) {
8928 TALLOC_FREE(r
->out
.info
);
8932 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, NULL
,
8933 r
->out
.info
, r
->in
.level
);
8934 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8936 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8939 /****************************************************************
8940 _spoolss_GetPrinterDataEx
8941 ****************************************************************/
8943 WERROR
_spoolss_GetPrinterDataEx(pipes_struct
*p
,
8944 struct spoolss_GetPrinterDataEx
*r
)
8947 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8948 REGISTRY_VALUE
*val
= NULL
;
8949 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8951 WERROR result
= WERR_OK
;
8954 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8956 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8957 r
->in
.key_name
, r
->in
.value_name
));
8959 /* in case of problem, return some default values */
8962 *r
->out
.type
= REG_NONE
;
8965 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8966 OUR_HANDLE(r
->in
.handle
)));
8967 result
= WERR_BADFID
;
8971 /* Is the handle to a printer or to the server? */
8973 if (Printer
->printer_type
== SPLHND_SERVER
) {
8975 union spoolss_PrinterData data
;
8977 result
= getprinterdata_printer_server(p
->mem_ctx
,
8981 if (!W_ERROR_IS_OK(result
)) {
8985 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
8986 *r
->out
.type
, &data
);
8987 if (!W_ERROR_IS_OK(result
)) {
8991 *r
->out
.needed
= blob
.length
;
8993 if (r
->in
.offered
>= *r
->out
.needed
) {
8994 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
8997 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9000 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9001 result
= WERR_BADFID
;
9005 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9006 if (!W_ERROR_IS_OK(result
)) {
9010 /* check to see if the keyname is valid */
9011 if (!strlen(r
->in
.key_name
)) {
9012 result
= WERR_INVALID_PARAM
;
9016 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
9018 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
9019 strequal(r
->in
.value_name
, "ChangeId")) {
9020 *r
->out
.type
= REG_DWORD
;
9022 if (r
->in
.offered
>= *r
->out
.needed
) {
9023 SIVAL(r
->out
.data
, 0, printer
->info_2
->changeid
);
9029 if (lookup_printerkey(printer
->info_2
->data
, r
->in
.key_name
) == -1) {
9030 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9031 "Invalid keyname [%s]\n", r
->in
.key_name
));
9032 result
= WERR_BADFILE
;
9036 val
= get_printer_data(printer
->info_2
,
9037 r
->in
.key_name
, r
->in
.value_name
);
9039 result
= WERR_BADFILE
;
9043 *r
->out
.needed
= regval_size(val
);
9044 *r
->out
.type
= regval_type(val
);
9046 if (r
->in
.offered
>= *r
->out
.needed
) {
9047 memcpy(r
->out
.data
, regval_data_p(val
), regval_size(val
));
9051 free_a_printer(&printer
, 2);
9054 if (!W_ERROR_IS_OK(result
)) {
9058 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
9059 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
9061 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9064 /****************************************************************
9065 _spoolss_SetPrinterDataEx
9066 ****************************************************************/
9068 WERROR
_spoolss_SetPrinterDataEx(pipes_struct
*p
,
9069 struct spoolss_SetPrinterDataEx
*r
)
9071 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9073 WERROR result
= WERR_OK
;
9074 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9077 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9079 /* From MSDN documentation of SetPrinterDataEx: pass request to
9080 SetPrinterData if key is "PrinterDriverData" */
9083 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9084 OUR_HANDLE(r
->in
.handle
)));
9088 if (Printer
->printer_type
== SPLHND_SERVER
) {
9089 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9090 "Not implemented for server handles yet\n"));
9091 return WERR_INVALID_PARAM
;
9094 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9099 * Access check : NT returns "access denied" if you make a
9100 * SetPrinterData call without the necessary privildge.
9101 * we were originally returning OK if nothing changed
9102 * which made Win2k issue **a lot** of SetPrinterData
9103 * when connecting to a printer --jerry
9106 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9107 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9108 "change denied by handle access permissions\n"));
9109 return WERR_ACCESS_DENIED
;
9112 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9113 if (!W_ERROR_IS_OK(result
)) {
9117 /* check for OID in valuename */
9119 oid_string
= strchr(r
->in
.value_name
, ',');
9126 * When client side code sets a magic printer data key, detect it and save
9127 * the current printer data and the magic key's data (its the DEVMODE) for
9128 * future printer/driver initializations.
9130 if ((r
->in
.type
== REG_BINARY
) && strequal(r
->in
.value_name
, PHANTOM_DEVMODE_KEY
)) {
9131 /* Set devmode and printer initialization info */
9132 result
= save_driver_init(printer
, 2, r
->in
.data
, r
->in
.offered
);
9134 srv_spoolss_reset_printerdata(printer
->info_2
->drivername
);
9139 /* save the registry data */
9141 result
= set_printer_dataex(printer
, r
->in
.key_name
, r
->in
.value_name
,
9142 r
->in
.type
, r
->in
.data
, r
->in
.offered
);
9144 if (W_ERROR_IS_OK(result
)) {
9145 /* save the OID if one was specified */
9147 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
9148 r
->in
.key_name
, SPOOL_OID_KEY
);
9150 result
= WERR_NOMEM
;
9155 * I'm not checking the status here on purpose. Don't know
9156 * if this is right, but I'm returning the status from the
9157 * previous set_printer_dataex() call. I have no idea if
9158 * this is right. --jerry
9161 set_printer_dataex(printer
, str
, r
->in
.value_name
,
9162 REG_SZ
, (uint8_t *)oid_string
,
9163 strlen(oid_string
)+1);
9166 result
= mod_a_printer(printer
, 2);
9170 free_a_printer(&printer
, 2);
9175 /****************************************************************
9176 _spoolss_DeletePrinterDataEx
9177 ****************************************************************/
9179 WERROR
_spoolss_DeletePrinterDataEx(pipes_struct
*p
,
9180 struct spoolss_DeletePrinterDataEx
*r
)
9182 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9184 WERROR status
= WERR_OK
;
9185 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9187 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9190 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9191 "Invalid handle (%s:%u:%u).\n",
9192 OUR_HANDLE(r
->in
.handle
)));
9196 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
9199 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9200 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9201 "printer properties change denied by handle\n"));
9202 return WERR_ACCESS_DENIED
;
9205 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9209 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9210 if (!W_ERROR_IS_OK(status
))
9213 status
= delete_printer_dataex( printer
, r
->in
.key_name
, r
->in
.value_name
);
9215 if ( W_ERROR_IS_OK(status
) )
9216 mod_a_printer( printer
, 2 );
9218 free_a_printer(&printer
, 2);
9223 /****************************************************************
9224 _spoolss_EnumPrinterKey
9225 ****************************************************************/
9227 WERROR
_spoolss_EnumPrinterKey(pipes_struct
*p
,
9228 struct spoolss_EnumPrinterKey
*r
)
9230 fstring
*keynames
= NULL
;
9232 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9233 NT_PRINTER_DATA
*data
;
9234 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9236 WERROR result
= WERR_BADFILE
;
9238 const char **array
= NULL
;
9241 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9244 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9245 OUR_HANDLE(r
->in
.handle
)));
9249 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9253 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9254 if (!W_ERROR_IS_OK(result
)) {
9258 /* get the list of subkey names */
9260 data
= printer
->info_2
->data
;
9262 num_keys
= get_printer_subkeys(data
, r
->in
.key_name
, &keynames
);
9263 if (num_keys
== -1) {
9264 result
= WERR_BADFILE
;
9268 array
= talloc_zero_array(r
->out
.key_buffer
, const char *, num_keys
+ 2);
9270 result
= WERR_NOMEM
;
9275 array
[0] = talloc_strdup(array
, "");
9277 result
= WERR_NOMEM
;
9282 for (i
=0; i
< num_keys
; i
++) {
9284 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9287 array
[i
] = talloc_strdup(array
, keynames
[i
]);
9289 result
= WERR_NOMEM
;
9294 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9295 result
= WERR_NOMEM
;
9299 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
9300 *r
->out
.needed
= blob
.length
;
9302 if (r
->in
.offered
< *r
->out
.needed
) {
9303 result
= WERR_MORE_DATA
;
9306 r
->out
.key_buffer
->string_array
= array
;
9310 if (!W_ERROR_IS_OK(result
)) {
9312 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9317 free_a_printer(&printer
, 2);
9318 SAFE_FREE(keynames
);
9323 /****************************************************************
9324 _spoolss_DeletePrinterKey
9325 ****************************************************************/
9327 WERROR
_spoolss_DeletePrinterKey(pipes_struct
*p
,
9328 struct spoolss_DeletePrinterKey
*r
)
9330 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9331 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9335 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9338 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9339 OUR_HANDLE(r
->in
.handle
)));
9343 /* if keyname == NULL, return error */
9345 if ( !r
->in
.key_name
)
9346 return WERR_INVALID_PARAM
;
9348 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
9351 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9352 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9353 "printer properties change denied by handle\n"));
9354 return WERR_ACCESS_DENIED
;
9357 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9358 if (!W_ERROR_IS_OK(status
))
9361 /* delete the key and all subneys */
9363 status
= delete_all_printer_data( printer
->info_2
, r
->in
.key_name
);
9365 if ( W_ERROR_IS_OK(status
) )
9366 status
= mod_a_printer(printer
, 2);
9368 free_a_printer( &printer
, 2 );
9373 /****************************************************************
9374 ****************************************************************/
9376 static WERROR
registry_value_to_printer_enum_value(TALLOC_CTX
*mem_ctx
,
9378 struct spoolss_PrinterEnumValues
*r
)
9380 r
->data
= TALLOC_ZERO_P(mem_ctx
, DATA_BLOB
);
9381 W_ERROR_HAVE_NO_MEMORY(r
->data
);
9383 r
->value_name
= talloc_strdup(mem_ctx
, regval_name(v
));
9384 W_ERROR_HAVE_NO_MEMORY(r
->value_name
);
9386 r
->type
= regval_type(v
);
9387 r
->data_length
= regval_size(v
);
9389 if (r
->data_length
) {
9390 *r
->data
= data_blob_talloc(r
->data
, regval_data_p(v
), regval_size(v
));
9396 /****************************************************************
9397 _spoolss_EnumPrinterDataEx
9398 ****************************************************************/
9400 WERROR
_spoolss_EnumPrinterDataEx(pipes_struct
*p
,
9401 struct spoolss_EnumPrinterDataEx
*r
)
9404 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9405 struct spoolss_PrinterEnumValues
*info
= NULL
;
9406 NT_PRINTER_DATA
*p_data
;
9407 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9413 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9417 *r
->out
.info
= NULL
;
9420 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9421 OUR_HANDLE(r
->in
.handle
)));
9426 * first check for a keyname of NULL or "". Win2k seems to send
9427 * this a lot and we should send back WERR_INVALID_PARAM
9428 * no need to spend time looking up the printer in this case.
9432 if (!strlen(r
->in
.key_name
)) {
9433 result
= WERR_INVALID_PARAM
;
9437 /* get the printer off of disk */
9439 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9443 ZERO_STRUCT(printer
);
9444 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9445 if (!W_ERROR_IS_OK(result
)) {
9449 /* now look for a match on the key name */
9451 p_data
= printer
->info_2
->data
;
9453 key_index
= lookup_printerkey(p_data
, r
->in
.key_name
);
9454 if (key_index
== -1) {
9455 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9457 result
= WERR_INVALID_PARAM
;
9461 /* allocate the memory for the array of pointers -- if necessary */
9463 count
= regval_ctr_numvals(p_data
->keys
[key_index
].values
);
9465 result
= WERR_OK
; /* ??? */
9469 info
= TALLOC_ZERO_ARRAY(p
->mem_ctx
,
9470 struct spoolss_PrinterEnumValues
,
9473 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9474 result
= WERR_NOMEM
;
9479 * loop through all params and build the array to pass
9480 * back to the client
9483 for (i
=0; i
< count
; i
++) {
9485 REGISTRY_VALUE
*val
;
9487 /* lookup the registry value */
9489 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
, i
);
9491 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
)));
9495 result
= registry_value_to_printer_enum_value(info
, val
, &info
[i
]);
9496 if (!W_ERROR_IS_OK(result
)) {
9501 #if 0 /* FIXME - gd */
9502 /* housekeeping information in the reply */
9504 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9505 * the hand marshalled container size is a multiple
9506 * of 4 bytes for RPC alignment.
9510 needed
+= 4-(needed
% 4);
9513 *r
->out
.count
= count
;
9514 *r
->out
.info
= info
;
9519 free_a_printer(&printer
, 2);
9522 if (!W_ERROR_IS_OK(result
)) {
9526 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9527 spoolss_EnumPrinterDataEx
, NULL
,
9530 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9531 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9533 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9536 /****************************************************************************
9537 ****************************************************************************/
9539 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9540 const char *servername
,
9541 const char *environment
,
9542 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9547 werr
= compose_spoolss_server_path(mem_ctx
,
9550 SPOOLSS_PRTPROCS_PATH
,
9552 if (!W_ERROR_IS_OK(werr
)) {
9556 DEBUG(4,("print processor directory: [%s]\n", path
));
9558 r
->directory_name
= path
;
9563 /****************************************************************
9564 _spoolss_GetPrintProcessorDirectory
9565 ****************************************************************/
9567 WERROR
_spoolss_GetPrintProcessorDirectory(pipes_struct
*p
,
9568 struct spoolss_GetPrintProcessorDirectory
*r
)
9572 /* that's an [in out] buffer */
9574 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9575 return WERR_INVALID_PARAM
;
9578 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9583 /* r->in.level is ignored */
9585 /* We always should reply with a local print processor directory so that
9586 * users are not forced to have a [prnproc$] share on the Samba spoolss
9587 * server - Guenther */
9589 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9590 NULL
, /* r->in.server */
9592 &r
->out
.info
->info1
);
9593 if (!W_ERROR_IS_OK(result
)) {
9594 TALLOC_FREE(r
->out
.info
);
9598 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
, NULL
,
9599 r
->out
.info
, r
->in
.level
);
9600 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9602 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9605 /*******************************************************************
9606 ********************************************************************/
9608 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9609 const char *dllname
)
9611 enum ndr_err_code ndr_err
;
9612 struct spoolss_MonitorUi ui
;
9614 ui
.dll_name
= dllname
;
9616 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, NULL
, &ui
,
9617 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9618 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9619 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9621 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9624 /*******************************************************************
9625 Streams the monitor UI DLL name in UNICODE
9626 *******************************************************************/
9628 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9629 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9630 DATA_BLOB
*out
, uint32_t *needed
)
9632 const char *dllname
= "tcpmonui.dll";
9634 *needed
= (strlen(dllname
)+1) * 2;
9636 if (out
->length
< *needed
) {
9637 return WERR_INSUFFICIENT_BUFFER
;
9640 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9647 /*******************************************************************
9648 ********************************************************************/
9650 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9651 struct spoolss_PortData1
*port1
,
9652 const DATA_BLOB
*buf
)
9654 enum ndr_err_code ndr_err
;
9655 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, NULL
, port1
,
9656 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9657 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9658 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9660 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9663 /*******************************************************************
9664 ********************************************************************/
9666 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9667 struct spoolss_PortData2
*port2
,
9668 const DATA_BLOB
*buf
)
9670 enum ndr_err_code ndr_err
;
9671 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, NULL
, port2
,
9672 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9673 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9674 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9676 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9679 /*******************************************************************
9680 Create a new TCP/IP port
9681 *******************************************************************/
9683 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9684 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9685 DATA_BLOB
*out
, uint32_t *needed
)
9687 struct spoolss_PortData1 port1
;
9688 struct spoolss_PortData2 port2
;
9689 char *device_uri
= NULL
;
9692 const char *portname
;
9693 const char *hostaddress
;
9695 uint32_t port_number
;
9698 /* peek for spoolss_PortData version */
9700 if (!in
|| (in
->length
< (128 + 4))) {
9701 return WERR_GENERAL_FAILURE
;
9704 version
= IVAL(in
->data
, 128);
9710 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9714 portname
= port1
.portname
;
9715 hostaddress
= port1
.hostaddress
;
9716 queue
= port1
.queue
;
9717 protocol
= port1
.protocol
;
9718 port_number
= port1
.port_number
;
9724 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9728 portname
= port2
.portname
;
9729 hostaddress
= port2
.hostaddress
;
9730 queue
= port2
.queue
;
9731 protocol
= port2
.protocol
;
9732 port_number
= port2
.port_number
;
9736 DEBUG(1,("xcvtcp_addport: "
9737 "unknown version of port_data: %d\n", version
));
9738 return WERR_UNKNOWN_PORT
;
9741 /* create the device URI and call the add_port_hook() */
9744 case PROTOCOL_RAWTCP_TYPE
:
9745 device_uri
= talloc_asprintf(mem_ctx
,
9746 "socket://%s:%d/", hostaddress
,
9750 case PROTOCOL_LPR_TYPE
:
9751 device_uri
= talloc_asprintf(mem_ctx
,
9752 "lpr://%s/%s", hostaddress
, queue
);
9756 return WERR_UNKNOWN_PORT
;
9763 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9766 /*******************************************************************
9767 *******************************************************************/
9769 struct xcv_api_table xcvtcp_cmds
[] = {
9770 { "MonitorUI", xcvtcp_monitorui
},
9771 { "AddPort", xcvtcp_addport
},
9775 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9776 NT_USER_TOKEN
*token
, const char *command
,
9783 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9785 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9786 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9787 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9790 return WERR_BADFUNC
;
9793 /*******************************************************************
9794 *******************************************************************/
9795 #if 0 /* don't support management using the "Local Port" monitor */
9797 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9798 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9799 DATA_BLOB
*out
, uint32_t *needed
)
9801 const char *dllname
= "localui.dll";
9803 *needed
= (strlen(dllname
)+1) * 2;
9805 if (out
->length
< *needed
) {
9806 return WERR_INSUFFICIENT_BUFFER
;
9809 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9816 /*******************************************************************
9817 *******************************************************************/
9819 struct xcv_api_table xcvlocal_cmds
[] = {
9820 { "MonitorUI", xcvlocal_monitorui
},
9824 struct xcv_api_table xcvlocal_cmds
[] = {
9831 /*******************************************************************
9832 *******************************************************************/
9834 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9835 NT_USER_TOKEN
*token
, const char *command
,
9836 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9841 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9843 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9844 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9845 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9847 return WERR_BADFUNC
;
9850 /****************************************************************
9852 ****************************************************************/
9854 WERROR
_spoolss_XcvData(pipes_struct
*p
,
9855 struct spoolss_XcvData
*r
)
9857 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9858 DATA_BLOB out_data
= data_blob_null
;
9862 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9863 OUR_HANDLE(r
->in
.handle
)));
9867 /* Has to be a handle to the TCP/IP port monitor */
9869 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9870 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9874 /* requires administrative access to the server */
9876 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9877 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9878 return WERR_ACCESS_DENIED
;
9881 /* Allocate the outgoing buffer */
9883 if (r
->in
.out_data_size
) {
9884 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9885 if (out_data
.data
== NULL
) {
9890 switch ( Printer
->printer_type
) {
9891 case SPLHND_PORTMON_TCP
:
9892 werror
= process_xcvtcp_command(p
->mem_ctx
,
9893 p
->server_info
->ptok
,
9894 r
->in
.function_name
,
9895 &r
->in
.in_data
, &out_data
,
9898 case SPLHND_PORTMON_LOCAL
:
9899 werror
= process_xcvlocal_command(p
->mem_ctx
,
9900 p
->server_info
->ptok
,
9901 r
->in
.function_name
,
9902 &r
->in
.in_data
, &out_data
,
9906 werror
= WERR_INVALID_PRINT_MONITOR
;
9909 if (!W_ERROR_IS_OK(werror
)) {
9913 *r
->out
.status_code
= 0;
9915 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
9916 memcpy(r
->out
.out_data
, out_data
.data
,
9917 MIN(r
->in
.out_data_size
, out_data
.length
));
9923 /****************************************************************
9924 _spoolss_AddPrintProcessor
9925 ****************************************************************/
9927 WERROR
_spoolss_AddPrintProcessor(pipes_struct
*p
,
9928 struct spoolss_AddPrintProcessor
*r
)
9930 /* for now, just indicate success and ignore the add. We'll
9931 automatically set the winprint processor for printer
9932 entries later. Used to debug the LexMark Optra S 1855 PCL
9938 /****************************************************************
9940 ****************************************************************/
9942 WERROR
_spoolss_AddPort(pipes_struct
*p
,
9943 struct spoolss_AddPort
*r
)
9945 /* do what w2k3 does */
9947 return WERR_NOT_SUPPORTED
;
9950 /****************************************************************
9952 ****************************************************************/
9954 WERROR
_spoolss_AddPrinter(pipes_struct
*p
,
9955 struct spoolss_AddPrinter
*r
)
9957 p
->rng_fault_state
= true;
9958 return WERR_NOT_SUPPORTED
;
9961 /****************************************************************
9962 _spoolss_GetPrinterDriver
9963 ****************************************************************/
9965 WERROR
_spoolss_GetPrinterDriver(pipes_struct
*p
,
9966 struct spoolss_GetPrinterDriver
*r
)
9968 p
->rng_fault_state
= true;
9969 return WERR_NOT_SUPPORTED
;
9972 /****************************************************************
9973 _spoolss_ReadPrinter
9974 ****************************************************************/
9976 WERROR
_spoolss_ReadPrinter(pipes_struct
*p
,
9977 struct spoolss_ReadPrinter
*r
)
9979 p
->rng_fault_state
= true;
9980 return WERR_NOT_SUPPORTED
;
9983 /****************************************************************
9984 _spoolss_WaitForPrinterChange
9985 ****************************************************************/
9987 WERROR
_spoolss_WaitForPrinterChange(pipes_struct
*p
,
9988 struct spoolss_WaitForPrinterChange
*r
)
9990 p
->rng_fault_state
= true;
9991 return WERR_NOT_SUPPORTED
;
9994 /****************************************************************
9995 _spoolss_ConfigurePort
9996 ****************************************************************/
9998 WERROR
_spoolss_ConfigurePort(pipes_struct
*p
,
9999 struct spoolss_ConfigurePort
*r
)
10001 p
->rng_fault_state
= true;
10002 return WERR_NOT_SUPPORTED
;
10005 /****************************************************************
10006 _spoolss_DeletePort
10007 ****************************************************************/
10009 WERROR
_spoolss_DeletePort(pipes_struct
*p
,
10010 struct spoolss_DeletePort
*r
)
10012 p
->rng_fault_state
= true;
10013 return WERR_NOT_SUPPORTED
;
10016 /****************************************************************
10017 _spoolss_CreatePrinterIC
10018 ****************************************************************/
10020 WERROR
_spoolss_CreatePrinterIC(pipes_struct
*p
,
10021 struct spoolss_CreatePrinterIC
*r
)
10023 p
->rng_fault_state
= true;
10024 return WERR_NOT_SUPPORTED
;
10027 /****************************************************************
10028 _spoolss_PlayGDIScriptOnPrinterIC
10029 ****************************************************************/
10031 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(pipes_struct
*p
,
10032 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
10034 p
->rng_fault_state
= true;
10035 return WERR_NOT_SUPPORTED
;
10038 /****************************************************************
10039 _spoolss_DeletePrinterIC
10040 ****************************************************************/
10042 WERROR
_spoolss_DeletePrinterIC(pipes_struct
*p
,
10043 struct spoolss_DeletePrinterIC
*r
)
10045 p
->rng_fault_state
= true;
10046 return WERR_NOT_SUPPORTED
;
10049 /****************************************************************
10050 _spoolss_AddPrinterConnection
10051 ****************************************************************/
10053 WERROR
_spoolss_AddPrinterConnection(pipes_struct
*p
,
10054 struct spoolss_AddPrinterConnection
*r
)
10056 p
->rng_fault_state
= true;
10057 return WERR_NOT_SUPPORTED
;
10060 /****************************************************************
10061 _spoolss_DeletePrinterConnection
10062 ****************************************************************/
10064 WERROR
_spoolss_DeletePrinterConnection(pipes_struct
*p
,
10065 struct spoolss_DeletePrinterConnection
*r
)
10067 p
->rng_fault_state
= true;
10068 return WERR_NOT_SUPPORTED
;
10071 /****************************************************************
10072 _spoolss_PrinterMessageBox
10073 ****************************************************************/
10075 WERROR
_spoolss_PrinterMessageBox(pipes_struct
*p
,
10076 struct spoolss_PrinterMessageBox
*r
)
10078 p
->rng_fault_state
= true;
10079 return WERR_NOT_SUPPORTED
;
10082 /****************************************************************
10083 _spoolss_AddMonitor
10084 ****************************************************************/
10086 WERROR
_spoolss_AddMonitor(pipes_struct
*p
,
10087 struct spoolss_AddMonitor
*r
)
10089 p
->rng_fault_state
= true;
10090 return WERR_NOT_SUPPORTED
;
10093 /****************************************************************
10094 _spoolss_DeleteMonitor
10095 ****************************************************************/
10097 WERROR
_spoolss_DeleteMonitor(pipes_struct
*p
,
10098 struct spoolss_DeleteMonitor
*r
)
10100 p
->rng_fault_state
= true;
10101 return WERR_NOT_SUPPORTED
;
10104 /****************************************************************
10105 _spoolss_DeletePrintProcessor
10106 ****************************************************************/
10108 WERROR
_spoolss_DeletePrintProcessor(pipes_struct
*p
,
10109 struct spoolss_DeletePrintProcessor
*r
)
10111 p
->rng_fault_state
= true;
10112 return WERR_NOT_SUPPORTED
;
10115 /****************************************************************
10116 _spoolss_AddPrintProvidor
10117 ****************************************************************/
10119 WERROR
_spoolss_AddPrintProvidor(pipes_struct
*p
,
10120 struct spoolss_AddPrintProvidor
*r
)
10122 p
->rng_fault_state
= true;
10123 return WERR_NOT_SUPPORTED
;
10126 /****************************************************************
10127 _spoolss_DeletePrintProvidor
10128 ****************************************************************/
10130 WERROR
_spoolss_DeletePrintProvidor(pipes_struct
*p
,
10131 struct spoolss_DeletePrintProvidor
*r
)
10133 p
->rng_fault_state
= true;
10134 return WERR_NOT_SUPPORTED
;
10137 /****************************************************************
10138 _spoolss_FindFirstPrinterChangeNotification
10139 ****************************************************************/
10141 WERROR
_spoolss_FindFirstPrinterChangeNotification(pipes_struct
*p
,
10142 struct spoolss_FindFirstPrinterChangeNotification
*r
)
10144 p
->rng_fault_state
= true;
10145 return WERR_NOT_SUPPORTED
;
10148 /****************************************************************
10149 _spoolss_FindNextPrinterChangeNotification
10150 ****************************************************************/
10152 WERROR
_spoolss_FindNextPrinterChangeNotification(pipes_struct
*p
,
10153 struct spoolss_FindNextPrinterChangeNotification
*r
)
10155 p
->rng_fault_state
= true;
10156 return WERR_NOT_SUPPORTED
;
10159 /****************************************************************
10160 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10161 ****************************************************************/
10163 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct
*p
,
10164 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
10166 p
->rng_fault_state
= true;
10167 return WERR_NOT_SUPPORTED
;
10170 /****************************************************************
10171 _spoolss_ReplyOpenPrinter
10172 ****************************************************************/
10174 WERROR
_spoolss_ReplyOpenPrinter(pipes_struct
*p
,
10175 struct spoolss_ReplyOpenPrinter
*r
)
10177 p
->rng_fault_state
= true;
10178 return WERR_NOT_SUPPORTED
;
10181 /****************************************************************
10182 _spoolss_RouterReplyPrinter
10183 ****************************************************************/
10185 WERROR
_spoolss_RouterReplyPrinter(pipes_struct
*p
,
10186 struct spoolss_RouterReplyPrinter
*r
)
10188 p
->rng_fault_state
= true;
10189 return WERR_NOT_SUPPORTED
;
10192 /****************************************************************
10193 _spoolss_ReplyClosePrinter
10194 ****************************************************************/
10196 WERROR
_spoolss_ReplyClosePrinter(pipes_struct
*p
,
10197 struct spoolss_ReplyClosePrinter
*r
)
10199 p
->rng_fault_state
= true;
10200 return WERR_NOT_SUPPORTED
;
10203 /****************************************************************
10205 ****************************************************************/
10207 WERROR
_spoolss_AddPortEx(pipes_struct
*p
,
10208 struct spoolss_AddPortEx
*r
)
10210 p
->rng_fault_state
= true;
10211 return WERR_NOT_SUPPORTED
;
10214 /****************************************************************
10215 _spoolss_RouterFindFirstPrinterChangeNotification
10216 ****************************************************************/
10218 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct
*p
,
10219 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
10221 p
->rng_fault_state
= true;
10222 return WERR_NOT_SUPPORTED
;
10225 /****************************************************************
10226 _spoolss_SpoolerInit
10227 ****************************************************************/
10229 WERROR
_spoolss_SpoolerInit(pipes_struct
*p
,
10230 struct spoolss_SpoolerInit
*r
)
10232 p
->rng_fault_state
= true;
10233 return WERR_NOT_SUPPORTED
;
10236 /****************************************************************
10237 _spoolss_ResetPrinterEx
10238 ****************************************************************/
10240 WERROR
_spoolss_ResetPrinterEx(pipes_struct
*p
,
10241 struct spoolss_ResetPrinterEx
*r
)
10243 p
->rng_fault_state
= true;
10244 return WERR_NOT_SUPPORTED
;
10247 /****************************************************************
10248 _spoolss_RouterReplyPrinterEx
10249 ****************************************************************/
10251 WERROR
_spoolss_RouterReplyPrinterEx(pipes_struct
*p
,
10252 struct spoolss_RouterReplyPrinterEx
*r
)
10254 p
->rng_fault_state
= true;
10255 return WERR_NOT_SUPPORTED
;
10258 /****************************************************************
10260 ****************************************************************/
10262 WERROR
_spoolss_44(pipes_struct
*p
,
10263 struct spoolss_44
*r
)
10265 p
->rng_fault_state
= true;
10266 return WERR_NOT_SUPPORTED
;
10269 /****************************************************************
10271 ****************************************************************/
10273 WERROR
_spoolss_47(pipes_struct
*p
,
10274 struct spoolss_47
*r
)
10276 p
->rng_fault_state
= true;
10277 return WERR_NOT_SUPPORTED
;
10280 /****************************************************************
10282 ****************************************************************/
10284 WERROR
_spoolss_4a(pipes_struct
*p
,
10285 struct spoolss_4a
*r
)
10287 p
->rng_fault_state
= true;
10288 return WERR_NOT_SUPPORTED
;
10291 /****************************************************************
10293 ****************************************************************/
10295 WERROR
_spoolss_4b(pipes_struct
*p
,
10296 struct spoolss_4b
*r
)
10298 p
->rng_fault_state
= true;
10299 return WERR_NOT_SUPPORTED
;
10302 /****************************************************************
10304 ****************************************************************/
10306 WERROR
_spoolss_4c(pipes_struct
*p
,
10307 struct spoolss_4c
*r
)
10309 p
->rng_fault_state
= true;
10310 return WERR_NOT_SUPPORTED
;
10313 /****************************************************************
10315 ****************************************************************/
10317 WERROR
_spoolss_53(pipes_struct
*p
,
10318 struct spoolss_53
*r
)
10320 p
->rng_fault_state
= true;
10321 return WERR_NOT_SUPPORTED
;
10324 /****************************************************************
10326 ****************************************************************/
10328 WERROR
_spoolss_55(pipes_struct
*p
,
10329 struct spoolss_55
*r
)
10331 p
->rng_fault_state
= true;
10332 return WERR_NOT_SUPPORTED
;
10335 /****************************************************************
10337 ****************************************************************/
10339 WERROR
_spoolss_56(pipes_struct
*p
,
10340 struct spoolss_56
*r
)
10342 p
->rng_fault_state
= true;
10343 return WERR_NOT_SUPPORTED
;
10346 /****************************************************************
10348 ****************************************************************/
10350 WERROR
_spoolss_57(pipes_struct
*p
,
10351 struct spoolss_57
*r
)
10353 p
->rng_fault_state
= true;
10354 return WERR_NOT_SUPPORTED
;
10357 /****************************************************************
10359 ****************************************************************/
10361 WERROR
_spoolss_5a(pipes_struct
*p
,
10362 struct spoolss_5a
*r
)
10364 p
->rng_fault_state
= true;
10365 return WERR_NOT_SUPPORTED
;
10368 /****************************************************************
10370 ****************************************************************/
10372 WERROR
_spoolss_5b(pipes_struct
*p
,
10373 struct spoolss_5b
*r
)
10375 p
->rng_fault_state
= true;
10376 return WERR_NOT_SUPPORTED
;
10379 /****************************************************************
10381 ****************************************************************/
10383 WERROR
_spoolss_5c(pipes_struct
*p
,
10384 struct spoolss_5c
*r
)
10386 p
->rng_fault_state
= true;
10387 return WERR_NOT_SUPPORTED
;
10390 /****************************************************************
10392 ****************************************************************/
10394 WERROR
_spoolss_5d(pipes_struct
*p
,
10395 struct spoolss_5d
*r
)
10397 p
->rng_fault_state
= true;
10398 return WERR_NOT_SUPPORTED
;
10401 /****************************************************************
10403 ****************************************************************/
10405 WERROR
_spoolss_5e(pipes_struct
*p
,
10406 struct spoolss_5e
*r
)
10408 p
->rng_fault_state
= true;
10409 return WERR_NOT_SUPPORTED
;
10412 /****************************************************************
10414 ****************************************************************/
10416 WERROR
_spoolss_5f(pipes_struct
*p
,
10417 struct spoolss_5f
*r
)
10419 p
->rng_fault_state
= true;
10420 return WERR_NOT_SUPPORTED
;