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 rpcstr_push(nt_devmode
->devicename
, devmode
->devicename
, 31, 0);
1485 rpcstr_push(nt_devmode
->formname
, devmode
->formname
, 31, 0);
1487 nt_devmode
->specversion
= devmode
->specversion
;
1488 nt_devmode
->driverversion
= devmode
->driverversion
;
1489 nt_devmode
->size
= devmode
->size
;
1490 nt_devmode
->fields
= devmode
->fields
;
1491 nt_devmode
->orientation
= devmode
->orientation
;
1492 nt_devmode
->papersize
= devmode
->papersize
;
1493 nt_devmode
->paperlength
= devmode
->paperlength
;
1494 nt_devmode
->paperwidth
= devmode
->paperwidth
;
1495 nt_devmode
->scale
= devmode
->scale
;
1496 nt_devmode
->copies
= devmode
->copies
;
1497 nt_devmode
->defaultsource
= devmode
->defaultsource
;
1498 nt_devmode
->printquality
= devmode
->printquality
;
1499 nt_devmode
->color
= devmode
->color
;
1500 nt_devmode
->duplex
= devmode
->duplex
;
1501 nt_devmode
->yresolution
= devmode
->yresolution
;
1502 nt_devmode
->ttoption
= devmode
->ttoption
;
1503 nt_devmode
->collate
= devmode
->collate
;
1505 nt_devmode
->logpixels
= devmode
->logpixels
;
1506 nt_devmode
->bitsperpel
= devmode
->bitsperpel
;
1507 nt_devmode
->pelswidth
= devmode
->pelswidth
;
1508 nt_devmode
->pelsheight
= devmode
->pelsheight
;
1509 nt_devmode
->displayflags
= devmode
->displayflags
;
1510 nt_devmode
->displayfrequency
= devmode
->displayfrequency
;
1511 nt_devmode
->icmmethod
= devmode
->icmmethod
;
1512 nt_devmode
->icmintent
= devmode
->icmintent
;
1513 nt_devmode
->mediatype
= devmode
->mediatype
;
1514 nt_devmode
->dithertype
= devmode
->dithertype
;
1515 nt_devmode
->reserved1
= devmode
->reserved1
;
1516 nt_devmode
->reserved2
= devmode
->reserved2
;
1517 nt_devmode
->panningwidth
= devmode
->panningwidth
;
1518 nt_devmode
->panningheight
= devmode
->panningheight
;
1521 * Only change private and driverextra if the incoming devmode
1522 * has a new one. JRA.
1525 if ((devmode
->__driverextra_length
!= 0) && (devmode
->driverextra_data
.data
!= NULL
)) {
1526 SAFE_FREE(nt_devmode
->nt_dev_private
);
1527 nt_devmode
->driverextra
= devmode
->__driverextra_length
;
1528 if((nt_devmode
->nt_dev_private
= SMB_MALLOC_ARRAY(uint8_t, nt_devmode
->driverextra
)) == NULL
)
1530 memcpy(nt_devmode
->nt_dev_private
, devmode
->driverextra_data
.data
, nt_devmode
->driverextra
);
1533 *pp_nt_devmode
= nt_devmode
;
1538 /****************************************************************
1539 _spoolss_OpenPrinterEx
1540 ****************************************************************/
1542 WERROR
_spoolss_OpenPrinterEx(pipes_struct
*p
,
1543 struct spoolss_OpenPrinterEx
*r
)
1546 Printer_entry
*Printer
=NULL
;
1548 if (!r
->in
.printername
) {
1549 return WERR_INVALID_PARAM
;
1552 /* some sanity check because you can open a printer or a print server */
1553 /* aka: \\server\printer or \\server */
1555 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1557 if (!open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0)) {
1558 ZERO_STRUCTP(r
->out
.handle
);
1559 return WERR_INVALID_PARAM
;
1562 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1564 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1565 "handle we created for printer %s\n", r
->in
.printername
));
1566 close_printer_handle(p
, r
->out
.handle
);
1567 ZERO_STRUCTP(r
->out
.handle
);
1568 return WERR_INVALID_PARAM
;
1572 * First case: the user is opening the print server:
1574 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1575 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1577 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1578 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1579 * or if the user is listed in the smb.conf printer admin parameter.
1581 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1582 * client view printer folder, but does not show the MSAPW.
1584 * Note: this test needs code to check access rights here too. Jeremy
1585 * could you look at this?
1587 * Second case: the user is opening a printer:
1588 * NT doesn't let us connect to a printer if the connecting user
1589 * doesn't have print permission.
1591 * Third case: user is opening a Port Monitor
1592 * access checks same as opening a handle to the print server.
1595 switch (Printer
->printer_type
)
1598 case SPLHND_PORTMON_TCP
:
1599 case SPLHND_PORTMON_LOCAL
:
1600 /* Printserver handles use global struct... */
1604 /* Map standard access rights to object specific access rights */
1606 se_map_standard(&r
->in
.access_mask
,
1607 &printserver_std_mapping
);
1609 /* Deny any object specific bits that don't apply to print
1610 servers (i.e printer and job specific bits) */
1612 r
->in
.access_mask
&= SPECIFIC_RIGHTS_MASK
;
1614 if (r
->in
.access_mask
&
1615 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1616 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1617 close_printer_handle(p
, r
->out
.handle
);
1618 ZERO_STRUCTP(r
->out
.handle
);
1619 return WERR_ACCESS_DENIED
;
1622 /* Allow admin access */
1624 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1626 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1628 if (!lp_ms_add_printer_wizard()) {
1629 close_printer_handle(p
, r
->out
.handle
);
1630 ZERO_STRUCTP(r
->out
.handle
);
1631 return WERR_ACCESS_DENIED
;
1634 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1635 and not a printer admin, then fail */
1637 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
1638 !user_has_privileges(p
->server_info
->ptok
,
1640 !token_contains_name_in_list(
1641 uidtoname(p
->server_info
->utok
.uid
),
1643 p
->server_info
->ptok
,
1644 lp_printer_admin(snum
))) {
1645 close_printer_handle(p
, r
->out
.handle
);
1646 ZERO_STRUCTP(r
->out
.handle
);
1647 return WERR_ACCESS_DENIED
;
1650 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1654 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1657 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1658 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1660 /* We fall through to return WERR_OK */
1663 case SPLHND_PRINTER
:
1664 /* NT doesn't let us connect to a printer if the connecting user
1665 doesn't have print permission. */
1667 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1668 close_printer_handle(p
, r
->out
.handle
);
1669 ZERO_STRUCTP(r
->out
.handle
);
1673 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1675 /* map an empty access mask to the minimum access mask */
1676 if (r
->in
.access_mask
== 0x0)
1677 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1680 * If we are not serving the printer driver for this printer,
1681 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1682 * will keep NT clients happy --jerry
1685 if (lp_use_client_driver(snum
)
1686 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1688 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1691 /* check smb.conf parameters and the the sec_desc */
1693 if ( !check_access(get_client_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1694 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1695 ZERO_STRUCTP(r
->out
.handle
);
1696 return WERR_ACCESS_DENIED
;
1699 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1700 p
->server_info
->ptok
, snum
) ||
1701 !print_access_check(p
->server_info
, snum
,
1702 r
->in
.access_mask
)) {
1703 DEBUG(3, ("access DENIED for printer open\n"));
1704 close_printer_handle(p
, r
->out
.handle
);
1705 ZERO_STRUCTP(r
->out
.handle
);
1706 return WERR_ACCESS_DENIED
;
1709 if ((r
->in
.access_mask
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1710 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1711 close_printer_handle(p
, r
->out
.handle
);
1712 ZERO_STRUCTP(r
->out
.handle
);
1713 return WERR_ACCESS_DENIED
;
1716 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1717 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1719 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1721 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1722 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1727 /* sanity check to prevent programmer error */
1728 ZERO_STRUCTP(r
->out
.handle
);
1732 Printer
->access_granted
= r
->in
.access_mask
;
1735 * If the client sent a devmode in the OpenPrinter() call, then
1736 * save it here in case we get a job submission on this handle
1739 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1740 r
->in
.devmode_ctr
.devmode
) {
1741 convert_devicemode(Printer
->sharename
,
1742 r
->in
.devmode_ctr
.devmode
,
1743 &Printer
->nt_devmode
);
1746 #if 0 /* JERRY -- I'm doubtful this is really effective */
1747 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1748 optimization in Windows 2000 clients --jerry */
1750 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1751 && (RA_WIN2K
== get_remote_arch()) )
1753 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1754 sys_usleep( 500000 );
1761 /****************************************************************************
1762 ****************************************************************************/
1764 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2
*r
,
1765 NT_PRINTER_INFO_LEVEL_2
*d
)
1767 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1773 d
->attributes
= r
->attributes
;
1774 d
->priority
= r
->priority
;
1775 d
->default_priority
= r
->defaultpriority
;
1776 d
->starttime
= r
->starttime
;
1777 d
->untiltime
= r
->untiltime
;
1778 d
->status
= r
->status
;
1779 d
->cjobs
= r
->cjobs
;
1781 fstrcpy(d
->servername
, r
->servername
);
1782 fstrcpy(d
->printername
, r
->printername
);
1783 fstrcpy(d
->sharename
, r
->sharename
);
1784 fstrcpy(d
->portname
, r
->portname
);
1785 fstrcpy(d
->drivername
, r
->drivername
);
1786 slprintf(d
->comment
, sizeof(d
->comment
)-1, "%s", r
->comment
);
1787 fstrcpy(d
->location
, r
->location
);
1788 fstrcpy(d
->sepfile
, r
->sepfile
);
1789 fstrcpy(d
->printprocessor
, r
->printprocessor
);
1790 fstrcpy(d
->datatype
, r
->datatype
);
1791 fstrcpy(d
->parameters
, r
->parameters
);
1796 /****************************************************************************
1797 ****************************************************************************/
1799 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1800 NT_PRINTER_INFO_LEVEL
*printer
)
1804 switch (info_ctr
->level
) {
1806 /* allocate memory if needed. Messy because
1807 convert_printer_info is used to update an existing
1808 printer or build a new one */
1810 if (!printer
->info_2
) {
1811 printer
->info_2
= TALLOC_ZERO_P(printer
, NT_PRINTER_INFO_LEVEL_2
);
1812 if (!printer
->info_2
) {
1813 DEBUG(0,("convert_printer_info: "
1814 "talloc() failed!\n"));
1819 ret
= printer_info2_to_nt_printer_info2(info_ctr
->info
.info2
,
1821 printer
->info_2
->setuptime
= time(NULL
);
1828 /*******************************************************************
1829 ********************************************************************/
1831 static bool string_array_to_fstring_array(const char **sarray
, fstring
**farray
)
1840 *farray
= SMB_MALLOC_ARRAY(fstring
, 1);
1845 for (i
=0; sarray
[i
] != NULL
; i
++) {
1846 *farray
= SMB_REALLOC_ARRAY(*farray
, fstring
, i
+2);
1850 fstrcpy((*farray
)[i
], sarray
[i
]);
1853 fstrcpy((*farray
)[i
], "");
1858 /*******************************************************************
1859 ********************************************************************/
1861 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3
*r
,
1862 NT_PRINTER_DRIVER_INFO_LEVEL_3
**p
)
1864 NT_PRINTER_DRIVER_INFO_LEVEL_3
*d
;
1866 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1869 *p
= SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3
);
1878 d
->cversion
= r
->version
;
1880 fstrcpy(d
->name
, r
->driver_name
);
1881 fstrcpy(d
->environment
, r
->architecture
);
1882 fstrcpy(d
->driverpath
, r
->driver_path
);
1883 fstrcpy(d
->datafile
, r
->data_file
);
1884 fstrcpy(d
->configfile
, r
->config_file
);
1885 fstrcpy(d
->helpfile
, r
->help_file
);
1886 fstrcpy(d
->monitorname
, r
->monitor_name
);
1887 fstrcpy(d
->defaultdatatype
, r
->default_datatype
);
1889 DEBUGADD(8,( "version: %d\n", d
->cversion
));
1890 DEBUGADD(8,( "name: %s\n", d
->name
));
1891 DEBUGADD(8,( "environment: %s\n", d
->environment
));
1892 DEBUGADD(8,( "driverpath: %s\n", d
->driverpath
));
1893 DEBUGADD(8,( "datafile: %s\n", d
->datafile
));
1894 DEBUGADD(8,( "configfile: %s\n", d
->configfile
));
1895 DEBUGADD(8,( "helpfile: %s\n", d
->helpfile
));
1896 DEBUGADD(8,( "monitorname: %s\n", d
->monitorname
));
1897 DEBUGADD(8,( "defaultdatatype: %s\n", d
->defaultdatatype
));
1899 if (r
->dependent_files
) {
1900 if (!string_array_to_fstring_array(r
->dependent_files
->string
,
1901 &d
->dependentfiles
)) {
1910 /*******************************************************************
1911 ********************************************************************/
1913 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6
*r
,
1914 NT_PRINTER_DRIVER_INFO_LEVEL_6
**p
)
1916 NT_PRINTER_DRIVER_INFO_LEVEL_6
*d
;
1918 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1921 *p
= SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6
);
1930 d
->version
= r
->version
;
1932 fstrcpy(d
->name
, r
->driver_name
);
1933 fstrcpy(d
->environment
, r
->architecture
);
1934 fstrcpy(d
->driverpath
, r
->driver_path
);
1935 fstrcpy(d
->datafile
, r
->data_file
);
1936 fstrcpy(d
->configfile
, r
->config_file
);
1937 fstrcpy(d
->helpfile
, r
->help_file
);
1938 fstrcpy(d
->monitorname
, r
->monitor_name
);
1939 fstrcpy(d
->defaultdatatype
, r
->default_datatype
);
1941 DEBUGADD(8,( "version: %d\n", d
->version
));
1942 DEBUGADD(8,( "name: %s\n", d
->name
));
1943 DEBUGADD(8,( "environment: %s\n", d
->environment
));
1944 DEBUGADD(8,( "driverpath: %s\n", d
->driverpath
));
1945 DEBUGADD(8,( "datafile: %s\n", d
->datafile
));
1946 DEBUGADD(8,( "configfile: %s\n", d
->configfile
));
1947 DEBUGADD(8,( "helpfile: %s\n", d
->helpfile
));
1948 DEBUGADD(8,( "monitorname: %s\n", d
->monitorname
));
1949 DEBUGADD(8,( "defaultdatatype: %s\n", d
->defaultdatatype
));
1951 if (r
->dependent_files
) {
1952 if (!string_array_to_fstring_array(r
->dependent_files
->string
,
1953 &d
->dependentfiles
)) {
1958 if (r
->previous_names
) {
1959 if (!string_array_to_fstring_array(r
->previous_names
->string
,
1960 &d
->previousnames
)) {
1972 /********************************************************************
1973 ********************************************************************/
1975 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr
*r
,
1976 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
,
1981 printer
->info_3
= NULL
;
1982 if (!driver_info3_to_nt_driver_info3(r
->info
.info3
, &printer
->info_3
)) {
1987 printer
->info_6
= NULL
;
1988 if (!driver_info6_to_nt_driver_info6(r
->info
.info6
, &printer
->info_6
)) {
1999 /********************************************************************
2000 * _spoolss_enddocprinter_internal.
2001 ********************************************************************/
2003 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
,
2004 struct policy_handle
*handle
)
2006 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2010 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
2014 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
2017 Printer
->document_started
= false;
2018 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
2019 /* error codes unhandled so far ... */
2024 /****************************************************************
2025 _spoolss_ClosePrinter
2026 ****************************************************************/
2028 WERROR
_spoolss_ClosePrinter(pipes_struct
*p
,
2029 struct spoolss_ClosePrinter
*r
)
2031 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2033 if (Printer
&& Printer
->document_started
)
2034 _spoolss_enddocprinter_internal(p
, r
->in
.handle
); /* print job was not closed */
2036 if (!close_printer_handle(p
, r
->in
.handle
))
2039 /* clear the returned printer handle. Observed behavior
2040 from Win2k server. Don't think this really matters.
2041 Previous code just copied the value of the closed
2044 ZERO_STRUCTP(r
->out
.handle
);
2049 /****************************************************************
2050 _spoolss_DeletePrinter
2051 ****************************************************************/
2053 WERROR
_spoolss_DeletePrinter(pipes_struct
*p
,
2054 struct spoolss_DeletePrinter
*r
)
2056 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2059 if (Printer
&& Printer
->document_started
)
2060 _spoolss_enddocprinter_internal(p
, r
->in
.handle
); /* print job was not closed */
2062 result
= delete_printer_handle(p
, r
->in
.handle
);
2064 update_c_setprinter(false);
2069 /*******************************************************************
2070 * static function to lookup the version id corresponding to an
2071 * long architecture string
2072 ******************************************************************/
2074 static int get_version_id(const char *arch
)
2077 struct print_architecture_table_node archi_table
[]= {
2079 {"Windows 4.0", "WIN40", 0 },
2080 {"Windows NT x86", "W32X86", 2 },
2081 {"Windows NT R4000", "W32MIPS", 2 },
2082 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2083 {"Windows NT PowerPC", "W32PPC", 2 },
2084 {"Windows IA64", "IA64", 3 },
2085 {"Windows x64", "x64", 3 },
2089 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2091 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2092 return (archi_table
[i
].version
);
2098 /****************************************************************
2099 _spoolss_DeletePrinterDriver
2100 ****************************************************************/
2102 WERROR
_spoolss_DeletePrinterDriver(pipes_struct
*p
,
2103 struct spoolss_DeletePrinterDriver
*r
)
2105 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2106 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2109 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2110 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2112 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2113 and not a printer admin, then fail */
2115 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
2116 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
2117 && !token_contains_name_in_list(
2118 uidtoname(p
->server_info
->utok
.uid
), NULL
,
2119 NULL
, p
->server_info
->ptok
,
2120 lp_printer_admin(-1)) )
2122 return WERR_ACCESS_DENIED
;
2125 /* check that we have a valid driver name first */
2127 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
2128 return WERR_INVALID_ENVIRONMENT
;
2131 ZERO_STRUCT(info_win2k
);
2133 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, r
->in
.driver
,
2137 /* try for Win2k driver if "Windows NT x86" */
2139 if ( version
== 2 ) {
2141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3,
2145 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2149 /* otherwise it was a failure */
2151 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2157 if (printer_driver_in_use(info
.info_3
)) {
2158 status
= WERR_PRINTER_DRIVER_IN_USE
;
2164 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3,
2166 r
->in
.architecture
, 3)))
2168 /* if we get to here, we now have 2 driver info structures to remove */
2169 /* remove the Win2k driver first*/
2171 status_win2k
= delete_printer_driver(
2172 p
, info_win2k
.info_3
, 3, false);
2173 free_a_printer_driver( info_win2k
, 3 );
2175 /* this should not have failed---if it did, report to client */
2176 if ( !W_ERROR_IS_OK(status_win2k
) )
2178 status
= status_win2k
;
2184 status
= delete_printer_driver(p
, info
.info_3
, version
, false);
2186 /* if at least one of the deletes succeeded return OK */
2188 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2192 free_a_printer_driver( info
, 3 );
2197 /****************************************************************
2198 _spoolss_DeletePrinterDriverEx
2199 ****************************************************************/
2201 WERROR
_spoolss_DeletePrinterDriverEx(pipes_struct
*p
,
2202 struct spoolss_DeletePrinterDriverEx
*r
)
2204 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2205 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2209 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2210 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2212 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2213 and not a printer admin, then fail */
2215 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
2216 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
2217 && !token_contains_name_in_list(
2218 uidtoname(p
->server_info
->utok
.uid
), NULL
, NULL
,
2219 p
->server_info
->ptok
, lp_printer_admin(-1)) )
2221 return WERR_ACCESS_DENIED
;
2224 /* check that we have a valid driver name first */
2225 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
2226 /* this is what NT returns */
2227 return WERR_INVALID_ENVIRONMENT
;
2230 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2231 version
= r
->in
.version
;
2234 ZERO_STRUCT(info_win2k
);
2236 status
= get_a_printer_driver(&info
, 3, r
->in
.driver
,
2237 r
->in
.architecture
, version
);
2239 if ( !W_ERROR_IS_OK(status
) )
2242 * if the client asked for a specific version,
2243 * or this is something other than Windows NT x86,
2247 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2250 /* try for Win2k driver if "Windows NT x86" */
2253 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, r
->in
.driver
,
2256 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2261 if ( printer_driver_in_use(info
.info_3
) ) {
2262 status
= WERR_PRINTER_DRIVER_IN_USE
;
2267 * we have a couple of cases to consider.
2268 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2269 * then the delete should fail if **any** files overlap with
2271 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2272 * non-overlapping files
2273 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2274 * is set, the do not delete any files
2275 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2278 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2280 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2282 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) ) {
2283 /* no idea of the correct error here */
2284 status
= WERR_ACCESS_DENIED
;
2289 /* also check for W32X86/3 if necessary; maybe we already have? */
2291 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2292 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3,
2294 r
->in
.architecture
, 3)))
2297 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) ) {
2298 /* no idea of the correct error here */
2299 free_a_printer_driver( info_win2k
, 3 );
2300 status
= WERR_ACCESS_DENIED
;
2304 /* if we get to here, we now have 2 driver info structures to remove */
2305 /* remove the Win2k driver first*/
2307 status_win2k
= delete_printer_driver(
2308 p
, info_win2k
.info_3
, 3, delete_files
);
2309 free_a_printer_driver( info_win2k
, 3 );
2311 /* this should not have failed---if it did, report to client */
2313 if ( !W_ERROR_IS_OK(status_win2k
) )
2318 status
= delete_printer_driver(p
, info
.info_3
, version
, delete_files
);
2320 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2323 free_a_printer_driver( info
, 3 );
2329 /****************************************************************************
2330 Internal routine for removing printerdata
2331 ***************************************************************************/
2333 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2335 return delete_printer_data( printer
->info_2
, key
, value
);
2338 /****************************************************************************
2339 Internal routine for storing printerdata
2340 ***************************************************************************/
2342 WERROR
set_printer_dataex(NT_PRINTER_INFO_LEVEL
*printer
,
2343 const char *key
, const char *value
,
2344 uint32_t type
, uint8_t *data
, int real_len
)
2346 /* the registry objects enforce uniqueness based on value name */
2348 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2351 /********************************************************************
2352 GetPrinterData on a printer server Handle.
2353 ********************************************************************/
2355 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2357 enum winreg_Type
*type
,
2358 union spoolss_PrinterData
*data
)
2360 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2362 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2368 if (!StrCaseCmp(value
, "BeepEnabled")) {
2374 if (!StrCaseCmp(value
, "EventLog")) {
2376 /* formally was 0x1b */
2381 if (!StrCaseCmp(value
, "NetPopup")) {
2387 if (!StrCaseCmp(value
, "MajorVersion")) {
2390 /* Windows NT 4.0 seems to not allow uploading of drivers
2391 to a server that reports 0x3 as the MajorVersion.
2392 need to investigate more how Win2k gets around this .
2395 if (RA_WINNT
== get_remote_arch()) {
2404 if (!StrCaseCmp(value
, "MinorVersion")) {
2411 * uint32_t size = 0x114
2412 * uint32_t major = 5
2413 * uint32_t minor = [0|1]
2414 * uint32_t build = [2195|2600]
2415 * extra unicode string = e.g. "Service Pack 3"
2417 if (!StrCaseCmp(value
, "OSVersion")) {
2419 enum ndr_err_code ndr_err
;
2420 struct spoolss_OSVersion os
;
2422 os
.major
= 5; /* Windows 2000 == 5.0 */
2424 os
.build
= 2195; /* build */
2425 os
.extra_string
= ""; /* leave extra string empty */
2427 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, NULL
, &os
,
2428 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2429 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2430 return WERR_GENERAL_FAILURE
;
2434 data
->binary
= blob
;
2440 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2443 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2444 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2449 if (!StrCaseCmp(value
, "Architecture")) {
2452 data
->string
= talloc_strdup(mem_ctx
, "Windows NT x86");
2453 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2458 if (!StrCaseCmp(value
, "DsPresent")) {
2461 /* only show the publish check box if we are a
2462 member of a AD domain */
2464 if (lp_security() == SEC_ADS
) {
2472 if (!StrCaseCmp(value
, "DNSMachineName")) {
2473 const char *hostname
= get_mydnsfullname();
2476 return WERR_BADFILE
;
2480 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2481 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2486 return WERR_INVALID_PARAM
;
2489 /****************************************************************
2490 _spoolss_GetPrinterData
2491 ****************************************************************/
2493 WERROR
_spoolss_GetPrinterData(pipes_struct
*p
,
2494 struct spoolss_GetPrinterData
*r
)
2497 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2498 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2502 * Reminder: when it's a string, the length is in BYTES
2503 * even if UNICODE is negociated.
2508 /* in case of problem, return some default values */
2513 DEBUG(4,("_spoolss_GetPrinterData\n"));
2516 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2517 OUR_HANDLE(r
->in
.handle
)));
2518 result
= WERR_BADFID
;
2522 if (Printer
->printer_type
== SPLHND_SERVER
) {
2523 result
= getprinterdata_printer_server(p
->mem_ctx
,
2528 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
2529 result
= WERR_BADFID
;
2533 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2534 if (!W_ERROR_IS_OK(result
)) {
2538 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2540 if (strequal(r
->in
.value_name
, "ChangeId")) {
2541 *r
->out
.type
= REG_DWORD
;
2542 r
->out
.data
->value
= printer
->info_2
->changeid
;
2548 v
= get_printer_data(printer
->info_2
,
2549 SPOOL_PRINTERDATA_KEY
,
2552 result
= WERR_BADFILE
;
2556 *r
->out
.type
= v
->type
;
2558 blob
= data_blob_const(v
->data_p
, v
->size
);
2560 result
= pull_spoolss_PrinterData(p
->mem_ctx
, &blob
,
2567 /* cleanup & exit */
2570 free_a_printer(&printer
, 2);
2573 if (!W_ERROR_IS_OK(result
)) {
2577 *r
->out
.needed
= ndr_size_spoolss_PrinterData(r
->out
.data
, *r
->out
.type
, NULL
, 0);
2578 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
2579 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
2581 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
2584 /*********************************************************
2585 Connect to the client machine.
2586 **********************************************************/
2588 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2589 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2592 struct cli_state
*the_cli
;
2593 struct sockaddr_storage rm_addr
;
2595 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2596 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2597 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2601 if (ismyaddr((struct sockaddr
*)&rm_addr
)) {
2602 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2606 char addr
[INET6_ADDRSTRLEN
];
2607 rm_addr
= *client_ss
;
2608 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2609 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2613 /* setup the connection */
2615 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2616 &rm_addr
, 0, "IPC$", "IPC",
2620 0, lp_client_signing(), NULL
);
2622 if ( !NT_STATUS_IS_OK( ret
) ) {
2623 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2628 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2629 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2630 cli_shutdown(the_cli
);
2635 * Ok - we have an anonymous connection to the IPC$ share.
2636 * Now start the NT Domain stuff :-).
2639 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2640 if (!NT_STATUS_IS_OK(ret
)) {
2641 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2642 remote_machine
, nt_errstr(ret
)));
2643 cli_shutdown(the_cli
);
2650 /***************************************************************************
2651 Connect to the client.
2652 ****************************************************************************/
2654 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2655 uint32_t localprinter
, uint32_t type
,
2656 struct policy_handle
*handle
,
2657 struct sockaddr_storage
*client_ss
)
2663 * If it's the first connection, contact the client
2664 * and connect to the IPC$ share anonymously
2666 if (smb_connections
==0) {
2667 fstring unix_printer
;
2669 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2671 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2674 messaging_register(smbd_messaging_context(), NULL
,
2675 MSG_PRINTER_NOTIFY2
,
2676 receive_notify2_message_list
);
2677 /* Tell the connections db we're now interested in printer
2678 * notify messages. */
2679 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY
);
2683 * Tell the specific printing tdb we want messages for this printer
2684 * by registering our PID.
2687 if (!print_notify_register_pid(snum
))
2688 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2692 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2700 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2701 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2702 win_errstr(result
)));
2704 return (W_ERROR_IS_OK(result
));
2707 /****************************************************************
2708 ****************************************************************/
2710 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2711 const struct spoolss_NotifyOption
*r
)
2713 struct spoolss_NotifyOption
*option
;
2720 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2727 if (!option
->count
) {
2731 option
->types
= talloc_zero_array(option
,
2732 struct spoolss_NotifyOptionType
, option
->count
);
2733 if (!option
->types
) {
2734 talloc_free(option
);
2738 for (i
=0; i
< option
->count
; i
++) {
2739 option
->types
[i
] = r
->types
[i
];
2741 if (option
->types
[i
].count
) {
2742 option
->types
[i
].fields
= talloc_zero_array(option
,
2743 union spoolss_Field
, option
->types
[i
].count
);
2744 if (!option
->types
[i
].fields
) {
2745 talloc_free(option
);
2748 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2749 option
->types
[i
].fields
[k
] =
2750 r
->types
[i
].fields
[k
];
2758 /****************************************************************
2759 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2761 * before replying OK: status=0 a rpc call is made to the workstation
2762 * asking ReplyOpenPrinter
2764 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2765 * called from api_spoolss_rffpcnex
2766 ****************************************************************/
2768 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct
*p
,
2769 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2772 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2773 struct sockaddr_storage client_ss
;
2775 /* store the notify value in the printer struct */
2777 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2780 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2781 "Invalid handle (%s:%u:%u).\n",
2782 OUR_HANDLE(r
->in
.handle
)));
2786 Printer
->notify
.flags
= r
->in
.flags
;
2787 Printer
->notify
.options
= r
->in
.options
;
2788 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2790 TALLOC_FREE(Printer
->notify
.option
);
2791 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2793 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2795 /* Connect to the client machine and send a ReplyOpenPrinter */
2797 if ( Printer
->printer_type
== SPLHND_SERVER
)
2799 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2800 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2803 if (!interpret_string_addr(&client_ss
, p
->client_address
,
2805 return WERR_SERVER_UNAVAILABLE
;
2808 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2809 Printer
->notify
.printerlocal
, 1,
2810 &Printer
->notify
.client_hnd
, &client_ss
))
2811 return WERR_SERVER_UNAVAILABLE
;
2813 Printer
->notify
.client_connected
= true;
2818 /*******************************************************************
2819 * fill a notify_info_data with the servername
2820 ********************************************************************/
2822 void spoolss_notify_server_name(int snum
,
2823 struct spoolss_Notify
*data
,
2824 print_queue_struct
*queue
,
2825 NT_PRINTER_INFO_LEVEL
*printer
,
2826 TALLOC_CTX
*mem_ctx
)
2828 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->servername
);
2831 /*******************************************************************
2832 * fill a notify_info_data with the printername (not including the servername).
2833 ********************************************************************/
2835 void spoolss_notify_printer_name(int snum
,
2836 struct spoolss_Notify
*data
,
2837 print_queue_struct
*queue
,
2838 NT_PRINTER_INFO_LEVEL
*printer
,
2839 TALLOC_CTX
*mem_ctx
)
2841 /* the notify name should not contain the \\server\ part */
2842 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2845 p
= printer
->info_2
->printername
;
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2853 /*******************************************************************
2854 * fill a notify_info_data with the servicename
2855 ********************************************************************/
2857 void spoolss_notify_share_name(int snum
,
2858 struct spoolss_Notify
*data
,
2859 print_queue_struct
*queue
,
2860 NT_PRINTER_INFO_LEVEL
*printer
,
2861 TALLOC_CTX
*mem_ctx
)
2863 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2866 /*******************************************************************
2867 * fill a notify_info_data with the port name
2868 ********************************************************************/
2870 void spoolss_notify_port_name(int snum
,
2871 struct spoolss_Notify
*data
,
2872 print_queue_struct
*queue
,
2873 NT_PRINTER_INFO_LEVEL
*printer
,
2874 TALLOC_CTX
*mem_ctx
)
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->portname
);
2879 /*******************************************************************
2880 * fill a notify_info_data with the printername
2881 * but it doesn't exist, have to see what to do
2882 ********************************************************************/
2884 void spoolss_notify_driver_name(int snum
,
2885 struct spoolss_Notify
*data
,
2886 print_queue_struct
*queue
,
2887 NT_PRINTER_INFO_LEVEL
*printer
,
2888 TALLOC_CTX
*mem_ctx
)
2890 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->drivername
);
2893 /*******************************************************************
2894 * fill a notify_info_data with the comment
2895 ********************************************************************/
2897 void spoolss_notify_comment(int snum
,
2898 struct spoolss_Notify
*data
,
2899 print_queue_struct
*queue
,
2900 NT_PRINTER_INFO_LEVEL
*printer
,
2901 TALLOC_CTX
*mem_ctx
)
2905 if (*printer
->info_2
->comment
== '\0') {
2906 p
= lp_comment(snum
);
2908 p
= printer
->info_2
->comment
;
2911 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->comment
);
2914 /*******************************************************************
2915 * fill a notify_info_data with the comment
2916 * location = "Room 1, floor 2, building 3"
2917 ********************************************************************/
2919 void spoolss_notify_location(int snum
,
2920 struct spoolss_Notify
*data
,
2921 print_queue_struct
*queue
,
2922 NT_PRINTER_INFO_LEVEL
*printer
,
2923 TALLOC_CTX
*mem_ctx
)
2925 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->location
);
2928 /*******************************************************************
2929 * fill a notify_info_data with the device mode
2930 * jfm:xxxx don't to it for know but that's a real problem !!!
2931 ********************************************************************/
2933 static void spoolss_notify_devmode(int snum
,
2934 struct spoolss_Notify
*data
,
2935 print_queue_struct
*queue
,
2936 NT_PRINTER_INFO_LEVEL
*printer
,
2937 TALLOC_CTX
*mem_ctx
)
2939 /* for a dummy implementation we have to zero the fields */
2940 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2943 /*******************************************************************
2944 * fill a notify_info_data with the separator file name
2945 ********************************************************************/
2947 void spoolss_notify_sepfile(int snum
,
2948 struct spoolss_Notify
*data
,
2949 print_queue_struct
*queue
,
2950 NT_PRINTER_INFO_LEVEL
*printer
,
2951 TALLOC_CTX
*mem_ctx
)
2953 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->sepfile
);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor
2958 * jfm:xxxx return always winprint to indicate we don't do anything to it
2959 ********************************************************************/
2961 void spoolss_notify_print_processor(int snum
,
2962 struct spoolss_Notify
*data
,
2963 print_queue_struct
*queue
,
2964 NT_PRINTER_INFO_LEVEL
*printer
,
2965 TALLOC_CTX
*mem_ctx
)
2967 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->printprocessor
);
2970 /*******************************************************************
2971 * fill a notify_info_data with the print processor options
2972 * jfm:xxxx send an empty string
2973 ********************************************************************/
2975 void spoolss_notify_parameters(int snum
,
2976 struct spoolss_Notify
*data
,
2977 print_queue_struct
*queue
,
2978 NT_PRINTER_INFO_LEVEL
*printer
,
2979 TALLOC_CTX
*mem_ctx
)
2981 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->parameters
);
2984 /*******************************************************************
2985 * fill a notify_info_data with the data type
2986 * jfm:xxxx always send RAW as data type
2987 ********************************************************************/
2989 void spoolss_notify_datatype(int snum
,
2990 struct spoolss_Notify
*data
,
2991 print_queue_struct
*queue
,
2992 NT_PRINTER_INFO_LEVEL
*printer
,
2993 TALLOC_CTX
*mem_ctx
)
2995 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->datatype
);
2998 /*******************************************************************
2999 * fill a notify_info_data with the security descriptor
3000 * jfm:xxxx send an null pointer to say no security desc
3001 * have to implement security before !
3002 ********************************************************************/
3004 static void spoolss_notify_security_desc(int snum
,
3005 struct spoolss_Notify
*data
,
3006 print_queue_struct
*queue
,
3007 NT_PRINTER_INFO_LEVEL
*printer
,
3008 TALLOC_CTX
*mem_ctx
)
3010 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
,
3011 printer
->info_2
->secdesc_buf
->sd_size
,
3012 printer
->info_2
->secdesc_buf
->sd
);
3015 /*******************************************************************
3016 * fill a notify_info_data with the attributes
3017 * jfm:xxxx a samba printer is always shared
3018 ********************************************************************/
3020 void spoolss_notify_attributes(int snum
,
3021 struct spoolss_Notify
*data
,
3022 print_queue_struct
*queue
,
3023 NT_PRINTER_INFO_LEVEL
*printer
,
3024 TALLOC_CTX
*mem_ctx
)
3026 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->attributes
);
3029 /*******************************************************************
3030 * fill a notify_info_data with the priority
3031 ********************************************************************/
3033 static void spoolss_notify_priority(int snum
,
3034 struct spoolss_Notify
*data
,
3035 print_queue_struct
*queue
,
3036 NT_PRINTER_INFO_LEVEL
*printer
,
3037 TALLOC_CTX
*mem_ctx
)
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->priority
);
3042 /*******************************************************************
3043 * fill a notify_info_data with the default priority
3044 ********************************************************************/
3046 static void spoolss_notify_default_priority(int snum
,
3047 struct spoolss_Notify
*data
,
3048 print_queue_struct
*queue
,
3049 NT_PRINTER_INFO_LEVEL
*printer
,
3050 TALLOC_CTX
*mem_ctx
)
3052 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->default_priority
);
3055 /*******************************************************************
3056 * fill a notify_info_data with the start time
3057 ********************************************************************/
3059 static void spoolss_notify_start_time(int snum
,
3060 struct spoolss_Notify
*data
,
3061 print_queue_struct
*queue
,
3062 NT_PRINTER_INFO_LEVEL
*printer
,
3063 TALLOC_CTX
*mem_ctx
)
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->starttime
);
3068 /*******************************************************************
3069 * fill a notify_info_data with the until time
3070 ********************************************************************/
3072 static void spoolss_notify_until_time(int snum
,
3073 struct spoolss_Notify
*data
,
3074 print_queue_struct
*queue
,
3075 NT_PRINTER_INFO_LEVEL
*printer
,
3076 TALLOC_CTX
*mem_ctx
)
3078 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->untiltime
);
3081 /*******************************************************************
3082 * fill a notify_info_data with the status
3083 ********************************************************************/
3085 static void spoolss_notify_status(int snum
,
3086 struct spoolss_Notify
*data
,
3087 print_queue_struct
*queue
,
3088 NT_PRINTER_INFO_LEVEL
*printer
,
3089 TALLOC_CTX
*mem_ctx
)
3091 print_status_struct status
;
3093 print_queue_length(snum
, &status
);
3094 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3097 /*******************************************************************
3098 * fill a notify_info_data with the number of jobs queued
3099 ********************************************************************/
3101 void spoolss_notify_cjobs(int snum
,
3102 struct spoolss_Notify
*data
,
3103 print_queue_struct
*queue
,
3104 NT_PRINTER_INFO_LEVEL
*printer
,
3105 TALLOC_CTX
*mem_ctx
)
3107 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, print_queue_length(snum
, NULL
));
3110 /*******************************************************************
3111 * fill a notify_info_data with the average ppm
3112 ********************************************************************/
3114 static void spoolss_notify_average_ppm(int snum
,
3115 struct spoolss_Notify
*data
,
3116 print_queue_struct
*queue
,
3117 NT_PRINTER_INFO_LEVEL
*printer
,
3118 TALLOC_CTX
*mem_ctx
)
3120 /* always respond 8 pages per minutes */
3121 /* a little hard ! */
3122 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->averageppm
);
3125 /*******************************************************************
3126 * fill a notify_info_data with username
3127 ********************************************************************/
3129 static void spoolss_notify_username(int snum
,
3130 struct spoolss_Notify
*data
,
3131 print_queue_struct
*queue
,
3132 NT_PRINTER_INFO_LEVEL
*printer
,
3133 TALLOC_CTX
*mem_ctx
)
3135 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3138 /*******************************************************************
3139 * fill a notify_info_data with job status
3140 ********************************************************************/
3142 static void spoolss_notify_job_status(int snum
,
3143 struct spoolss_Notify
*data
,
3144 print_queue_struct
*queue
,
3145 NT_PRINTER_INFO_LEVEL
*printer
,
3146 TALLOC_CTX
*mem_ctx
)
3148 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3151 /*******************************************************************
3152 * fill a notify_info_data with job name
3153 ********************************************************************/
3155 static void spoolss_notify_job_name(int snum
,
3156 struct spoolss_Notify
*data
,
3157 print_queue_struct
*queue
,
3158 NT_PRINTER_INFO_LEVEL
*printer
,
3159 TALLOC_CTX
*mem_ctx
)
3161 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3164 /*******************************************************************
3165 * fill a notify_info_data with job status
3166 ********************************************************************/
3168 static void spoolss_notify_job_status_string(int snum
,
3169 struct spoolss_Notify
*data
,
3170 print_queue_struct
*queue
,
3171 NT_PRINTER_INFO_LEVEL
*printer
,
3172 TALLOC_CTX
*mem_ctx
)
3175 * Now we're returning job status codes we just return a "" here. JRA.
3180 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3183 switch (queue
->status
) {
3188 p
= ""; /* NT provides the paused string */
3197 #endif /* NO LONGER NEEDED. */
3199 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3202 /*******************************************************************
3203 * fill a notify_info_data with job time
3204 ********************************************************************/
3206 static void spoolss_notify_job_time(int snum
,
3207 struct spoolss_Notify
*data
,
3208 print_queue_struct
*queue
,
3209 NT_PRINTER_INFO_LEVEL
*printer
,
3210 TALLOC_CTX
*mem_ctx
)
3212 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3215 /*******************************************************************
3216 * fill a notify_info_data with job size
3217 ********************************************************************/
3219 static void spoolss_notify_job_size(int snum
,
3220 struct spoolss_Notify
*data
,
3221 print_queue_struct
*queue
,
3222 NT_PRINTER_INFO_LEVEL
*printer
,
3223 TALLOC_CTX
*mem_ctx
)
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3228 /*******************************************************************
3229 * fill a notify_info_data with page info
3230 ********************************************************************/
3231 static void spoolss_notify_total_pages(int snum
,
3232 struct spoolss_Notify
*data
,
3233 print_queue_struct
*queue
,
3234 NT_PRINTER_INFO_LEVEL
*printer
,
3235 TALLOC_CTX
*mem_ctx
)
3237 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3240 /*******************************************************************
3241 * fill a notify_info_data with pages printed info.
3242 ********************************************************************/
3243 static void spoolss_notify_pages_printed(int snum
,
3244 struct spoolss_Notify
*data
,
3245 print_queue_struct
*queue
,
3246 NT_PRINTER_INFO_LEVEL
*printer
,
3247 TALLOC_CTX
*mem_ctx
)
3249 /* Add code when back-end tracks this */
3250 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3253 /*******************************************************************
3254 Fill a notify_info_data with job position.
3255 ********************************************************************/
3257 static void spoolss_notify_job_position(int snum
,
3258 struct spoolss_Notify
*data
,
3259 print_queue_struct
*queue
,
3260 NT_PRINTER_INFO_LEVEL
*printer
,
3261 TALLOC_CTX
*mem_ctx
)
3263 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
3266 /*******************************************************************
3267 Fill a notify_info_data with submitted time.
3268 ********************************************************************/
3270 static void spoolss_notify_submitted_time(int snum
,
3271 struct spoolss_Notify
*data
,
3272 print_queue_struct
*queue
,
3273 NT_PRINTER_INFO_LEVEL
*printer
,
3274 TALLOC_CTX
*mem_ctx
)
3276 data
->data
.string
.string
= NULL
;
3277 data
->data
.string
.size
= 0;
3279 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3280 &data
->data
.string
.string
,
3281 &data
->data
.string
.size
);
3285 struct s_notify_info_data_table
3287 enum spoolss_NotifyType type
;
3290 enum spoolss_NotifyTable variable_type
;
3291 void (*fn
) (int snum
, struct spoolss_Notify
*data
,
3292 print_queue_struct
*queue
,
3293 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3296 /* A table describing the various print notification constants and
3297 whether the notification data is a pointer to a variable sized
3298 buffer, a one value uint32_t or a two value uint32_t. */
3300 static const struct s_notify_info_data_table notify_info_data_table
[] =
3302 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3303 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3304 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3305 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3306 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3307 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3308 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3309 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3310 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3311 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3312 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3313 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3314 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3315 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3316 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3317 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3318 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3319 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3320 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3321 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3322 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3323 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3324 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3325 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3326 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3327 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3328 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3329 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3330 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3331 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3332 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3333 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3334 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3335 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3336 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3337 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3338 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3339 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3340 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3341 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3342 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3343 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3344 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3345 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3346 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3347 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3348 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3349 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3350 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3353 /*******************************************************************
3354 Return the variable_type of info_data structure.
3355 ********************************************************************/
3357 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3362 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3363 if ( (notify_info_data_table
[i
].type
== type
) &&
3364 (notify_info_data_table
[i
].field
== field
) ) {
3365 return notify_info_data_table
[i
].variable_type
;
3369 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3374 /****************************************************************************
3375 ****************************************************************************/
3377 static bool search_notify(enum spoolss_NotifyType type
,
3383 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3384 if (notify_info_data_table
[i
].type
== type
&&
3385 notify_info_data_table
[i
].field
== field
&&
3386 notify_info_data_table
[i
].fn
!= NULL
) {
3395 /****************************************************************************
3396 ****************************************************************************/
3398 void construct_info_data(struct spoolss_Notify
*info_data
,
3399 enum spoolss_NotifyType type
,
3403 info_data
->type
= type
;
3404 info_data
->field
.field
= field
;
3405 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3406 info_data
->job_id
= id
;
3409 /*******************************************************************
3411 * fill a notify_info struct with info asked
3413 ********************************************************************/
3415 static bool construct_notify_printer_info(Printer_entry
*print_hnd
,
3416 struct spoolss_NotifyInfo
*info
,
3418 const struct spoolss_NotifyOptionType
*option_type
,
3420 TALLOC_CTX
*mem_ctx
)
3423 enum spoolss_NotifyType type
;
3426 struct spoolss_Notify
*current_data
;
3427 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3428 print_queue_struct
*queue
=NULL
;
3430 type
= option_type
->type
;
3432 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3433 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3434 option_type
->count
, lp_servicename(snum
)));
3436 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3439 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3440 field
= option_type
->fields
[field_num
].field
;
3442 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3444 if (!search_notify(type
, field
, &j
) )
3447 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3448 struct spoolss_Notify
,
3450 if (info
->notifies
== NULL
) {
3451 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3452 free_a_printer(&printer
, 2);
3456 current_data
= &info
->notifies
[info
->count
];
3458 construct_info_data(current_data
, type
, field
, id
);
3460 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3461 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3463 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3469 free_a_printer(&printer
, 2);
3473 /*******************************************************************
3475 * fill a notify_info struct with info asked
3477 ********************************************************************/
3479 static bool construct_notify_jobs_info(print_queue_struct
*queue
,
3480 struct spoolss_NotifyInfo
*info
,
3481 NT_PRINTER_INFO_LEVEL
*printer
,
3483 const struct spoolss_NotifyOptionType
*option_type
,
3485 TALLOC_CTX
*mem_ctx
)
3488 enum spoolss_NotifyType type
;
3490 struct spoolss_Notify
*current_data
;
3492 DEBUG(4,("construct_notify_jobs_info\n"));
3494 type
= option_type
->type
;
3496 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3497 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3498 option_type
->count
));
3500 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3501 field
= option_type
->fields
[field_num
].field
;
3503 if (!search_notify(type
, field
, &j
) )
3506 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3507 struct spoolss_Notify
,
3509 if (info
->notifies
== NULL
) {
3510 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3514 current_data
=&(info
->notifies
[info
->count
]);
3516 construct_info_data(current_data
, type
, field
, id
);
3517 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3526 * JFM: The enumeration is not that simple, it's even non obvious.
3528 * let's take an example: I want to monitor the PRINTER SERVER for
3529 * the printer's name and the number of jobs currently queued.
3530 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3531 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3533 * I have 3 printers on the back of my server.
3535 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3538 * 1 printer 1 name 1
3539 * 2 printer 1 cjob 1
3540 * 3 printer 2 name 2
3541 * 4 printer 2 cjob 2
3542 * 5 printer 3 name 3
3543 * 6 printer 3 name 3
3545 * that's the print server case, the printer case is even worse.
3548 /*******************************************************************
3550 * enumerate all printers on the printserver
3551 * fill a notify_info struct with info asked
3553 ********************************************************************/
3555 static WERROR
printserver_notify_info(pipes_struct
*p
,
3556 struct policy_handle
*hnd
,
3557 struct spoolss_NotifyInfo
*info
,
3558 TALLOC_CTX
*mem_ctx
)
3561 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3562 int n_services
=lp_numservices();
3564 struct spoolss_NotifyOption
*option
;
3565 struct spoolss_NotifyOptionType option_type
;
3567 DEBUG(4,("printserver_notify_info\n"));
3572 option
= Printer
->notify
.option
;
3575 info
->notifies
= NULL
;
3578 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3579 sending a ffpcn() request first */
3584 for (i
=0; i
<option
->count
; i
++) {
3585 option_type
= option
->types
[i
];
3587 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3590 for (snum
=0; snum
<n_services
; snum
++)
3592 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3593 construct_notify_printer_info ( Printer
, info
, snum
, &option_type
, snum
, mem_ctx
);
3599 * Debugging information, don't delete.
3602 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3603 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3604 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3606 for (i
=0; i
<info
->count
; i
++) {
3607 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3608 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3609 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3616 /*******************************************************************
3618 * fill a notify_info struct with info asked
3620 ********************************************************************/
3622 static WERROR
printer_notify_info(pipes_struct
*p
, struct policy_handle
*hnd
,
3623 struct spoolss_NotifyInfo
*info
,
3624 TALLOC_CTX
*mem_ctx
)
3627 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3630 struct spoolss_NotifyOption
*option
;
3631 struct spoolss_NotifyOptionType option_type
;
3633 print_queue_struct
*queue
=NULL
;
3634 print_status_struct status
;
3636 DEBUG(4,("printer_notify_info\n"));
3641 option
= Printer
->notify
.option
;
3645 info
->notifies
= NULL
;
3648 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3649 sending a ffpcn() request first */
3654 get_printer_snum(p
, hnd
, &snum
, NULL
);
3656 for (i
=0; i
<option
->count
; i
++) {
3657 option_type
= option
->types
[i
];
3659 switch (option_type
.type
) {
3660 case PRINTER_NOTIFY_TYPE
:
3661 if(construct_notify_printer_info(Printer
, info
, snum
,
3667 case JOB_NOTIFY_TYPE
: {
3668 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3670 count
= print_queue_status(snum
, &queue
, &status
);
3672 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3675 for (j
=0; j
<count
; j
++) {
3676 construct_notify_jobs_info(&queue
[j
], info
,
3683 free_a_printer(&printer
, 2);
3693 * Debugging information, don't delete.
3696 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3697 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3698 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3700 for (i=0; i<info->count; i++) {
3701 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3702 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3703 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3709 /****************************************************************
3710 _spoolss_RouterRefreshPrinterChangeNotify
3711 ****************************************************************/
3713 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(pipes_struct
*p
,
3714 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3716 struct spoolss_NotifyInfo
*info
;
3718 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3719 WERROR result
= WERR_BADFID
;
3721 /* we always have a spoolss_NotifyInfo struct */
3722 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3724 result
= WERR_NOMEM
;
3728 *r
->out
.info
= info
;
3731 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3732 "Invalid handle (%s:%u:%u).\n",
3733 OUR_HANDLE(r
->in
.handle
)));
3737 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3740 * We are now using the change value, and
3741 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3742 * I don't have a global notification system, I'm sending back all the
3743 * informations even when _NOTHING_ has changed.
3746 /* We need to keep track of the change value to send back in
3747 RRPCN replies otherwise our updates are ignored. */
3749 Printer
->notify
.fnpcn
= true;
3751 if (Printer
->notify
.client_connected
) {
3752 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3753 "Saving change value in request [%x]\n",
3755 Printer
->notify
.change
= r
->in
.change_low
;
3758 /* just ignore the spoolss_NotifyOption */
3760 switch (Printer
->printer_type
) {
3762 result
= printserver_notify_info(p
, r
->in
.handle
,
3766 case SPLHND_PRINTER
:
3767 result
= printer_notify_info(p
, r
->in
.handle
,
3772 Printer
->notify
.fnpcn
= false;
3778 /********************************************************************
3779 * construct_printer_info_0
3780 * fill a printer_info_0 struct
3781 ********************************************************************/
3783 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3784 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3785 struct spoolss_PrinterInfo0
*r
,
3789 counter_printer_0
*session_counter
;
3791 print_status_struct status
;
3793 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3794 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3796 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3797 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3799 count
= print_queue_length(snum
, &status
);
3801 /* check if we already have a counter for this printer */
3802 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3803 if (session_counter
->snum
== snum
)
3807 /* it's the first time, add it to the list */
3808 if (session_counter
== NULL
) {
3809 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3810 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3811 ZERO_STRUCTP(session_counter
);
3812 session_counter
->snum
= snum
;
3813 session_counter
->counter
= 0;
3814 DLIST_ADD(counter_list
, session_counter
);
3818 session_counter
->counter
++;
3824 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3826 init_systemtime(&r
->time
, gmtime(&setuptime
));
3829 * the global_counter should be stored in a TDB as it's common to all the clients
3830 * and should be zeroed on samba startup
3832 r
->global_counter
= session_counter
->counter
;
3834 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3835 r
->version
= 0x0005; /* NT 5 */
3836 r
->free_build
= 0x0893; /* build 2195 */
3838 r
->max_spooling
= 0;
3839 r
->session_counter
= session_counter
->counter
;
3840 r
->num_error_out_of_paper
= 0x0;
3841 r
->num_error_not_ready
= 0x0; /* number of print failure */
3843 r
->number_of_processors
= 0x1;
3844 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3845 r
->high_part_total_bytes
= 0x0;
3846 r
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3847 r
->last_error
= WERR_OK
;
3848 r
->status
= nt_printq_status(status
.status
);
3849 r
->enumerate_network_printers
= 0x0;
3850 r
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3851 r
->processor_architecture
= 0x0;
3852 r
->processor_level
= 0x6; /* 6 ???*/
3860 /****************************************************************************
3861 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3862 should be valid upon entry
3863 ****************************************************************************/
3865 static WERROR
convert_nt_devicemode(TALLOC_CTX
*mem_ctx
,
3866 struct spoolss_DeviceMode
*r
,
3867 const NT_DEVICEMODE
*ntdevmode
)
3869 if (!r
|| !ntdevmode
) {
3870 return WERR_INVALID_PARAM
;
3873 r
->devicename
= talloc_strdup(mem_ctx
, ntdevmode
->devicename
);
3874 W_ERROR_HAVE_NO_MEMORY(r
->devicename
);
3876 r
->specversion
= ntdevmode
->specversion
;
3877 r
->driverversion
= ntdevmode
->driverversion
;
3878 r
->size
= ntdevmode
->size
;
3879 r
->__driverextra_length
= ntdevmode
->driverextra
;
3880 r
->fields
= ntdevmode
->fields
;
3882 r
->orientation
= ntdevmode
->orientation
;
3883 r
->papersize
= ntdevmode
->papersize
;
3884 r
->paperlength
= ntdevmode
->paperlength
;
3885 r
->paperwidth
= ntdevmode
->paperwidth
;
3886 r
->scale
= ntdevmode
->scale
;
3887 r
->copies
= ntdevmode
->copies
;
3888 r
->defaultsource
= ntdevmode
->defaultsource
;
3889 r
->printquality
= ntdevmode
->printquality
;
3890 r
->color
= ntdevmode
->color
;
3891 r
->duplex
= ntdevmode
->duplex
;
3892 r
->yresolution
= ntdevmode
->yresolution
;
3893 r
->ttoption
= ntdevmode
->ttoption
;
3894 r
->collate
= ntdevmode
->collate
;
3896 r
->formname
= talloc_strdup(mem_ctx
, ntdevmode
->formname
);
3897 W_ERROR_HAVE_NO_MEMORY(r
->formname
);
3899 /* all 0 below are values that have not been set in the old parsing/copy
3900 * function, maybe they should... - gd */
3906 r
->displayflags
= 0;
3907 r
->displayfrequency
= 0;
3908 r
->icmmethod
= ntdevmode
->icmmethod
;
3909 r
->icmintent
= ntdevmode
->icmintent
;
3910 r
->mediatype
= ntdevmode
->mediatype
;
3911 r
->dithertype
= ntdevmode
->dithertype
;
3914 r
->panningwidth
= 0;
3915 r
->panningheight
= 0;
3917 if (ntdevmode
->nt_dev_private
!= NULL
) {
3918 r
->driverextra_data
= data_blob_talloc(mem_ctx
,
3919 ntdevmode
->nt_dev_private
,
3920 ntdevmode
->driverextra
);
3921 W_ERROR_HAVE_NO_MEMORY(r
->driverextra_data
.data
);
3928 /****************************************************************************
3929 Create a spoolss_DeviceMode struct. Returns talloced memory.
3930 ****************************************************************************/
3932 struct spoolss_DeviceMode
*construct_dev_mode(TALLOC_CTX
*mem_ctx
,
3933 const char *servicename
)
3936 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3937 struct spoolss_DeviceMode
*devmode
= NULL
;
3939 DEBUG(7,("construct_dev_mode\n"));
3941 DEBUGADD(8,("getting printer characteristics\n"));
3943 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
3946 if (!printer
->info_2
->devmode
) {
3947 DEBUG(5, ("BONG! There was no device mode!\n"));
3951 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
3953 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3957 DEBUGADD(8,("loading DEVICEMODE\n"));
3959 result
= convert_nt_devicemode(mem_ctx
, devmode
, printer
->info_2
->devmode
);
3960 if (!W_ERROR_IS_OK(result
)) {
3961 TALLOC_FREE(devmode
);
3965 free_a_printer(&printer
,2);
3970 /********************************************************************
3971 * construct_printer_info3
3972 * fill a spoolss_PrinterInfo3 struct
3973 ********************************************************************/
3975 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3976 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3977 struct spoolss_PrinterInfo3
*r
,
3980 /* These are the components of the SD we are returning. */
3982 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3983 /* don't use talloc_steal() here unless you do a deep steal of all
3984 the SEC_DESC members */
3986 r
->secdesc
= dup_sec_desc(mem_ctx
,
3987 ntprinter
->info_2
->secdesc_buf
->sd
);
3988 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3994 /********************************************************************
3995 * construct_printer_info4
3996 * fill a spoolss_PrinterInfo4 struct
3997 ********************************************************************/
3999 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
4000 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4001 struct spoolss_PrinterInfo4
*r
,
4004 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4005 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
4006 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
4007 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4009 r
->attributes
= ntprinter
->info_2
->attributes
;
4014 /********************************************************************
4015 * construct_printer_info5
4016 * fill a spoolss_PrinterInfo5 struct
4017 ********************************************************************/
4019 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
4020 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4021 struct spoolss_PrinterInfo5
*r
,
4024 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4025 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
4026 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
4027 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4029 r
->attributes
= ntprinter
->info_2
->attributes
;
4031 /* these two are not used by NT+ according to MSDN */
4033 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4034 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4039 /********************************************************************
4040 * construct_printer_info_6
4041 * fill a spoolss_PrinterInfo6 struct
4042 ********************************************************************/
4044 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
4045 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4046 struct spoolss_PrinterInfo6
*r
,
4050 print_status_struct status
;
4052 count
= print_queue_length(snum
, &status
);
4054 r
->status
= nt_printq_status(status
.status
);
4059 /********************************************************************
4060 * construct_printer_info7
4061 * fill a spoolss_PrinterInfo7 struct
4062 ********************************************************************/
4064 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4065 Printer_entry
*print_hnd
,
4066 struct spoolss_PrinterInfo7
*r
,
4071 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4072 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4073 r
->action
= DSPRINT_PUBLISH
;
4075 r
->guid
= talloc_strdup(mem_ctx
, "");
4076 r
->action
= DSPRINT_UNPUBLISH
;
4078 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
4083 /********************************************************************
4084 * construct_printer_info8
4085 * fill a spoolss_PrinterInfo8 struct
4086 ********************************************************************/
4088 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
4089 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4090 struct spoolss_DeviceModeInfo
*r
,
4093 struct spoolss_DeviceMode
*devmode
;
4096 if (!ntprinter
->info_2
->devmode
) {
4101 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
4102 W_ERROR_HAVE_NO_MEMORY(devmode
);
4104 result
= convert_nt_devicemode(mem_ctx
, devmode
, ntprinter
->info_2
->devmode
);
4105 if (!W_ERROR_IS_OK(result
)) {
4106 TALLOC_FREE(devmode
);
4110 r
->devmode
= devmode
;
4116 /********************************************************************
4117 * construct_printer_info1
4118 * fill a spoolss_PrinterInfo1 struct
4119 ********************************************************************/
4121 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
4122 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4124 struct spoolss_PrinterInfo1
*r
,
4129 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
4130 ntprinter
->info_2
->printername
,
4131 ntprinter
->info_2
->drivername
,
4132 ntprinter
->info_2
->location
);
4133 W_ERROR_HAVE_NO_MEMORY(r
->description
);
4135 if (*ntprinter
->info_2
->comment
== '\0') {
4136 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4138 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
); /* saved comment */
4140 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4142 r
->name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4143 W_ERROR_HAVE_NO_MEMORY(r
->name
);
4148 /********************************************************************
4149 * construct_printer_info2
4150 * fill a spoolss_PrinterInfo2 struct
4151 ********************************************************************/
4153 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
4154 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
4155 struct spoolss_PrinterInfo2
*r
,
4160 print_status_struct status
;
4162 count
= print_queue_length(snum
, &status
);
4164 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
4165 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4166 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
4167 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
4168 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
4169 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
4170 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
4171 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4172 r
->drivername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
4173 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
4175 if (*ntprinter
->info_2
->comment
== '\0') {
4176 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4178 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
);
4180 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4182 r
->location
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->location
);
4183 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4184 r
->sepfile
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->sepfile
);
4185 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4186 r
->printprocessor
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printprocessor
);
4187 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4188 r
->datatype
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->datatype
);
4189 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4190 r
->parameters
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->parameters
);
4191 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4193 r
->attributes
= ntprinter
->info_2
->attributes
;
4195 r
->priority
= ntprinter
->info_2
->priority
;
4196 r
->defaultpriority
= ntprinter
->info_2
->default_priority
;
4197 r
->starttime
= ntprinter
->info_2
->starttime
;
4198 r
->untiltime
= ntprinter
->info_2
->untiltime
;
4199 r
->status
= nt_printq_status(status
.status
);
4201 r
->averageppm
= ntprinter
->info_2
->averageppm
;
4203 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
4205 DEBUG(8,("Returning NULL Devicemode!\n"));
4210 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
4211 /* don't use talloc_steal() here unless you do a deep steal of all
4212 the SEC_DESC members */
4214 r
->secdesc
= dup_sec_desc(mem_ctx
, ntprinter
->info_2
->secdesc_buf
->sd
);
4220 /********************************************************************
4221 ********************************************************************/
4223 static bool snum_is_shared_printer(int snum
)
4225 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
4228 /********************************************************************
4229 Spoolss_enumprinters.
4230 ********************************************************************/
4232 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
4235 union spoolss_PrinterInfo
**info_p
,
4239 int n_services
= lp_numservices();
4240 union spoolss_PrinterInfo
*info
= NULL
;
4242 WERROR result
= WERR_OK
;
4247 for (snum
= 0; snum
< n_services
; snum
++) {
4249 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4251 if (!snum_is_shared_printer(snum
)) {
4255 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4256 lp_servicename(snum
), snum
));
4258 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4259 union spoolss_PrinterInfo
,
4262 result
= WERR_NOMEM
;
4266 result
= get_a_printer(NULL
, &ntprinter
, 2,
4267 lp_const_servicename(snum
));
4268 if (!W_ERROR_IS_OK(result
)) {
4274 result
= construct_printer_info0(info
, ntprinter
,
4275 &info
[count
].info0
, snum
);
4278 result
= construct_printer_info1(info
, ntprinter
, flags
,
4279 &info
[count
].info1
, snum
);
4282 result
= construct_printer_info2(info
, ntprinter
,
4283 &info
[count
].info2
, snum
);
4286 result
= construct_printer_info4(info
, ntprinter
,
4287 &info
[count
].info4
, snum
);
4290 result
= construct_printer_info5(info
, ntprinter
,
4291 &info
[count
].info5
, snum
);
4295 result
= WERR_UNKNOWN_LEVEL
;
4296 free_a_printer(&ntprinter
, 2);
4300 free_a_printer(&ntprinter
, 2);
4301 if (!W_ERROR_IS_OK(result
)) {
4312 if (!W_ERROR_IS_OK(result
)) {
4322 /********************************************************************
4323 * handle enumeration of printers at level 0
4324 ********************************************************************/
4326 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4328 const char *servername
,
4329 union spoolss_PrinterInfo
**info
,
4332 DEBUG(4,("enum_all_printers_info_0\n"));
4334 return enum_all_printers_info_level(mem_ctx
, 0, flags
, info
, count
);
4338 /********************************************************************
4339 ********************************************************************/
4341 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4343 union spoolss_PrinterInfo
**info
,
4346 DEBUG(4,("enum_all_printers_info_1\n"));
4348 return enum_all_printers_info_level(mem_ctx
, 1, flags
, info
, count
);
4351 /********************************************************************
4352 enum_all_printers_info_1_local.
4353 *********************************************************************/
4355 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4356 union spoolss_PrinterInfo
**info
,
4359 DEBUG(4,("enum_all_printers_info_1_local\n"));
4361 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4364 /********************************************************************
4365 enum_all_printers_info_1_name.
4366 *********************************************************************/
4368 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4370 union spoolss_PrinterInfo
**info
,
4373 const char *s
= name
;
4375 DEBUG(4,("enum_all_printers_info_1_name\n"));
4377 if ((name
[0] == '\\') && (name
[1] == '\\')) {
4381 if (!is_myname_or_ipaddr(s
)) {
4382 return WERR_INVALID_NAME
;
4385 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4388 /********************************************************************
4389 enum_all_printers_info_1_network.
4390 *********************************************************************/
4392 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4394 union spoolss_PrinterInfo
**info
,
4397 const char *s
= name
;
4399 DEBUG(4,("enum_all_printers_info_1_network\n"));
4401 /* If we respond to a enum_printers level 1 on our name with flags
4402 set to PRINTER_ENUM_REMOTE with a list of printers then these
4403 printers incorrectly appear in the APW browse list.
4404 Specifically the printers for the server appear at the workgroup
4405 level where all the other servers in the domain are
4406 listed. Windows responds to this call with a
4407 WERR_CAN_NOT_COMPLETE so we should do the same. */
4409 if (name
[0] == '\\' && name
[1] == '\\') {
4413 if (is_myname_or_ipaddr(s
)) {
4414 return WERR_CAN_NOT_COMPLETE
;
4417 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_NAME
, info
, count
);
4420 /********************************************************************
4421 * api_spoolss_enumprinters
4423 * called from api_spoolss_enumprinters (see this to understand)
4424 ********************************************************************/
4426 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4427 union spoolss_PrinterInfo
**info
,
4430 DEBUG(4,("enum_all_printers_info_2\n"));
4432 return enum_all_printers_info_level(mem_ctx
, 2, 0, info
, count
);
4435 /********************************************************************
4436 * handle enumeration of printers at level 1
4437 ********************************************************************/
4439 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4442 union spoolss_PrinterInfo
**info
,
4445 /* Not all the flags are equals */
4447 if (flags
& PRINTER_ENUM_LOCAL
) {
4448 return enum_all_printers_info_1_local(mem_ctx
, info
, count
);
4451 if (flags
& PRINTER_ENUM_NAME
) {
4452 return enum_all_printers_info_1_name(mem_ctx
, name
, info
, count
);
4455 if (flags
& PRINTER_ENUM_NETWORK
) {
4456 return enum_all_printers_info_1_network(mem_ctx
, name
, info
, count
);
4459 return WERR_OK
; /* NT4sp5 does that */
4462 /********************************************************************
4463 * handle enumeration of printers at level 2
4464 ********************************************************************/
4466 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4468 const char *servername
,
4469 union spoolss_PrinterInfo
**info
,
4472 if (flags
& PRINTER_ENUM_LOCAL
) {
4473 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4476 if (flags
& PRINTER_ENUM_NAME
) {
4477 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4478 return WERR_INVALID_NAME
;
4481 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4484 if (flags
& PRINTER_ENUM_REMOTE
) {
4485 return WERR_UNKNOWN_LEVEL
;
4491 /********************************************************************
4492 * handle enumeration of printers at level 4
4493 ********************************************************************/
4495 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4497 const char *servername
,
4498 union spoolss_PrinterInfo
**info
,
4501 DEBUG(4,("enum_all_printers_info_4\n"));
4503 return enum_all_printers_info_level(mem_ctx
, 4, flags
, info
, count
);
4507 /********************************************************************
4508 * handle enumeration of printers at level 5
4509 ********************************************************************/
4511 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4513 const char *servername
,
4514 union spoolss_PrinterInfo
**info
,
4517 DEBUG(4,("enum_all_printers_info_5\n"));
4519 return enum_all_printers_info_level(mem_ctx
, 5, flags
, info
, count
);
4522 /****************************************************************
4523 _spoolss_EnumPrinters
4524 ****************************************************************/
4526 WERROR
_spoolss_EnumPrinters(pipes_struct
*p
,
4527 struct spoolss_EnumPrinters
*r
)
4532 /* that's an [in out] buffer */
4534 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4535 return WERR_INVALID_PARAM
;
4538 DEBUG(4,("_spoolss_EnumPrinters\n"));
4542 *r
->out
.info
= NULL
;
4546 * flags==PRINTER_ENUM_NAME
4547 * if name=="" then enumerates all printers
4548 * if name!="" then enumerate the printer
4549 * flags==PRINTER_ENUM_REMOTE
4550 * name is NULL, enumerate printers
4551 * Level 2: name!="" enumerates printers, name can't be NULL
4552 * Level 3: doesn't exist
4553 * Level 4: does a local registry lookup
4554 * Level 5: same as Level 2
4557 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4558 W_ERROR_HAVE_NO_MEMORY(name
);
4560 switch (r
->in
.level
) {
4562 result
= enumprinters_level0(p
->mem_ctx
, r
->in
.flags
, name
,
4563 r
->out
.info
, r
->out
.count
);
4566 result
= enumprinters_level1(p
->mem_ctx
, r
->in
.flags
, name
,
4567 r
->out
.info
, r
->out
.count
);
4570 result
= enumprinters_level2(p
->mem_ctx
, r
->in
.flags
, name
,
4571 r
->out
.info
, r
->out
.count
);
4574 result
= enumprinters_level4(p
->mem_ctx
, r
->in
.flags
, name
,
4575 r
->out
.info
, r
->out
.count
);
4578 result
= enumprinters_level5(p
->mem_ctx
, r
->in
.flags
, name
,
4579 r
->out
.info
, r
->out
.count
);
4582 return WERR_UNKNOWN_LEVEL
;
4585 if (!W_ERROR_IS_OK(result
)) {
4589 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4590 spoolss_EnumPrinters
, NULL
,
4591 *r
->out
.info
, r
->in
.level
,
4593 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4594 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4596 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4599 /****************************************************************
4601 ****************************************************************/
4603 WERROR
_spoolss_GetPrinter(pipes_struct
*p
,
4604 struct spoolss_GetPrinter
*r
)
4606 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4607 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4608 WERROR result
= WERR_OK
;
4612 /* that's an [in out] buffer */
4614 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4615 return WERR_INVALID_PARAM
;
4620 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4624 result
= get_a_printer(Printer
, &ntprinter
, 2,
4625 lp_const_servicename(snum
));
4626 if (!W_ERROR_IS_OK(result
)) {
4630 switch (r
->in
.level
) {
4632 result
= construct_printer_info0(p
->mem_ctx
, ntprinter
,
4633 &r
->out
.info
->info0
, snum
);
4636 result
= construct_printer_info1(p
->mem_ctx
, ntprinter
,
4638 &r
->out
.info
->info1
, snum
);
4641 result
= construct_printer_info2(p
->mem_ctx
, ntprinter
,
4642 &r
->out
.info
->info2
, snum
);
4645 result
= construct_printer_info3(p
->mem_ctx
, ntprinter
,
4646 &r
->out
.info
->info3
, snum
);
4649 result
= construct_printer_info4(p
->mem_ctx
, ntprinter
,
4650 &r
->out
.info
->info4
, snum
);
4653 result
= construct_printer_info5(p
->mem_ctx
, ntprinter
,
4654 &r
->out
.info
->info5
, snum
);
4657 result
= construct_printer_info6(p
->mem_ctx
, ntprinter
,
4658 &r
->out
.info
->info6
, snum
);
4661 result
= construct_printer_info7(p
->mem_ctx
, Printer
,
4662 &r
->out
.info
->info7
, snum
);
4665 result
= construct_printer_info8(p
->mem_ctx
, ntprinter
,
4666 &r
->out
.info
->info8
, snum
);
4669 result
= WERR_UNKNOWN_LEVEL
;
4673 free_a_printer(&ntprinter
, 2);
4675 if (!W_ERROR_IS_OK(result
)) {
4676 TALLOC_FREE(r
->out
.info
);
4680 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
, NULL
,
4681 r
->out
.info
, r
->in
.level
);
4682 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4684 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4687 /********************************************************************
4688 ********************************************************************/
4690 static const char **string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4691 fstring
*fstring_array
,
4692 const char *cservername
)
4694 int i
, num_strings
= 0;
4695 const char **array
= NULL
;
4697 for (i
=0; fstring_array
&& fstring_array
[i
][0] != '\0'; i
++) {
4699 const char *str
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4700 cservername
, fstring_array
[i
]);
4707 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4714 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4715 &array
, &num_strings
);
4721 /********************************************************************
4722 * fill a spoolss_DriverInfo1 struct
4723 ********************************************************************/
4725 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4726 struct spoolss_DriverInfo1
*r
,
4727 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4728 const char *servername
,
4729 const char *architecture
)
4731 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4732 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4737 /********************************************************************
4738 * fill a spoolss_DriverInfo2 struct
4739 ********************************************************************/
4741 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4742 struct spoolss_DriverInfo2
*r
,
4743 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4744 const char *servername
)
4747 const char *cservername
= canon_servername(servername
);
4749 r
->version
= driver
->info_3
->cversion
;
4751 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4752 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4753 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4754 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4756 if (strlen(driver
->info_3
->driverpath
)) {
4757 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4758 cservername
, driver
->info_3
->driverpath
);
4760 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4762 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4764 if (strlen(driver
->info_3
->datafile
)) {
4765 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4766 cservername
, driver
->info_3
->datafile
);
4768 r
->data_file
= talloc_strdup(mem_ctx
, "");
4770 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4772 if (strlen(driver
->info_3
->configfile
)) {
4773 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4774 cservername
, driver
->info_3
->configfile
);
4776 r
->config_file
= talloc_strdup(mem_ctx
, "");
4778 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4783 /********************************************************************
4784 * fill a spoolss_DriverInfo3 struct
4785 ********************************************************************/
4787 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4788 struct spoolss_DriverInfo3
*r
,
4789 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4790 const char *servername
)
4792 const char *cservername
= canon_servername(servername
);
4794 r
->version
= driver
->info_3
->cversion
;
4796 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4797 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4798 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4799 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4801 if (strlen(driver
->info_3
->driverpath
)) {
4802 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4803 cservername
, driver
->info_3
->driverpath
);
4805 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4807 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4809 if (strlen(driver
->info_3
->datafile
)) {
4810 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4811 cservername
, driver
->info_3
->datafile
);
4813 r
->data_file
= talloc_strdup(mem_ctx
, "");
4815 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4817 if (strlen(driver
->info_3
->configfile
)) {
4818 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4819 cservername
, driver
->info_3
->configfile
);
4821 r
->config_file
= talloc_strdup(mem_ctx
, "");
4823 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4825 if (strlen(driver
->info_3
->helpfile
)) {
4826 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4827 cservername
, driver
->info_3
->helpfile
);
4829 r
->help_file
= talloc_strdup(mem_ctx
, "");
4831 W_ERROR_HAVE_NO_MEMORY(r
->help_file
);
4833 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
4834 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
4835 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
4836 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
4838 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4839 driver
->info_3
->dependentfiles
,
4844 /********************************************************************
4845 * fill a spoolss_DriverInfo4 struct
4846 ********************************************************************/
4848 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4849 struct spoolss_DriverInfo4
*r
,
4850 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4851 const char *servername
)
4853 const char *cservername
= canon_servername(servername
);
4855 r
->version
= driver
->info_3
->cversion
;
4857 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4858 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4859 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4860 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4862 if (strlen(driver
->info_3
->driverpath
)) {
4863 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4864 cservername
, driver
->info_3
->driverpath
);
4866 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4868 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4870 if (strlen(driver
->info_3
->datafile
)) {
4871 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4872 cservername
, driver
->info_3
->datafile
);
4874 r
->data_file
= talloc_strdup(mem_ctx
, "");
4876 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4878 if (strlen(driver
->info_3
->configfile
)) {
4879 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4880 cservername
, driver
->info_3
->configfile
);
4882 r
->config_file
= talloc_strdup(mem_ctx
, "");
4884 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4886 if (strlen(driver
->info_3
->helpfile
)) {
4887 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4888 cservername
, driver
->info_3
->helpfile
);
4890 r
->help_file
= talloc_strdup(mem_ctx
, "");
4892 W_ERROR_HAVE_NO_MEMORY(r
->help_file
);
4894 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4895 driver
->info_3
->dependentfiles
,
4899 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
4900 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
4901 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
4902 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
4904 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4911 /********************************************************************
4912 * fill a spoolss_DriverInfo5 struct
4913 ********************************************************************/
4915 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
4916 struct spoolss_DriverInfo5
*r
,
4917 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4918 const char *servername
)
4920 const char *cservername
= canon_servername(servername
);
4922 r
->version
= driver
->info_3
->cversion
;
4924 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4925 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4926 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4927 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4929 if (strlen(driver
->info_3
->driverpath
)) {
4930 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4931 cservername
, driver
->info_3
->driverpath
);
4933 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4935 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4937 if (strlen(driver
->info_3
->datafile
)) {
4938 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4939 cservername
, driver
->info_3
->datafile
);
4941 r
->data_file
= talloc_strdup(mem_ctx
, "");
4943 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4945 if (strlen(driver
->info_3
->configfile
)) {
4946 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4947 cservername
, driver
->info_3
->configfile
);
4949 r
->config_file
= talloc_strdup(mem_ctx
, "");
4951 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
4953 r
->driver_attributes
= 0;
4954 r
->config_version
= 0;
4955 r
->driver_version
= 0;
4959 /********************************************************************
4960 * fill a spoolss_DriverInfo6 struct
4961 ********************************************************************/
4963 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4964 struct spoolss_DriverInfo6
*r
,
4965 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
4966 const char *servername
)
4968 const char *cservername
= canon_servername(servername
);
4970 r
->version
= driver
->info_3
->cversion
;
4972 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
4973 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4974 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
4975 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4977 if (strlen(driver
->info_3
->driverpath
)) {
4978 r
->driver_path
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4979 cservername
, driver
->info_3
->driverpath
);
4981 r
->driver_path
= talloc_strdup(mem_ctx
, "");
4983 W_ERROR_HAVE_NO_MEMORY(r
->driver_path
);
4985 if (strlen(driver
->info_3
->datafile
)) {
4986 r
->data_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4987 cservername
, driver
->info_3
->datafile
);
4989 r
->data_file
= talloc_strdup(mem_ctx
, "");
4991 W_ERROR_HAVE_NO_MEMORY(r
->data_file
);
4993 if (strlen(driver
->info_3
->configfile
)) {
4994 r
->config_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4995 cservername
, driver
->info_3
->configfile
);
4997 r
->config_file
= talloc_strdup(mem_ctx
, "");
4999 W_ERROR_HAVE_NO_MEMORY(r
->config_file
);
5001 if (strlen(driver
->info_3
->helpfile
)) {
5002 r
->help_file
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
5003 cservername
, driver
->info_3
->helpfile
);
5005 r
->help_file
= talloc_strdup(mem_ctx
, "");
5007 W_ERROR_HAVE_NO_MEMORY(r
->help_file
);
5009 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
5010 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
5011 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
5012 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
5014 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
5015 driver
->info_3
->dependentfiles
,
5017 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
5022 r
->driver_version
= 0;
5024 r
->manufacturer_name
= talloc_strdup(mem_ctx
, "");
5025 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_name
);
5026 r
->manufacturer_url
= talloc_strdup(mem_ctx
, "");
5027 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_url
);
5028 r
->hardware_id
= talloc_strdup(mem_ctx
, "");
5029 W_ERROR_HAVE_NO_MEMORY(r
->hardware_id
);
5030 r
->provider
= talloc_strdup(mem_ctx
, "");
5031 W_ERROR_HAVE_NO_MEMORY(r
->provider
);
5036 /********************************************************************
5037 ********************************************************************/
5039 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
5040 struct spoolss_DriverFileInfo
*r
,
5041 const char *cservername
,
5042 const char *file_name
,
5043 enum spoolss_DriverFileType file_type
,
5044 uint32_t file_version
)
5046 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
5047 cservername
, file_name
);
5048 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
5049 r
->file_type
= file_type
;
5050 r
->file_version
= file_version
;
5055 /********************************************************************
5056 ********************************************************************/
5058 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
5059 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
5060 const char *cservername
,
5061 struct spoolss_DriverFileInfo
**info_p
,
5064 struct spoolss_DriverFileInfo
*info
= NULL
;
5072 if (strlen(driver
->info_3
->driverpath
)) {
5073 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5074 struct spoolss_DriverFileInfo
,
5076 W_ERROR_HAVE_NO_MEMORY(info
);
5077 result
= fill_spoolss_DriverFileInfo(info
,
5080 driver
->info_3
->driverpath
,
5081 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
5083 W_ERROR_NOT_OK_RETURN(result
);
5087 if (strlen(driver
->info_3
->configfile
)) {
5088 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5089 struct spoolss_DriverFileInfo
,
5091 W_ERROR_HAVE_NO_MEMORY(info
);
5092 result
= fill_spoolss_DriverFileInfo(info
,
5095 driver
->info_3
->configfile
,
5096 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
5098 W_ERROR_NOT_OK_RETURN(result
);
5102 if (strlen(driver
->info_3
->datafile
)) {
5103 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5104 struct spoolss_DriverFileInfo
,
5106 W_ERROR_HAVE_NO_MEMORY(info
);
5107 result
= fill_spoolss_DriverFileInfo(info
,
5110 driver
->info_3
->datafile
,
5111 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5113 W_ERROR_NOT_OK_RETURN(result
);
5117 if (strlen(driver
->info_3
->helpfile
)) {
5118 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5119 struct spoolss_DriverFileInfo
,
5121 W_ERROR_HAVE_NO_MEMORY(info
);
5122 result
= fill_spoolss_DriverFileInfo(info
,
5125 driver
->info_3
->helpfile
,
5126 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5128 W_ERROR_NOT_OK_RETURN(result
);
5132 for (i
=0; driver
->info_3
->dependentfiles
[i
][0] != '\0'; i
++) {
5133 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5134 struct spoolss_DriverFileInfo
,
5136 W_ERROR_HAVE_NO_MEMORY(info
);
5137 result
= fill_spoolss_DriverFileInfo(info
,
5140 driver
->info_3
->dependentfiles
[i
],
5141 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5143 W_ERROR_NOT_OK_RETURN(result
);
5153 /********************************************************************
5154 * fill a spoolss_DriverInfo101 sttruct
5155 ********************************************************************/
5157 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5158 struct spoolss_DriverInfo101
*r
,
5159 const NT_PRINTER_DRIVER_INFO_LEVEL
*driver
,
5160 const char *servername
)
5162 const char *cservername
= canon_servername(servername
);
5165 r
->version
= driver
->info_3
->cversion
;
5167 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->info_3
->name
);
5168 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5169 r
->architecture
= talloc_strdup(mem_ctx
, driver
->info_3
->environment
);
5170 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5172 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5176 if (!W_ERROR_IS_OK(result
)) {
5180 r
->monitor_name
= talloc_strdup(mem_ctx
, driver
->info_3
->monitorname
);
5181 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
5183 r
->default_datatype
= talloc_strdup(mem_ctx
, driver
->info_3
->defaultdatatype
);
5184 W_ERROR_HAVE_NO_MEMORY(r
->default_datatype
);
5186 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
5190 r
->driver_version
= 0;
5192 r
->manufacturer_name
= talloc_strdup(mem_ctx
, "");
5193 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_name
);
5194 r
->manufacturer_url
= talloc_strdup(mem_ctx
, "");
5195 W_ERROR_HAVE_NO_MEMORY(r
->manufacturer_url
);
5196 r
->hardware_id
= talloc_strdup(mem_ctx
, "");
5197 W_ERROR_HAVE_NO_MEMORY(r
->hardware_id
);
5198 r
->provider
= talloc_strdup(mem_ctx
, "");
5199 W_ERROR_HAVE_NO_MEMORY(r
->provider
);
5204 /********************************************************************
5205 * construct_printer_driver_info_1
5206 ********************************************************************/
5208 static WERROR
construct_printer_driver_info_1(TALLOC_CTX
*mem_ctx
,
5209 struct spoolss_DriverInfo1
*r
,
5211 const char *servername
,
5212 const char *architecture
,
5215 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5216 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5219 ZERO_STRUCT(driver
);
5221 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5222 return WERR_INVALID_PRINTER_NAME
;
5224 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5225 free_a_printer(&printer
, 2);
5226 return WERR_UNKNOWN_PRINTER_DRIVER
;
5229 result
= fill_printer_driver_info1(mem_ctx
, r
, &driver
, servername
, architecture
);
5231 free_a_printer(&printer
,2);
5236 /********************************************************************
5237 * construct_printer_driver_info_2
5238 * fill a printer_info_2 struct
5239 ********************************************************************/
5241 static WERROR
construct_printer_driver_info_2(TALLOC_CTX
*mem_ctx
,
5242 struct spoolss_DriverInfo2
*r
,
5244 const char *servername
,
5245 const char *architecture
,
5248 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5249 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5252 ZERO_STRUCT(printer
);
5253 ZERO_STRUCT(driver
);
5255 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5256 return WERR_INVALID_PRINTER_NAME
;
5258 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5259 free_a_printer(&printer
, 2);
5260 return WERR_UNKNOWN_PRINTER_DRIVER
;
5263 result
= fill_printer_driver_info2(mem_ctx
, r
, &driver
, servername
);
5265 free_a_printer(&printer
,2);
5270 /********************************************************************
5271 * construct_printer_info_3
5272 * fill a printer_info_3 struct
5273 ********************************************************************/
5275 static WERROR
construct_printer_driver_info_3(TALLOC_CTX
*mem_ctx
,
5276 struct spoolss_DriverInfo3
*r
,
5278 const char *servername
,
5279 const char *architecture
,
5282 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5283 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5285 ZERO_STRUCT(driver
);
5287 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5288 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
5289 if (!W_ERROR_IS_OK(status
))
5290 return WERR_INVALID_PRINTER_NAME
;
5292 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5293 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
5298 * I put this code in during testing. Helpful when commenting out the
5299 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5300 * as win2k always queries the driver using an infor level of 6.
5301 * I've left it in (but ifdef'd out) because I'll probably
5302 * use it in experimentation again in the future. --jerry 22/01/2002
5305 if (!W_ERROR_IS_OK(status
)) {
5307 * Is this a W2k client ?
5310 /* Yes - try again with a WinNT driver. */
5312 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5313 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status
)));
5317 if (!W_ERROR_IS_OK(status
)) {
5318 free_a_printer(&printer
,2);
5319 return WERR_UNKNOWN_PRINTER_DRIVER
;
5327 status
= fill_printer_driver_info3(mem_ctx
, r
, &driver
, servername
);
5329 free_a_printer(&printer
,2);
5334 /********************************************************************
5335 * construct_printer_info_6
5336 * fill a printer_info_6 struct
5337 ********************************************************************/
5339 static WERROR
construct_printer_driver_info_6(TALLOC_CTX
*mem_ctx
,
5340 struct spoolss_DriverInfo6
*r
,
5342 const char *servername
,
5343 const char *architecture
,
5346 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5347 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5350 ZERO_STRUCT(driver
);
5352 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5354 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5356 if (!W_ERROR_IS_OK(status
))
5357 return WERR_INVALID_PRINTER_NAME
;
5359 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5361 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5363 if (!W_ERROR_IS_OK(status
))
5366 * Is this a W2k client ?
5370 free_a_printer(&printer
,2);
5371 return WERR_UNKNOWN_PRINTER_DRIVER
;
5374 /* Yes - try again with a WinNT driver. */
5376 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5377 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status
)));
5378 if (!W_ERROR_IS_OK(status
)) {
5379 free_a_printer(&printer
,2);
5380 return WERR_UNKNOWN_PRINTER_DRIVER
;
5384 status
= fill_printer_driver_info6(mem_ctx
, r
, &driver
, servername
);
5386 free_a_printer(&printer
,2);
5387 free_a_printer_driver(driver
, 3);
5392 /********************************************************************
5393 * construct_printer_info_101
5394 * fill a printer_info_101 struct
5395 ********************************************************************/
5397 static WERROR
construct_printer_driver_info_101(TALLOC_CTX
*mem_ctx
,
5398 struct spoolss_DriverInfo101
*r
,
5400 const char *servername
,
5401 const char *architecture
,
5404 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5405 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5408 ZERO_STRUCT(driver
);
5410 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
5412 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5413 win_errstr(result
)));
5415 if (!W_ERROR_IS_OK(result
)) {
5416 return WERR_INVALID_PRINTER_NAME
;
5419 result
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
5420 architecture
, version
);
5422 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5423 win_errstr(result
)));
5425 if (!W_ERROR_IS_OK(result
)) {
5427 * Is this a W2k client ?
5431 free_a_printer(&printer
, 2);
5432 return WERR_UNKNOWN_PRINTER_DRIVER
;
5435 /* Yes - try again with a WinNT driver. */
5437 result
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
5438 architecture
, version
);
5439 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5440 win_errstr(result
)));
5441 if (!W_ERROR_IS_OK(result
)) {
5442 free_a_printer(&printer
, 2);
5443 return WERR_UNKNOWN_PRINTER_DRIVER
;
5447 result
= fill_printer_driver_info101(mem_ctx
, r
, &driver
, servername
);
5449 free_a_printer(&printer
, 2);
5450 free_a_printer_driver(driver
, 3);
5455 /****************************************************************
5456 _spoolss_GetPrinterDriver2
5457 ****************************************************************/
5459 WERROR
_spoolss_GetPrinterDriver2(pipes_struct
*p
,
5460 struct spoolss_GetPrinterDriver2
*r
)
5462 Printer_entry
*printer
;
5465 const char *servername
;
5468 /* that's an [in out] buffer */
5470 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5471 return WERR_INVALID_PARAM
;
5474 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5476 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5477 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5478 return WERR_INVALID_PRINTER_NAME
;
5482 *r
->out
.server_major_version
= 0;
5483 *r
->out
.server_minor_version
= 0;
5485 servername
= get_server_name(printer
);
5487 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5491 switch (r
->in
.level
) {
5493 result
= construct_printer_driver_info_1(p
->mem_ctx
,
5494 &r
->out
.info
->info1
,
5498 r
->in
.client_major_version
);
5501 result
= construct_printer_driver_info_2(p
->mem_ctx
,
5502 &r
->out
.info
->info2
,
5506 r
->in
.client_major_version
);
5509 result
= construct_printer_driver_info_3(p
->mem_ctx
,
5510 &r
->out
.info
->info3
,
5514 r
->in
.client_major_version
);
5517 result
= construct_printer_driver_info_6(p
->mem_ctx
,
5518 &r
->out
.info
->info6
,
5522 r
->in
.client_major_version
);
5525 result
= construct_printer_driver_info_101(p
->mem_ctx
,
5526 &r
->out
.info
->info101
,
5530 r
->in
.client_major_version
);
5533 result
= WERR_UNKNOWN_LEVEL
;
5537 if (!W_ERROR_IS_OK(result
)) {
5538 TALLOC_FREE(r
->out
.info
);
5542 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
, NULL
,
5543 r
->out
.info
, r
->in
.level
);
5544 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5546 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5550 /****************************************************************
5551 _spoolss_StartPagePrinter
5552 ****************************************************************/
5554 WERROR
_spoolss_StartPagePrinter(pipes_struct
*p
,
5555 struct spoolss_StartPagePrinter
*r
)
5557 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5560 DEBUG(3,("_spoolss_StartPagePrinter: "
5561 "Error in startpageprinter printer handle\n"));
5565 Printer
->page_started
= true;
5569 /****************************************************************
5570 _spoolss_EndPagePrinter
5571 ****************************************************************/
5573 WERROR
_spoolss_EndPagePrinter(pipes_struct
*p
,
5574 struct spoolss_EndPagePrinter
*r
)
5578 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5581 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5582 OUR_HANDLE(r
->in
.handle
)));
5586 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5589 Printer
->page_started
= false;
5590 print_job_endpage(snum
, Printer
->jobid
);
5595 /****************************************************************
5596 _spoolss_StartDocPrinter
5597 ****************************************************************/
5599 WERROR
_spoolss_StartDocPrinter(pipes_struct
*p
,
5600 struct spoolss_StartDocPrinter
*r
)
5602 struct spoolss_DocumentInfo1
*info_1
;
5604 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5607 DEBUG(2,("_spoolss_StartDocPrinter: "
5608 "Invalid handle (%s:%u:%u)\n",
5609 OUR_HANDLE(r
->in
.handle
)));
5613 if (r
->in
.level
!= 1) {
5614 return WERR_UNKNOWN_LEVEL
;
5617 info_1
= r
->in
.info
.info1
;
5620 * a nice thing with NT is it doesn't listen to what you tell it.
5621 * when asked to send _only_ RAW datas, it tries to send datas
5624 * So I add checks like in NT Server ...
5627 if (info_1
->datatype
) {
5628 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5630 return WERR_INVALID_DATATYPE
;
5634 /* get the share number of the printer */
5635 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5639 Printer
->jobid
= print_job_start(p
->server_info
, snum
,
5640 info_1
->document_name
,
5641 Printer
->nt_devmode
);
5643 /* An error occured in print_job_start() so return an appropriate
5646 if (Printer
->jobid
== -1) {
5647 return map_werror_from_unix(errno
);
5650 Printer
->document_started
= true;
5651 *r
->out
.job_id
= Printer
->jobid
;
5656 /****************************************************************
5657 _spoolss_EndDocPrinter
5658 ****************************************************************/
5660 WERROR
_spoolss_EndDocPrinter(pipes_struct
*p
,
5661 struct spoolss_EndDocPrinter
*r
)
5663 return _spoolss_enddocprinter_internal(p
, r
->in
.handle
);
5666 /****************************************************************
5667 _spoolss_WritePrinter
5668 ****************************************************************/
5670 WERROR
_spoolss_WritePrinter(pipes_struct
*p
,
5671 struct spoolss_WritePrinter
*r
)
5673 uint32_t buffer_written
;
5675 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5678 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5679 OUR_HANDLE(r
->in
.handle
)));
5680 *r
->out
.num_written
= r
->in
._data_size
;
5684 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5687 buffer_written
= (uint32_t)print_job_write(snum
, Printer
->jobid
,
5688 (const char *)r
->in
.data
.data
,
5690 (size_t)r
->in
._data_size
);
5691 if (buffer_written
== (uint32_t)-1) {
5692 *r
->out
.num_written
= 0;
5693 if (errno
== ENOSPC
)
5694 return WERR_NO_SPOOL_SPACE
;
5696 return WERR_ACCESS_DENIED
;
5699 *r
->out
.num_written
= r
->in
._data_size
;
5704 /********************************************************************
5705 * api_spoolss_getprinter
5706 * called from the spoolss dispatcher
5708 ********************************************************************/
5710 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5714 WERROR errcode
= WERR_BADFUNC
;
5715 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5718 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5719 OUR_HANDLE(handle
)));
5723 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5727 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5728 errcode
= print_queue_pause(p
->server_info
, snum
);
5730 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5731 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5732 errcode
= print_queue_resume(p
->server_info
, snum
);
5734 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5735 errcode
= print_queue_purge(p
->server_info
, snum
);
5738 return WERR_UNKNOWN_LEVEL
;
5745 /****************************************************************
5746 _spoolss_AbortPrinter
5747 * From MSDN: "Deletes printer's spool file if printer is configured
5749 ****************************************************************/
5751 WERROR
_spoolss_AbortPrinter(pipes_struct
*p
,
5752 struct spoolss_AbortPrinter
*r
)
5754 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5756 WERROR errcode
= WERR_OK
;
5759 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5760 OUR_HANDLE(r
->in
.handle
)));
5764 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5767 print_job_delete(p
->server_info
, snum
, Printer
->jobid
, &errcode
);
5772 /********************************************************************
5773 * called by spoolss_api_setprinter
5774 * when updating a printer description
5775 ********************************************************************/
5777 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5778 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5780 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5784 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5786 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5787 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5788 OUR_HANDLE(handle
)));
5790 result
= WERR_BADFID
;
5795 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5796 result
= WERR_INVALID_PARAM
;
5800 /* Check the user has permissions to change the security
5801 descriptor. By experimentation with two NT machines, the user
5802 requires Full Access to the printer to change security
5805 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5806 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5807 result
= WERR_ACCESS_DENIED
;
5811 /* NT seems to like setting the security descriptor even though
5812 nothing may have actually changed. */
5814 if ( !nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
)) {
5815 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5816 result
= WERR_BADFID
;
5820 if (DEBUGLEVEL
>= 10) {
5824 the_acl
= old_secdesc_ctr
->sd
->dacl
;
5825 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5826 PRINTERNAME(snum
), the_acl
->num_aces
));
5828 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5829 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5830 &the_acl
->aces
[i
].trustee
),
5831 the_acl
->aces
[i
].access_mask
));
5834 the_acl
= secdesc_ctr
->sd
->dacl
;
5837 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5838 PRINTERNAME(snum
), the_acl
->num_aces
));
5840 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5841 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5842 &the_acl
->aces
[i
].trustee
),
5843 the_acl
->aces
[i
].access_mask
));
5846 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5850 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5851 if (!new_secdesc_ctr
) {
5852 result
= WERR_NOMEM
;
5856 if (sec_desc_equal(new_secdesc_ctr
->sd
, old_secdesc_ctr
->sd
)) {
5861 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5868 /********************************************************************
5869 Canonicalize printer info from a client
5871 ATTN: It does not matter what we set the servername to hear
5872 since we do the necessary work in get_a_printer() to set it to
5873 the correct value based on what the client sent in the
5874 _spoolss_open_printer_ex().
5875 ********************************************************************/
5877 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5879 fstring printername
;
5882 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5883 "portname=%s drivername=%s comment=%s location=%s\n",
5884 info
->servername
, info
->printername
, info
->sharename
,
5885 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5887 /* we force some elements to "correct" values */
5888 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5889 fstrcpy(info
->sharename
, lp_servicename(snum
));
5891 /* check to see if we allow printername != sharename */
5893 if ( lp_force_printername(snum
) ) {
5894 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5895 global_myname(), info
->sharename
);
5898 /* make sure printername is in \\server\printername format */
5900 fstrcpy( printername
, info
->printername
);
5902 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5903 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5907 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5908 global_myname(), p
);
5911 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5912 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5919 /****************************************************************************
5920 ****************************************************************************/
5922 WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5924 char *cmd
= lp_addport_cmd();
5925 char *command
= NULL
;
5927 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5928 bool is_print_op
= false;
5931 return WERR_ACCESS_DENIED
;
5934 command
= talloc_asprintf(ctx
,
5935 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5941 is_print_op
= user_has_privileges( token
, &se_printop
);
5943 DEBUG(10,("Running [%s]\n", command
));
5945 /********* BEGIN SePrintOperatorPrivilege **********/
5950 ret
= smbrun(command
, NULL
);
5955 /********* END SePrintOperatorPrivilege **********/
5957 DEBUGADD(10,("returned [%d]\n", ret
));
5959 TALLOC_FREE(command
);
5962 return WERR_ACCESS_DENIED
;
5968 /****************************************************************************
5969 ****************************************************************************/
5971 bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
5973 char *cmd
= lp_addprinter_cmd();
5975 char *command
= NULL
;
5979 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5980 bool is_print_op
= false;
5981 char *remote_machine
= talloc_strdup(ctx
, "%m");
5983 if (!remote_machine
) {
5986 remote_machine
= talloc_sub_basic(ctx
,
5987 current_user_info
.smb_name
,
5988 current_user_info
.domain
,
5990 if (!remote_machine
) {
5994 command
= talloc_asprintf(ctx
,
5995 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5996 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5997 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5998 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6004 is_print_op
= user_has_privileges( token
, &se_printop
);
6006 DEBUG(10,("Running [%s]\n", command
));
6008 /********* BEGIN SePrintOperatorPrivilege **********/
6013 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6014 /* Tell everyone we updated smb.conf. */
6015 message_send_all(smbd_messaging_context(),
6016 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
6022 /********* END SePrintOperatorPrivilege **********/
6024 DEBUGADD(10,("returned [%d]\n", ret
));
6026 TALLOC_FREE(command
);
6027 TALLOC_FREE(remote_machine
);
6035 /* reload our services immediately */
6037 reload_services(false);
6041 /* Get lines and convert them back to dos-codepage */
6042 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6043 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6046 /* Set the portname to what the script says the portname should be. */
6047 /* but don't require anything to be return from the script exit a good error code */
6050 /* Set the portname to what the script says the portname should be. */
6051 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6052 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6055 TALLOC_FREE(qlines
);
6060 /********************************************************************
6061 * Called by spoolss_api_setprinter
6062 * when updating a printer description.
6063 ********************************************************************/
6065 static WERROR
update_printer(pipes_struct
*p
, struct policy_handle
*handle
,
6066 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6067 struct spoolss_DeviceMode
*devmode
)
6070 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6071 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6076 DEBUG(8,("update_printer\n"));
6081 result
= WERR_BADFID
;
6085 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6086 result
= WERR_BADFID
;
6090 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6091 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6092 result
= WERR_BADFID
;
6096 DEBUGADD(8,("Converting info_2 struct\n"));
6099 * convert_printer_info converts the incoming
6100 * info from the client and overwrites the info
6101 * just read from the tdb in the pointer 'printer'.
6104 if (!convert_printer_info(info_ctr
, printer
)) {
6105 result
= WERR_NOMEM
;
6110 /* we have a valid devmode
6111 convert it and link it*/
6113 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6114 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6115 &printer
->info_2
->devmode
)) {
6116 result
= WERR_NOMEM
;
6121 /* Do sanity check on the requested changes for Samba */
6123 if (!check_printer_ok(printer
->info_2
, snum
)) {
6124 result
= WERR_INVALID_PARAM
;
6128 /* FIXME!!! If the driver has changed we really should verify that
6129 it is installed before doing much else --jerry */
6131 /* Check calling user has permission to update printer description */
6133 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6134 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6135 result
= WERR_ACCESS_DENIED
;
6139 /* Call addprinter hook */
6140 /* Check changes to see if this is really needed */
6142 if ( *lp_addprinter_cmd()
6143 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6144 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6145 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6146 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6148 /* add_printer_hook() will call reload_services() */
6150 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
6152 result
= WERR_ACCESS_DENIED
;
6158 * When a *new* driver is bound to a printer, the drivername is used to
6159 * lookup previously saved driver initialization info, which is then
6160 * bound to the printer, simulating what happens in the Windows arch.
6162 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6164 if (!set_driver_init(printer
, 2))
6166 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6167 printer
->info_2
->drivername
));
6170 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6171 printer
->info_2
->drivername
));
6173 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6177 * flag which changes actually occured. This is a small subset of
6178 * all the possible changes. We also have to update things in the
6182 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6183 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6184 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6185 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6187 notify_printer_comment(snum
, printer
->info_2
->comment
);
6190 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6191 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6192 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6193 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6195 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6198 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6201 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6204 pname
= printer
->info_2
->printername
;
6207 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6208 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6209 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6211 notify_printer_printername( snum
, pname
);
6214 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6215 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6216 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6217 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6219 notify_printer_port(snum
, printer
->info_2
->portname
);
6222 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6223 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6224 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6225 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6227 notify_printer_location(snum
, printer
->info_2
->location
);
6230 /* here we need to update some more DsSpooler keys */
6231 /* uNCName, serverName, shortServerName */
6233 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6234 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6235 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6236 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6237 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6239 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6240 global_myname(), printer
->info_2
->sharename
);
6241 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6242 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6243 REG_SZ
, (uint8_t *)buffer
.buffer
, buffer
.uni_str_len
*2 );
6245 /* Update printer info */
6246 result
= mod_a_printer(printer
, 2);
6249 free_a_printer(&printer
, 2);
6250 free_a_printer(&old_printer
, 2);
6256 /****************************************************************************
6257 ****************************************************************************/
6258 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
,
6259 struct policy_handle
*handle
,
6260 struct spoolss_SetPrinterInfo7
*info7
)
6264 Printer_entry
*Printer
;
6266 if ( lp_security() != SEC_ADS
) {
6267 return WERR_UNKNOWN_LEVEL
;
6270 Printer
= find_printer_index_by_hnd(p
, handle
);
6272 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6277 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6280 nt_printer_publish(Printer
, snum
, info7
->action
);
6284 return WERR_UNKNOWN_LEVEL
;
6288 /****************************************************************
6290 ****************************************************************/
6292 WERROR
_spoolss_SetPrinter(pipes_struct
*p
,
6293 struct spoolss_SetPrinter
*r
)
6297 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6300 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6301 OUR_HANDLE(r
->in
.handle
)));
6305 /* check the level */
6306 switch (r
->in
.info_ctr
->level
) {
6308 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6310 result
= update_printer(p
, r
->in
.handle
,
6312 r
->in
.devmode_ctr
->devmode
);
6313 if (!W_ERROR_IS_OK(result
))
6315 if (r
->in
.secdesc_ctr
->sd
)
6316 result
= update_printer_sec(r
->in
.handle
, p
,
6320 return update_printer_sec(r
->in
.handle
, p
,
6323 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6324 r
->in
.info_ctr
->info
.info7
);
6326 return WERR_UNKNOWN_LEVEL
;
6330 /****************************************************************
6331 _spoolss_FindClosePrinterNotify
6332 ****************************************************************/
6334 WERROR
_spoolss_FindClosePrinterNotify(pipes_struct
*p
,
6335 struct spoolss_FindClosePrinterNotify
*r
)
6337 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6340 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6341 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6345 if (Printer
->notify
.client_connected
== true) {
6348 if ( Printer
->printer_type
== SPLHND_SERVER
)
6350 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6351 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
6354 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6357 Printer
->notify
.flags
=0;
6358 Printer
->notify
.options
=0;
6359 Printer
->notify
.localmachine
[0]='\0';
6360 Printer
->notify
.printerlocal
=0;
6361 TALLOC_FREE(Printer
->notify
.option
);
6362 Printer
->notify
.client_connected
= false;
6367 /****************************************************************
6369 ****************************************************************/
6371 WERROR
_spoolss_AddJob(pipes_struct
*p
,
6372 struct spoolss_AddJob
*r
)
6374 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6375 return WERR_INVALID_PARAM
;
6378 /* this is what a NT server returns for AddJob. AddJob must fail on
6379 * non-local printers */
6381 if (r
->in
.level
!= 1) {
6382 return WERR_UNKNOWN_LEVEL
;
6385 return WERR_INVALID_PARAM
;
6388 /****************************************************************************
6390 ****************************************************************************/
6392 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
6393 struct spoolss_JobInfo1
*r
,
6394 const print_queue_struct
*queue
,
6395 int position
, int snum
,
6396 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6400 t
= gmtime(&queue
->time
);
6402 r
->job_id
= queue
->job
;
6404 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6405 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6406 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6407 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6408 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6409 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6410 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6411 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6412 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6413 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6414 r
->text_status
= talloc_strdup(mem_ctx
, "");
6415 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6417 r
->status
= nt_printj_status(queue
->status
);
6418 r
->priority
= queue
->priority
;
6419 r
->position
= position
;
6420 r
->total_pages
= queue
->page_count
;
6421 r
->pages_printed
= 0; /* ??? */
6423 init_systemtime(&r
->submitted
, t
);
6428 /****************************************************************************
6430 ****************************************************************************/
6432 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6433 struct spoolss_JobInfo2
*r
,
6434 const print_queue_struct
*queue
,
6435 int position
, int snum
,
6436 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6437 struct spoolss_DeviceMode
*devmode
)
6441 t
= gmtime(&queue
->time
);
6443 r
->job_id
= queue
->job
;
6445 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6446 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6447 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6448 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6449 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6450 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6451 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6452 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6453 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6454 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6455 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6456 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6457 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6458 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6459 r
->parameters
= talloc_strdup(mem_ctx
, "");
6460 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6461 r
->driver_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
6462 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6464 r
->devmode
= devmode
;
6466 r
->text_status
= talloc_strdup(mem_ctx
, "");
6467 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6471 r
->status
= nt_printj_status(queue
->status
);
6472 r
->priority
= queue
->priority
;
6473 r
->position
= position
;
6476 r
->total_pages
= queue
->page_count
;
6477 r
->size
= queue
->size
;
6478 init_systemtime(&r
->submitted
, t
);
6480 r
->pages_printed
= 0; /* ??? */
6485 /****************************************************************************
6486 Enumjobs at level 1.
6487 ****************************************************************************/
6489 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6490 const print_queue_struct
*queue
,
6491 uint32_t num_queues
, int snum
,
6492 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6493 union spoolss_JobInfo
**info_p
,
6496 union spoolss_JobInfo
*info
;
6498 WERROR result
= WERR_OK
;
6500 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6501 W_ERROR_HAVE_NO_MEMORY(info
);
6503 *count
= num_queues
;
6505 for (i
=0; i
<*count
; i
++) {
6506 result
= fill_job_info1(info
,
6512 if (!W_ERROR_IS_OK(result
)) {
6518 if (!W_ERROR_IS_OK(result
)) {
6529 /****************************************************************************
6530 Enumjobs at level 2.
6531 ****************************************************************************/
6533 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6534 const print_queue_struct
*queue
,
6535 uint32_t num_queues
, int snum
,
6536 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6537 union spoolss_JobInfo
**info_p
,
6540 union spoolss_JobInfo
*info
;
6542 WERROR result
= WERR_OK
;
6544 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6545 W_ERROR_HAVE_NO_MEMORY(info
);
6547 *count
= num_queues
;
6549 for (i
=0; i
<*count
; i
++) {
6551 struct spoolss_DeviceMode
*devmode
;
6553 devmode
= construct_dev_mode(info
, lp_const_servicename(snum
));
6555 result
= WERR_NOMEM
;
6559 result
= fill_job_info2(info
,
6566 if (!W_ERROR_IS_OK(result
)) {
6572 if (!W_ERROR_IS_OK(result
)) {
6583 /****************************************************************
6585 ****************************************************************/
6587 WERROR
_spoolss_EnumJobs(pipes_struct
*p
,
6588 struct spoolss_EnumJobs
*r
)
6591 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6593 print_status_struct prt_status
;
6594 print_queue_struct
*queue
= NULL
;
6597 /* that's an [in out] buffer */
6599 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6600 return WERR_INVALID_PARAM
;
6603 DEBUG(4,("_spoolss_EnumJobs\n"));
6607 *r
->out
.info
= NULL
;
6609 /* lookup the printer snum and tdb entry */
6611 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6615 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6616 if (!W_ERROR_IS_OK(result
)) {
6620 count
= print_queue_status(snum
, &queue
, &prt_status
);
6621 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6622 count
, prt_status
.status
, prt_status
.message
));
6626 free_a_printer(&ntprinter
, 2);
6630 switch (r
->in
.level
) {
6632 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6633 ntprinter
, r
->out
.info
, r
->out
.count
);
6636 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6637 ntprinter
, r
->out
.info
, r
->out
.count
);
6640 result
= WERR_UNKNOWN_LEVEL
;
6645 free_a_printer(&ntprinter
, 2);
6647 if (!W_ERROR_IS_OK(result
)) {
6651 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6652 spoolss_EnumJobs
, NULL
,
6653 *r
->out
.info
, r
->in
.level
,
6655 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6656 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6658 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6661 /****************************************************************
6662 _spoolss_ScheduleJob
6663 ****************************************************************/
6665 WERROR
_spoolss_ScheduleJob(pipes_struct
*p
,
6666 struct spoolss_ScheduleJob
*r
)
6671 /****************************************************************
6673 ****************************************************************/
6675 WERROR
_spoolss_SetJob(pipes_struct
*p
,
6676 struct spoolss_SetJob
*r
)
6679 WERROR errcode
= WERR_BADFUNC
;
6681 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6685 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
6686 return WERR_INVALID_PRINTER_NAME
;
6689 switch (r
->in
.command
) {
6690 case SPOOLSS_JOB_CONTROL_CANCEL
:
6691 case SPOOLSS_JOB_CONTROL_DELETE
:
6692 if (print_job_delete(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6696 case SPOOLSS_JOB_CONTROL_PAUSE
:
6697 if (print_job_pause(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6701 case SPOOLSS_JOB_CONTROL_RESTART
:
6702 case SPOOLSS_JOB_CONTROL_RESUME
:
6703 if (print_job_resume(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6708 return WERR_UNKNOWN_LEVEL
;
6714 /****************************************************************************
6715 Enumerates all printer drivers by level.
6716 ****************************************************************************/
6718 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
6719 const char *servername
,
6720 const char *architecture
,
6722 union spoolss_DriverInfo
**info_p
,
6728 fstring
*list
= NULL
;
6729 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6730 union spoolss_DriverInfo
*info
= NULL
;
6732 WERROR result
= WERR_OK
;
6737 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6739 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6740 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6741 ndrivers
, architecture
, version
));
6743 if (ndrivers
== -1) {
6744 result
= WERR_NOMEM
;
6748 if (ndrivers
!= 0) {
6749 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6750 union spoolss_DriverInfo
,
6753 DEBUG(0,("enumprinterdrivers_level1: "
6754 "failed to enlarge driver info buffer!\n"));
6755 result
= WERR_NOMEM
;
6760 for (i
=0; i
<ndrivers
; i
++) {
6761 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6762 ZERO_STRUCT(driver
);
6763 result
= get_a_printer_driver(&driver
, 3, list
[i
],
6764 architecture
, version
);
6765 if (!W_ERROR_IS_OK(result
)) {
6771 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
6772 &driver
, servername
,
6776 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
6777 &driver
, servername
);
6780 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
6781 &driver
, servername
);
6784 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
6785 &driver
, servername
);
6788 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
6789 &driver
, servername
);
6792 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
6793 &driver
, servername
);
6796 result
= WERR_UNKNOWN_LEVEL
;
6800 if (!W_ERROR_IS_OK(result
)) {
6801 free_a_printer_driver(driver
, 3);
6804 free_a_printer_driver(driver
, 3);
6814 if (!W_ERROR_IS_OK(result
)) {
6825 /****************************************************************************
6826 Enumerates all printer drivers at level 1.
6827 ****************************************************************************/
6829 static WERROR
enumprinterdrivers_level1(TALLOC_CTX
*mem_ctx
,
6830 const char *servername
,
6831 const char *architecture
,
6832 union spoolss_DriverInfo
**info_p
,
6835 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 1,
6839 /****************************************************************************
6840 Enumerates all printer drivers at level 2.
6841 ****************************************************************************/
6843 static WERROR
enumprinterdrivers_level2(TALLOC_CTX
*mem_ctx
,
6844 const char *servername
,
6845 const char *architecture
,
6846 union spoolss_DriverInfo
**info_p
,
6849 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 2,
6853 /****************************************************************************
6854 Enumerates all printer drivers at level 3.
6855 ****************************************************************************/
6857 static WERROR
enumprinterdrivers_level3(TALLOC_CTX
*mem_ctx
,
6858 const char *servername
,
6859 const char *architecture
,
6860 union spoolss_DriverInfo
**info_p
,
6863 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 3,
6867 /****************************************************************************
6868 Enumerates all printer drivers at level 4.
6869 ****************************************************************************/
6871 static WERROR
enumprinterdrivers_level4(TALLOC_CTX
*mem_ctx
,
6872 const char *servername
,
6873 const char *architecture
,
6874 union spoolss_DriverInfo
**info_p
,
6877 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 4,
6881 /****************************************************************************
6882 Enumerates all printer drivers at level 5.
6883 ****************************************************************************/
6885 static WERROR
enumprinterdrivers_level5(TALLOC_CTX
*mem_ctx
,
6886 const char *servername
,
6887 const char *architecture
,
6888 union spoolss_DriverInfo
**info_p
,
6891 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 5,
6895 /****************************************************************************
6896 Enumerates all printer drivers at level 6.
6897 ****************************************************************************/
6899 static WERROR
enumprinterdrivers_level6(TALLOC_CTX
*mem_ctx
,
6900 const char *servername
,
6901 const char *architecture
,
6902 union spoolss_DriverInfo
**info_p
,
6905 return enumprinterdrivers_level(mem_ctx
, servername
, architecture
, 6,
6910 /****************************************************************
6911 _spoolss_EnumPrinterDrivers
6912 ****************************************************************/
6914 WERROR
_spoolss_EnumPrinterDrivers(pipes_struct
*p
,
6915 struct spoolss_EnumPrinterDrivers
*r
)
6917 const char *cservername
;
6920 /* that's an [in out] buffer */
6922 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6923 return WERR_INVALID_PARAM
;
6926 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6930 *r
->out
.info
= NULL
;
6932 cservername
= canon_servername(r
->in
.server
);
6934 if (!is_myname_or_ipaddr(cservername
)) {
6935 return WERR_UNKNOWN_PRINTER_DRIVER
;
6938 switch (r
->in
.level
) {
6940 result
= enumprinterdrivers_level1(p
->mem_ctx
, cservername
,
6942 r
->out
.info
, r
->out
.count
);
6945 result
= enumprinterdrivers_level2(p
->mem_ctx
, cservername
,
6947 r
->out
.info
, r
->out
.count
);
6950 result
= enumprinterdrivers_level3(p
->mem_ctx
, cservername
,
6952 r
->out
.info
, r
->out
.count
);
6955 result
= enumprinterdrivers_level4(p
->mem_ctx
, cservername
,
6957 r
->out
.info
, r
->out
.count
);
6960 result
= enumprinterdrivers_level5(p
->mem_ctx
, cservername
,
6962 r
->out
.info
, r
->out
.count
);
6965 result
= enumprinterdrivers_level6(p
->mem_ctx
, cservername
,
6967 r
->out
.info
, r
->out
.count
);
6970 return WERR_UNKNOWN_LEVEL
;
6973 if (!W_ERROR_IS_OK(result
)) {
6977 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6978 spoolss_EnumPrinterDrivers
, NULL
,
6979 *r
->out
.info
, r
->in
.level
,
6981 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6982 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6984 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6987 /****************************************************************************
6988 ****************************************************************************/
6990 static WERROR
fill_form_info_1(TALLOC_CTX
*mem_ctx
,
6991 struct spoolss_FormInfo1
*r
,
6992 const nt_forms_struct
*form
)
6994 r
->form_name
= talloc_strdup(mem_ctx
, form
->name
);
6995 W_ERROR_HAVE_NO_MEMORY(r
->form_name
);
6997 r
->flags
= form
->flag
;
6998 r
->size
.width
= form
->width
;
6999 r
->size
.height
= form
->length
;
7000 r
->area
.left
= form
->left
;
7001 r
->area
.top
= form
->top
;
7002 r
->area
.right
= form
->right
;
7003 r
->area
.bottom
= form
->bottom
;
7008 /****************************************************************
7009 spoolss_enumforms_level1
7010 ****************************************************************/
7012 static WERROR
spoolss_enumforms_level1(TALLOC_CTX
*mem_ctx
,
7013 const nt_forms_struct
*builtin_forms
,
7014 uint32_t num_builtin_forms
,
7015 const nt_forms_struct
*user_forms
,
7016 uint32_t num_user_forms
,
7017 union spoolss_FormInfo
**info_p
,
7020 union spoolss_FormInfo
*info
;
7021 WERROR result
= WERR_OK
;
7024 *count
= num_builtin_forms
+ num_user_forms
;
7026 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_FormInfo
, *count
);
7027 W_ERROR_HAVE_NO_MEMORY(info
);
7029 /* construct the list of form structures */
7030 for (i
=0; i
<num_builtin_forms
; i
++) {
7031 DEBUGADD(6,("Filling builtin form number [%d]\n",i
));
7032 result
= fill_form_info_1(info
, &info
[i
].info1
,
7034 if (!W_ERROR_IS_OK(result
)) {
7039 for (i
=0; i
<num_user_forms
; i
++) {
7040 DEBUGADD(6,("Filling user form number [%d]\n",i
));
7041 result
= fill_form_info_1(info
, &info
[i
+num_builtin_forms
].info1
,
7043 if (!W_ERROR_IS_OK(result
)) {
7049 if (!W_ERROR_IS_OK(result
)) {
7060 /****************************************************************
7062 ****************************************************************/
7064 WERROR
_spoolss_EnumForms(pipes_struct
*p
,
7065 struct spoolss_EnumForms
*r
)
7068 nt_forms_struct
*user_forms
= NULL
;
7069 nt_forms_struct
*builtin_forms
= NULL
;
7070 uint32_t num_user_forms
;
7071 uint32_t num_builtin_forms
;
7075 *r
->out
.info
= NULL
;
7077 /* that's an [in out] buffer */
7079 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7080 return WERR_INVALID_PARAM
;
7083 DEBUG(4,("_spoolss_EnumForms\n"));
7084 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7085 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7087 num_builtin_forms
= get_builtin_ntforms(&builtin_forms
);
7088 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms
));
7089 num_user_forms
= get_ntforms(&user_forms
);
7090 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms
));
7092 if (num_user_forms
+ num_builtin_forms
== 0) {
7093 SAFE_FREE(builtin_forms
);
7094 SAFE_FREE(user_forms
);
7095 return WERR_NO_MORE_ITEMS
;
7098 switch (r
->in
.level
) {
7100 result
= spoolss_enumforms_level1(p
->mem_ctx
,
7109 result
= WERR_UNKNOWN_LEVEL
;
7113 SAFE_FREE(user_forms
);
7114 SAFE_FREE(builtin_forms
);
7116 if (!W_ERROR_IS_OK(result
)) {
7120 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7121 spoolss_EnumForms
, NULL
,
7122 *r
->out
.info
, r
->in
.level
,
7124 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7125 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7127 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7130 /****************************************************************
7131 ****************************************************************/
7133 static WERROR
find_form_byname(const char *name
,
7134 nt_forms_struct
*form
)
7136 nt_forms_struct
*list
= NULL
;
7137 int num_forms
= 0, i
= 0;
7139 if (get_a_builtin_ntform_by_string(name
, form
)) {
7143 num_forms
= get_ntforms(&list
);
7144 DEBUGADD(5,("Number of forms [%d]\n", num_forms
));
7146 if (num_forms
== 0) {
7150 /* Check if the requested name is in the list of form structures */
7151 for (i
= 0; i
< num_forms
; i
++) {
7153 DEBUG(4,("checking form %s (want %s)\n", list
[i
].name
, name
));
7155 if (strequal(name
, list
[i
].name
)) {
7156 DEBUGADD(6,("Found form %s number [%d]\n", name
, i
));
7168 /****************************************************************
7170 ****************************************************************/
7172 WERROR
_spoolss_GetForm(pipes_struct
*p
,
7173 struct spoolss_GetForm
*r
)
7176 nt_forms_struct form
;
7178 /* that's an [in out] buffer */
7180 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7181 return WERR_INVALID_PARAM
;
7184 DEBUG(4,("_spoolss_GetForm\n"));
7185 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7186 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7188 result
= find_form_byname(r
->in
.form_name
, &form
);
7189 if (!W_ERROR_IS_OK(result
)) {
7190 TALLOC_FREE(r
->out
.info
);
7194 switch (r
->in
.level
) {
7196 result
= fill_form_info_1(p
->mem_ctx
,
7197 &r
->out
.info
->info1
,
7202 result
= WERR_UNKNOWN_LEVEL
;
7206 if (!W_ERROR_IS_OK(result
)) {
7207 TALLOC_FREE(r
->out
.info
);
7211 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
, NULL
,
7212 r
->out
.info
, r
->in
.level
);
7213 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7215 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7218 /****************************************************************************
7219 ****************************************************************************/
7221 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7222 struct spoolss_PortInfo1
*r
,
7225 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7226 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7231 /****************************************************************************
7232 TODO: This probably needs distinguish between TCP/IP and Local ports
7234 ****************************************************************************/
7236 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7237 struct spoolss_PortInfo2
*r
,
7240 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7241 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7243 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7244 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7246 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7247 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7249 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7256 /****************************************************************************
7257 wrapper around the enumer ports command
7258 ****************************************************************************/
7260 WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7262 char *cmd
= lp_enumports_cmd();
7263 char **qlines
= NULL
;
7264 char *command
= NULL
;
7272 /* if no hook then just fill in the default port */
7275 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
7278 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7279 TALLOC_FREE(qlines
);
7286 /* we have a valid enumport command */
7288 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7293 DEBUG(10,("Running [%s]\n", command
));
7294 ret
= smbrun(command
, &fd
);
7295 DEBUG(10,("Returned [%d]\n", ret
));
7296 TALLOC_FREE(command
);
7301 return WERR_ACCESS_DENIED
;
7305 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7306 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7316 /****************************************************************************
7318 ****************************************************************************/
7320 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7321 union spoolss_PortInfo
**info_p
,
7324 union spoolss_PortInfo
*info
= NULL
;
7326 WERROR result
= WERR_OK
;
7327 char **qlines
= NULL
;
7330 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7331 if (!W_ERROR_IS_OK(result
)) {
7336 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7338 DEBUG(10,("Returning WERR_NOMEM\n"));
7339 result
= WERR_NOMEM
;
7343 for (i
=0; i
<numlines
; i
++) {
7344 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7345 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7346 if (!W_ERROR_IS_OK(result
)) {
7351 TALLOC_FREE(qlines
);
7354 if (!W_ERROR_IS_OK(result
)) {
7356 TALLOC_FREE(qlines
);
7368 /****************************************************************************
7370 ****************************************************************************/
7372 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7373 union spoolss_PortInfo
**info_p
,
7376 union spoolss_PortInfo
*info
= NULL
;
7378 WERROR result
= WERR_OK
;
7379 char **qlines
= NULL
;
7382 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7383 if (!W_ERROR_IS_OK(result
)) {
7388 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7390 DEBUG(10,("Returning WERR_NOMEM\n"));
7391 result
= WERR_NOMEM
;
7395 for (i
=0; i
<numlines
; i
++) {
7396 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7397 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7398 if (!W_ERROR_IS_OK(result
)) {
7403 TALLOC_FREE(qlines
);
7406 if (!W_ERROR_IS_OK(result
)) {
7408 TALLOC_FREE(qlines
);
7420 /****************************************************************
7422 ****************************************************************/
7424 WERROR
_spoolss_EnumPorts(pipes_struct
*p
,
7425 struct spoolss_EnumPorts
*r
)
7429 /* that's an [in out] buffer */
7431 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7432 return WERR_INVALID_PARAM
;
7435 DEBUG(4,("_spoolss_EnumPorts\n"));
7439 *r
->out
.info
= NULL
;
7441 switch (r
->in
.level
) {
7443 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7447 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7451 return WERR_UNKNOWN_LEVEL
;
7454 if (!W_ERROR_IS_OK(result
)) {
7458 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7459 spoolss_EnumPorts
, NULL
,
7460 *r
->out
.info
, r
->in
.level
,
7462 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7463 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7465 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7468 /****************************************************************************
7469 ****************************************************************************/
7471 static WERROR
spoolss_addprinterex_level_2(pipes_struct
*p
,
7473 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7474 struct spoolss_DeviceMode
*devmode
,
7475 struct security_descriptor
*sec_desc
,
7476 struct spoolss_UserLevelCtr
*user_ctr
,
7477 struct policy_handle
*handle
)
7479 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7482 WERROR err
= WERR_OK
;
7484 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7485 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7489 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7490 if (!convert_printer_info(info_ctr
, printer
)) {
7491 free_a_printer(&printer
, 2);
7495 /* check to see if the printer already exists */
7497 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7498 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7499 printer
->info_2
->sharename
));
7500 free_a_printer(&printer
, 2);
7501 return WERR_PRINTER_ALREADY_EXISTS
;
7504 /* FIXME!!! smbd should check to see if the driver is installed before
7505 trying to add a printer like this --jerry */
7507 if (*lp_addprinter_cmd() ) {
7508 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7510 free_a_printer(&printer
,2);
7511 return WERR_ACCESS_DENIED
;
7514 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7515 "smb.conf parameter \"addprinter command\" is defined. This"
7516 "parameter must exist for this call to succeed\n",
7517 printer
->info_2
->sharename
));
7520 /* use our primary netbios name since get_a_printer() will convert
7521 it to what the client expects on a case by case basis */
7523 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7524 printer
->info_2
->sharename
);
7527 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7528 free_a_printer(&printer
,2);
7529 return WERR_ACCESS_DENIED
;
7532 /* you must be a printer admin to add a new printer */
7533 if (!print_access_check(p
->server_info
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7534 free_a_printer(&printer
,2);
7535 return WERR_ACCESS_DENIED
;
7539 * Do sanity check on the requested changes for Samba.
7542 if (!check_printer_ok(printer
->info_2
, snum
)) {
7543 free_a_printer(&printer
,2);
7544 return WERR_INVALID_PARAM
;
7548 * When a printer is created, the drivername bound to the printer is used
7549 * to lookup previously saved driver initialization info, which is then
7550 * bound to the new printer, simulating what happens in the Windows arch.
7555 set_driver_init(printer
, 2);
7559 /* A valid devmode was included, convert and link it
7561 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7563 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7564 &printer
->info_2
->devmode
)) {
7569 /* write the ASCII on disk */
7570 err
= mod_a_printer(printer
, 2);
7571 if (!W_ERROR_IS_OK(err
)) {
7572 free_a_printer(&printer
,2);
7576 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7577 /* Handle open failed - remove addition. */
7578 del_a_printer(printer
->info_2
->sharename
);
7579 free_a_printer(&printer
,2);
7580 ZERO_STRUCTP(handle
);
7581 return WERR_ACCESS_DENIED
;
7584 update_c_setprinter(false);
7585 free_a_printer(&printer
,2);
7590 /****************************************************************
7591 _spoolss_AddPrinterEx
7592 ****************************************************************/
7594 WERROR
_spoolss_AddPrinterEx(pipes_struct
*p
,
7595 struct spoolss_AddPrinterEx
*r
)
7597 switch (r
->in
.info_ctr
->level
) {
7599 /* we don't handle yet */
7600 /* but I know what to do ... */
7601 return WERR_UNKNOWN_LEVEL
;
7603 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7605 r
->in
.devmode_ctr
->devmode
,
7606 r
->in
.secdesc_ctr
->sd
,
7607 r
->in
.userlevel_ctr
,
7610 return WERR_UNKNOWN_LEVEL
;
7614 /****************************************************************
7615 _spoolss_AddPrinterDriver
7616 ****************************************************************/
7618 WERROR
_spoolss_AddPrinterDriver(pipes_struct
*p
,
7619 struct spoolss_AddPrinterDriver
*r
)
7621 uint32_t level
= r
->in
.info_ctr
->level
;
7622 struct spoolss_AddDriverInfoCtr
*info
= r
->in
.info_ctr
;
7623 WERROR err
= WERR_OK
;
7624 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7625 const char *driver_name
= NULL
;
7629 switch (p
->hdr_req
.opnum
) {
7630 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7631 fn
= "_spoolss_AddPrinterDriver";
7633 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7634 fn
= "_spoolss_AddPrinterDriverEx";
7637 return WERR_INVALID_PARAM
;
7642 if (level
!= 3 && level
!= 6) {
7643 /* Clever hack from Martin Zielinski <mz@seh.de>
7644 * to allow downgrade from level 8 (Vista).
7646 DEBUG(0,("%s: level %d not yet implemented\n", fn
, level
));
7647 return WERR_UNKNOWN_LEVEL
;
7650 ZERO_STRUCT(driver
);
7652 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7657 DEBUG(5,("Cleaning driver's information\n"));
7658 err
= clean_up_driver_struct(p
, driver
, level
);
7659 if (!W_ERROR_IS_OK(err
))
7662 DEBUG(5,("Moving driver to final destination\n"));
7663 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, driver
, level
,
7668 if (add_a_printer_driver(driver
, level
)!=0) {
7669 err
= WERR_ACCESS_DENIED
;
7675 driver_name
= driver
.info_3
->name
? driver
.info_3
->name
: "";
7678 driver_name
= driver
.info_6
->name
? driver
.info_6
->name
: "";
7683 * I think this is where he DrvUpgradePrinter() hook would be
7684 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7685 * server. Right now, we just need to send ourselves a message
7686 * to update each printer bound to this driver. --jerry
7689 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7690 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7695 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7696 * decide if the driver init data should be deleted. The rules are:
7697 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7698 * 2) delete init data only if there is no 2k/Xp driver
7699 * 3) always delete init data
7700 * The generalized rule is always use init data from the highest order driver.
7701 * It is necessary to follow the driver install by an initialization step to
7702 * finish off this process.
7705 version
= driver
.info_3
->cversion
;
7706 else if (level
== 6)
7707 version
= driver
.info_6
->version
;
7712 * 9x printer driver - never delete init data
7715 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7720 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7721 * there is no 2k/Xp driver init data for this driver name.
7725 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7727 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7729 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7731 if (!del_driver_init(driver_name
))
7732 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7736 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7738 free_a_printer_driver(driver1
,3);
7739 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7746 * 2k or Xp printer driver - always delete init data
7749 if (!del_driver_init(driver_name
))
7750 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7755 DEBUG(0,("%s: invalid level=%d\n", fn
, level
));
7761 free_a_printer_driver(driver
, level
);
7765 /****************************************************************
7766 _spoolss_AddPrinterDriverEx
7767 ****************************************************************/
7769 WERROR
_spoolss_AddPrinterDriverEx(pipes_struct
*p
,
7770 struct spoolss_AddPrinterDriverEx
*r
)
7772 struct spoolss_AddPrinterDriver a
;
7775 * we only support the semantics of AddPrinterDriver()
7776 * i.e. only copy files that are newer than existing ones
7779 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7780 return WERR_ACCESS_DENIED
;
7783 a
.in
.servername
= r
->in
.servername
;
7784 a
.in
.info_ctr
= r
->in
.info_ctr
;
7786 return _spoolss_AddPrinterDriver(p
, &a
);
7789 /****************************************************************************
7790 ****************************************************************************/
7792 struct _spoolss_paths
{
7798 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7800 static const struct _spoolss_paths spoolss_paths
[]= {
7801 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7802 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7805 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7806 const char *servername
,
7807 const char *environment
,
7811 const char *pservername
= NULL
;
7812 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7813 const char *short_archi
;
7817 /* environment may be empty */
7818 if (environment
&& strlen(environment
)) {
7819 long_archi
= environment
;
7822 /* servername may be empty */
7823 if (servername
&& strlen(servername
)) {
7824 pservername
= canon_servername(servername
);
7826 if (!is_myname_or_ipaddr(pservername
)) {
7827 return WERR_INVALID_PARAM
;
7831 if (!(short_archi
= get_short_archi(long_archi
))) {
7832 return WERR_INVALID_ENVIRONMENT
;
7835 switch (component
) {
7836 case SPOOLSS_PRTPROCS_PATH
:
7837 case SPOOLSS_DRIVER_PATH
:
7839 *path
= talloc_asprintf(mem_ctx
,
7842 spoolss_paths
[component
].share
,
7845 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7846 SPOOLSS_DEFAULT_SERVER_PATH
,
7847 spoolss_paths
[component
].dir
,
7852 return WERR_INVALID_PARAM
;
7862 /****************************************************************************
7863 ****************************************************************************/
7865 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7866 const char *servername
,
7867 const char *environment
,
7868 struct spoolss_DriverDirectoryInfo1
*r
)
7873 werr
= compose_spoolss_server_path(mem_ctx
,
7876 SPOOLSS_DRIVER_PATH
,
7878 if (!W_ERROR_IS_OK(werr
)) {
7882 DEBUG(4,("printer driver directory: [%s]\n", path
));
7884 r
->directory_name
= path
;
7889 /****************************************************************
7890 _spoolss_GetPrinterDriverDirectory
7891 ****************************************************************/
7893 WERROR
_spoolss_GetPrinterDriverDirectory(pipes_struct
*p
,
7894 struct spoolss_GetPrinterDriverDirectory
*r
)
7898 /* that's an [in out] buffer */
7900 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7901 return WERR_INVALID_PARAM
;
7904 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7909 /* r->in.level is ignored */
7911 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7914 &r
->out
.info
->info1
);
7915 if (!W_ERROR_IS_OK(werror
)) {
7916 TALLOC_FREE(r
->out
.info
);
7920 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
, NULL
,
7921 r
->out
.info
, r
->in
.level
);
7922 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7924 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7927 /****************************************************************
7928 _spoolss_EnumPrinterData
7929 ****************************************************************/
7931 WERROR
_spoolss_EnumPrinterData(pipes_struct
*p
,
7932 struct spoolss_EnumPrinterData
*r
)
7934 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7935 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7938 REGISTRY_VALUE
*val
= NULL
;
7939 NT_PRINTER_DATA
*p_data
;
7940 int i
, key_index
, num_values
;
7943 *r
->out
.value_needed
= 0;
7944 *r
->out
.type
= REG_NONE
;
7945 *r
->out
.data_needed
= 0;
7947 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7950 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7951 OUR_HANDLE(r
->in
.handle
)));
7955 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7959 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7960 if (!W_ERROR_IS_OK(result
)) {
7964 p_data
= printer
->info_2
->data
;
7965 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7970 * The NT machine wants to know the biggest size of value and data
7972 * cf: MSDN EnumPrinterData remark section
7975 if (!r
->in
.value_offered
&& !r
->in
.data_offered
&& (key_index
!= -1)) {
7977 uint32_t biggest_valuesize
= 0;
7978 uint32_t biggest_datasize
= 0;
7980 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7982 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
7984 for ( i
=0; i
<num_values
; i
++ )
7986 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
7988 name_length
= strlen(val
->valuename
);
7989 if ( strlen(val
->valuename
) > biggest_valuesize
)
7990 biggest_valuesize
= name_length
;
7992 if ( val
->size
> biggest_datasize
)
7993 biggest_datasize
= val
->size
;
7995 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7999 /* the value is an UNICODE string but real_value_size is the length
8000 in bytes including the trailing 0 */
8002 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
8003 *r
->out
.data_needed
= biggest_datasize
;
8005 DEBUG(6,("final values: [%d], [%d]\n",
8006 *r
->out
.value_needed
, *r
->out
.data_needed
));
8012 * the value len is wrong in NT sp3
8013 * that's the number of bytes not the number of unicode chars
8016 if (key_index
!= -1) {
8017 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
,
8023 /* out_value should default to "" or else NT4 has
8024 problems unmarshalling the response */
8026 if (r
->in
.value_offered
) {
8027 *r
->out
.value_needed
= 1;
8028 r
->out
.value_name
= talloc_strdup(r
, "");
8029 if (!r
->out
.value_name
) {
8030 result
= WERR_NOMEM
;
8034 r
->out
.value_name
= NULL
;
8035 *r
->out
.value_needed
= 0;
8038 /* the data is counted in bytes */
8040 *r
->out
.data_needed
= r
->in
.data_offered
;
8042 result
= WERR_NO_MORE_ITEMS
;
8046 * - counted in bytes in the request
8047 * - counted in UNICODE chars in the max reply
8048 * - counted in bytes in the real size
8050 * take a pause *before* coding not *during* coding
8054 if (r
->in
.value_offered
) {
8055 r
->out
.value_name
= talloc_strdup(r
, regval_name(val
));
8056 if (!r
->out
.value_name
) {
8057 result
= WERR_NOMEM
;
8060 *r
->out
.value_needed
= strlen_m(regval_name(val
));
8062 r
->out
.value_name
= NULL
;
8063 *r
->out
.value_needed
= 0;
8068 *r
->out
.type
= regval_type(val
);
8070 /* data - counted in bytes */
8072 if (r
->out
.data
&& regval_size(val
)) {
8073 memcpy(r
->out
.data
, regval_data_p(val
), regval_size(val
));
8076 *r
->out
.data_needed
= regval_size(val
);
8080 free_a_printer(&printer
, 2);
8084 /****************************************************************
8085 _spoolss_SetPrinterData
8086 ****************************************************************/
8088 WERROR
_spoolss_SetPrinterData(pipes_struct
*p
,
8089 struct spoolss_SetPrinterData
*r
)
8091 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8093 WERROR result
= WERR_OK
;
8094 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8097 DEBUG(5,("_spoolss_SetPrinterData\n"));
8100 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8101 OUR_HANDLE(r
->in
.handle
)));
8105 if (Printer
->printer_type
== SPLHND_SERVER
) {
8106 DEBUG(10,("_spoolss_SetPrinterData: "
8107 "Not implemented for server handles yet\n"));
8108 return WERR_INVALID_PARAM
;
8111 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8116 * Access check : NT returns "access denied" if you make a
8117 * SetPrinterData call without the necessary privildge.
8118 * we were originally returning OK if nothing changed
8119 * which made Win2k issue **a lot** of SetPrinterData
8120 * when connecting to a printer --jerry
8123 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8124 DEBUG(3,("_spoolss_SetPrinterData: "
8125 "change denied by handle access permissions\n"));
8126 result
= WERR_ACCESS_DENIED
;
8130 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8131 if (!W_ERROR_IS_OK(result
)) {
8135 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
8136 r
->in
.type
, &r
->in
.data
);
8137 if (!W_ERROR_IS_OK(result
)) {
8142 * When client side code sets a magic printer data key, detect it and save
8143 * the current printer data and the magic key's data (its the DEVMODE) for
8144 * future printer/driver initializations.
8146 if ((r
->in
.type
== REG_BINARY
) && strequal(r
->in
.value_name
, PHANTOM_DEVMODE_KEY
)) {
8147 /* Set devmode and printer initialization info */
8148 result
= save_driver_init(printer
, 2, blob
.data
, blob
.length
);
8150 srv_spoolss_reset_printerdata(printer
->info_2
->drivername
);
8155 result
= set_printer_dataex(printer
, SPOOL_PRINTERDATA_KEY
,
8156 r
->in
.value_name
, r
->in
.type
,
8157 blob
.data
, blob
.length
);
8158 if (W_ERROR_IS_OK(result
)) {
8159 result
= mod_a_printer(printer
, 2);
8163 free_a_printer(&printer
, 2);
8168 /****************************************************************
8169 _spoolss_ResetPrinter
8170 ****************************************************************/
8172 WERROR
_spoolss_ResetPrinter(pipes_struct
*p
,
8173 struct spoolss_ResetPrinter
*r
)
8175 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8178 DEBUG(5,("_spoolss_ResetPrinter\n"));
8181 * All we do is to check to see if the handle and queue is valid.
8182 * This call really doesn't mean anything to us because we only
8183 * support RAW printing. --jerry
8187 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8188 OUR_HANDLE(r
->in
.handle
)));
8192 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8196 /* blindly return success */
8200 /****************************************************************
8201 _spoolss_DeletePrinterData
8202 ****************************************************************/
8204 WERROR
_spoolss_DeletePrinterData(pipes_struct
*p
,
8205 struct spoolss_DeletePrinterData
*r
)
8207 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8209 WERROR status
= WERR_OK
;
8210 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8212 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8215 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8216 OUR_HANDLE(r
->in
.handle
)));
8220 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8223 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8224 DEBUG(3, ("_spoolss_DeletePrinterData: "
8225 "printer properties change denied by handle\n"));
8226 return WERR_ACCESS_DENIED
;
8229 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8230 if (!W_ERROR_IS_OK(status
))
8233 if (!r
->in
.value_name
) {
8234 free_a_printer(&printer
, 2);
8238 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
,
8241 if ( W_ERROR_IS_OK(status
) )
8242 mod_a_printer( printer
, 2 );
8244 free_a_printer(&printer
, 2);
8249 /****************************************************************
8251 ****************************************************************/
8253 WERROR
_spoolss_AddForm(pipes_struct
*p
,
8254 struct spoolss_AddForm
*r
)
8256 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8257 nt_forms_struct tmpForm
;
8259 WERROR status
= WERR_OK
;
8260 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8261 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8264 nt_forms_struct
*list
=NULL
;
8265 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8267 DEBUG(5,("_spoolss_AddForm\n"));
8270 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8271 OUR_HANDLE(r
->in
.handle
)));
8276 /* forms can be added on printer of on the print server handle */
8278 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8280 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8283 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8284 if (!W_ERROR_IS_OK(status
))
8288 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8289 and not a printer admin, then fail */
8291 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8292 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8293 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8295 p
->server_info
->ptok
,
8296 lp_printer_admin(snum
))) {
8297 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8298 return WERR_ACCESS_DENIED
;
8301 /* can't add if builtin */
8303 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8304 status
= WERR_FILE_EXISTS
;
8308 count
= get_ntforms(&list
);
8310 if(!add_a_form(&list
, form
, &count
)) {
8311 status
= WERR_NOMEM
;
8316 write_ntforms(&list
, count
);
8320 * ChangeID must always be set if this is a printer
8323 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8324 status
= mod_a_printer(printer
, 2);
8328 free_a_printer(&printer
, 2);
8334 /****************************************************************
8336 ****************************************************************/
8338 WERROR
_spoolss_DeleteForm(pipes_struct
*p
,
8339 struct spoolss_DeleteForm
*r
)
8341 const char *form_name
= r
->in
.form_name
;
8342 nt_forms_struct tmpForm
;
8344 nt_forms_struct
*list
=NULL
;
8345 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8347 WERROR status
= WERR_OK
;
8348 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8349 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8352 DEBUG(5,("_spoolss_DeleteForm\n"));
8355 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8356 OUR_HANDLE(r
->in
.handle
)));
8360 /* forms can be deleted on printer of on the print server handle */
8362 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8364 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8367 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8368 if (!W_ERROR_IS_OK(status
))
8372 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8373 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8374 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8376 p
->server_info
->ptok
,
8377 lp_printer_admin(snum
))) {
8378 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8379 return WERR_ACCESS_DENIED
;
8383 /* can't delete if builtin */
8385 if (get_a_builtin_ntform_by_string(form_name
,&tmpForm
)) {
8386 status
= WERR_INVALID_PARAM
;
8390 count
= get_ntforms(&list
);
8393 ret
= delete_a_form(&list
, form_name
, &count
, &status
);
8400 * ChangeID must always be set if this is a printer
8403 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8404 status
= mod_a_printer(printer
, 2);
8408 free_a_printer(&printer
, 2);
8414 /****************************************************************
8416 ****************************************************************/
8418 WERROR
_spoolss_SetForm(pipes_struct
*p
,
8419 struct spoolss_SetForm
*r
)
8421 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8422 nt_forms_struct tmpForm
;
8424 WERROR status
= WERR_OK
;
8425 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8426 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8429 nt_forms_struct
*list
=NULL
;
8430 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8432 DEBUG(5,("_spoolss_SetForm\n"));
8435 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8436 OUR_HANDLE(r
->in
.handle
)));
8440 /* forms can be modified on printer of on the print server handle */
8442 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8444 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8447 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8448 if (!W_ERROR_IS_OK(status
))
8452 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8453 and not a printer admin, then fail */
8455 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8456 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8457 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8459 p
->server_info
->ptok
,
8460 lp_printer_admin(snum
))) {
8461 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8462 return WERR_ACCESS_DENIED
;
8465 /* can't set if builtin */
8466 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8467 status
= WERR_INVALID_PARAM
;
8471 count
= get_ntforms(&list
);
8472 update_a_form(&list
, form
, count
);
8474 write_ntforms(&list
, count
);
8478 * ChangeID must always be set if this is a printer
8481 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8482 status
= mod_a_printer(printer
, 2);
8487 free_a_printer(&printer
, 2);
8493 /****************************************************************************
8494 fill_print_processor1
8495 ****************************************************************************/
8497 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8498 struct spoolss_PrintProcessorInfo1
*r
,
8499 const char *print_processor_name
)
8501 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8502 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8507 /****************************************************************************
8508 enumprintprocessors level 1.
8509 ****************************************************************************/
8511 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8512 union spoolss_PrintProcessorInfo
**info_p
,
8515 union spoolss_PrintProcessorInfo
*info
;
8518 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8519 W_ERROR_HAVE_NO_MEMORY(info
);
8523 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8524 if (!W_ERROR_IS_OK(result
)) {
8529 if (!W_ERROR_IS_OK(result
)) {
8540 /****************************************************************
8541 _spoolss_EnumPrintProcessors
8542 ****************************************************************/
8544 WERROR
_spoolss_EnumPrintProcessors(pipes_struct
*p
,
8545 struct spoolss_EnumPrintProcessors
*r
)
8549 /* that's an [in out] buffer */
8551 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8552 return WERR_INVALID_PARAM
;
8555 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8558 * Enumerate the print processors ...
8560 * Just reply with "winprint", to keep NT happy
8561 * and I can use my nice printer checker.
8566 *r
->out
.info
= NULL
;
8568 switch (r
->in
.level
) {
8570 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8574 return WERR_UNKNOWN_LEVEL
;
8577 if (!W_ERROR_IS_OK(result
)) {
8581 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8582 spoolss_EnumPrintProcessors
, NULL
,
8583 *r
->out
.info
, r
->in
.level
,
8585 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8586 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8588 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8591 /****************************************************************************
8592 fill_printprocdatatype1
8593 ****************************************************************************/
8595 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8596 struct spoolss_PrintProcDataTypesInfo1
*r
,
8597 const char *name_array
)
8599 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8600 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8605 /****************************************************************************
8606 enumprintprocdatatypes level 1.
8607 ****************************************************************************/
8609 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8610 union spoolss_PrintProcDataTypesInfo
**info_p
,
8614 union spoolss_PrintProcDataTypesInfo
*info
;
8616 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8617 W_ERROR_HAVE_NO_MEMORY(info
);
8621 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8622 if (!W_ERROR_IS_OK(result
)) {
8627 if (!W_ERROR_IS_OK(result
)) {
8638 /****************************************************************
8639 _spoolss_EnumPrintProcDataTypes
8640 ****************************************************************/
8642 WERROR
_spoolss_EnumPrintProcDataTypes(pipes_struct
*p
,
8643 struct spoolss_EnumPrintProcDataTypes
*r
)
8647 /* that's an [in out] buffer */
8649 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8650 return WERR_INVALID_PARAM
;
8653 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8657 *r
->out
.info
= NULL
;
8659 switch (r
->in
.level
) {
8661 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8665 return WERR_UNKNOWN_LEVEL
;
8668 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8669 spoolss_EnumPrintProcDataTypes
, NULL
,
8670 *r
->out
.info
, r
->in
.level
,
8672 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8673 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8675 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8678 /****************************************************************************
8680 ****************************************************************************/
8682 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8683 struct spoolss_MonitorInfo1
*r
,
8684 const char *monitor_name
)
8686 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8687 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8692 /****************************************************************************
8694 ****************************************************************************/
8696 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8697 struct spoolss_MonitorInfo2
*r
,
8698 const char *monitor_name
,
8699 const char *environment
,
8700 const char *dll_name
)
8702 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8703 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8704 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8705 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8706 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8707 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8712 /****************************************************************************
8713 enumprintmonitors level 1.
8714 ****************************************************************************/
8716 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8717 union spoolss_MonitorInfo
**info_p
,
8720 union spoolss_MonitorInfo
*info
;
8721 WERROR result
= WERR_OK
;
8723 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8724 W_ERROR_HAVE_NO_MEMORY(info
);
8728 result
= fill_monitor_1(info
, &info
[0].info1
,
8730 if (!W_ERROR_IS_OK(result
)) {
8734 result
= fill_monitor_1(info
, &info
[1].info1
,
8736 if (!W_ERROR_IS_OK(result
)) {
8741 if (!W_ERROR_IS_OK(result
)) {
8752 /****************************************************************************
8753 enumprintmonitors level 2.
8754 ****************************************************************************/
8756 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8757 union spoolss_MonitorInfo
**info_p
,
8760 union spoolss_MonitorInfo
*info
;
8761 WERROR result
= WERR_OK
;
8763 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8764 W_ERROR_HAVE_NO_MEMORY(info
);
8768 result
= fill_monitor_2(info
, &info
[0].info2
,
8770 "Windows NT X86", /* FIXME */
8772 if (!W_ERROR_IS_OK(result
)) {
8776 result
= fill_monitor_2(info
, &info
[1].info2
,
8778 "Windows NT X86", /* FIXME */
8780 if (!W_ERROR_IS_OK(result
)) {
8785 if (!W_ERROR_IS_OK(result
)) {
8796 /****************************************************************
8797 _spoolss_EnumMonitors
8798 ****************************************************************/
8800 WERROR
_spoolss_EnumMonitors(pipes_struct
*p
,
8801 struct spoolss_EnumMonitors
*r
)
8805 /* that's an [in out] buffer */
8807 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8808 return WERR_INVALID_PARAM
;
8811 DEBUG(5,("_spoolss_EnumMonitors\n"));
8814 * Enumerate the print monitors ...
8816 * Just reply with "Local Port", to keep NT happy
8817 * and I can use my nice printer checker.
8822 *r
->out
.info
= NULL
;
8824 switch (r
->in
.level
) {
8826 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8830 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8834 return WERR_UNKNOWN_LEVEL
;
8837 if (!W_ERROR_IS_OK(result
)) {
8841 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8842 spoolss_EnumMonitors
, NULL
,
8843 *r
->out
.info
, r
->in
.level
,
8845 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8846 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8848 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8851 /****************************************************************************
8852 ****************************************************************************/
8854 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8855 const print_queue_struct
*queue
,
8856 int count
, int snum
,
8857 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8859 struct spoolss_JobInfo1
*r
)
8864 for (i
=0; i
<count
&& found
== false; i
++) {
8865 if (queue
[i
].job
== (int)jobid
) {
8870 if (found
== false) {
8871 /* NT treats not found as bad param... yet another bad choice */
8872 return WERR_INVALID_PARAM
;
8875 return fill_job_info1(mem_ctx
,
8883 /****************************************************************************
8884 ****************************************************************************/
8886 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8887 const print_queue_struct
*queue
,
8888 int count
, int snum
,
8889 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8891 struct spoolss_JobInfo2
*r
)
8895 struct spoolss_DeviceMode
*devmode
;
8896 NT_DEVICEMODE
*nt_devmode
;
8899 for (i
=0; i
<count
&& found
== false; i
++) {
8900 if (queue
[i
].job
== (int)jobid
) {
8905 if (found
== false) {
8906 /* NT treats not found as bad param... yet another bad
8908 return WERR_INVALID_PARAM
;
8912 * if the print job does not have a DEVMODE associated with it,
8913 * just use the one for the printer. A NULL devicemode is not
8914 * a failure condition
8917 nt_devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8919 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
8920 W_ERROR_HAVE_NO_MEMORY(devmode
);
8921 result
= convert_nt_devicemode(devmode
, devmode
, nt_devmode
);
8922 if (!W_ERROR_IS_OK(result
)) {
8926 devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
8927 W_ERROR_HAVE_NO_MEMORY(devmode
);
8930 return fill_job_info2(mem_ctx
,
8939 /****************************************************************
8941 ****************************************************************/
8943 WERROR
_spoolss_GetJob(pipes_struct
*p
,
8944 struct spoolss_GetJob
*r
)
8946 WERROR result
= WERR_OK
;
8947 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8950 print_queue_struct
*queue
= NULL
;
8951 print_status_struct prt_status
;
8953 /* that's an [in out] buffer */
8955 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8956 return WERR_INVALID_PARAM
;
8959 DEBUG(5,("_spoolss_GetJob\n"));
8963 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8967 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8968 if (!W_ERROR_IS_OK(result
)) {
8972 count
= print_queue_status(snum
, &queue
, &prt_status
);
8974 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8975 count
, prt_status
.status
, prt_status
.message
));
8977 switch (r
->in
.level
) {
8979 result
= getjob_level_1(p
->mem_ctx
,
8980 queue
, count
, snum
, ntprinter
,
8981 r
->in
.job_id
, &r
->out
.info
->info1
);
8984 result
= getjob_level_2(p
->mem_ctx
,
8985 queue
, count
, snum
, ntprinter
,
8986 r
->in
.job_id
, &r
->out
.info
->info2
);
8989 result
= WERR_UNKNOWN_LEVEL
;
8994 free_a_printer(&ntprinter
, 2);
8996 if (!W_ERROR_IS_OK(result
)) {
8997 TALLOC_FREE(r
->out
.info
);
9001 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, NULL
,
9002 r
->out
.info
, r
->in
.level
);
9003 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9005 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9008 /****************************************************************
9009 _spoolss_GetPrinterDataEx
9011 From MSDN documentation of GetPrinterDataEx: pass request
9012 to GetPrinterData if key is "PrinterDriverData".
9013 ****************************************************************/
9015 WERROR
_spoolss_GetPrinterDataEx(pipes_struct
*p
,
9016 struct spoolss_GetPrinterDataEx
*r
)
9019 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9020 REGISTRY_VALUE
*val
= NULL
;
9021 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9023 WERROR result
= WERR_OK
;
9025 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9027 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9028 r
->in
.key_name
, r
->in
.value_name
));
9030 /* in case of problem, return some default values */
9033 *r
->out
.type
= REG_NONE
;
9036 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9037 OUR_HANDLE(r
->in
.handle
)));
9038 result
= WERR_BADFID
;
9042 /* Is the handle to a printer or to the server? */
9044 if (Printer
->printer_type
== SPLHND_SERVER
) {
9045 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9046 "Not implemented for server handles yet\n"));
9047 result
= WERR_INVALID_PARAM
;
9051 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9055 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9056 if (!W_ERROR_IS_OK(result
)) {
9060 /* check to see if the keyname is valid */
9061 if (!strlen(r
->in
.key_name
)) {
9062 result
= WERR_INVALID_PARAM
;
9066 if (lookup_printerkey(printer
->info_2
->data
, r
->in
.key_name
) == -1) {
9067 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9068 "Invalid keyname [%s]\n", r
->in
.key_name
));
9069 result
= WERR_BADFILE
;
9073 /* When given a new keyname, we should just create it */
9075 val
= get_printer_data(printer
->info_2
,
9076 r
->in
.key_name
, r
->in
.value_name
);
9078 result
= WERR_BADFILE
;
9082 *r
->out
.needed
= regval_size(val
);
9084 if (*r
->out
.needed
> r
->in
.offered
) {
9085 result
= WERR_MORE_DATA
;
9089 *r
->out
.type
= regval_type(val
);
9091 memcpy(r
->out
.buffer
, regval_data_p(val
), regval_size(val
));
9095 free_a_printer(&printer
, 2);
9101 /****************************************************************
9102 _spoolss_SetPrinterDataEx
9103 ****************************************************************/
9105 WERROR
_spoolss_SetPrinterDataEx(pipes_struct
*p
,
9106 struct spoolss_SetPrinterDataEx
*r
)
9108 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9110 WERROR result
= WERR_OK
;
9111 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9114 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9116 /* From MSDN documentation of SetPrinterDataEx: pass request to
9117 SetPrinterData if key is "PrinterDriverData" */
9120 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9121 OUR_HANDLE(r
->in
.handle
)));
9125 if (Printer
->printer_type
== SPLHND_SERVER
) {
9126 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9127 "Not implemented for server handles yet\n"));
9128 return WERR_INVALID_PARAM
;
9131 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9136 * Access check : NT returns "access denied" if you make a
9137 * SetPrinterData call without the necessary privildge.
9138 * we were originally returning OK if nothing changed
9139 * which made Win2k issue **a lot** of SetPrinterData
9140 * when connecting to a printer --jerry
9143 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9144 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9145 "change denied by handle access permissions\n"));
9146 return WERR_ACCESS_DENIED
;
9149 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9150 if (!W_ERROR_IS_OK(result
)) {
9154 /* check for OID in valuename */
9156 oid_string
= strchr(r
->in
.value_name
, ',');
9162 /* save the registry data */
9164 result
= set_printer_dataex(printer
, r
->in
.key_name
, r
->in
.value_name
,
9165 r
->in
.type
, r
->in
.buffer
, r
->in
.offered
);
9167 if (W_ERROR_IS_OK(result
)) {
9168 /* save the OID if one was specified */
9170 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
9171 r
->in
.key_name
, SPOOL_OID_KEY
);
9173 result
= WERR_NOMEM
;
9178 * I'm not checking the status here on purpose. Don't know
9179 * if this is right, but I'm returning the status from the
9180 * previous set_printer_dataex() call. I have no idea if
9181 * this is right. --jerry
9184 set_printer_dataex(printer
, str
, r
->in
.value_name
,
9185 REG_SZ
, (uint8_t *)oid_string
,
9186 strlen(oid_string
)+1);
9189 result
= mod_a_printer(printer
, 2);
9193 free_a_printer(&printer
, 2);
9198 /****************************************************************
9199 _spoolss_DeletePrinterDataEx
9200 ****************************************************************/
9202 WERROR
_spoolss_DeletePrinterDataEx(pipes_struct
*p
,
9203 struct spoolss_DeletePrinterDataEx
*r
)
9205 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9207 WERROR status
= WERR_OK
;
9208 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9210 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9213 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9214 "Invalid handle (%s:%u:%u).\n",
9215 OUR_HANDLE(r
->in
.handle
)));
9219 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
9222 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9223 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9224 "printer properties change denied by handle\n"));
9225 return WERR_ACCESS_DENIED
;
9228 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9232 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9233 if (!W_ERROR_IS_OK(status
))
9236 status
= delete_printer_dataex( printer
, r
->in
.key_name
, r
->in
.value_name
);
9238 if ( W_ERROR_IS_OK(status
) )
9239 mod_a_printer( printer
, 2 );
9241 free_a_printer(&printer
, 2);
9246 /****************************************************************
9247 _spoolss_EnumPrinterKey
9248 ****************************************************************/
9250 WERROR
_spoolss_EnumPrinterKey(pipes_struct
*p
,
9251 struct spoolss_EnumPrinterKey
*r
)
9253 fstring
*keynames
= NULL
;
9255 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9256 NT_PRINTER_DATA
*data
;
9257 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9259 WERROR result
= WERR_BADFILE
;
9261 const char **array
= NULL
;
9264 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9267 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9268 OUR_HANDLE(r
->in
.handle
)));
9272 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9276 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9277 if (!W_ERROR_IS_OK(result
)) {
9281 /* get the list of subkey names */
9283 data
= printer
->info_2
->data
;
9285 num_keys
= get_printer_subkeys(data
, r
->in
.key_name
, &keynames
);
9286 if (num_keys
== -1) {
9287 result
= WERR_BADFILE
;
9291 array
= talloc_zero_array(r
->out
.key_buffer
, const char *, num_keys
+ 1);
9293 result
= WERR_NOMEM
;
9297 for (i
=0; i
< num_keys
; i
++) {
9299 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9302 array
[i
] = talloc_strdup(array
, keynames
[i
]);
9304 result
= WERR_NOMEM
;
9309 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9310 result
= WERR_NOMEM
;
9314 *r
->out
.needed
= blob
.length
;
9316 if (r
->in
.offered
< *r
->out
.needed
) {
9317 result
= WERR_MORE_DATA
;
9320 r
->out
.key_buffer
->string
= array
;
9324 if (!W_ERROR_IS_OK(result
)) {
9326 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9331 free_a_printer(&printer
, 2);
9332 SAFE_FREE(keynames
);
9337 /****************************************************************
9338 _spoolss_DeletePrinterKey
9339 ****************************************************************/
9341 WERROR
_spoolss_DeletePrinterKey(pipes_struct
*p
,
9342 struct spoolss_DeletePrinterKey
*r
)
9344 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9345 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9349 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9352 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9353 OUR_HANDLE(r
->in
.handle
)));
9357 /* if keyname == NULL, return error */
9359 if ( !r
->in
.key_name
)
9360 return WERR_INVALID_PARAM
;
9362 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
9365 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9366 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9367 "printer properties change denied by handle\n"));
9368 return WERR_ACCESS_DENIED
;
9371 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9372 if (!W_ERROR_IS_OK(status
))
9375 /* delete the key and all subneys */
9377 status
= delete_all_printer_data( printer
->info_2
, r
->in
.key_name
);
9379 if ( W_ERROR_IS_OK(status
) )
9380 status
= mod_a_printer(printer
, 2);
9382 free_a_printer( &printer
, 2 );
9387 /****************************************************************
9388 ****************************************************************/
9390 static WERROR
registry_value_to_printer_enum_value(TALLOC_CTX
*mem_ctx
,
9392 struct spoolss_PrinterEnumValues
*r
)
9396 r
->data
= TALLOC_ZERO_P(mem_ctx
, union spoolss_PrinterData
);
9397 W_ERROR_HAVE_NO_MEMORY(r
->data
);
9399 r
->value_name
= talloc_strdup(mem_ctx
, regval_name(v
));
9400 W_ERROR_HAVE_NO_MEMORY(r
->value_name
);
9402 r
->type
= regval_type(v
);
9403 r
->data_length
= regval_size(v
);
9405 if (r
->data_length
) {
9406 DATA_BLOB blob
= data_blob_const(regval_data_p(v
),
9408 result
= pull_spoolss_PrinterData(mem_ctx
, &blob
,
9411 if (!W_ERROR_IS_OK(result
)) {
9419 /****************************************************************
9420 _spoolss_EnumPrinterDataEx
9421 ****************************************************************/
9423 WERROR
_spoolss_EnumPrinterDataEx(pipes_struct
*p
,
9424 struct spoolss_EnumPrinterDataEx
*r
)
9427 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9428 struct spoolss_PrinterEnumValues
*info
= NULL
;
9429 NT_PRINTER_DATA
*p_data
;
9430 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9436 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9440 *r
->out
.info
= NULL
;
9443 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9444 OUR_HANDLE(r
->in
.handle
)));
9449 * first check for a keyname of NULL or "". Win2k seems to send
9450 * this a lot and we should send back WERR_INVALID_PARAM
9451 * no need to spend time looking up the printer in this case.
9455 if (!strlen(r
->in
.key_name
)) {
9456 result
= WERR_INVALID_PARAM
;
9460 /* get the printer off of disk */
9462 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9466 ZERO_STRUCT(printer
);
9467 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9468 if (!W_ERROR_IS_OK(result
)) {
9472 /* now look for a match on the key name */
9474 p_data
= printer
->info_2
->data
;
9476 key_index
= lookup_printerkey(p_data
, r
->in
.key_name
);
9477 if (key_index
== -1) {
9478 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9480 result
= WERR_INVALID_PARAM
;
9484 /* allocate the memory for the array of pointers -- if necessary */
9486 count
= regval_ctr_numvals(p_data
->keys
[key_index
].values
);
9488 result
= WERR_OK
; /* ??? */
9492 info
= TALLOC_ZERO_ARRAY(p
->mem_ctx
,
9493 struct spoolss_PrinterEnumValues
,
9496 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9497 result
= WERR_NOMEM
;
9502 * loop through all params and build the array to pass
9503 * back to the client
9506 for (i
=0; i
< count
; i
++) {
9508 REGISTRY_VALUE
*val
;
9510 /* lookup the registry value */
9512 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
, i
);
9514 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
)));
9518 result
= registry_value_to_printer_enum_value(info
, val
, &info
[i
]);
9519 if (!W_ERROR_IS_OK(result
)) {
9524 #if 0 /* FIXME - gd */
9525 /* housekeeping information in the reply */
9527 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9528 * the hand marshalled container size is a multiple
9529 * of 4 bytes for RPC alignment.
9533 needed
+= 4-(needed
% 4);
9536 *r
->out
.count
= count
;
9537 *r
->out
.info
= info
;
9542 free_a_printer(&printer
, 2);
9545 if (!W_ERROR_IS_OK(result
)) {
9549 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9550 spoolss_EnumPrinterDataEx
, NULL
,
9553 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9554 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9556 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9559 /****************************************************************************
9560 ****************************************************************************/
9562 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9563 const char *servername
,
9564 const char *environment
,
9565 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9570 werr
= compose_spoolss_server_path(mem_ctx
,
9573 SPOOLSS_PRTPROCS_PATH
,
9575 if (!W_ERROR_IS_OK(werr
)) {
9579 DEBUG(4,("print processor directory: [%s]\n", path
));
9581 r
->directory_name
= path
;
9586 /****************************************************************
9587 _spoolss_GetPrintProcessorDirectory
9588 ****************************************************************/
9590 WERROR
_spoolss_GetPrintProcessorDirectory(pipes_struct
*p
,
9591 struct spoolss_GetPrintProcessorDirectory
*r
)
9595 /* that's an [in out] buffer */
9597 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9598 return WERR_INVALID_PARAM
;
9601 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9606 /* r->in.level is ignored */
9608 /* We always should reply with a local print processor directory so that
9609 * users are not forced to have a [prnproc$] share on the Samba spoolss
9610 * server - Guenther */
9612 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9613 NULL
, /* r->in.server */
9615 &r
->out
.info
->info1
);
9616 if (!W_ERROR_IS_OK(result
)) {
9617 TALLOC_FREE(r
->out
.info
);
9621 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
, NULL
,
9622 r
->out
.info
, r
->in
.level
);
9623 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9625 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9628 /*******************************************************************
9629 ********************************************************************/
9631 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9632 const char *dllname
)
9634 enum ndr_err_code ndr_err
;
9635 struct spoolss_MonitorUi ui
;
9637 ui
.dll_name
= dllname
;
9639 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, NULL
, &ui
,
9640 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9641 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9642 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9644 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9647 /*******************************************************************
9648 Streams the monitor UI DLL name in UNICODE
9649 *******************************************************************/
9651 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9652 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9653 DATA_BLOB
*out
, uint32_t *needed
)
9655 const char *dllname
= "tcpmonui.dll";
9657 *needed
= (strlen(dllname
)+1) * 2;
9659 if (out
->length
< *needed
) {
9660 return WERR_INSUFFICIENT_BUFFER
;
9663 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9670 /*******************************************************************
9671 ********************************************************************/
9673 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9674 struct spoolss_PortData1
*port1
,
9675 const DATA_BLOB
*buf
)
9677 enum ndr_err_code ndr_err
;
9678 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, NULL
, port1
,
9679 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9680 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9681 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9683 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9686 /*******************************************************************
9687 ********************************************************************/
9689 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9690 struct spoolss_PortData2
*port2
,
9691 const DATA_BLOB
*buf
)
9693 enum ndr_err_code ndr_err
;
9694 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, NULL
, port2
,
9695 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9696 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9697 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9699 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9702 /*******************************************************************
9703 Create a new TCP/IP port
9704 *******************************************************************/
9706 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9707 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9708 DATA_BLOB
*out
, uint32_t *needed
)
9710 struct spoolss_PortData1 port1
;
9711 struct spoolss_PortData2 port2
;
9712 char *device_uri
= NULL
;
9715 const char *portname
;
9716 const char *hostaddress
;
9718 uint32_t port_number
;
9721 /* peek for spoolss_PortData version */
9723 if (!in
|| (in
->length
< (128 + 4))) {
9724 return WERR_GENERAL_FAILURE
;
9727 version
= IVAL(in
->data
, 128);
9733 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9737 portname
= port1
.portname
;
9738 hostaddress
= port1
.hostaddress
;
9739 queue
= port1
.queue
;
9740 protocol
= port1
.protocol
;
9741 port_number
= port1
.port_number
;
9747 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9751 portname
= port2
.portname
;
9752 hostaddress
= port2
.hostaddress
;
9753 queue
= port2
.queue
;
9754 protocol
= port2
.protocol
;
9755 port_number
= port2
.port_number
;
9759 DEBUG(1,("xcvtcp_addport: "
9760 "unknown version of port_data: %d\n", version
));
9761 return WERR_UNKNOWN_PORT
;
9764 /* create the device URI and call the add_port_hook() */
9767 case PROTOCOL_RAWTCP_TYPE
:
9768 device_uri
= talloc_asprintf(mem_ctx
,
9769 "socket://%s:%d/", hostaddress
,
9773 case PROTOCOL_LPR_TYPE
:
9774 device_uri
= talloc_asprintf(mem_ctx
,
9775 "lpr://%s/%s", hostaddress
, queue
);
9779 return WERR_UNKNOWN_PORT
;
9786 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9789 /*******************************************************************
9790 *******************************************************************/
9792 struct xcv_api_table xcvtcp_cmds
[] = {
9793 { "MonitorUI", xcvtcp_monitorui
},
9794 { "AddPort", xcvtcp_addport
},
9798 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9799 NT_USER_TOKEN
*token
, const char *command
,
9806 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9808 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9809 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9810 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9813 return WERR_BADFUNC
;
9816 /*******************************************************************
9817 *******************************************************************/
9818 #if 0 /* don't support management using the "Local Port" monitor */
9820 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9821 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9822 DATA_BLOB
*out
, uint32_t *needed
)
9824 const char *dllname
= "localui.dll";
9826 *needed
= (strlen(dllname
)+1) * 2;
9828 if (out
->length
< *needed
) {
9829 return WERR_INSUFFICIENT_BUFFER
;
9832 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9839 /*******************************************************************
9840 *******************************************************************/
9842 struct xcv_api_table xcvlocal_cmds
[] = {
9843 { "MonitorUI", xcvlocal_monitorui
},
9847 struct xcv_api_table xcvlocal_cmds
[] = {
9854 /*******************************************************************
9855 *******************************************************************/
9857 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9858 NT_USER_TOKEN
*token
, const char *command
,
9859 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9864 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9866 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9867 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9868 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9870 return WERR_BADFUNC
;
9873 /****************************************************************
9875 ****************************************************************/
9877 WERROR
_spoolss_XcvData(pipes_struct
*p
,
9878 struct spoolss_XcvData
*r
)
9880 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9881 DATA_BLOB out_data
= data_blob_null
;
9885 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9886 OUR_HANDLE(r
->in
.handle
)));
9890 /* Has to be a handle to the TCP/IP port monitor */
9892 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9893 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9897 /* requires administrative access to the server */
9899 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9900 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9901 return WERR_ACCESS_DENIED
;
9904 /* Allocate the outgoing buffer */
9906 if (r
->in
.out_data_size
) {
9907 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9908 if (out_data
.data
== NULL
) {
9913 switch ( Printer
->printer_type
) {
9914 case SPLHND_PORTMON_TCP
:
9915 werror
= process_xcvtcp_command(p
->mem_ctx
,
9916 p
->server_info
->ptok
,
9917 r
->in
.function_name
,
9918 &r
->in
.in_data
, &out_data
,
9921 case SPLHND_PORTMON_LOCAL
:
9922 werror
= process_xcvlocal_command(p
->mem_ctx
,
9923 p
->server_info
->ptok
,
9924 r
->in
.function_name
,
9925 &r
->in
.in_data
, &out_data
,
9929 werror
= WERR_INVALID_PRINT_MONITOR
;
9932 if (!W_ERROR_IS_OK(werror
)) {
9936 *r
->out
.status_code
= 0;
9938 memcpy(r
->out
.out_data
, out_data
.data
, out_data
.length
);
9943 /****************************************************************
9944 _spoolss_AddPrintProcessor
9945 ****************************************************************/
9947 WERROR
_spoolss_AddPrintProcessor(pipes_struct
*p
,
9948 struct spoolss_AddPrintProcessor
*r
)
9950 /* for now, just indicate success and ignore the add. We'll
9951 automatically set the winprint processor for printer
9952 entries later. Used to debug the LexMark Optra S 1855 PCL
9958 /****************************************************************
9960 ****************************************************************/
9962 WERROR
_spoolss_AddPort(pipes_struct
*p
,
9963 struct spoolss_AddPort
*r
)
9965 /* do what w2k3 does */
9967 return WERR_NOT_SUPPORTED
;
9970 /****************************************************************
9972 ****************************************************************/
9974 WERROR
_spoolss_AddPrinter(pipes_struct
*p
,
9975 struct spoolss_AddPrinter
*r
)
9977 p
->rng_fault_state
= true;
9978 return WERR_NOT_SUPPORTED
;
9981 /****************************************************************
9982 _spoolss_GetPrinterDriver
9983 ****************************************************************/
9985 WERROR
_spoolss_GetPrinterDriver(pipes_struct
*p
,
9986 struct spoolss_GetPrinterDriver
*r
)
9988 p
->rng_fault_state
= true;
9989 return WERR_NOT_SUPPORTED
;
9992 /****************************************************************
9993 _spoolss_ReadPrinter
9994 ****************************************************************/
9996 WERROR
_spoolss_ReadPrinter(pipes_struct
*p
,
9997 struct spoolss_ReadPrinter
*r
)
9999 p
->rng_fault_state
= true;
10000 return WERR_NOT_SUPPORTED
;
10003 /****************************************************************
10004 _spoolss_WaitForPrinterChange
10005 ****************************************************************/
10007 WERROR
_spoolss_WaitForPrinterChange(pipes_struct
*p
,
10008 struct spoolss_WaitForPrinterChange
*r
)
10010 p
->rng_fault_state
= true;
10011 return WERR_NOT_SUPPORTED
;
10014 /****************************************************************
10015 _spoolss_ConfigurePort
10016 ****************************************************************/
10018 WERROR
_spoolss_ConfigurePort(pipes_struct
*p
,
10019 struct spoolss_ConfigurePort
*r
)
10021 p
->rng_fault_state
= true;
10022 return WERR_NOT_SUPPORTED
;
10025 /****************************************************************
10026 _spoolss_DeletePort
10027 ****************************************************************/
10029 WERROR
_spoolss_DeletePort(pipes_struct
*p
,
10030 struct spoolss_DeletePort
*r
)
10032 p
->rng_fault_state
= true;
10033 return WERR_NOT_SUPPORTED
;
10036 /****************************************************************
10037 _spoolss_CreatePrinterIC
10038 ****************************************************************/
10040 WERROR
_spoolss_CreatePrinterIC(pipes_struct
*p
,
10041 struct spoolss_CreatePrinterIC
*r
)
10043 p
->rng_fault_state
= true;
10044 return WERR_NOT_SUPPORTED
;
10047 /****************************************************************
10048 _spoolss_PlayGDIScriptOnPrinterIC
10049 ****************************************************************/
10051 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(pipes_struct
*p
,
10052 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
10054 p
->rng_fault_state
= true;
10055 return WERR_NOT_SUPPORTED
;
10058 /****************************************************************
10059 _spoolss_DeletePrinterIC
10060 ****************************************************************/
10062 WERROR
_spoolss_DeletePrinterIC(pipes_struct
*p
,
10063 struct spoolss_DeletePrinterIC
*r
)
10065 p
->rng_fault_state
= true;
10066 return WERR_NOT_SUPPORTED
;
10069 /****************************************************************
10070 _spoolss_AddPrinterConnection
10071 ****************************************************************/
10073 WERROR
_spoolss_AddPrinterConnection(pipes_struct
*p
,
10074 struct spoolss_AddPrinterConnection
*r
)
10076 p
->rng_fault_state
= true;
10077 return WERR_NOT_SUPPORTED
;
10080 /****************************************************************
10081 _spoolss_DeletePrinterConnection
10082 ****************************************************************/
10084 WERROR
_spoolss_DeletePrinterConnection(pipes_struct
*p
,
10085 struct spoolss_DeletePrinterConnection
*r
)
10087 p
->rng_fault_state
= true;
10088 return WERR_NOT_SUPPORTED
;
10091 /****************************************************************
10092 _spoolss_PrinterMessageBox
10093 ****************************************************************/
10095 WERROR
_spoolss_PrinterMessageBox(pipes_struct
*p
,
10096 struct spoolss_PrinterMessageBox
*r
)
10098 p
->rng_fault_state
= true;
10099 return WERR_NOT_SUPPORTED
;
10102 /****************************************************************
10103 _spoolss_AddMonitor
10104 ****************************************************************/
10106 WERROR
_spoolss_AddMonitor(pipes_struct
*p
,
10107 struct spoolss_AddMonitor
*r
)
10109 p
->rng_fault_state
= true;
10110 return WERR_NOT_SUPPORTED
;
10113 /****************************************************************
10114 _spoolss_DeleteMonitor
10115 ****************************************************************/
10117 WERROR
_spoolss_DeleteMonitor(pipes_struct
*p
,
10118 struct spoolss_DeleteMonitor
*r
)
10120 p
->rng_fault_state
= true;
10121 return WERR_NOT_SUPPORTED
;
10124 /****************************************************************
10125 _spoolss_DeletePrintProcessor
10126 ****************************************************************/
10128 WERROR
_spoolss_DeletePrintProcessor(pipes_struct
*p
,
10129 struct spoolss_DeletePrintProcessor
*r
)
10131 p
->rng_fault_state
= true;
10132 return WERR_NOT_SUPPORTED
;
10135 /****************************************************************
10136 _spoolss_AddPrintProvidor
10137 ****************************************************************/
10139 WERROR
_spoolss_AddPrintProvidor(pipes_struct
*p
,
10140 struct spoolss_AddPrintProvidor
*r
)
10142 p
->rng_fault_state
= true;
10143 return WERR_NOT_SUPPORTED
;
10146 /****************************************************************
10147 _spoolss_DeletePrintProvidor
10148 ****************************************************************/
10150 WERROR
_spoolss_DeletePrintProvidor(pipes_struct
*p
,
10151 struct spoolss_DeletePrintProvidor
*r
)
10153 p
->rng_fault_state
= true;
10154 return WERR_NOT_SUPPORTED
;
10157 /****************************************************************
10158 _spoolss_FindFirstPrinterChangeNotification
10159 ****************************************************************/
10161 WERROR
_spoolss_FindFirstPrinterChangeNotification(pipes_struct
*p
,
10162 struct spoolss_FindFirstPrinterChangeNotification
*r
)
10164 p
->rng_fault_state
= true;
10165 return WERR_NOT_SUPPORTED
;
10168 /****************************************************************
10169 _spoolss_FindNextPrinterChangeNotification
10170 ****************************************************************/
10172 WERROR
_spoolss_FindNextPrinterChangeNotification(pipes_struct
*p
,
10173 struct spoolss_FindNextPrinterChangeNotification
*r
)
10175 p
->rng_fault_state
= true;
10176 return WERR_NOT_SUPPORTED
;
10179 /****************************************************************
10180 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10181 ****************************************************************/
10183 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct
*p
,
10184 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
10186 p
->rng_fault_state
= true;
10187 return WERR_NOT_SUPPORTED
;
10190 /****************************************************************
10191 _spoolss_ReplyOpenPrinter
10192 ****************************************************************/
10194 WERROR
_spoolss_ReplyOpenPrinter(pipes_struct
*p
,
10195 struct spoolss_ReplyOpenPrinter
*r
)
10197 p
->rng_fault_state
= true;
10198 return WERR_NOT_SUPPORTED
;
10201 /****************************************************************
10202 _spoolss_RouterReplyPrinter
10203 ****************************************************************/
10205 WERROR
_spoolss_RouterReplyPrinter(pipes_struct
*p
,
10206 struct spoolss_RouterReplyPrinter
*r
)
10208 p
->rng_fault_state
= true;
10209 return WERR_NOT_SUPPORTED
;
10212 /****************************************************************
10213 _spoolss_ReplyClosePrinter
10214 ****************************************************************/
10216 WERROR
_spoolss_ReplyClosePrinter(pipes_struct
*p
,
10217 struct spoolss_ReplyClosePrinter
*r
)
10219 p
->rng_fault_state
= true;
10220 return WERR_NOT_SUPPORTED
;
10223 /****************************************************************
10225 ****************************************************************/
10227 WERROR
_spoolss_AddPortEx(pipes_struct
*p
,
10228 struct spoolss_AddPortEx
*r
)
10230 p
->rng_fault_state
= true;
10231 return WERR_NOT_SUPPORTED
;
10234 /****************************************************************
10235 _spoolss_RouterFindFirstPrinterChangeNotification
10236 ****************************************************************/
10238 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct
*p
,
10239 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
10241 p
->rng_fault_state
= true;
10242 return WERR_NOT_SUPPORTED
;
10245 /****************************************************************
10246 _spoolss_SpoolerInit
10247 ****************************************************************/
10249 WERROR
_spoolss_SpoolerInit(pipes_struct
*p
,
10250 struct spoolss_SpoolerInit
*r
)
10252 p
->rng_fault_state
= true;
10253 return WERR_NOT_SUPPORTED
;
10256 /****************************************************************
10257 _spoolss_ResetPrinterEx
10258 ****************************************************************/
10260 WERROR
_spoolss_ResetPrinterEx(pipes_struct
*p
,
10261 struct spoolss_ResetPrinterEx
*r
)
10263 p
->rng_fault_state
= true;
10264 return WERR_NOT_SUPPORTED
;
10267 /****************************************************************
10268 _spoolss_RouterReplyPrinterEx
10269 ****************************************************************/
10271 WERROR
_spoolss_RouterReplyPrinterEx(pipes_struct
*p
,
10272 struct spoolss_RouterReplyPrinterEx
*r
)
10274 p
->rng_fault_state
= true;
10275 return WERR_NOT_SUPPORTED
;
10278 /****************************************************************
10280 ****************************************************************/
10282 WERROR
_spoolss_44(pipes_struct
*p
,
10283 struct spoolss_44
*r
)
10285 p
->rng_fault_state
= true;
10286 return WERR_NOT_SUPPORTED
;
10289 /****************************************************************
10291 ****************************************************************/
10293 WERROR
_spoolss_47(pipes_struct
*p
,
10294 struct spoolss_47
*r
)
10296 p
->rng_fault_state
= true;
10297 return WERR_NOT_SUPPORTED
;
10300 /****************************************************************
10302 ****************************************************************/
10304 WERROR
_spoolss_4a(pipes_struct
*p
,
10305 struct spoolss_4a
*r
)
10307 p
->rng_fault_state
= true;
10308 return WERR_NOT_SUPPORTED
;
10311 /****************************************************************
10313 ****************************************************************/
10315 WERROR
_spoolss_4b(pipes_struct
*p
,
10316 struct spoolss_4b
*r
)
10318 p
->rng_fault_state
= true;
10319 return WERR_NOT_SUPPORTED
;
10322 /****************************************************************
10324 ****************************************************************/
10326 WERROR
_spoolss_4c(pipes_struct
*p
,
10327 struct spoolss_4c
*r
)
10329 p
->rng_fault_state
= true;
10330 return WERR_NOT_SUPPORTED
;
10333 /****************************************************************
10335 ****************************************************************/
10337 WERROR
_spoolss_53(pipes_struct
*p
,
10338 struct spoolss_53
*r
)
10340 p
->rng_fault_state
= true;
10341 return WERR_NOT_SUPPORTED
;
10344 /****************************************************************
10346 ****************************************************************/
10348 WERROR
_spoolss_55(pipes_struct
*p
,
10349 struct spoolss_55
*r
)
10351 p
->rng_fault_state
= true;
10352 return WERR_NOT_SUPPORTED
;
10355 /****************************************************************
10357 ****************************************************************/
10359 WERROR
_spoolss_56(pipes_struct
*p
,
10360 struct spoolss_56
*r
)
10362 p
->rng_fault_state
= true;
10363 return WERR_NOT_SUPPORTED
;
10366 /****************************************************************
10368 ****************************************************************/
10370 WERROR
_spoolss_57(pipes_struct
*p
,
10371 struct spoolss_57
*r
)
10373 p
->rng_fault_state
= true;
10374 return WERR_NOT_SUPPORTED
;
10377 /****************************************************************
10379 ****************************************************************/
10381 WERROR
_spoolss_5a(pipes_struct
*p
,
10382 struct spoolss_5a
*r
)
10384 p
->rng_fault_state
= true;
10385 return WERR_NOT_SUPPORTED
;
10388 /****************************************************************
10390 ****************************************************************/
10392 WERROR
_spoolss_5b(pipes_struct
*p
,
10393 struct spoolss_5b
*r
)
10395 p
->rng_fault_state
= true;
10396 return WERR_NOT_SUPPORTED
;
10399 /****************************************************************
10401 ****************************************************************/
10403 WERROR
_spoolss_5c(pipes_struct
*p
,
10404 struct spoolss_5c
*r
)
10406 p
->rng_fault_state
= true;
10407 return WERR_NOT_SUPPORTED
;
10410 /****************************************************************
10412 ****************************************************************/
10414 WERROR
_spoolss_5d(pipes_struct
*p
,
10415 struct spoolss_5d
*r
)
10417 p
->rng_fault_state
= true;
10418 return WERR_NOT_SUPPORTED
;
10421 /****************************************************************
10423 ****************************************************************/
10425 WERROR
_spoolss_5e(pipes_struct
*p
,
10426 struct spoolss_5e
*r
)
10428 p
->rng_fault_state
= true;
10429 return WERR_NOT_SUPPORTED
;
10432 /****************************************************************
10434 ****************************************************************/
10436 WERROR
_spoolss_5f(pipes_struct
*p
,
10437 struct spoolss_5f
*r
)
10439 p
->rng_fault_state
= true;
10440 return WERR_NOT_SUPPORTED
;