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-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
31 #include "srv_spoolss_util.h"
32 #include "../librpc/gen_ndr/srv_spoolss.h"
33 #include "../librpc/gen_ndr/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "librpc/gen_ndr/messaging.h"
36 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry/reg_objects.h"
40 /* macros stolen from s4 spoolss server */
41 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
42 ((info)?ndr_size_##fn(info, level, 0):0)
44 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
45 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
47 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
48 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
50 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
53 extern userdom_struct current_user_info
;
56 #define DBGC_CLASS DBGC_RPC_SRV
58 #ifndef MAX_OPEN_PRINTER_EXS
59 #define MAX_OPEN_PRINTER_EXS 50
62 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
64 static Printer_entry
*printers_list
;
66 typedef struct _counter_printer_0
{
67 struct _counter_printer_0
*next
;
68 struct _counter_printer_0
*prev
;
74 static counter_printer_0
*counter_list
;
76 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
77 static uint32_t smb_connections
= 0;
80 /* in printing/nt_printing.c */
82 extern struct standard_mapping printer_std_mapping
, printserver_std_mapping
;
84 /* API table for Xcv Monitor functions */
86 struct xcv_api_table
{
88 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, NT_USER_TOKEN
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
91 /********************************************************************
92 * Canonicalize servername.
93 ********************************************************************/
95 static const char *canon_servername(const char *servername
)
97 const char *pservername
= servername
;
98 while (*pservername
== '\\') {
104 /* translate between internal status numbers and NT status numbers */
105 static int nt_printj_status(int v
)
111 return JOB_STATUS_PAUSED
;
113 return JOB_STATUS_SPOOLING
;
115 return JOB_STATUS_PRINTING
;
117 return JOB_STATUS_ERROR
;
119 return JOB_STATUS_DELETING
;
121 return JOB_STATUS_OFFLINE
;
123 return JOB_STATUS_PAPEROUT
;
125 return JOB_STATUS_PRINTED
;
127 return JOB_STATUS_DELETED
;
129 return JOB_STATUS_BLOCKED_DEVQ
;
130 case LPQ_USER_INTERVENTION
:
131 return JOB_STATUS_USER_INTERVENTION
;
136 static int nt_printq_status(int v
)
140 return PRINTER_STATUS_PAUSED
;
149 /***************************************************************************
150 Disconnect from the client
151 ****************************************************************************/
153 static void srv_spoolss_replycloseprinter(int snum
, struct policy_handle
*handle
)
159 * Tell the specific printing tdb we no longer want messages for this printer
160 * by deregistering our PID.
163 if (!print_notify_deregister_pid(snum
))
164 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
166 /* weird if the test succeds !!! */
167 if (smb_connections
==0) {
168 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
172 status
= rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe
, talloc_tos(),
175 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
176 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
177 win_errstr(result
)));
179 /* if it's the last connection, deconnect the IPC$ share */
180 if (smb_connections
==1) {
182 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe
) );
183 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
185 messaging_deregister(smbd_messaging_context(),
186 MSG_PRINTER_NOTIFY2
, NULL
);
188 /* Tell the connections db we're no longer interested in
189 * printer notify messages. */
191 serverid_register_msg_flags(
192 messaging_server_id(smbd_messaging_context()),
193 false, FLAG_MSG_PRINT_NOTIFY
);
199 /****************************************************************************
200 Functions to free a printer entry datastruct.
201 ****************************************************************************/
203 static int printer_entry_destructor(Printer_entry
*Printer
)
205 if (Printer
->notify
.client_connected
== true) {
208 if ( Printer
->printer_type
== SPLHND_SERVER
) {
210 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
211 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
212 snum
= print_queue_snum(Printer
->sharename
);
214 srv_spoolss_replycloseprinter(snum
,
215 &Printer
->notify
.client_hnd
);
219 Printer
->notify
.flags
=0;
220 Printer
->notify
.options
=0;
221 Printer
->notify
.localmachine
[0]='\0';
222 Printer
->notify
.printerlocal
=0;
223 TALLOC_FREE(Printer
->notify
.option
);
224 Printer
->notify
.client_connected
= false;
226 TALLOC_FREE(Printer
->devmode
);
227 free_a_printer( &Printer
->printer_info
, 2 );
229 /* Remove from the internal list. */
230 DLIST_REMOVE(printers_list
, Printer
);
234 /****************************************************************************
235 find printer index by handle
236 ****************************************************************************/
238 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
,
239 struct policy_handle
*hnd
)
241 Printer_entry
*find_printer
= NULL
;
243 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
244 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
251 /****************************************************************************
252 Close printer index by handle.
253 ****************************************************************************/
255 static bool close_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
257 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
260 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
265 close_policy_hnd(p
, hnd
);
270 /****************************************************************************
271 Delete a printer given a handle.
272 ****************************************************************************/
274 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *sharename
)
276 char *cmd
= lp_deleteprinter_cmd();
277 char *command
= NULL
;
279 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
280 bool is_print_op
= false;
282 /* can't fail if we don't try */
287 command
= talloc_asprintf(ctx
,
294 is_print_op
= user_has_privileges( token
, &se_printop
);
296 DEBUG(10,("Running [%s]\n", command
));
298 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
303 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
304 /* Tell everyone we updated smb.conf. */
305 message_send_all(smbd_messaging_context(),
306 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
312 /********** END SePrintOperatorPrivlege BLOCK **********/
314 DEBUGADD(10,("returned [%d]\n", ret
));
316 TALLOC_FREE(command
);
319 return WERR_BADFID
; /* What to return here? */
321 /* go ahead and re-read the services immediately */
323 reload_services(false);
326 if ( lp_servicenumber( sharename
) > 0 )
327 return WERR_ACCESS_DENIED
;
332 /****************************************************************************
333 Delete a printer given a handle.
334 ****************************************************************************/
336 static WERROR
delete_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
338 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
342 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
348 * It turns out that Windows allows delete printer on a handle
349 * opened by an admin user, then used on a pipe handle created
350 * by an anonymous user..... but they're working on security.... riiight !
354 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
355 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
356 return WERR_ACCESS_DENIED
;
359 /* this does not need a become root since the access check has been
360 done on the handle already */
362 result
= winreg_delete_printer_key(p
->mem_ctx
, p
->server_info
,
363 Printer
->sharename
, "");
364 if (!W_ERROR_IS_OK(result
)) {
365 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
369 return delete_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
370 Printer
->sharename
);
373 /****************************************************************************
374 Return the snum of a printer corresponding to an handle.
375 ****************************************************************************/
377 static bool get_printer_snum(pipes_struct
*p
, struct policy_handle
*hnd
,
378 int *number
, struct share_params
**params
)
380 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
383 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
388 switch (Printer
->printer_type
) {
390 DEBUG(4,("short name:%s\n", Printer
->sharename
));
391 *number
= print_queue_snum(Printer
->sharename
);
392 return (*number
!= -1);
400 /****************************************************************************
401 Set printer handle type.
402 Check if it's \\server or \\server\printer
403 ****************************************************************************/
405 static bool set_printer_hnd_printertype(Printer_entry
*Printer
, const char *handlename
)
407 DEBUG(3,("Setting printer type=%s\n", handlename
));
409 if ( strlen(handlename
) < 3 ) {
410 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
414 /* it's a print server */
415 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
416 DEBUGADD(4,("Printer is a print server\n"));
417 Printer
->printer_type
= SPLHND_SERVER
;
419 /* it's a printer (set_printer_hnd_name() will handle port monitors */
421 DEBUGADD(4,("Printer is a printer\n"));
422 Printer
->printer_type
= SPLHND_PRINTER
;
428 /****************************************************************************
429 Set printer handle name.. Accept names like \\server, \\server\printer,
430 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
431 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
432 XcvDataPort() interface.
433 ****************************************************************************/
435 static bool set_printer_hnd_name(TALLOC_CTX
*mem_ctx
,
436 struct auth_serversupplied_info
*server_info
,
437 Printer_entry
*Printer
,
438 const char *handlename
)
441 int n_services
=lp_numservices();
443 const char *printername
;
444 const char *servername
;
447 struct spoolss_PrinterInfo2
*info2
= NULL
;
450 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
451 (unsigned long)strlen(handlename
)));
453 aprinter
= CONST_DISCARD(char *, handlename
);
454 if ( *handlename
== '\\' ) {
455 servername
= canon_servername(handlename
);
456 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
460 if (!is_myname_or_ipaddr(servername
)) {
464 fstrcpy(Printer
->servername
, servername
);
467 if (Printer
->printer_type
== SPLHND_SERVER
) {
471 if (Printer
->printer_type
!= SPLHND_PRINTER
) {
475 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
477 /* check for the Port Monitor Interface */
478 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
479 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
480 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
483 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
484 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
485 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
489 /* Search all sharenames first as this is easier than pulling
490 the printer_info_2 off of disk. Don't use find_service() since
491 that calls out to map_username() */
493 /* do another loop to look for printernames */
494 for (snum
= 0; !found
&& snum
< n_services
; snum
++) {
495 const char *printer
= lp_const_servicename(snum
);
497 /* no point going on if this is not a printer */
498 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
))) {
502 /* ignore [printers] share */
503 if (strequal(printer
, "printers")) {
507 fstrcpy(sname
, printer
);
508 if (strequal(aprinter
, printer
)) {
513 /* no point looking up the printer object if
514 we aren't allowing printername != sharename */
515 if (lp_force_printername(snum
)) {
519 result
= winreg_get_printer(mem_ctx
,
524 if ( !W_ERROR_IS_OK(result
) ) {
525 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
526 sname
, win_errstr(result
)));
530 printername
= strrchr(info2
->printername
, '\\');
531 if (printername
== NULL
) {
532 printername
= info2
->printername
;
537 if (strequal(printername
, aprinter
)) {
542 DEBUGADD(10, ("printername: %s\n", printername
));
548 DEBUGADD(4,("Printer not found\n"));
552 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
554 fstrcpy(Printer
->sharename
, sname
);
559 /****************************************************************************
560 Find first available printer slot. creates a printer handle for you.
561 ****************************************************************************/
563 static bool open_printer_hnd(pipes_struct
*p
, struct policy_handle
*hnd
,
564 const char *name
, uint32_t access_granted
)
566 Printer_entry
*new_printer
;
568 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
570 new_printer
= TALLOC_ZERO_P(NULL
, Printer_entry
);
571 if (new_printer
== NULL
) {
574 talloc_set_destructor(new_printer
, printer_entry_destructor
);
576 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
577 TALLOC_FREE(new_printer
);
581 /* Add to the internal list. */
582 DLIST_ADD(printers_list
, new_printer
);
584 new_printer
->notify
.option
=NULL
;
586 if (!set_printer_hnd_printertype(new_printer
, name
)) {
587 close_printer_handle(p
, hnd
);
591 if (!set_printer_hnd_name(p
->mem_ctx
, p
->server_info
, new_printer
, name
)) {
592 close_printer_handle(p
, hnd
);
596 new_printer
->access_granted
= access_granted
;
598 DEBUG(5, ("%d printer handles active\n",
599 (int)num_pipe_handles(p
)));
604 /***************************************************************************
605 check to see if the client motify handle is monitoring the notification
606 given by (notify_type, notify_field).
607 **************************************************************************/
609 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
610 uint16_t notify_field
)
615 static bool is_monitoring_event(Printer_entry
*p
, uint16_t notify_type
,
616 uint16_t notify_field
)
618 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
622 * Flags should always be zero when the change notify
623 * is registered by the client's spooler. A user Win32 app
624 * might use the flags though instead of the NOTIFY_OPTION_INFO
633 return is_monitoring_event_flags(
634 p
->notify
.flags
, notify_type
, notify_field
);
636 for (i
= 0; i
< option
->count
; i
++) {
638 /* Check match for notify_type */
640 if (option
->types
[i
].type
!= notify_type
)
643 /* Check match for field */
645 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
646 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
652 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
653 p
->servername
, p
->sharename
, notify_type
, notify_field
));
658 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
659 _data->data.integer[0] = _integer; \
660 _data->data.integer[1] = 0;
663 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
664 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
665 if (!_data->data.string.string) {\
666 _data->data.string.size = 0; \
668 _data->data.string.size = strlen_m_term(_p) * 2;
670 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
671 _data->data.devmode.devmode = _devmode;
673 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
674 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
675 if (!_data->data.sd.sd) { \
676 _data->data.sd.sd_size = 0; \
678 _data->data.sd.sd_size = \
679 ndr_size_security_descriptor(_data->data.sd.sd, 0);
681 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
686 struct spoolss_Time st
;
690 if (!init_systemtime(&st
, t
)) {
694 p
= talloc_array(mem_ctx
, char, len
);
700 * Systemtime must be linearized as a set of UINT16's.
701 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
704 SSVAL(p
, 0, st
.year
);
705 SSVAL(p
, 2, st
.month
);
706 SSVAL(p
, 4, st
.day_of_week
);
708 SSVAL(p
, 8, st
.hour
);
709 SSVAL(p
, 10, st
.minute
);
710 SSVAL(p
, 12, st
.second
);
711 SSVAL(p
, 14, st
.millisecond
);
717 /* Convert a notification message to a struct spoolss_Notify */
719 static void notify_one_value(struct spoolss_notify_msg
*msg
,
720 struct spoolss_Notify
*data
,
723 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
726 static void notify_string(struct spoolss_notify_msg
*msg
,
727 struct spoolss_Notify
*data
,
730 /* The length of the message includes the trailing \0 */
732 data
->data
.string
.size
= msg
->len
* 2;
733 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
734 if (!data
->data
.string
.string
) {
735 data
->data
.string
.size
= 0;
740 static void notify_system_time(struct spoolss_notify_msg
*msg
,
741 struct spoolss_Notify
*data
,
744 data
->data
.string
.string
= NULL
;
745 data
->data
.string
.size
= 0;
747 if (msg
->len
!= sizeof(time_t)) {
748 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
753 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
754 &data
->data
.string
.string
,
755 &data
->data
.string
.size
);
758 struct notify2_message_table
{
760 void (*fn
)(struct spoolss_notify_msg
*msg
,
761 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
764 static struct notify2_message_table printer_notify_table
[] = {
765 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
766 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
767 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
768 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
769 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
770 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
771 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
772 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
773 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
774 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
775 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
776 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
777 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
778 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
779 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
780 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
781 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
782 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
783 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
786 static struct notify2_message_table job_notify_table
[] = {
787 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
788 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
789 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
790 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
791 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
792 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
793 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
794 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
795 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
796 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
797 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
798 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
799 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
800 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
801 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
802 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
803 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
804 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
805 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
806 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
807 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
808 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
809 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
810 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
814 /***********************************************************************
815 Allocate talloc context for container object
816 **********************************************************************/
818 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
823 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
828 /***********************************************************************
829 release all allocated memory and zero out structure
830 **********************************************************************/
832 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
838 talloc_destroy(ctr
->ctx
);
845 /***********************************************************************
846 **********************************************************************/
848 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
856 /***********************************************************************
857 **********************************************************************/
859 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
861 if ( !ctr
|| !ctr
->msg_groups
)
864 if ( idx
>= ctr
->num_groups
)
867 return &ctr
->msg_groups
[idx
];
871 /***********************************************************************
872 How many groups of change messages do we have ?
873 **********************************************************************/
875 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
880 return ctr
->num_groups
;
883 /***********************************************************************
884 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
885 **********************************************************************/
887 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
889 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
890 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
891 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
897 /* loop over all groups looking for a matching printer name */
899 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
900 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
904 /* add a new group? */
906 if ( i
== ctr
->num_groups
) {
909 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
913 ctr
->msg_groups
= groups
;
915 /* clear the new entry and set the printer name */
917 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
918 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
921 /* add the change messages; 'i' is the correct index now regardless */
923 msg_grp
= &ctr
->msg_groups
[i
];
927 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
928 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
931 msg_grp
->msgs
= msg_list
;
933 new_slot
= msg_grp
->num_msgs
-1;
934 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
936 /* need to allocate own copy of data */
939 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
940 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
942 return ctr
->num_groups
;
945 static void construct_info_data(struct spoolss_Notify
*info_data
,
946 enum spoolss_NotifyType type
,
947 uint16_t field
, int id
);
949 /***********************************************************************
950 Send a change notication message on all handles which have a call
952 **********************************************************************/
954 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
957 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
958 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
959 SPOOLSS_NOTIFY_MSG
*messages
;
960 int sending_msg_count
;
963 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
967 messages
= msg_group
->msgs
;
970 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
974 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
976 /* loop over all printers */
978 for (p
= printers_list
; p
; p
= p
->next
) {
979 struct spoolss_Notify
*notifies
;
984 /* Is there notification on this handle? */
986 if ( !p
->notify
.client_connected
)
989 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
991 /* For this printer? Print servers always receive
994 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
995 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
998 DEBUG(10,("Our printer\n"));
1000 /* allocate the max entries possible */
1002 notifies
= TALLOC_ZERO_ARRAY(mem_ctx
, struct spoolss_Notify
, msg_group
->num_msgs
);
1007 /* build the array of change notifications */
1009 sending_msg_count
= 0;
1011 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1012 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1014 /* Are we monitoring this event? */
1016 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1019 sending_msg_count
++;
1022 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1023 msg
->type
, msg
->field
, p
->sharename
));
1026 * if the is a printer notification handle and not a job notification
1027 * type, then set the id to 0. Other wise just use what was specified
1030 * When registering change notification on a print server handle
1031 * we always need to send back the id (snum) matching the printer
1032 * for which the change took place. For change notify registered
1033 * on a printer handle, this does not matter and the id should be 0.
1038 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1044 /* Convert unix jobid to smb jobid */
1046 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1047 id
= sysjob_to_jobid(msg
->id
);
1050 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1055 construct_info_data( ¬ifies
[count
], msg
->type
, msg
->field
, id
);
1058 case PRINTER_NOTIFY_TYPE
:
1059 if ( printer_notify_table
[msg
->field
].fn
)
1060 printer_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1063 case JOB_NOTIFY_TYPE
:
1064 if ( job_notify_table
[msg
->field
].fn
)
1065 job_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1069 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1076 if ( sending_msg_count
) {
1079 union spoolss_ReplyPrinterInfo info
;
1080 struct spoolss_NotifyInfo info0
;
1081 uint32_t reply_result
;
1083 info0
.version
= 0x2;
1084 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1085 info0
.count
= count
;
1086 info0
.notifies
= notifies
;
1088 info
.info0
= &info0
;
1090 status
= rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe
, mem_ctx
,
1091 &p
->notify
.client_hnd
,
1092 p
->notify
.change
, /* color */
1095 0, /* reply_type, must be 0 */
1098 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
1099 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1100 notify_cli_pipe
->srv_name_slash
,
1103 switch (reply_result
) {
1106 case PRINTER_NOTIFY_INFO_DISCARDED
:
1107 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1108 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1117 DEBUG(8,("send_notify2_changes: Exit...\n"));
1121 /***********************************************************************
1122 **********************************************************************/
1124 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1127 uint32_t tv_sec
, tv_usec
;
1130 /* Unpack message */
1132 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1135 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1137 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1140 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1141 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1143 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1144 &msg
->len
, &msg
->notify
.data
);
1146 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1147 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1149 tv
->tv_sec
= tv_sec
;
1150 tv
->tv_usec
= tv_usec
;
1153 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1154 msg
->notify
.value
[1]));
1156 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1161 /********************************************************************
1162 Receive a notify2 message list
1163 ********************************************************************/
1165 static void receive_notify2_message_list(struct messaging_context
*msg
,
1168 struct server_id server_id
,
1171 size_t msg_count
, i
;
1172 char *buf
= (char *)data
->data
;
1175 SPOOLSS_NOTIFY_MSG notify
;
1176 SPOOLSS_NOTIFY_MSG_CTR messages
;
1179 if (data
->length
< 4) {
1180 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1184 msg_count
= IVAL(buf
, 0);
1187 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1189 if (msg_count
== 0) {
1190 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1194 /* initialize the container */
1196 ZERO_STRUCT( messages
);
1197 notify_msg_ctr_init( &messages
);
1200 * build message groups for each printer identified
1201 * in a change_notify msg. Remember that a PCN message
1202 * includes the handle returned for the srv_spoolss_replyopenprinter()
1203 * call. Therefore messages are grouped according to printer handle.
1206 for ( i
=0; i
<msg_count
; i
++ ) {
1207 struct timeval msg_tv
;
1209 if (msg_ptr
+ 4 - buf
> data
->length
) {
1210 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1214 msg_len
= IVAL(msg_ptr
,0);
1217 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1218 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1222 /* unpack messages */
1224 ZERO_STRUCT( notify
);
1225 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1228 /* add to correct list in container */
1230 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1232 /* free memory that might have been allocated by notify2_unpack_msg() */
1234 if ( notify
.len
!= 0 )
1235 SAFE_FREE( notify
.notify
.data
);
1238 /* process each group of messages */
1240 num_groups
= notify_msg_ctr_numgroups( &messages
);
1241 for ( i
=0; i
<num_groups
; i
++ )
1242 send_notify2_changes( &messages
, i
);
1247 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1248 (uint32_t)msg_count
));
1250 notify_msg_ctr_destroy( &messages
);
1255 /********************************************************************
1256 Send a message to ourself about new driver being installed
1257 so we can upgrade the information for each printer bound to this
1259 ********************************************************************/
1261 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
)
1263 int len
= strlen(drivername
);
1268 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1271 messaging_send_buf(smbd_messaging_context(),
1272 messaging_server_id(smbd_messaging_context()),
1273 MSG_PRINTER_DRVUPGRADE
,
1274 (uint8_t *)drivername
, len
+1);
1279 /**********************************************************************
1280 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1281 over all printers, upgrading ones as necessary
1282 **********************************************************************/
1284 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1287 struct server_id server_id
,
1290 TALLOC_CTX
*tmp_ctx
;
1291 struct auth_serversupplied_info
*server_info
= NULL
;
1292 struct spoolss_PrinterInfo2
*pinfo2
;
1295 const char *drivername
;
1297 int n_services
= lp_numservices();
1300 tmp_ctx
= talloc_new(NULL
);
1301 if (!tmp_ctx
) return;
1303 status
= make_server_info_system(tmp_ctx
, &server_info
);
1304 if (!NT_STATUS_IS_OK(status
)) {
1305 DEBUG(0, ("do_drv_upgrade_printer: "
1306 "Could not create system server_info\n"));
1310 len
= MIN(data
->length
,sizeof(drivername
)-1);
1311 drivername
= talloc_strndup(tmp_ctx
, (const char *)data
->data
, len
);
1313 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1317 DEBUG(10, ("do_drv_upgrade_printer: "
1318 "Got message for new driver [%s]\n", drivername
));
1320 /* Iterate the printer list */
1322 for (snum
= 0; snum
< n_services
; snum
++) {
1323 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1327 result
= winreg_get_printer(tmp_ctx
, server_info
, NULL
,
1328 lp_const_servicename(snum
),
1331 if (!W_ERROR_IS_OK(result
)) {
1335 if (strcmp(drivername
, pinfo2
->drivername
) != 0) {
1339 DEBUG(6,("Updating printer [%s]\n", pinfo2
->printername
));
1341 /* all we care about currently is the change_id */
1342 result
= winreg_printer_update_changeid(tmp_ctx
,
1344 pinfo2
->printername
);
1346 if (!W_ERROR_IS_OK(result
)) {
1347 DEBUG(3, ("do_drv_upgrade_printer: "
1348 "Failed to update changeid [%s]\n",
1349 win_errstr(result
)));
1355 talloc_free(tmp_ctx
);
1358 /********************************************************************
1359 Update the cache for all printq's with a registered client
1361 ********************************************************************/
1363 void update_monitored_printq_cache( void )
1365 Printer_entry
*printer
= printers_list
;
1368 /* loop through all printers and update the cache where
1369 client_connected == true */
1372 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1373 && printer
->notify
.client_connected
)
1375 snum
= print_queue_snum(printer
->sharename
);
1376 print_queue_status( snum
, NULL
, NULL
);
1379 printer
= printer
->next
;
1385 /****************************************************************
1386 _spoolss_OpenPrinter
1387 ****************************************************************/
1389 WERROR
_spoolss_OpenPrinter(pipes_struct
*p
,
1390 struct spoolss_OpenPrinter
*r
)
1392 struct spoolss_OpenPrinterEx e
;
1395 ZERO_STRUCT(e
.in
.userlevel
);
1397 e
.in
.printername
= r
->in
.printername
;
1398 e
.in
.datatype
= r
->in
.datatype
;
1399 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1400 e
.in
.access_mask
= r
->in
.access_mask
;
1403 e
.out
.handle
= r
->out
.handle
;
1405 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1407 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1408 /* OpenPrinterEx returns this for a bad
1409 * printer name. We must return WERR_INVALID_PRINTER_NAME
1412 werr
= WERR_INVALID_PRINTER_NAME
;
1418 static WERROR
copy_devicemode(TALLOC_CTX
*mem_ctx
,
1419 struct spoolss_DeviceMode
*orig
,
1420 struct spoolss_DeviceMode
**dest
)
1422 struct spoolss_DeviceMode
*dm
;
1424 dm
= talloc(mem_ctx
, struct spoolss_DeviceMode
);
1429 /* copy all values, then duplicate strings and structs */
1432 dm
->devicename
= talloc_strdup(dm
, orig
->devicename
);
1433 if (!dm
->devicename
) {
1436 dm
->formname
= talloc_strdup(dm
, orig
->formname
);
1437 if (!dm
->formname
) {
1440 if (orig
->driverextra_data
.data
) {
1441 dm
->driverextra_data
.data
=
1442 (uint8_t *) talloc_memdup(dm
, orig
->driverextra_data
.data
,
1443 orig
->driverextra_data
.length
);
1444 if (!dm
->driverextra_data
.data
) {
1453 /****************************************************************
1454 _spoolss_OpenPrinterEx
1455 ****************************************************************/
1457 WERROR
_spoolss_OpenPrinterEx(pipes_struct
*p
,
1458 struct spoolss_OpenPrinterEx
*r
)
1461 Printer_entry
*Printer
=NULL
;
1463 if (!r
->in
.printername
) {
1464 return WERR_INVALID_PARAM
;
1467 /* some sanity check because you can open a printer or a print server */
1468 /* aka: \\server\printer or \\server */
1470 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1472 if (!open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0)) {
1473 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1474 " for printer %s\n", r
->in
.printername
));
1475 ZERO_STRUCTP(r
->out
.handle
);
1476 return WERR_INVALID_PARAM
;
1479 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1481 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1482 "handle we created for printer %s\n", r
->in
.printername
));
1483 close_printer_handle(p
, r
->out
.handle
);
1484 ZERO_STRUCTP(r
->out
.handle
);
1485 return WERR_INVALID_PARAM
;
1489 * First case: the user is opening the print server:
1491 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1492 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1494 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1495 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1496 * or if the user is listed in the smb.conf printer admin parameter.
1498 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1499 * client view printer folder, but does not show the MSAPW.
1501 * Note: this test needs code to check access rights here too. Jeremy
1502 * could you look at this?
1504 * Second case: the user is opening a printer:
1505 * NT doesn't let us connect to a printer if the connecting user
1506 * doesn't have print permission.
1508 * Third case: user is opening a Port Monitor
1509 * access checks same as opening a handle to the print server.
1512 switch (Printer
->printer_type
)
1515 case SPLHND_PORTMON_TCP
:
1516 case SPLHND_PORTMON_LOCAL
:
1517 /* Printserver handles use global struct... */
1521 /* Map standard access rights to object specific access rights */
1523 se_map_standard(&r
->in
.access_mask
,
1524 &printserver_std_mapping
);
1526 /* Deny any object specific bits that don't apply to print
1527 servers (i.e printer and job specific bits) */
1529 r
->in
.access_mask
&= SEC_MASK_SPECIFIC
;
1531 if (r
->in
.access_mask
&
1532 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1533 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1534 close_printer_handle(p
, r
->out
.handle
);
1535 ZERO_STRUCTP(r
->out
.handle
);
1536 return WERR_ACCESS_DENIED
;
1539 /* Allow admin access */
1541 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1543 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1545 if (!lp_ms_add_printer_wizard()) {
1546 close_printer_handle(p
, r
->out
.handle
);
1547 ZERO_STRUCTP(r
->out
.handle
);
1548 return WERR_ACCESS_DENIED
;
1551 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1552 and not a printer admin, then fail */
1554 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
1555 !user_has_privileges(p
->server_info
->ptok
,
1557 !token_contains_name_in_list(
1558 uidtoname(p
->server_info
->utok
.uid
),
1559 p
->server_info
->info3
->base
.domain
.string
,
1561 p
->server_info
->ptok
,
1562 lp_printer_admin(snum
))) {
1563 close_printer_handle(p
, r
->out
.handle
);
1564 ZERO_STRUCTP(r
->out
.handle
);
1565 return WERR_ACCESS_DENIED
;
1568 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1572 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1575 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1576 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1578 /* We fall through to return WERR_OK */
1581 case SPLHND_PRINTER
:
1582 /* NT doesn't let us connect to a printer if the connecting user
1583 doesn't have print permission. */
1585 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1586 close_printer_handle(p
, r
->out
.handle
);
1587 ZERO_STRUCTP(r
->out
.handle
);
1591 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1592 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1595 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1597 /* map an empty access mask to the minimum access mask */
1598 if (r
->in
.access_mask
== 0x0)
1599 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1602 * If we are not serving the printer driver for this printer,
1603 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1604 * will keep NT clients happy --jerry
1607 if (lp_use_client_driver(snum
)
1608 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1610 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1613 /* check smb.conf parameters and the the sec_desc */
1615 if ( !check_access(get_client_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1616 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1617 ZERO_STRUCTP(r
->out
.handle
);
1618 return WERR_ACCESS_DENIED
;
1621 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1622 p
->server_info
->ptok
, snum
) ||
1623 !print_access_check(p
->server_info
, snum
,
1624 r
->in
.access_mask
)) {
1625 DEBUG(3, ("access DENIED for printer open\n"));
1626 close_printer_handle(p
, r
->out
.handle
);
1627 ZERO_STRUCTP(r
->out
.handle
);
1628 return WERR_ACCESS_DENIED
;
1631 if ((r
->in
.access_mask
& SEC_MASK_SPECIFIC
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1632 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1633 close_printer_handle(p
, r
->out
.handle
);
1634 ZERO_STRUCTP(r
->out
.handle
);
1635 return WERR_ACCESS_DENIED
;
1638 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1639 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1641 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1643 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1644 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1646 winreg_create_printer(p
->mem_ctx
,
1648 Printer
->servername
,
1649 lp_const_servicename(snum
));
1654 /* sanity check to prevent programmer error */
1655 ZERO_STRUCTP(r
->out
.handle
);
1659 Printer
->access_granted
= r
->in
.access_mask
;
1662 * If the client sent a devmode in the OpenPrinter() call, then
1663 * save it here in case we get a job submission on this handle
1666 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1667 r
->in
.devmode_ctr
.devmode
) {
1668 copy_devicemode(NULL
, r
->in
.devmode_ctr
.devmode
,
1672 #if 0 /* JERRY -- I'm doubtful this is really effective */
1673 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1674 optimization in Windows 2000 clients --jerry */
1676 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1677 && (RA_WIN2K
== get_remote_arch()) )
1679 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1680 sys_usleep( 500000 );
1687 /****************************************************************
1688 _spoolss_ClosePrinter
1689 ****************************************************************/
1691 WERROR
_spoolss_ClosePrinter(pipes_struct
*p
,
1692 struct spoolss_ClosePrinter
*r
)
1694 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1696 if (Printer
&& Printer
->document_started
) {
1697 struct spoolss_EndDocPrinter e
;
1699 e
.in
.handle
= r
->in
.handle
;
1701 _spoolss_EndDocPrinter(p
, &e
);
1704 if (!close_printer_handle(p
, r
->in
.handle
))
1707 /* clear the returned printer handle. Observed behavior
1708 from Win2k server. Don't think this really matters.
1709 Previous code just copied the value of the closed
1712 ZERO_STRUCTP(r
->out
.handle
);
1717 /****************************************************************
1718 _spoolss_DeletePrinter
1719 ****************************************************************/
1721 WERROR
_spoolss_DeletePrinter(pipes_struct
*p
,
1722 struct spoolss_DeletePrinter
*r
)
1724 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1728 if (Printer
&& Printer
->document_started
) {
1729 struct spoolss_EndDocPrinter e
;
1731 e
.in
.handle
= r
->in
.handle
;
1733 _spoolss_EndDocPrinter(p
, &e
);
1736 if (get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
1737 winreg_delete_printer_key(p
->mem_ctx
,
1739 lp_const_servicename(snum
),
1743 result
= delete_printer_handle(p
, r
->in
.handle
);
1748 /*******************************************************************
1749 * static function to lookup the version id corresponding to an
1750 * long architecture string
1751 ******************************************************************/
1753 static const struct print_architecture_table_node archi_table
[]= {
1755 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
1756 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
1757 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
1758 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
1759 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
1760 {"Windows IA64", SPL_ARCH_IA64
, 3 },
1761 {"Windows x64", SPL_ARCH_X64
, 3 },
1765 static int get_version_id(const char *arch
)
1769 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1771 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1772 return (archi_table
[i
].version
);
1778 /****************************************************************
1779 _spoolss_DeletePrinterDriver
1780 ****************************************************************/
1782 WERROR
_spoolss_DeletePrinterDriver(pipes_struct
*p
,
1783 struct spoolss_DeletePrinterDriver
*r
)
1786 struct spoolss_DriverInfo8
*info
= NULL
;
1787 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1790 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1792 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1793 and not a printer admin, then fail */
1795 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1796 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1797 && !token_contains_name_in_list(
1798 uidtoname(p
->server_info
->utok
.uid
),
1799 p
->server_info
->info3
->base
.domain
.string
,
1801 p
->server_info
->ptok
,
1802 lp_printer_admin(-1)) )
1804 return WERR_ACCESS_DENIED
;
1807 /* check that we have a valid driver name first */
1809 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
1810 return WERR_INVALID_ENVIRONMENT
;
1812 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
,
1813 r
->in
.architecture
, r
->in
.driver
,
1815 if (!W_ERROR_IS_OK(status
)) {
1816 /* try for Win2k driver if "Windows NT x86" */
1818 if ( version
== 2 ) {
1821 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
,
1825 if (!W_ERROR_IS_OK(status
)) {
1826 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1830 /* otherwise it was a failure */
1832 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1838 if (printer_driver_in_use(p
->mem_ctx
, p
->server_info
, info
)) {
1839 status
= WERR_PRINTER_DRIVER_IN_USE
;
1844 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
,
1846 r
->in
.driver
, 3, &info_win2k
);
1847 if (W_ERROR_IS_OK(status
)) {
1848 /* if we get to here, we now have 2 driver info structures to remove */
1849 /* remove the Win2k driver first*/
1851 status
= winreg_del_driver(p
->mem_ctx
,
1854 talloc_free(info_win2k
);
1856 /* this should not have failed---if it did, report to client */
1857 if (!W_ERROR_IS_OK(status
)) {
1863 status
= winreg_del_driver(p
->mem_ctx
, p
->server_info
, info
, version
);
1871 /****************************************************************
1872 _spoolss_DeletePrinterDriverEx
1873 ****************************************************************/
1875 WERROR
_spoolss_DeletePrinterDriverEx(pipes_struct
*p
,
1876 struct spoolss_DeletePrinterDriverEx
*r
)
1878 struct spoolss_DriverInfo8
*info
= NULL
;
1879 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1883 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1885 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1886 and not a printer admin, then fail */
1888 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1889 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1890 && !token_contains_name_in_list(
1891 uidtoname(p
->server_info
->utok
.uid
),
1892 p
->server_info
->info3
->base
.domain
.string
,
1894 p
->server_info
->ptok
, lp_printer_admin(-1)) )
1896 return WERR_ACCESS_DENIED
;
1899 /* check that we have a valid driver name first */
1900 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
1901 /* this is what NT returns */
1902 return WERR_INVALID_ENVIRONMENT
;
1905 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
1906 version
= r
->in
.version
;
1908 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
,
1909 r
->in
.architecture
, r
->in
.driver
,
1911 if (!W_ERROR_IS_OK(status
)) {
1912 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1915 * if the client asked for a specific version,
1916 * or this is something other than Windows NT x86,
1920 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
1923 /* try for Win2k driver if "Windows NT x86" */
1926 status
= winreg_get_driver(info
, p
->server_info
,
1930 if (!W_ERROR_IS_OK(status
)) {
1931 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1936 if (printer_driver_in_use(info
, p
->server_info
, info
)) {
1937 status
= WERR_PRINTER_DRIVER_IN_USE
;
1942 * we have a couple of cases to consider.
1943 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1944 * then the delete should fail if **any** files overlap with
1946 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1947 * non-overlapping files
1948 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1949 * is set, the do not delete any files
1950 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1953 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
1955 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1958 (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) &&
1959 printer_driver_files_in_use(info
, p
->server_info
, info
)) {
1960 /* no idea of the correct error here */
1961 status
= WERR_ACCESS_DENIED
;
1966 /* also check for W32X86/3 if necessary; maybe we already have? */
1968 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
1969 status
= winreg_get_driver(info
, p
->server_info
,
1971 r
->in
.driver
, 3, &info_win2k
);
1972 if (W_ERROR_IS_OK(status
)) {
1975 (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) &&
1976 printer_driver_files_in_use(info
, p
->server_info
,
1978 /* no idea of the correct error here */
1979 talloc_free(info_win2k
);
1980 status
= WERR_ACCESS_DENIED
;
1984 /* if we get to here, we now have 2 driver info structures to remove */
1985 /* remove the Win2k driver first*/
1987 status
= winreg_del_driver(info
, p
->server_info
,
1990 /* this should not have failed---if it did, report to client */
1992 if (!W_ERROR_IS_OK(status
)) {
1997 * now delete any associated files if delete_files is
1998 * true. Even if this part failes, we return succes
1999 * because the driver doesn not exist any more
2002 delete_driver_files(p
->server_info
,
2008 status
= winreg_del_driver(info
, p
->server_info
, info
, version
);
2009 if (!W_ERROR_IS_OK(status
)) {
2014 * now delete any associated files if delete_files is
2015 * true. Even if this part failes, we return succes
2016 * because the driver doesn not exist any more
2019 delete_driver_files(p
->server_info
, info
);
2028 /****************************************************************************
2029 Internal routine for storing printerdata
2030 ***************************************************************************/
2032 WERROR
set_printer_dataex(NT_PRINTER_INFO_LEVEL
*printer
,
2033 const char *key
, const char *value
,
2034 uint32_t type
, uint8_t *data
, int real_len
)
2036 /* the registry objects enforce uniqueness based on value name */
2038 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2041 /********************************************************************
2042 GetPrinterData on a printer server Handle.
2043 ********************************************************************/
2045 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2047 enum winreg_Type
*type
,
2048 union spoolss_PrinterData
*data
)
2050 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2052 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2058 if (!StrCaseCmp(value
, "BeepEnabled")) {
2064 if (!StrCaseCmp(value
, "EventLog")) {
2066 /* formally was 0x1b */
2071 if (!StrCaseCmp(value
, "NetPopup")) {
2077 if (!StrCaseCmp(value
, "MajorVersion")) {
2080 /* Windows NT 4.0 seems to not allow uploading of drivers
2081 to a server that reports 0x3 as the MajorVersion.
2082 need to investigate more how Win2k gets around this .
2085 if (RA_WINNT
== get_remote_arch()) {
2094 if (!StrCaseCmp(value
, "MinorVersion")) {
2101 * uint32_t size = 0x114
2102 * uint32_t major = 5
2103 * uint32_t minor = [0|1]
2104 * uint32_t build = [2195|2600]
2105 * extra unicode string = e.g. "Service Pack 3"
2107 if (!StrCaseCmp(value
, "OSVersion")) {
2109 enum ndr_err_code ndr_err
;
2110 struct spoolss_OSVersion os
;
2112 os
.major
= 5; /* Windows 2000 == 5.0 */
2114 os
.build
= 2195; /* build */
2115 os
.extra_string
= ""; /* leave extra string empty */
2117 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2118 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2119 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2120 return WERR_GENERAL_FAILURE
;
2124 data
->binary
= blob
;
2130 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2133 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2134 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2139 if (!StrCaseCmp(value
, "Architecture")) {
2141 data
->string
= talloc_strdup(mem_ctx
,
2142 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2143 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2148 if (!StrCaseCmp(value
, "DsPresent")) {
2151 /* only show the publish check box if we are a
2152 member of a AD domain */
2154 if (lp_security() == SEC_ADS
) {
2162 if (!StrCaseCmp(value
, "DNSMachineName")) {
2163 const char *hostname
= get_mydnsfullname();
2166 return WERR_BADFILE
;
2170 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2171 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2178 return WERR_INVALID_PARAM
;
2181 /****************************************************************
2182 _spoolss_GetPrinterData
2183 ****************************************************************/
2185 WERROR
_spoolss_GetPrinterData(pipes_struct
*p
,
2186 struct spoolss_GetPrinterData
*r
)
2188 struct spoolss_GetPrinterDataEx r2
;
2190 r2
.in
.handle
= r
->in
.handle
;
2191 r2
.in
.key_name
= "PrinterDriverData";
2192 r2
.in
.value_name
= r
->in
.value_name
;
2193 r2
.in
.offered
= r
->in
.offered
;
2194 r2
.out
.type
= r
->out
.type
;
2195 r2
.out
.data
= r
->out
.data
;
2196 r2
.out
.needed
= r
->out
.needed
;
2198 return _spoolss_GetPrinterDataEx(p
, &r2
);
2201 /*********************************************************
2202 Connect to the client machine.
2203 **********************************************************/
2205 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2206 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2209 struct cli_state
*the_cli
;
2210 struct sockaddr_storage rm_addr
;
2211 char addr
[INET6_ADDRSTRLEN
];
2213 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2214 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2216 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2217 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2220 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2222 rm_addr
= *client_ss
;
2223 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2224 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2228 if (ismyaddr((struct sockaddr
*)&rm_addr
)) {
2229 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2234 /* setup the connection */
2235 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2236 &rm_addr
, 0, "IPC$", "IPC",
2240 0, lp_client_signing(), NULL
);
2242 if ( !NT_STATUS_IS_OK( ret
) ) {
2243 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2248 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2249 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2250 cli_shutdown(the_cli
);
2255 * Ok - we have an anonymous connection to the IPC$ share.
2256 * Now start the NT Domain stuff :-).
2259 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2260 if (!NT_STATUS_IS_OK(ret
)) {
2261 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2262 remote_machine
, nt_errstr(ret
)));
2263 cli_shutdown(the_cli
);
2270 /***************************************************************************
2271 Connect to the client.
2272 ****************************************************************************/
2274 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2275 uint32_t localprinter
, uint32_t type
,
2276 struct policy_handle
*handle
,
2277 struct sockaddr_storage
*client_ss
)
2283 * If it's the first connection, contact the client
2284 * and connect to the IPC$ share anonymously
2286 if (smb_connections
==0) {
2287 fstring unix_printer
;
2289 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2291 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2294 messaging_register(smbd_messaging_context(), NULL
,
2295 MSG_PRINTER_NOTIFY2
,
2296 receive_notify2_message_list
);
2297 /* Tell the connections db we're now interested in printer
2298 * notify messages. */
2299 serverid_register_msg_flags(
2300 messaging_server_id(smbd_messaging_context()),
2301 true, FLAG_MSG_PRINT_NOTIFY
);
2305 * Tell the specific printing tdb we want messages for this printer
2306 * by registering our PID.
2309 if (!print_notify_register_pid(snum
))
2310 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2314 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2322 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2323 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2324 win_errstr(result
)));
2326 return (W_ERROR_IS_OK(result
));
2329 /****************************************************************
2330 ****************************************************************/
2332 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2333 const struct spoolss_NotifyOption
*r
)
2335 struct spoolss_NotifyOption
*option
;
2342 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2349 if (!option
->count
) {
2353 option
->types
= talloc_zero_array(option
,
2354 struct spoolss_NotifyOptionType
, option
->count
);
2355 if (!option
->types
) {
2356 talloc_free(option
);
2360 for (i
=0; i
< option
->count
; i
++) {
2361 option
->types
[i
] = r
->types
[i
];
2363 if (option
->types
[i
].count
) {
2364 option
->types
[i
].fields
= talloc_zero_array(option
,
2365 union spoolss_Field
, option
->types
[i
].count
);
2366 if (!option
->types
[i
].fields
) {
2367 talloc_free(option
);
2370 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2371 option
->types
[i
].fields
[k
] =
2372 r
->types
[i
].fields
[k
];
2380 /****************************************************************
2381 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2383 * before replying OK: status=0 a rpc call is made to the workstation
2384 * asking ReplyOpenPrinter
2386 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2387 * called from api_spoolss_rffpcnex
2388 ****************************************************************/
2390 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct
*p
,
2391 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2394 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2395 struct sockaddr_storage client_ss
;
2397 /* store the notify value in the printer struct */
2399 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2402 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2403 "Invalid handle (%s:%u:%u).\n",
2404 OUR_HANDLE(r
->in
.handle
)));
2408 Printer
->notify
.flags
= r
->in
.flags
;
2409 Printer
->notify
.options
= r
->in
.options
;
2410 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2412 TALLOC_FREE(Printer
->notify
.option
);
2413 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2415 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2417 /* Connect to the client machine and send a ReplyOpenPrinter */
2419 if ( Printer
->printer_type
== SPLHND_SERVER
)
2421 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2422 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2425 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2426 "client_address is %s\n", p
->client_address
));
2428 if (!interpret_string_addr(&client_ss
, p
->client_address
,
2430 return WERR_SERVER_UNAVAILABLE
;
2433 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2434 Printer
->notify
.printerlocal
, 1,
2435 &Printer
->notify
.client_hnd
, &client_ss
))
2436 return WERR_SERVER_UNAVAILABLE
;
2438 Printer
->notify
.client_connected
= true;
2443 /*******************************************************************
2444 * fill a notify_info_data with the servername
2445 ********************************************************************/
2447 static void spoolss_notify_server_name(int snum
,
2448 struct spoolss_Notify
*data
,
2449 print_queue_struct
*queue
,
2450 struct spoolss_PrinterInfo2
*pinfo2
,
2451 TALLOC_CTX
*mem_ctx
)
2453 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->servername
);
2456 /*******************************************************************
2457 * fill a notify_info_data with the printername (not including the servername).
2458 ********************************************************************/
2460 static void spoolss_notify_printer_name(int snum
,
2461 struct spoolss_Notify
*data
,
2462 print_queue_struct
*queue
,
2463 struct spoolss_PrinterInfo2
*pinfo2
,
2464 TALLOC_CTX
*mem_ctx
)
2466 /* the notify name should not contain the \\server\ part */
2467 const char *p
= strrchr(pinfo2
->printername
, '\\');
2470 p
= pinfo2
->printername
;
2475 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2478 /*******************************************************************
2479 * fill a notify_info_data with the servicename
2480 ********************************************************************/
2482 static void spoolss_notify_share_name(int snum
,
2483 struct spoolss_Notify
*data
,
2484 print_queue_struct
*queue
,
2485 struct spoolss_PrinterInfo2
*pinfo2
,
2486 TALLOC_CTX
*mem_ctx
)
2488 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2491 /*******************************************************************
2492 * fill a notify_info_data with the port name
2493 ********************************************************************/
2495 static void spoolss_notify_port_name(int snum
,
2496 struct spoolss_Notify
*data
,
2497 print_queue_struct
*queue
,
2498 struct spoolss_PrinterInfo2
*pinfo2
,
2499 TALLOC_CTX
*mem_ctx
)
2501 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->portname
);
2504 /*******************************************************************
2505 * fill a notify_info_data with the printername
2506 * but it doesn't exist, have to see what to do
2507 ********************************************************************/
2509 static void spoolss_notify_driver_name(int snum
,
2510 struct spoolss_Notify
*data
,
2511 print_queue_struct
*queue
,
2512 struct spoolss_PrinterInfo2
*pinfo2
,
2513 TALLOC_CTX
*mem_ctx
)
2515 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->drivername
);
2518 /*******************************************************************
2519 * fill a notify_info_data with the comment
2520 ********************************************************************/
2522 static void spoolss_notify_comment(int snum
,
2523 struct spoolss_Notify
*data
,
2524 print_queue_struct
*queue
,
2525 struct spoolss_PrinterInfo2
*pinfo2
,
2526 TALLOC_CTX
*mem_ctx
)
2530 if (*pinfo2
->comment
== '\0') {
2531 p
= lp_comment(snum
);
2533 p
= pinfo2
->comment
;
2536 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2539 /*******************************************************************
2540 * fill a notify_info_data with the comment
2541 * location = "Room 1, floor 2, building 3"
2542 ********************************************************************/
2544 static void spoolss_notify_location(int snum
,
2545 struct spoolss_Notify
*data
,
2546 print_queue_struct
*queue
,
2547 struct spoolss_PrinterInfo2
*pinfo2
,
2548 TALLOC_CTX
*mem_ctx
)
2550 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->location
);
2553 /*******************************************************************
2554 * fill a notify_info_data with the device mode
2555 * jfm:xxxx don't to it for know but that's a real problem !!!
2556 ********************************************************************/
2558 static void spoolss_notify_devmode(int snum
,
2559 struct spoolss_Notify
*data
,
2560 print_queue_struct
*queue
,
2561 struct spoolss_PrinterInfo2
*pinfo2
,
2562 TALLOC_CTX
*mem_ctx
)
2564 /* for a dummy implementation we have to zero the fields */
2565 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2568 /*******************************************************************
2569 * fill a notify_info_data with the separator file name
2570 ********************************************************************/
2572 static void spoolss_notify_sepfile(int snum
,
2573 struct spoolss_Notify
*data
,
2574 print_queue_struct
*queue
,
2575 struct spoolss_PrinterInfo2
*pinfo2
,
2576 TALLOC_CTX
*mem_ctx
)
2578 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->sepfile
);
2581 /*******************************************************************
2582 * fill a notify_info_data with the print processor
2583 * jfm:xxxx return always winprint to indicate we don't do anything to it
2584 ********************************************************************/
2586 static void spoolss_notify_print_processor(int snum
,
2587 struct spoolss_Notify
*data
,
2588 print_queue_struct
*queue
,
2589 struct spoolss_PrinterInfo2
*pinfo2
,
2590 TALLOC_CTX
*mem_ctx
)
2592 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->printprocessor
);
2595 /*******************************************************************
2596 * fill a notify_info_data with the print processor options
2597 * jfm:xxxx send an empty string
2598 ********************************************************************/
2600 static void spoolss_notify_parameters(int snum
,
2601 struct spoolss_Notify
*data
,
2602 print_queue_struct
*queue
,
2603 struct spoolss_PrinterInfo2
*pinfo2
,
2604 TALLOC_CTX
*mem_ctx
)
2606 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->parameters
);
2609 /*******************************************************************
2610 * fill a notify_info_data with the data type
2611 * jfm:xxxx always send RAW as data type
2612 ********************************************************************/
2614 static void spoolss_notify_datatype(int snum
,
2615 struct spoolss_Notify
*data
,
2616 print_queue_struct
*queue
,
2617 struct spoolss_PrinterInfo2
*pinfo2
,
2618 TALLOC_CTX
*mem_ctx
)
2620 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->datatype
);
2623 /*******************************************************************
2624 * fill a notify_info_data with the security descriptor
2625 * jfm:xxxx send an null pointer to say no security desc
2626 * have to implement security before !
2627 ********************************************************************/
2629 static void spoolss_notify_security_desc(int snum
,
2630 struct spoolss_Notify
*data
,
2631 print_queue_struct
*queue
,
2632 struct spoolss_PrinterInfo2
*pinfo2
,
2633 TALLOC_CTX
*mem_ctx
)
2635 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
, pinfo2
->secdesc
);
2638 /*******************************************************************
2639 * fill a notify_info_data with the attributes
2640 * jfm:xxxx a samba printer is always shared
2641 ********************************************************************/
2643 static void spoolss_notify_attributes(int snum
,
2644 struct spoolss_Notify
*data
,
2645 print_queue_struct
*queue
,
2646 struct spoolss_PrinterInfo2
*pinfo2
,
2647 TALLOC_CTX
*mem_ctx
)
2649 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->attributes
);
2652 /*******************************************************************
2653 * fill a notify_info_data with the priority
2654 ********************************************************************/
2656 static void spoolss_notify_priority(int snum
,
2657 struct spoolss_Notify
*data
,
2658 print_queue_struct
*queue
,
2659 struct spoolss_PrinterInfo2
*pinfo2
,
2660 TALLOC_CTX
*mem_ctx
)
2662 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->priority
);
2665 /*******************************************************************
2666 * fill a notify_info_data with the default priority
2667 ********************************************************************/
2669 static void spoolss_notify_default_priority(int snum
,
2670 struct spoolss_Notify
*data
,
2671 print_queue_struct
*queue
,
2672 struct spoolss_PrinterInfo2
*pinfo2
,
2673 TALLOC_CTX
*mem_ctx
)
2675 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->defaultpriority
);
2678 /*******************************************************************
2679 * fill a notify_info_data with the start time
2680 ********************************************************************/
2682 static void spoolss_notify_start_time(int snum
,
2683 struct spoolss_Notify
*data
,
2684 print_queue_struct
*queue
,
2685 struct spoolss_PrinterInfo2
*pinfo2
,
2686 TALLOC_CTX
*mem_ctx
)
2688 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->starttime
);
2691 /*******************************************************************
2692 * fill a notify_info_data with the until time
2693 ********************************************************************/
2695 static void spoolss_notify_until_time(int snum
,
2696 struct spoolss_Notify
*data
,
2697 print_queue_struct
*queue
,
2698 struct spoolss_PrinterInfo2
*pinfo2
,
2699 TALLOC_CTX
*mem_ctx
)
2701 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->untiltime
);
2704 /*******************************************************************
2705 * fill a notify_info_data with the status
2706 ********************************************************************/
2708 static void spoolss_notify_status(int snum
,
2709 struct spoolss_Notify
*data
,
2710 print_queue_struct
*queue
,
2711 struct spoolss_PrinterInfo2
*pinfo2
,
2712 TALLOC_CTX
*mem_ctx
)
2714 print_status_struct status
;
2716 print_queue_length(snum
, &status
);
2717 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
2720 /*******************************************************************
2721 * fill a notify_info_data with the number of jobs queued
2722 ********************************************************************/
2724 static void spoolss_notify_cjobs(int snum
,
2725 struct spoolss_Notify
*data
,
2726 print_queue_struct
*queue
,
2727 struct spoolss_PrinterInfo2
*pinfo2
,
2728 TALLOC_CTX
*mem_ctx
)
2730 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, print_queue_length(snum
, NULL
));
2733 /*******************************************************************
2734 * fill a notify_info_data with the average ppm
2735 ********************************************************************/
2737 static void spoolss_notify_average_ppm(int snum
,
2738 struct spoolss_Notify
*data
,
2739 print_queue_struct
*queue
,
2740 struct spoolss_PrinterInfo2
*pinfo2
,
2741 TALLOC_CTX
*mem_ctx
)
2743 /* always respond 8 pages per minutes */
2744 /* a little hard ! */
2745 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->averageppm
);
2748 /*******************************************************************
2749 * fill a notify_info_data with username
2750 ********************************************************************/
2752 static void spoolss_notify_username(int snum
,
2753 struct spoolss_Notify
*data
,
2754 print_queue_struct
*queue
,
2755 struct spoolss_PrinterInfo2
*pinfo2
,
2756 TALLOC_CTX
*mem_ctx
)
2758 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
2761 /*******************************************************************
2762 * fill a notify_info_data with job status
2763 ********************************************************************/
2765 static void spoolss_notify_job_status(int snum
,
2766 struct spoolss_Notify
*data
,
2767 print_queue_struct
*queue
,
2768 struct spoolss_PrinterInfo2
*pinfo2
,
2769 TALLOC_CTX
*mem_ctx
)
2771 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
2774 /*******************************************************************
2775 * fill a notify_info_data with job name
2776 ********************************************************************/
2778 static void spoolss_notify_job_name(int snum
,
2779 struct spoolss_Notify
*data
,
2780 print_queue_struct
*queue
,
2781 struct spoolss_PrinterInfo2
*pinfo2
,
2782 TALLOC_CTX
*mem_ctx
)
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
2787 /*******************************************************************
2788 * fill a notify_info_data with job status
2789 ********************************************************************/
2791 static void spoolss_notify_job_status_string(int snum
,
2792 struct spoolss_Notify
*data
,
2793 print_queue_struct
*queue
,
2794 struct spoolss_PrinterInfo2
*pinfo2
,
2795 TALLOC_CTX
*mem_ctx
)
2798 * Now we're returning job status codes we just return a "" here. JRA.
2803 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2806 switch (queue
->status
) {
2811 p
= ""; /* NT provides the paused string */
2820 #endif /* NO LONGER NEEDED. */
2822 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2825 /*******************************************************************
2826 * fill a notify_info_data with job time
2827 ********************************************************************/
2829 static void spoolss_notify_job_time(int snum
,
2830 struct spoolss_Notify
*data
,
2831 print_queue_struct
*queue
,
2832 struct spoolss_PrinterInfo2
*pinfo2
,
2833 TALLOC_CTX
*mem_ctx
)
2835 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2838 /*******************************************************************
2839 * fill a notify_info_data with job size
2840 ********************************************************************/
2842 static void spoolss_notify_job_size(int snum
,
2843 struct spoolss_Notify
*data
,
2844 print_queue_struct
*queue
,
2845 struct spoolss_PrinterInfo2
*pinfo2
,
2846 TALLOC_CTX
*mem_ctx
)
2848 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
2851 /*******************************************************************
2852 * fill a notify_info_data with page info
2853 ********************************************************************/
2854 static void spoolss_notify_total_pages(int snum
,
2855 struct spoolss_Notify
*data
,
2856 print_queue_struct
*queue
,
2857 struct spoolss_PrinterInfo2
*pinfo2
,
2858 TALLOC_CTX
*mem_ctx
)
2860 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
2863 /*******************************************************************
2864 * fill a notify_info_data with pages printed info.
2865 ********************************************************************/
2866 static void spoolss_notify_pages_printed(int snum
,
2867 struct spoolss_Notify
*data
,
2868 print_queue_struct
*queue
,
2869 struct spoolss_PrinterInfo2
*pinfo2
,
2870 TALLOC_CTX
*mem_ctx
)
2872 /* Add code when back-end tracks this */
2873 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2876 /*******************************************************************
2877 Fill a notify_info_data with job position.
2878 ********************************************************************/
2880 static void spoolss_notify_job_position(int snum
,
2881 struct spoolss_Notify
*data
,
2882 print_queue_struct
*queue
,
2883 struct spoolss_PrinterInfo2
*pinfo2
,
2884 TALLOC_CTX
*mem_ctx
)
2886 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
2889 /*******************************************************************
2890 Fill a notify_info_data with submitted time.
2891 ********************************************************************/
2893 static void spoolss_notify_submitted_time(int snum
,
2894 struct spoolss_Notify
*data
,
2895 print_queue_struct
*queue
,
2896 struct spoolss_PrinterInfo2
*pinfo2
,
2897 TALLOC_CTX
*mem_ctx
)
2899 data
->data
.string
.string
= NULL
;
2900 data
->data
.string
.size
= 0;
2902 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
2903 &data
->data
.string
.string
,
2904 &data
->data
.string
.size
);
2908 struct s_notify_info_data_table
2910 enum spoolss_NotifyType type
;
2913 enum spoolss_NotifyTable variable_type
;
2914 void (*fn
) (int snum
, struct spoolss_Notify
*data
,
2915 print_queue_struct
*queue
,
2916 struct spoolss_PrinterInfo2
*pinfo2
,
2917 TALLOC_CTX
*mem_ctx
);
2920 /* A table describing the various print notification constants and
2921 whether the notification data is a pointer to a variable sized
2922 buffer, a one value uint32_t or a two value uint32_t. */
2924 static const struct s_notify_info_data_table notify_info_data_table
[] =
2926 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
2927 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
2928 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
2929 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
2930 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
2931 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
2932 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
2933 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
2934 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
2935 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
2936 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
2937 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
2938 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
2939 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
2940 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
2941 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
2942 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
2943 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
2944 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
2945 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
2946 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
2947 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
2948 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
2949 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
2950 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
2951 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
2952 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
2953 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
2954 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
2955 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
2956 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
2957 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
2958 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
2959 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
2960 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
2961 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
2962 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
2963 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
2964 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
2965 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
2966 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
2967 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
2968 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
2969 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
2970 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
2971 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
2972 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
2973 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
2974 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
2977 /*******************************************************************
2978 Return the variable_type of info_data structure.
2979 ********************************************************************/
2981 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
2986 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
2987 if ( (notify_info_data_table
[i
].type
== type
) &&
2988 (notify_info_data_table
[i
].field
== field
) ) {
2989 return notify_info_data_table
[i
].variable_type
;
2993 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
2998 /****************************************************************************
2999 ****************************************************************************/
3001 static bool search_notify(enum spoolss_NotifyType type
,
3007 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3008 if (notify_info_data_table
[i
].type
== type
&&
3009 notify_info_data_table
[i
].field
== field
&&
3010 notify_info_data_table
[i
].fn
!= NULL
) {
3019 /****************************************************************************
3020 ****************************************************************************/
3022 static void construct_info_data(struct spoolss_Notify
*info_data
,
3023 enum spoolss_NotifyType type
,
3024 uint16_t field
, int id
)
3026 info_data
->type
= type
;
3027 info_data
->field
.field
= field
;
3028 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3029 info_data
->job_id
= id
;
3032 /*******************************************************************
3034 * fill a notify_info struct with info asked
3036 ********************************************************************/
3038 static bool construct_notify_printer_info(Printer_entry
*print_hnd
,
3039 struct spoolss_NotifyInfo
*info
,
3040 struct spoolss_PrinterInfo2
*pinfo2
,
3042 const struct spoolss_NotifyOptionType
*option_type
,
3044 TALLOC_CTX
*mem_ctx
)
3047 enum spoolss_NotifyType type
;
3050 struct spoolss_Notify
*current_data
;
3051 print_queue_struct
*queue
=NULL
;
3053 type
= option_type
->type
;
3055 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3056 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3057 option_type
->count
, lp_servicename(snum
)));
3059 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3060 field
= option_type
->fields
[field_num
].field
;
3062 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3064 if (!search_notify(type
, field
, &j
) )
3067 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3068 struct spoolss_Notify
,
3070 if (info
->notifies
== NULL
) {
3071 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3075 current_data
= &info
->notifies
[info
->count
];
3077 construct_info_data(current_data
, type
, field
, id
);
3079 DEBUG(10, ("construct_notify_printer_info: "
3080 "calling [%s] snum=%d printername=[%s])\n",
3081 notify_info_data_table
[j
].name
, snum
,
3082 pinfo2
->printername
));
3084 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3093 /*******************************************************************
3095 * fill a notify_info struct with info asked
3097 ********************************************************************/
3099 static bool construct_notify_jobs_info(print_queue_struct
*queue
,
3100 struct spoolss_NotifyInfo
*info
,
3101 struct spoolss_PrinterInfo2
*pinfo2
,
3103 const struct spoolss_NotifyOptionType
*option_type
,
3105 TALLOC_CTX
*mem_ctx
)
3108 enum spoolss_NotifyType type
;
3110 struct spoolss_Notify
*current_data
;
3112 DEBUG(4,("construct_notify_jobs_info\n"));
3114 type
= option_type
->type
;
3116 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3117 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3118 option_type
->count
));
3120 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3121 field
= option_type
->fields
[field_num
].field
;
3123 if (!search_notify(type
, field
, &j
) )
3126 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3127 struct spoolss_Notify
,
3129 if (info
->notifies
== NULL
) {
3130 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3134 current_data
=&(info
->notifies
[info
->count
]);
3136 construct_info_data(current_data
, type
, field
, id
);
3137 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3146 * JFM: The enumeration is not that simple, it's even non obvious.
3148 * let's take an example: I want to monitor the PRINTER SERVER for
3149 * the printer's name and the number of jobs currently queued.
3150 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3151 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3153 * I have 3 printers on the back of my server.
3155 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3158 * 1 printer 1 name 1
3159 * 2 printer 1 cjob 1
3160 * 3 printer 2 name 2
3161 * 4 printer 2 cjob 2
3162 * 5 printer 3 name 3
3163 * 6 printer 3 name 3
3165 * that's the print server case, the printer case is even worse.
3168 /*******************************************************************
3170 * enumerate all printers on the printserver
3171 * fill a notify_info struct with info asked
3173 ********************************************************************/
3175 static WERROR
printserver_notify_info(pipes_struct
*p
,
3176 struct policy_handle
*hnd
,
3177 struct spoolss_NotifyInfo
*info
,
3178 TALLOC_CTX
*mem_ctx
)
3181 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3182 int n_services
=lp_numservices();
3184 struct spoolss_NotifyOption
*option
;
3185 struct spoolss_NotifyOptionType option_type
;
3186 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3189 DEBUG(4,("printserver_notify_info\n"));
3194 option
= Printer
->notify
.option
;
3197 info
->notifies
= NULL
;
3200 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3201 sending a ffpcn() request first */
3206 for (i
=0; i
<option
->count
; i
++) {
3207 option_type
= option
->types
[i
];
3209 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3212 for (snum
= 0; snum
< n_services
; snum
++) {
3213 if (!lp_browseable(snum
) ||
3214 !lp_snum_ok(snum
) ||
3215 !lp_print_ok(snum
)) {
3216 continue; /* skip */
3219 /* FIXME: should we use a SYSTEM server_info here? */
3220 result
= winreg_get_printer(mem_ctx
, p
->server_info
,
3221 Printer
->servername
,
3222 lp_servicename(snum
),
3224 if (!W_ERROR_IS_OK(result
)) {
3225 DEBUG(4, ("printserver_notify_info: "
3226 "Failed to get printer [%s]\n",
3227 lp_servicename(snum
)));
3232 construct_notify_printer_info(Printer
, info
,
3237 TALLOC_FREE(pinfo2
);
3243 * Debugging information, don't delete.
3246 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3247 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3248 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3250 for (i
=0; i
<info
->count
; i
++) {
3251 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3252 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3253 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3260 /*******************************************************************
3262 * fill a notify_info struct with info asked
3264 ********************************************************************/
3266 static WERROR
printer_notify_info(pipes_struct
*p
, struct policy_handle
*hnd
,
3267 struct spoolss_NotifyInfo
*info
,
3268 TALLOC_CTX
*mem_ctx
)
3271 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3274 struct spoolss_NotifyOption
*option
;
3275 struct spoolss_NotifyOptionType option_type
;
3277 print_queue_struct
*queue
=NULL
;
3278 print_status_struct status
;
3279 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3282 DEBUG(4,("printer_notify_info\n"));
3287 option
= Printer
->notify
.option
;
3291 info
->notifies
= NULL
;
3294 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3295 sending a ffpcn() request first */
3300 get_printer_snum(p
, hnd
, &snum
, NULL
);
3302 /* FIXME: should we use a SYSTEM server_info here ? */
3303 result
= winreg_get_printer(mem_ctx
, p
->server_info
,
3304 Printer
->servername
,
3305 lp_servicename(snum
), &pinfo2
);
3306 if (!W_ERROR_IS_OK(result
)) {
3310 for (i
=0; i
<option
->count
; i
++) {
3311 option_type
= option
->types
[i
];
3313 switch (option_type
.type
) {
3314 case PRINTER_NOTIFY_TYPE
:
3315 if (construct_notify_printer_info(Printer
, info
,
3323 case JOB_NOTIFY_TYPE
:
3325 count
= print_queue_status(snum
, &queue
, &status
);
3327 for (j
=0; j
<count
; j
++) {
3328 construct_notify_jobs_info(&queue
[j
], info
,
3341 * Debugging information, don't delete.
3344 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3345 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3346 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3348 for (i=0; i<info->count; i++) {
3349 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3350 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3351 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3355 talloc_free(pinfo2
);
3359 /****************************************************************
3360 _spoolss_RouterRefreshPrinterChangeNotify
3361 ****************************************************************/
3363 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(pipes_struct
*p
,
3364 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3366 struct spoolss_NotifyInfo
*info
;
3368 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3369 WERROR result
= WERR_BADFID
;
3371 /* we always have a spoolss_NotifyInfo struct */
3372 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3374 result
= WERR_NOMEM
;
3378 *r
->out
.info
= info
;
3381 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3382 "Invalid handle (%s:%u:%u).\n",
3383 OUR_HANDLE(r
->in
.handle
)));
3387 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3390 * We are now using the change value, and
3391 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3392 * I don't have a global notification system, I'm sending back all the
3393 * informations even when _NOTHING_ has changed.
3396 /* We need to keep track of the change value to send back in
3397 RRPCN replies otherwise our updates are ignored. */
3399 Printer
->notify
.fnpcn
= true;
3401 if (Printer
->notify
.client_connected
) {
3402 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3403 "Saving change value in request [%x]\n",
3405 Printer
->notify
.change
= r
->in
.change_low
;
3408 /* just ignore the spoolss_NotifyOption */
3410 switch (Printer
->printer_type
) {
3412 result
= printserver_notify_info(p
, r
->in
.handle
,
3416 case SPLHND_PRINTER
:
3417 result
= printer_notify_info(p
, r
->in
.handle
,
3422 Printer
->notify
.fnpcn
= false;
3428 /********************************************************************
3429 * construct_printer_info_0
3430 * fill a printer_info_0 struct
3431 ********************************************************************/
3433 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3434 struct auth_serversupplied_info
*server_info
,
3435 struct spoolss_PrinterInfo2
*info2
,
3436 struct spoolss_PrinterInfo0
*r
,
3440 counter_printer_0
*session_counter
;
3441 struct timeval setuptime
;
3442 print_status_struct status
;
3444 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3445 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3447 r
->servername
= talloc_strdup(mem_ctx
, info2
->servername
);
3448 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3450 count
= print_queue_length(snum
, &status
);
3452 /* check if we already have a counter for this printer */
3453 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3454 if (session_counter
->snum
== snum
)
3458 /* it's the first time, add it to the list */
3459 if (session_counter
== NULL
) {
3460 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3461 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3462 ZERO_STRUCTP(session_counter
);
3463 session_counter
->snum
= snum
;
3464 session_counter
->counter
= 0;
3465 DLIST_ADD(counter_list
, session_counter
);
3469 session_counter
->counter
++;
3475 get_startup_time(&setuptime
);
3476 init_systemtime(&r
->time
, gmtime(&setuptime
.tv_sec
));
3479 * the global_counter should be stored in a TDB as it's common to all the clients
3480 * and should be zeroed on samba startup
3482 r
->global_counter
= session_counter
->counter
;
3484 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3485 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3486 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3487 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3489 r
->max_spooling
= 0;
3490 r
->session_counter
= session_counter
->counter
;
3491 r
->num_error_out_of_paper
= 0x0;
3492 r
->num_error_not_ready
= 0x0; /* number of print failure */
3494 r
->number_of_processors
= 0x1;
3495 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3496 r
->high_part_total_bytes
= 0x0;
3497 winreg_printer_get_changeid(mem_ctx
, server_info
, info2
->sharename
, &r
->change_id
); /* ChangeID in milliseconds*/
3498 r
->last_error
= WERR_OK
;
3499 r
->status
= nt_printq_status(status
.status
);
3500 r
->enumerate_network_printers
= 0x0;
3501 r
->c_setprinter
= 0x0;
3502 r
->processor_architecture
= 0x0;
3503 r
->processor_level
= 0x6; /* 6 ???*/
3512 /********************************************************************
3513 * construct_printer_info1
3514 * fill a spoolss_PrinterInfo1 struct
3515 ********************************************************************/
3517 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3518 const struct spoolss_PrinterInfo2
*info2
,
3520 struct spoolss_PrinterInfo1
*r
,
3525 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3529 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3531 if (info2
->comment
== NULL
|| info2
->comment
[0] == '\0') {
3532 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3534 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
); /* saved comment */
3536 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3538 r
->name
= talloc_strdup(mem_ctx
, info2
->printername
);
3539 W_ERROR_HAVE_NO_MEMORY(r
->name
);
3544 /********************************************************************
3545 * construct_printer_info2
3546 * fill a spoolss_PrinterInfo2 struct
3547 ********************************************************************/
3549 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3550 const struct spoolss_PrinterInfo2
*info2
,
3551 struct spoolss_PrinterInfo2
*r
,
3555 print_status_struct status
;
3557 count
= print_queue_length(snum
, &status
);
3559 r
->servername
= talloc_strdup(mem_ctx
, info2
->servername
);
3560 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3561 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3562 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3563 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
3564 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
3565 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
3566 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3567 r
->drivername
= talloc_strdup(mem_ctx
, info2
->drivername
);
3568 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
3570 if (info2
->comment
[0] == '\0') {
3571 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3573 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
);
3575 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3577 r
->location
= talloc_strdup(mem_ctx
, info2
->location
);
3578 W_ERROR_HAVE_NO_MEMORY(r
->location
);
3579 r
->sepfile
= talloc_strdup(mem_ctx
, info2
->sepfile
);
3580 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
3581 r
->printprocessor
= talloc_strdup(mem_ctx
, info2
->printprocessor
);
3582 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
3583 r
->datatype
= talloc_strdup(mem_ctx
, info2
->datatype
);
3584 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
3585 r
->parameters
= talloc_strdup(mem_ctx
, info2
->parameters
);
3586 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
3588 r
->attributes
= info2
->attributes
;
3590 r
->priority
= info2
->priority
;
3591 r
->defaultpriority
= info2
->defaultpriority
;
3592 r
->starttime
= info2
->starttime
;
3593 r
->untiltime
= info2
->untiltime
;
3594 r
->status
= nt_printq_status(status
.status
);
3596 r
->averageppm
= info2
->averageppm
;
3598 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
3600 DEBUG(8,("Returning NULL Devicemode!\n"));
3605 if (info2
->secdesc
!= NULL
) {
3606 /* don't use talloc_steal() here unless you do a deep steal of all
3607 the SEC_DESC members */
3609 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
3615 /********************************************************************
3616 * construct_printer_info3
3617 * fill a spoolss_PrinterInfo3 struct
3618 ********************************************************************/
3620 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3621 const struct spoolss_PrinterInfo2
*info2
,
3622 struct spoolss_PrinterInfo3
*r
,
3625 /* These are the components of the SD we are returning. */
3627 if (info2
->secdesc
!= NULL
) {
3628 /* don't use talloc_steal() here unless you do a deep steal of all
3629 the SEC_DESC members */
3631 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
3632 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3638 /********************************************************************
3639 * construct_printer_info4
3640 * fill a spoolss_PrinterInfo4 struct
3641 ********************************************************************/
3643 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
3644 const struct spoolss_PrinterInfo2
*info2
,
3645 struct spoolss_PrinterInfo4
*r
,
3648 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3649 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3650 r
->servername
= talloc_strdup(mem_ctx
, info2
->servername
);
3651 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3653 r
->attributes
= info2
->attributes
;
3658 /********************************************************************
3659 * construct_printer_info5
3660 * fill a spoolss_PrinterInfo5 struct
3661 ********************************************************************/
3663 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
3664 const struct spoolss_PrinterInfo2
*info2
,
3665 struct spoolss_PrinterInfo5
*r
,
3668 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3669 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3670 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
3671 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3673 r
->attributes
= info2
->attributes
;
3675 /* these two are not used by NT+ according to MSDN */
3676 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
3677 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
3682 /********************************************************************
3683 * construct_printer_info_6
3684 * fill a spoolss_PrinterInfo6 struct
3685 ********************************************************************/
3687 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
3688 const struct spoolss_PrinterInfo2
*info2
,
3689 struct spoolss_PrinterInfo6
*r
,
3693 print_status_struct status
;
3695 count
= print_queue_length(snum
, &status
);
3697 r
->status
= nt_printq_status(status
.status
);
3702 /********************************************************************
3703 * construct_printer_info7
3704 * fill a spoolss_PrinterInfo7 struct
3705 ********************************************************************/
3707 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
3708 Printer_entry
*print_hnd
,
3709 struct spoolss_PrinterInfo7
*r
,
3712 struct auth_serversupplied_info
*server_info
;
3716 status
= make_server_info_system(mem_ctx
, &server_info
);
3717 if (!NT_STATUS_IS_OK(status
)) {
3718 DEBUG(0, ("construct_printer_info7: "
3719 "Could not create system server_info\n"));
3723 if (is_printer_published(mem_ctx
, server_info
, print_hnd
->servername
,
3724 lp_servicename(snum
), &guid
, NULL
)) {
3725 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
3726 r
->action
= DSPRINT_PUBLISH
;
3728 r
->guid
= talloc_strdup(mem_ctx
, "");
3729 r
->action
= DSPRINT_UNPUBLISH
;
3731 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
3733 TALLOC_FREE(server_info
);
3737 /********************************************************************
3738 * construct_printer_info8
3739 * fill a spoolss_PrinterInfo8 struct
3740 ********************************************************************/
3742 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
3743 const struct spoolss_PrinterInfo2
*info2
,
3744 struct spoolss_DeviceModeInfo
*r
,
3747 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
3749 DEBUG(8,("Returning NULL Devicemode!\n"));
3756 /********************************************************************
3757 ********************************************************************/
3759 static bool snum_is_shared_printer(int snum
)
3761 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
3764 /********************************************************************
3765 Spoolss_enumprinters.
3766 ********************************************************************/
3768 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
3769 struct auth_serversupplied_info
*server_info
,
3772 union spoolss_PrinterInfo
**info_p
,
3776 int n_services
= lp_numservices();
3777 union spoolss_PrinterInfo
*info
= NULL
;
3779 WERROR result
= WERR_OK
;
3784 for (snum
= 0; snum
< n_services
; snum
++) {
3786 const char *printer
;
3787 struct spoolss_PrinterInfo2
*info2
;
3789 if (!snum_is_shared_printer(snum
)) {
3793 printer
= lp_const_servicename(snum
);
3795 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3798 result
= winreg_create_printer(mem_ctx
,
3802 if (!W_ERROR_IS_OK(result
)) {
3806 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
3807 union spoolss_PrinterInfo
,
3810 result
= WERR_NOMEM
;
3814 result
= winreg_get_printer(mem_ctx
, server_info
,
3815 NULL
, printer
, &info2
);
3816 if (!W_ERROR_IS_OK(result
)) {
3822 result
= construct_printer_info0(info
, server_info
, info2
,
3823 &info
[count
].info0
, snum
);
3826 result
= construct_printer_info1(info
, info2
, flags
,
3827 &info
[count
].info1
, snum
);
3830 result
= construct_printer_info2(info
, info2
,
3831 &info
[count
].info2
, snum
);
3834 result
= construct_printer_info4(info
, info2
,
3835 &info
[count
].info4
, snum
);
3838 result
= construct_printer_info5(info
, info2
,
3839 &info
[count
].info5
, snum
);
3843 result
= WERR_UNKNOWN_LEVEL
;
3847 if (!W_ERROR_IS_OK(result
)) {
3858 if (!W_ERROR_IS_OK(result
)) {
3868 /********************************************************************
3869 * handle enumeration of printers at level 0
3870 ********************************************************************/
3872 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
3873 struct auth_serversupplied_info
*server_info
,
3875 const char *servername
,
3876 union spoolss_PrinterInfo
**info
,
3879 DEBUG(4,("enum_all_printers_info_0\n"));
3881 return enum_all_printers_info_level(mem_ctx
, server_info
, 0, flags
, info
, count
);
3885 /********************************************************************
3886 ********************************************************************/
3888 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
3889 struct auth_serversupplied_info
*server_info
,
3891 union spoolss_PrinterInfo
**info
,
3894 DEBUG(4,("enum_all_printers_info_1\n"));
3896 return enum_all_printers_info_level(mem_ctx
, server_info
, 1, flags
, info
, count
);
3899 /********************************************************************
3900 enum_all_printers_info_1_local.
3901 *********************************************************************/
3903 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
3904 struct auth_serversupplied_info
*server_info
,
3905 union spoolss_PrinterInfo
**info
,
3908 DEBUG(4,("enum_all_printers_info_1_local\n"));
3910 return enum_all_printers_info_1(mem_ctx
, server_info
, PRINTER_ENUM_ICON8
, info
, count
);
3913 /********************************************************************
3914 enum_all_printers_info_1_name.
3915 *********************************************************************/
3917 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
3918 struct auth_serversupplied_info
*server_info
,
3920 union spoolss_PrinterInfo
**info
,
3923 const char *s
= name
;
3925 DEBUG(4,("enum_all_printers_info_1_name\n"));
3927 if ((name
[0] == '\\') && (name
[1] == '\\')) {
3931 if (!is_myname_or_ipaddr(s
)) {
3932 return WERR_INVALID_NAME
;
3935 return enum_all_printers_info_1(mem_ctx
, server_info
, PRINTER_ENUM_ICON8
, info
, count
);
3938 /********************************************************************
3939 enum_all_printers_info_1_network.
3940 *********************************************************************/
3942 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
3943 struct auth_serversupplied_info
*server_info
,
3945 union spoolss_PrinterInfo
**info
,
3948 const char *s
= name
;
3950 DEBUG(4,("enum_all_printers_info_1_network\n"));
3952 /* If we respond to a enum_printers level 1 on our name with flags
3953 set to PRINTER_ENUM_REMOTE with a list of printers then these
3954 printers incorrectly appear in the APW browse list.
3955 Specifically the printers for the server appear at the workgroup
3956 level where all the other servers in the domain are
3957 listed. Windows responds to this call with a
3958 WERR_CAN_NOT_COMPLETE so we should do the same. */
3960 if (name
[0] == '\\' && name
[1] == '\\') {
3964 if (is_myname_or_ipaddr(s
)) {
3965 return WERR_CAN_NOT_COMPLETE
;
3968 return enum_all_printers_info_1(mem_ctx
, server_info
, PRINTER_ENUM_NAME
, info
, count
);
3971 /********************************************************************
3972 * api_spoolss_enumprinters
3974 * called from api_spoolss_enumprinters (see this to understand)
3975 ********************************************************************/
3977 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
3978 struct auth_serversupplied_info
*server_info
,
3979 union spoolss_PrinterInfo
**info
,
3982 DEBUG(4,("enum_all_printers_info_2\n"));
3984 return enum_all_printers_info_level(mem_ctx
, server_info
, 2, 0, info
, count
);
3987 /********************************************************************
3988 * handle enumeration of printers at level 1
3989 ********************************************************************/
3991 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
3992 struct auth_serversupplied_info
*server_info
,
3995 union spoolss_PrinterInfo
**info
,
3998 /* Not all the flags are equals */
4000 if (flags
& PRINTER_ENUM_LOCAL
) {
4001 return enum_all_printers_info_1_local(mem_ctx
, server_info
, info
, count
);
4004 if (flags
& PRINTER_ENUM_NAME
) {
4005 return enum_all_printers_info_1_name(mem_ctx
, server_info
, name
, info
, count
);
4008 if (flags
& PRINTER_ENUM_NETWORK
) {
4009 return enum_all_printers_info_1_network(mem_ctx
, server_info
, name
, info
, count
);
4012 return WERR_OK
; /* NT4sp5 does that */
4015 /********************************************************************
4016 * handle enumeration of printers at level 2
4017 ********************************************************************/
4019 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4020 struct auth_serversupplied_info
*server_info
,
4022 const char *servername
,
4023 union spoolss_PrinterInfo
**info
,
4026 if (flags
& PRINTER_ENUM_LOCAL
) {
4027 return enum_all_printers_info_2(mem_ctx
, server_info
, info
, count
);
4030 if (flags
& PRINTER_ENUM_NAME
) {
4031 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4032 return WERR_INVALID_NAME
;
4035 return enum_all_printers_info_2(mem_ctx
, server_info
, info
, count
);
4038 if (flags
& PRINTER_ENUM_REMOTE
) {
4039 return WERR_UNKNOWN_LEVEL
;
4045 /********************************************************************
4046 * handle enumeration of printers at level 4
4047 ********************************************************************/
4049 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4050 struct auth_serversupplied_info
*server_info
,
4052 const char *servername
,
4053 union spoolss_PrinterInfo
**info
,
4056 DEBUG(4,("enum_all_printers_info_4\n"));
4058 return enum_all_printers_info_level(mem_ctx
, server_info
, 4, flags
, info
, count
);
4062 /********************************************************************
4063 * handle enumeration of printers at level 5
4064 ********************************************************************/
4066 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4067 struct auth_serversupplied_info
*server_info
,
4069 const char *servername
,
4070 union spoolss_PrinterInfo
**info
,
4073 DEBUG(4,("enum_all_printers_info_5\n"));
4075 return enum_all_printers_info_level(mem_ctx
, server_info
, 5, flags
, info
, count
);
4078 /****************************************************************
4079 _spoolss_EnumPrinters
4080 ****************************************************************/
4082 WERROR
_spoolss_EnumPrinters(pipes_struct
*p
,
4083 struct spoolss_EnumPrinters
*r
)
4085 const char *name
= NULL
;
4088 /* that's an [in out] buffer */
4090 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4091 return WERR_INVALID_PARAM
;
4094 DEBUG(4,("_spoolss_EnumPrinters\n"));
4098 *r
->out
.info
= NULL
;
4102 * flags==PRINTER_ENUM_NAME
4103 * if name=="" then enumerates all printers
4104 * if name!="" then enumerate the printer
4105 * flags==PRINTER_ENUM_REMOTE
4106 * name is NULL, enumerate printers
4107 * Level 2: name!="" enumerates printers, name can't be NULL
4108 * Level 3: doesn't exist
4109 * Level 4: does a local registry lookup
4110 * Level 5: same as Level 2
4114 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4115 W_ERROR_HAVE_NO_MEMORY(name
);
4118 switch (r
->in
.level
) {
4120 result
= enumprinters_level0(p
->mem_ctx
, p
->server_info
,
4122 r
->out
.info
, r
->out
.count
);
4125 result
= enumprinters_level1(p
->mem_ctx
, p
->server_info
,
4127 r
->out
.info
, r
->out
.count
);
4130 result
= enumprinters_level2(p
->mem_ctx
, p
->server_info
,
4132 r
->out
.info
, r
->out
.count
);
4135 result
= enumprinters_level4(p
->mem_ctx
, p
->server_info
,
4137 r
->out
.info
, r
->out
.count
);
4140 result
= enumprinters_level5(p
->mem_ctx
, p
->server_info
,
4142 r
->out
.info
, r
->out
.count
);
4145 return WERR_UNKNOWN_LEVEL
;
4148 if (!W_ERROR_IS_OK(result
)) {
4152 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4153 spoolss_EnumPrinters
,
4154 *r
->out
.info
, r
->in
.level
,
4156 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4157 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4159 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4162 /****************************************************************
4164 ****************************************************************/
4166 WERROR
_spoolss_GetPrinter(pipes_struct
*p
,
4167 struct spoolss_GetPrinter
*r
)
4169 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4170 struct spoolss_PrinterInfo2
*info2
= NULL
;
4171 WERROR result
= WERR_OK
;
4172 const char *servername
= NULL
;
4175 /* that's an [in out] buffer */
4177 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4178 return WERR_INVALID_PARAM
;
4183 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4187 if (Printer
!= NULL
|| Printer
->servername
!= NULL
) {
4188 servername
= Printer
->servername
;
4191 result
= winreg_get_printer(p
->mem_ctx
,
4194 lp_const_servicename(snum
),
4196 if (!W_ERROR_IS_OK(result
)) {
4200 switch (r
->in
.level
) {
4202 result
= construct_printer_info0(p
->mem_ctx
, p
->server_info
,
4204 &r
->out
.info
->info0
, snum
);
4207 result
= construct_printer_info1(p
->mem_ctx
, info2
,
4209 &r
->out
.info
->info1
, snum
);
4212 result
= construct_printer_info2(p
->mem_ctx
, info2
,
4213 &r
->out
.info
->info2
, snum
);
4216 result
= construct_printer_info3(p
->mem_ctx
, info2
,
4217 &r
->out
.info
->info3
, snum
);
4220 result
= construct_printer_info4(p
->mem_ctx
, info2
,
4221 &r
->out
.info
->info4
, snum
);
4224 result
= construct_printer_info5(p
->mem_ctx
, info2
,
4225 &r
->out
.info
->info5
, snum
);
4228 result
= construct_printer_info6(p
->mem_ctx
, info2
,
4229 &r
->out
.info
->info6
, snum
);
4232 result
= construct_printer_info7(p
->mem_ctx
, Printer
,
4233 &r
->out
.info
->info7
, snum
);
4236 result
= construct_printer_info8(p
->mem_ctx
, info2
,
4237 &r
->out
.info
->info8
, snum
);
4240 result
= WERR_UNKNOWN_LEVEL
;
4244 if (!W_ERROR_IS_OK(result
)) {
4245 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4246 r
->in
.level
, win_errstr(result
)));
4247 TALLOC_FREE(r
->out
.info
);
4251 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4252 r
->out
.info
, r
->in
.level
);
4253 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4255 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4258 /********************************************************************
4259 ********************************************************************/
4261 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4263 if (in && strlen(in)) { \
4264 out = talloc_strdup(mem_ctx, in); \
4265 W_ERROR_HAVE_NO_MEMORY(out); \
4271 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4273 if (in && strlen(in)) { \
4274 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4276 out = talloc_strdup(mem_ctx, ""); \
4278 W_ERROR_HAVE_NO_MEMORY(out); \
4281 static WERROR
string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4282 const char **string_array
,
4283 const char ***presult
,
4284 const char *cservername
,
4288 int i
, num_strings
= 0;
4289 const char **array
= NULL
;
4291 if (string_array
== NULL
) {
4292 return WERR_INVALID_PARAMETER
;;
4295 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4296 const char *str
= NULL
;
4298 if (cservername
== NULL
|| arch
== NULL
) {
4299 FILL_DRIVER_STRING(mem_ctx
, string_array
[i
], str
);
4301 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
, arch
, version
, string_array
[i
], str
);
4304 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4311 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4312 &array
, &num_strings
);
4322 /********************************************************************
4323 * fill a spoolss_DriverInfo1 struct
4324 ********************************************************************/
4326 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4327 struct spoolss_DriverInfo1
*r
,
4328 const struct spoolss_DriverInfo8
*driver
,
4329 const char *servername
)
4331 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4332 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4337 /********************************************************************
4338 * fill a spoolss_DriverInfo2 struct
4339 ********************************************************************/
4341 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4342 struct spoolss_DriverInfo2
*r
,
4343 const struct spoolss_DriverInfo8
*driver
,
4344 const char *servername
)
4347 const char *cservername
= canon_servername(servername
);
4349 r
->version
= driver
->version
;
4351 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4352 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4353 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4354 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4356 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4357 driver
->architecture
,
4359 driver
->driver_path
,
4362 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4363 driver
->architecture
,
4368 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4369 driver
->architecture
,
4371 driver
->config_file
,
4377 /********************************************************************
4378 * fill a spoolss_DriverInfo3 struct
4379 ********************************************************************/
4381 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4382 struct spoolss_DriverInfo3
*r
,
4383 const struct spoolss_DriverInfo8
*driver
,
4384 const char *servername
)
4386 const char *cservername
= canon_servername(servername
);
4388 r
->version
= driver
->version
;
4390 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4391 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4392 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4393 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4395 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4396 driver
->architecture
,
4398 driver
->driver_path
,
4401 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4402 driver
->architecture
,
4407 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4408 driver
->architecture
,
4410 driver
->config_file
,
4413 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4414 driver
->architecture
,
4419 FILL_DRIVER_STRING(mem_ctx
,
4420 driver
->monitor_name
,
4423 FILL_DRIVER_STRING(mem_ctx
,
4424 driver
->default_datatype
,
4425 r
->default_datatype
);
4427 return string_array_from_driver_info(mem_ctx
,
4428 driver
->dependent_files
,
4429 &r
->dependent_files
,
4431 driver
->architecture
,
4435 /********************************************************************
4436 * fill a spoolss_DriverInfo4 struct
4437 ********************************************************************/
4439 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4440 struct spoolss_DriverInfo4
*r
,
4441 const struct spoolss_DriverInfo8
*driver
,
4442 const char *servername
)
4444 const char *cservername
= canon_servername(servername
);
4447 r
->version
= driver
->version
;
4449 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4450 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4451 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4452 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4454 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4455 driver
->architecture
,
4457 driver
->driver_path
,
4460 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4461 driver
->architecture
,
4466 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4467 driver
->architecture
,
4469 driver
->config_file
,
4472 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4473 driver
->architecture
,
4478 result
= string_array_from_driver_info(mem_ctx
,
4479 driver
->dependent_files
,
4480 &r
->dependent_files
,
4482 driver
->architecture
,
4484 if (!W_ERROR_IS_OK(result
)) {
4488 FILL_DRIVER_STRING(mem_ctx
,
4489 driver
->monitor_name
,
4492 FILL_DRIVER_STRING(mem_ctx
,
4493 driver
->default_datatype
,
4494 r
->default_datatype
);
4497 result
= string_array_from_driver_info(mem_ctx
,
4498 driver
->previous_names
,
4505 /********************************************************************
4506 * fill a spoolss_DriverInfo5 struct
4507 ********************************************************************/
4509 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
4510 struct spoolss_DriverInfo5
*r
,
4511 const struct spoolss_DriverInfo8
*driver
,
4512 const char *servername
)
4514 const char *cservername
= canon_servername(servername
);
4516 r
->version
= driver
->version
;
4518 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4519 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4520 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4521 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4523 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4524 driver
->architecture
,
4526 driver
->driver_path
,
4529 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4530 driver
->architecture
,
4535 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4536 driver
->architecture
,
4538 driver
->config_file
,
4541 r
->driver_attributes
= 0;
4542 r
->config_version
= 0;
4543 r
->driver_version
= 0;
4547 /********************************************************************
4548 * fill a spoolss_DriverInfo6 struct
4549 ********************************************************************/
4551 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4552 struct spoolss_DriverInfo6
*r
,
4553 const struct spoolss_DriverInfo8
*driver
,
4554 const char *servername
)
4556 const char *cservername
= canon_servername(servername
);
4559 r
->version
= driver
->version
;
4561 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4562 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4563 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4564 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4566 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4567 driver
->architecture
,
4569 driver
->driver_path
,
4572 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4573 driver
->architecture
,
4578 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4579 driver
->architecture
,
4581 driver
->config_file
,
4584 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4585 driver
->architecture
,
4590 FILL_DRIVER_STRING(mem_ctx
,
4591 driver
->monitor_name
,
4594 FILL_DRIVER_STRING(mem_ctx
,
4595 driver
->default_datatype
,
4596 r
->default_datatype
);
4598 result
= string_array_from_driver_info(mem_ctx
,
4599 driver
->dependent_files
,
4600 &r
->dependent_files
,
4602 driver
->architecture
,
4604 if (!W_ERROR_IS_OK(result
)) {
4608 result
= string_array_from_driver_info(mem_ctx
,
4609 driver
->previous_names
,
4612 if (!W_ERROR_IS_OK(result
)) {
4616 r
->driver_date
= driver
->driver_date
;
4617 r
->driver_version
= driver
->driver_version
;
4619 FILL_DRIVER_STRING(mem_ctx
,
4620 driver
->manufacturer_name
,
4621 r
->manufacturer_name
);
4622 FILL_DRIVER_STRING(mem_ctx
,
4623 driver
->manufacturer_url
,
4624 r
->manufacturer_url
);
4625 FILL_DRIVER_STRING(mem_ctx
,
4626 driver
->hardware_id
,
4628 FILL_DRIVER_STRING(mem_ctx
,
4635 /********************************************************************
4636 * fill a spoolss_DriverInfo8 struct
4637 ********************************************************************/
4639 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
4640 struct spoolss_DriverInfo8
*r
,
4641 const struct spoolss_DriverInfo8
*driver
,
4642 const char *servername
)
4644 const char *cservername
= canon_servername(servername
);
4647 r
->version
= driver
->version
;
4649 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4650 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4651 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4652 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4654 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4655 driver
->architecture
,
4657 driver
->driver_path
,
4660 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4661 driver
->architecture
,
4666 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4667 driver
->architecture
,
4669 driver
->config_file
,
4672 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4673 driver
->architecture
,
4678 FILL_DRIVER_STRING(mem_ctx
,
4679 driver
->monitor_name
,
4682 FILL_DRIVER_STRING(mem_ctx
,
4683 driver
->default_datatype
,
4684 r
->default_datatype
);
4686 result
= string_array_from_driver_info(mem_ctx
,
4687 driver
->dependent_files
,
4688 &r
->dependent_files
,
4690 driver
->architecture
,
4692 if (!W_ERROR_IS_OK(result
)) {
4696 result
= string_array_from_driver_info(mem_ctx
,
4697 driver
->previous_names
,
4700 if (!W_ERROR_IS_OK(result
)) {
4704 r
->driver_date
= driver
->driver_date
;
4705 r
->driver_version
= driver
->driver_version
;
4707 FILL_DRIVER_STRING(mem_ctx
,
4708 driver
->manufacturer_name
,
4709 r
->manufacturer_name
);
4710 FILL_DRIVER_STRING(mem_ctx
,
4711 driver
->manufacturer_url
,
4712 r
->manufacturer_url
);
4713 FILL_DRIVER_STRING(mem_ctx
,
4714 driver
->hardware_id
,
4716 FILL_DRIVER_STRING(mem_ctx
,
4720 FILL_DRIVER_STRING(mem_ctx
,
4721 driver
->print_processor
,
4722 r
->print_processor
);
4723 FILL_DRIVER_STRING(mem_ctx
,
4724 driver
->vendor_setup
,
4727 result
= string_array_from_driver_info(mem_ctx
,
4728 driver
->color_profiles
,
4731 if (!W_ERROR_IS_OK(result
)) {
4735 FILL_DRIVER_STRING(mem_ctx
,
4739 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
4741 result
= string_array_from_driver_info(mem_ctx
,
4742 driver
->core_driver_dependencies
,
4743 &r
->core_driver_dependencies
,
4745 if (!W_ERROR_IS_OK(result
)) {
4749 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
4750 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
4755 #if 0 /* disabled until marshalling issues are resolved - gd */
4756 /********************************************************************
4757 ********************************************************************/
4759 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
4760 struct spoolss_DriverFileInfo
*r
,
4761 const char *cservername
,
4762 const char *file_name
,
4763 enum spoolss_DriverFileType file_type
,
4764 uint32_t file_version
)
4766 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4767 cservername
, file_name
);
4768 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
4769 r
->file_type
= file_type
;
4770 r
->file_version
= file_version
;
4775 /********************************************************************
4776 ********************************************************************/
4778 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
4779 const struct spoolss_DriverInfo8
*driver
,
4780 const char *cservername
,
4781 struct spoolss_DriverFileInfo
**info_p
,
4784 struct spoolss_DriverFileInfo
*info
= NULL
;
4792 if (strlen(driver
->driver_path
)) {
4793 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4794 struct spoolss_DriverFileInfo
,
4796 W_ERROR_HAVE_NO_MEMORY(info
);
4797 result
= fill_spoolss_DriverFileInfo(info
,
4800 driver
->driver_path
,
4801 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
4803 W_ERROR_NOT_OK_RETURN(result
);
4807 if (strlen(driver
->config_file
)) {
4808 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4809 struct spoolss_DriverFileInfo
,
4811 W_ERROR_HAVE_NO_MEMORY(info
);
4812 result
= fill_spoolss_DriverFileInfo(info
,
4815 driver
->config_file
,
4816 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
4818 W_ERROR_NOT_OK_RETURN(result
);
4822 if (strlen(driver
->data_file
)) {
4823 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4824 struct spoolss_DriverFileInfo
,
4826 W_ERROR_HAVE_NO_MEMORY(info
);
4827 result
= fill_spoolss_DriverFileInfo(info
,
4831 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
4833 W_ERROR_NOT_OK_RETURN(result
);
4837 if (strlen(driver
->help_file
)) {
4838 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4839 struct spoolss_DriverFileInfo
,
4841 W_ERROR_HAVE_NO_MEMORY(info
);
4842 result
= fill_spoolss_DriverFileInfo(info
,
4846 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
4848 W_ERROR_NOT_OK_RETURN(result
);
4852 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
4853 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4854 struct spoolss_DriverFileInfo
,
4856 W_ERROR_HAVE_NO_MEMORY(info
);
4857 result
= fill_spoolss_DriverFileInfo(info
,
4860 driver
->dependent_files
[i
],
4861 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
4863 W_ERROR_NOT_OK_RETURN(result
);
4873 /********************************************************************
4874 * fill a spoolss_DriverInfo101 struct
4875 ********************************************************************/
4877 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
4878 struct spoolss_DriverInfo101
*r
,
4879 const struct spoolss_DriverInfo8
*driver
,
4880 const char *servername
)
4882 const char *cservername
= canon_servername(servername
);
4885 r
->version
= driver
->version
;
4887 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4888 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4889 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4890 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4892 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
4896 if (!W_ERROR_IS_OK(result
)) {
4900 FILL_DRIVER_STRING(mem_ctx
,
4901 driver
->monitor_name
,
4904 FILL_DRIVER_STRING(mem_ctx
,
4905 driver
->default_datatype
,
4906 r
->default_datatype
);
4908 result
= string_array_from_driver_info(mem_ctx
,
4909 driver
->previous_names
,
4912 if (!W_ERROR_IS_OK(result
)) {
4916 r
->driver_date
= driver
->driver_date
;
4917 r
->driver_version
= driver
->driver_version
;
4919 FILL_DRIVER_STRING(mem_ctx
,
4920 driver
->manufacturer_name
,
4921 r
->manufacturer_name
);
4922 FILL_DRIVER_STRING(mem_ctx
,
4923 driver
->manufacturer_url
,
4924 r
->manufacturer_url
);
4925 FILL_DRIVER_STRING(mem_ctx
,
4926 driver
->hardware_id
,
4928 FILL_DRIVER_STRING(mem_ctx
,
4935 /********************************************************************
4936 ********************************************************************/
4938 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
4939 struct auth_serversupplied_info
*server_info
,
4941 union spoolss_DriverInfo
*r
,
4943 const char *servername
,
4944 const char *architecture
,
4947 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
4948 struct spoolss_DriverInfo8
*driver
;
4951 result
= winreg_get_printer(mem_ctx
,
4954 lp_const_servicename(snum
),
4957 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4958 win_errstr(result
)));
4960 if (!W_ERROR_IS_OK(result
)) {
4961 return WERR_INVALID_PRINTER_NAME
;
4964 result
= winreg_get_driver(mem_ctx
, server_info
, architecture
,
4965 pinfo2
->drivername
, version
, &driver
);
4967 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4968 win_errstr(result
)));
4970 if (!W_ERROR_IS_OK(result
)) {
4972 * Is this a W2k client ?
4976 talloc_free(pinfo2
);
4977 return WERR_UNKNOWN_PRINTER_DRIVER
;
4980 /* Yes - try again with a WinNT driver. */
4982 result
= winreg_get_driver(mem_ctx
, server_info
, architecture
,
4985 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4986 win_errstr(result
)));
4987 if (!W_ERROR_IS_OK(result
)) {
4988 talloc_free(pinfo2
);
4989 return WERR_UNKNOWN_PRINTER_DRIVER
;
4995 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
4998 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
5001 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
5004 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
5007 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
5010 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5013 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5015 #if 0 /* disabled until marshalling issues are resolved - gd */
5017 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5021 result
= WERR_UNKNOWN_LEVEL
;
5025 talloc_free(pinfo2
);
5026 talloc_free(driver
);
5031 /****************************************************************
5032 _spoolss_GetPrinterDriver2
5033 ****************************************************************/
5035 WERROR
_spoolss_GetPrinterDriver2(pipes_struct
*p
,
5036 struct spoolss_GetPrinterDriver2
*r
)
5038 Printer_entry
*printer
;
5043 /* that's an [in out] buffer */
5045 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5046 return WERR_INVALID_PARAM
;
5049 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5051 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5052 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5053 return WERR_INVALID_PRINTER_NAME
;
5057 *r
->out
.server_major_version
= 0;
5058 *r
->out
.server_minor_version
= 0;
5060 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5064 result
= construct_printer_driver_info_level(p
->mem_ctx
, p
->server_info
,
5065 r
->in
.level
, r
->out
.info
,
5066 snum
, printer
->servername
,
5068 r
->in
.client_major_version
);
5069 if (!W_ERROR_IS_OK(result
)) {
5070 TALLOC_FREE(r
->out
.info
);
5074 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5075 r
->out
.info
, r
->in
.level
);
5076 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5078 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5082 /****************************************************************
5083 _spoolss_StartPagePrinter
5084 ****************************************************************/
5086 WERROR
_spoolss_StartPagePrinter(pipes_struct
*p
,
5087 struct spoolss_StartPagePrinter
*r
)
5089 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5092 DEBUG(3,("_spoolss_StartPagePrinter: "
5093 "Error in startpageprinter printer handle\n"));
5097 Printer
->page_started
= true;
5101 /****************************************************************
5102 _spoolss_EndPagePrinter
5103 ****************************************************************/
5105 WERROR
_spoolss_EndPagePrinter(pipes_struct
*p
,
5106 struct spoolss_EndPagePrinter
*r
)
5110 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5113 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5114 OUR_HANDLE(r
->in
.handle
)));
5118 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5121 Printer
->page_started
= false;
5122 print_job_endpage(snum
, Printer
->jobid
);
5127 /****************************************************************
5128 _spoolss_StartDocPrinter
5129 ****************************************************************/
5131 WERROR
_spoolss_StartDocPrinter(pipes_struct
*p
,
5132 struct spoolss_StartDocPrinter
*r
)
5134 struct spoolss_DocumentInfo1
*info_1
;
5136 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5139 DEBUG(2,("_spoolss_StartDocPrinter: "
5140 "Invalid handle (%s:%u:%u)\n",
5141 OUR_HANDLE(r
->in
.handle
)));
5145 if (r
->in
.level
!= 1) {
5146 return WERR_UNKNOWN_LEVEL
;
5149 info_1
= r
->in
.info
.info1
;
5152 * a nice thing with NT is it doesn't listen to what you tell it.
5153 * when asked to send _only_ RAW datas, it tries to send datas
5156 * So I add checks like in NT Server ...
5159 if (info_1
->datatype
) {
5160 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5162 return WERR_INVALID_DATATYPE
;
5166 /* get the share number of the printer */
5167 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5171 Printer
->jobid
= print_job_start(p
->server_info
, snum
,
5172 info_1
->document_name
,
5175 /* An error occured in print_job_start() so return an appropriate
5178 if (Printer
->jobid
== -1) {
5179 return map_werror_from_unix(errno
);
5182 Printer
->document_started
= true;
5183 *r
->out
.job_id
= Printer
->jobid
;
5188 /****************************************************************
5189 _spoolss_EndDocPrinter
5190 ****************************************************************/
5192 WERROR
_spoolss_EndDocPrinter(pipes_struct
*p
,
5193 struct spoolss_EndDocPrinter
*r
)
5195 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5199 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5200 OUR_HANDLE(r
->in
.handle
)));
5204 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5208 Printer
->document_started
= false;
5209 print_job_end(snum
, Printer
->jobid
, NORMAL_CLOSE
);
5210 /* error codes unhandled so far ... */
5215 /****************************************************************
5216 _spoolss_WritePrinter
5217 ****************************************************************/
5219 WERROR
_spoolss_WritePrinter(pipes_struct
*p
,
5220 struct spoolss_WritePrinter
*r
)
5222 ssize_t buffer_written
;
5224 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5227 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5228 OUR_HANDLE(r
->in
.handle
)));
5229 *r
->out
.num_written
= r
->in
._data_size
;
5233 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5236 buffer_written
= print_job_write(snum
, Printer
->jobid
,
5237 (const char *)r
->in
.data
.data
,
5239 (size_t)r
->in
._data_size
);
5240 if (buffer_written
== (ssize_t
)-1) {
5241 *r
->out
.num_written
= 0;
5242 if (errno
== ENOSPC
)
5243 return WERR_NO_SPOOL_SPACE
;
5245 return WERR_ACCESS_DENIED
;
5248 *r
->out
.num_written
= r
->in
._data_size
;
5253 /********************************************************************
5254 * api_spoolss_getprinter
5255 * called from the spoolss dispatcher
5257 ********************************************************************/
5259 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5263 WERROR errcode
= WERR_BADFUNC
;
5264 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5267 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5268 OUR_HANDLE(handle
)));
5272 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5276 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5277 errcode
= print_queue_pause(p
->server_info
, snum
);
5279 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5280 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5281 errcode
= print_queue_resume(p
->server_info
, snum
);
5283 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5284 errcode
= print_queue_purge(p
->server_info
, snum
);
5287 return WERR_UNKNOWN_LEVEL
;
5294 /****************************************************************
5295 _spoolss_AbortPrinter
5296 * From MSDN: "Deletes printer's spool file if printer is configured
5298 ****************************************************************/
5300 WERROR
_spoolss_AbortPrinter(pipes_struct
*p
,
5301 struct spoolss_AbortPrinter
*r
)
5303 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5305 WERROR errcode
= WERR_OK
;
5308 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5309 OUR_HANDLE(r
->in
.handle
)));
5313 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5316 print_job_delete(p
->server_info
, snum
, Printer
->jobid
, &errcode
);
5321 /********************************************************************
5322 * called by spoolss_api_setprinter
5323 * when updating a printer description
5324 ********************************************************************/
5326 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5327 pipes_struct
*p
, struct sec_desc_buf
*secdesc_ctr
)
5329 struct spoolss_security_descriptor
*new_secdesc
= NULL
;
5330 struct spoolss_security_descriptor
*old_secdesc
= NULL
;
5331 const char *printer
;
5335 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5337 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5338 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5339 OUR_HANDLE(handle
)));
5341 result
= WERR_BADFID
;
5345 if (secdesc_ctr
== NULL
) {
5346 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5347 result
= WERR_INVALID_PARAM
;
5350 printer
= lp_const_servicename(snum
);
5352 /* Check the user has permissions to change the security
5353 descriptor. By experimentation with two NT machines, the user
5354 requires Full Access to the printer to change security
5357 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5358 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5359 result
= WERR_ACCESS_DENIED
;
5363 /* NT seems to like setting the security descriptor even though
5364 nothing may have actually changed. */
5365 result
= winreg_get_printer_secdesc(p
->mem_ctx
,
5369 if (!W_ERROR_IS_OK(result
)) {
5370 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5371 result
= WERR_BADFID
;
5375 if (DEBUGLEVEL
>= 10) {
5376 struct security_acl
*the_acl
;
5379 the_acl
= secdesc_ctr
->sd
->dacl
;
5380 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5381 printer
, the_acl
->num_aces
));
5383 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5384 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5385 &the_acl
->aces
[i
].trustee
),
5386 the_acl
->aces
[i
].access_mask
));
5389 the_acl
= secdesc_ctr
->sd
->dacl
;
5392 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5393 printer
, the_acl
->num_aces
));
5395 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5396 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5397 &the_acl
->aces
[i
].trustee
),
5398 the_acl
->aces
[i
].access_mask
));
5401 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5405 new_secdesc
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
->sd
, old_secdesc
);
5406 if (new_secdesc
== NULL
) {
5407 result
= WERR_NOMEM
;
5411 if (security_descriptor_equal(new_secdesc
, old_secdesc
)) {
5416 result
= winreg_set_printer_secdesc(p
->mem_ctx
,
5425 /********************************************************************
5426 Canonicalize printer info from a client
5428 ATTN: It does not matter what we set the servername to hear
5429 since we do the necessary work in get_a_printer() to set it to
5430 the correct value based on what the client sent in the
5431 _spoolss_open_printer_ex().
5432 ********************************************************************/
5434 static bool check_printer_ok(TALLOC_CTX
*mem_ctx
,
5435 struct spoolss_SetPrinterInfo2
*info2
,
5438 fstring printername
;
5441 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5442 "portname=%s drivername=%s comment=%s location=%s\n",
5443 info2
->servername
, info2
->printername
, info2
->sharename
,
5444 info2
->portname
, info2
->drivername
, info2
->comment
,
5447 /* we force some elements to "correct" values */
5448 info2
->servername
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
5449 if (info2
->servername
== NULL
) {
5452 info2
->sharename
= talloc_strdup(mem_ctx
, lp_const_servicename(snum
));
5453 if (info2
->sharename
== NULL
) {
5457 /* check to see if we allow printername != sharename */
5458 if (lp_force_printername(snum
)) {
5459 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
5460 global_myname(), info2
->sharename
);
5462 /* make sure printername is in \\server\printername format */
5463 fstrcpy(printername
, info2
->printername
);
5465 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5466 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5470 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
5471 global_myname(), p
);
5473 if (info2
->printername
== NULL
) {
5477 info2
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5478 info2
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5483 /****************************************************************************
5484 ****************************************************************************/
5486 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5488 char *cmd
= lp_addport_cmd();
5489 char *command
= NULL
;
5491 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5492 bool is_print_op
= false;
5495 return WERR_ACCESS_DENIED
;
5498 command
= talloc_asprintf(ctx
,
5499 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5505 is_print_op
= user_has_privileges( token
, &se_printop
);
5507 DEBUG(10,("Running [%s]\n", command
));
5509 /********* BEGIN SePrintOperatorPrivilege **********/
5514 ret
= smbrun(command
, NULL
);
5519 /********* END SePrintOperatorPrivilege **********/
5521 DEBUGADD(10,("returned [%d]\n", ret
));
5523 TALLOC_FREE(command
);
5526 return WERR_ACCESS_DENIED
;
5532 /****************************************************************************
5533 ****************************************************************************/
5535 bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
,
5536 struct spoolss_SetPrinterInfo2
*info2
)
5538 char *cmd
= lp_addprinter_cmd();
5540 char *command
= NULL
;
5544 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5545 bool is_print_op
= false;
5546 char *remote_machine
= talloc_strdup(ctx
, "%m");
5548 if (!remote_machine
) {
5551 remote_machine
= talloc_sub_basic(ctx
,
5552 current_user_info
.smb_name
,
5553 current_user_info
.domain
,
5555 if (!remote_machine
) {
5559 command
= talloc_asprintf(ctx
,
5560 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5561 cmd
, info2
->printername
, info2
->sharename
,
5562 info2
->portname
, info2
->drivername
,
5563 info2
->location
, info2
->comment
, remote_machine
);
5569 is_print_op
= user_has_privileges( token
, &se_printop
);
5571 DEBUG(10,("Running [%s]\n", command
));
5573 /********* BEGIN SePrintOperatorPrivilege **********/
5578 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5579 /* Tell everyone we updated smb.conf. */
5580 message_send_all(smbd_messaging_context(),
5581 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
5587 /********* END SePrintOperatorPrivilege **********/
5589 DEBUGADD(10,("returned [%d]\n", ret
));
5591 TALLOC_FREE(command
);
5592 TALLOC_FREE(remote_machine
);
5600 /* reload our services immediately */
5602 reload_services(false);
5606 /* Get lines and convert them back to dos-codepage */
5607 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
5608 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5611 /* Set the portname to what the script says the portname should be. */
5612 /* but don't require anything to be return from the script exit a good error code */
5615 /* Set the portname to what the script says the portname should be. */
5616 info2
->portname
= talloc_strdup(ctx
, qlines
[0]);
5617 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5620 TALLOC_FREE(qlines
);
5624 static WERROR
update_dsspooler(TALLOC_CTX
*mem_ctx
,
5625 struct auth_serversupplied_info
*server_info
,
5627 struct spoolss_SetPrinterInfo2
*printer
,
5628 struct spoolss_PrinterInfo2
*old_printer
)
5630 bool force_update
= (old_printer
== NULL
);
5631 const char *dnsdomname
;
5632 const char *longname
;
5633 const char *uncname
;
5634 const char *spooling
;
5636 WERROR result
= WERR_OK
;
5638 if (force_update
|| !strequal(printer
->drivername
, old_printer
->drivername
)) {
5639 push_reg_sz(mem_ctx
, &buffer
, printer
->drivername
);
5640 winreg_set_printer_dataex(mem_ctx
,
5643 SPOOL_DSSPOOLER_KEY
,
5644 SPOOL_REG_DRIVERNAME
,
5649 if (!force_update
) {
5650 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5651 printer
->drivername
));
5653 notify_printer_driver(snum
, printer
->drivername
);
5657 if (force_update
|| !strequal(printer
->comment
, old_printer
->comment
)) {
5658 push_reg_sz(mem_ctx
, &buffer
, printer
->comment
);
5659 winreg_set_printer_dataex(mem_ctx
,
5662 SPOOL_DSSPOOLER_KEY
,
5663 SPOOL_REG_DESCRIPTION
,
5668 if (!force_update
) {
5669 notify_printer_comment(snum
, printer
->comment
);
5673 if (force_update
|| !strequal(printer
->sharename
, old_printer
->sharename
)) {
5674 push_reg_sz(mem_ctx
, &buffer
, printer
->sharename
);
5675 winreg_set_printer_dataex(mem_ctx
,
5678 SPOOL_DSSPOOLER_KEY
,
5679 SPOOL_REG_PRINTSHARENAME
,
5684 if (!force_update
) {
5685 notify_printer_sharename(snum
, printer
->sharename
);
5689 if (force_update
|| !strequal(printer
->printername
, old_printer
->printername
)) {
5692 p
= strrchr(printer
->printername
, '\\' );
5696 p
= printer
->printername
;
5699 push_reg_sz(mem_ctx
, &buffer
, p
);
5700 winreg_set_printer_dataex(mem_ctx
,
5703 SPOOL_DSSPOOLER_KEY
,
5704 SPOOL_REG_PRINTERNAME
,
5709 if (!force_update
) {
5710 notify_printer_printername(snum
, p
);
5714 if (force_update
|| !strequal(printer
->portname
, old_printer
->portname
)) {
5715 push_reg_sz(mem_ctx
, &buffer
, printer
->portname
);
5716 winreg_set_printer_dataex(mem_ctx
,
5719 SPOOL_DSSPOOLER_KEY
,
5725 if (!force_update
) {
5726 notify_printer_port(snum
, printer
->portname
);
5730 if (force_update
|| !strequal(printer
->location
, old_printer
->location
)) {
5731 push_reg_sz(mem_ctx
, &buffer
, printer
->location
);
5732 winreg_set_printer_dataex(mem_ctx
,
5735 SPOOL_DSSPOOLER_KEY
,
5741 if (!force_update
) {
5742 notify_printer_location(snum
, printer
->location
);
5746 if (force_update
|| !strequal(printer
->sepfile
, old_printer
->sepfile
)) {
5747 push_reg_sz(mem_ctx
, &buffer
, printer
->sepfile
);
5748 winreg_set_printer_dataex(mem_ctx
,
5751 SPOOL_DSSPOOLER_KEY
,
5752 SPOOL_REG_PRINTSEPARATORFILE
,
5757 if (!force_update
) {
5758 notify_printer_location(snum
, printer
->location
);
5762 if (force_update
|| printer
->starttime
!= old_printer
->starttime
) {
5763 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
5764 SIVAL(buffer
.data
, 0, printer
->starttime
);
5765 winreg_set_printer_dataex(mem_ctx
,
5768 SPOOL_DSSPOOLER_KEY
,
5769 SPOOL_REG_PRINTSTARTTIME
,
5775 if (force_update
|| printer
->untiltime
!= old_printer
->untiltime
) {
5776 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
5777 SIVAL(buffer
.data
, 0, printer
->untiltime
);
5778 winreg_set_printer_dataex(mem_ctx
,
5781 SPOOL_DSSPOOLER_KEY
,
5782 SPOOL_REG_PRINTENDTIME
,
5788 if (force_update
|| printer
->priority
!= old_printer
->priority
) {
5789 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
5790 SIVAL(buffer
.data
, 0, printer
->priority
);
5791 winreg_set_printer_dataex(mem_ctx
,
5794 SPOOL_DSSPOOLER_KEY
,
5801 if (force_update
|| printer
->attributes
!= old_printer
->attributes
) {
5802 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
5803 SIVAL(buffer
.data
, 0, (printer
->attributes
&
5804 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
5805 winreg_set_printer_dataex(mem_ctx
,
5808 SPOOL_DSSPOOLER_KEY
,
5809 SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
5814 switch (printer
->attributes
& 0x3) {
5816 spooling
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
5819 spooling
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
5822 spooling
= SPOOL_REGVAL_PRINTDIRECT
;
5825 spooling
= "unknown";
5827 push_reg_sz(mem_ctx
, &buffer
, spooling
);
5828 winreg_set_printer_dataex(mem_ctx
,
5831 SPOOL_DSSPOOLER_KEY
,
5832 SPOOL_REG_PRINTSPOOLING
,
5838 push_reg_sz(mem_ctx
, &buffer
, global_myname());
5839 winreg_set_printer_dataex(mem_ctx
,
5842 SPOOL_DSSPOOLER_KEY
,
5843 SPOOL_REG_SHORTSERVERNAME
,
5848 dnsdomname
= get_mydnsfullname();
5849 if (dnsdomname
!= NULL
&& dnsdomname
[0] != '\0') {
5850 longname
= talloc_strdup(mem_ctx
, dnsdomname
);
5852 longname
= talloc_strdup(mem_ctx
, global_myname());
5854 if (longname
== NULL
) {
5855 result
= WERR_NOMEM
;
5859 push_reg_sz(mem_ctx
, &buffer
, longname
);
5860 winreg_set_printer_dataex(mem_ctx
,
5863 SPOOL_DSSPOOLER_KEY
,
5864 SPOOL_REG_SERVERNAME
,
5869 uncname
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
5870 global_myname(), printer
->sharename
);
5871 push_reg_sz(mem_ctx
, &buffer
, uncname
);
5872 winreg_set_printer_dataex(mem_ctx
,
5875 SPOOL_DSSPOOLER_KEY
,
5885 /********************************************************************
5886 * Called by spoolss_api_setprinter
5887 * when updating a printer description.
5888 ********************************************************************/
5890 static WERROR
update_printer(pipes_struct
*p
, struct policy_handle
*handle
,
5891 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
5892 struct spoolss_DeviceMode
*devmode
)
5894 uint32_t printer_mask
= SPOOLSS_PRINTER_INFO_ALL
;
5895 struct spoolss_SetPrinterInfo2
*printer
= info_ctr
->info
.info2
;
5896 struct spoolss_PrinterInfo2
*old_printer
;
5897 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5898 const char *servername
= NULL
;
5900 WERROR result
= WERR_OK
;
5901 TALLOC_CTX
*tmp_ctx
;
5903 DEBUG(8,("update_printer\n"));
5905 tmp_ctx
= talloc_new(p
->mem_ctx
);
5906 if (tmp_ctx
== NULL
) {
5911 result
= WERR_BADFID
;
5915 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5916 result
= WERR_BADFID
;
5920 if (Printer
!= NULL
|| Printer
->servername
!= NULL
) {
5921 servername
= Printer
->servername
;
5924 result
= winreg_get_printer(tmp_ctx
,
5927 lp_const_servicename(snum
),
5929 if (!W_ERROR_IS_OK(result
)) {
5930 result
= WERR_BADFID
;
5934 /* Do sanity check on the requested changes for Samba */
5935 if (!check_printer_ok(tmp_ctx
, printer
, snum
)) {
5936 result
= WERR_INVALID_PARAM
;
5940 /* FIXME!!! If the driver has changed we really should verify that
5941 it is installed before doing much else --jerry */
5943 /* Check calling user has permission to update printer description */
5944 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5945 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5946 result
= WERR_ACCESS_DENIED
;
5950 /* Call addprinter hook */
5951 /* Check changes to see if this is really needed */
5953 if (*lp_addprinter_cmd() &&
5954 (!strequal(printer
->drivername
, old_printer
->drivername
) ||
5955 !strequal(printer
->comment
, old_printer
->comment
) ||
5956 !strequal(printer
->portname
, old_printer
->portname
) ||
5957 !strequal(printer
->location
, old_printer
->location
)) )
5959 /* add_printer_hook() will call reload_services() */
5960 if (!add_printer_hook(tmp_ctx
, p
->server_info
->ptok
,
5962 result
= WERR_ACCESS_DENIED
;
5967 update_dsspooler(tmp_ctx
,
5973 printer_mask
&= ~SPOOLSS_PRINTER_INFO_SECDESC
;
5975 if (devmode
== NULL
) {
5976 printer_mask
&= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
5978 result
= winreg_update_printer(tmp_ctx
,
5987 talloc_free(tmp_ctx
);
5992 /****************************************************************************
5993 ****************************************************************************/
5994 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
,
5995 struct policy_handle
*handle
,
5996 struct spoolss_SetPrinterInfo7
*info7
)
5999 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6002 Printer_entry
*Printer
;
6004 if ( lp_security() != SEC_ADS
) {
6005 return WERR_UNKNOWN_LEVEL
;
6008 Printer
= find_printer_index_by_hnd(p
, handle
);
6010 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6015 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6018 result
= winreg_get_printer(p
->mem_ctx
, p
->server_info
,
6019 Printer
->servername
,
6020 lp_servicename(snum
), &pinfo2
);
6021 if (!W_ERROR_IS_OK(result
)) {
6025 nt_printer_publish(pinfo2
, p
->server_info
, pinfo2
, info7
->action
);
6027 TALLOC_FREE(pinfo2
);
6030 return WERR_UNKNOWN_LEVEL
;
6034 /********************************************************************
6035 ********************************************************************/
6037 static WERROR
update_printer_devmode(pipes_struct
*p
, struct policy_handle
*handle
,
6038 struct spoolss_DeviceMode
*devmode
)
6041 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6042 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_DEVMODE
;
6044 DEBUG(8,("update_printer_devmode\n"));
6050 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6054 /* Check calling user has permission to update printer description */
6055 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6056 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6057 return WERR_ACCESS_DENIED
;
6060 return winreg_update_printer(p
->mem_ctx
,
6062 lp_const_servicename(snum
),
6070 /****************************************************************
6072 ****************************************************************/
6074 WERROR
_spoolss_SetPrinter(pipes_struct
*p
,
6075 struct spoolss_SetPrinter
*r
)
6079 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6082 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6083 OUR_HANDLE(r
->in
.handle
)));
6087 /* check the level */
6088 switch (r
->in
.info_ctr
->level
) {
6090 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6092 result
= update_printer(p
, r
->in
.handle
,
6094 r
->in
.devmode_ctr
->devmode
);
6095 if (!W_ERROR_IS_OK(result
))
6097 if (r
->in
.secdesc_ctr
->sd
)
6098 result
= update_printer_sec(r
->in
.handle
, p
,
6102 return update_printer_sec(r
->in
.handle
, p
,
6105 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6106 r
->in
.info_ctr
->info
.info7
);
6108 return update_printer_devmode(p
, r
->in
.handle
,
6109 r
->in
.devmode_ctr
->devmode
);
6111 return WERR_UNKNOWN_LEVEL
;
6115 /****************************************************************
6116 _spoolss_FindClosePrinterNotify
6117 ****************************************************************/
6119 WERROR
_spoolss_FindClosePrinterNotify(pipes_struct
*p
,
6120 struct spoolss_FindClosePrinterNotify
*r
)
6122 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6125 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6126 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6130 if (Printer
->notify
.client_connected
== true) {
6133 if ( Printer
->printer_type
== SPLHND_SERVER
)
6135 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6136 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
6139 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6142 Printer
->notify
.flags
=0;
6143 Printer
->notify
.options
=0;
6144 Printer
->notify
.localmachine
[0]='\0';
6145 Printer
->notify
.printerlocal
=0;
6146 TALLOC_FREE(Printer
->notify
.option
);
6147 Printer
->notify
.client_connected
= false;
6152 /****************************************************************
6154 ****************************************************************/
6156 WERROR
_spoolss_AddJob(pipes_struct
*p
,
6157 struct spoolss_AddJob
*r
)
6159 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6160 return WERR_INVALID_PARAM
;
6163 /* this is what a NT server returns for AddJob. AddJob must fail on
6164 * non-local printers */
6166 if (r
->in
.level
!= 1) {
6167 return WERR_UNKNOWN_LEVEL
;
6170 return WERR_INVALID_PARAM
;
6173 /****************************************************************************
6175 ****************************************************************************/
6177 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
6178 struct spoolss_JobInfo1
*r
,
6179 const print_queue_struct
*queue
,
6180 int position
, int snum
,
6181 struct spoolss_PrinterInfo2
*pinfo2
)
6185 t
= gmtime(&queue
->time
);
6187 r
->job_id
= queue
->job
;
6189 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6190 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6191 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6192 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6193 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6194 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6195 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6196 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6197 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6198 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6199 r
->text_status
= talloc_strdup(mem_ctx
, "");
6200 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6202 r
->status
= nt_printj_status(queue
->status
);
6203 r
->priority
= queue
->priority
;
6204 r
->position
= position
;
6205 r
->total_pages
= queue
->page_count
;
6206 r
->pages_printed
= 0; /* ??? */
6208 init_systemtime(&r
->submitted
, t
);
6213 /****************************************************************************
6215 ****************************************************************************/
6217 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6218 struct spoolss_JobInfo2
*r
,
6219 const print_queue_struct
*queue
,
6220 int position
, int snum
,
6221 struct spoolss_PrinterInfo2
*pinfo2
,
6222 struct spoolss_DeviceMode
*devmode
)
6226 t
= gmtime(&queue
->time
);
6228 r
->job_id
= queue
->job
;
6230 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6231 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6232 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6233 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6234 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6235 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6236 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6237 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6238 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6239 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6240 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6241 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6242 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6243 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6244 r
->parameters
= talloc_strdup(mem_ctx
, "");
6245 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6246 r
->driver_name
= talloc_strdup(mem_ctx
, pinfo2
->drivername
);
6247 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6249 r
->devmode
= devmode
;
6251 r
->text_status
= talloc_strdup(mem_ctx
, "");
6252 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6256 r
->status
= nt_printj_status(queue
->status
);
6257 r
->priority
= queue
->priority
;
6258 r
->position
= position
;
6261 r
->total_pages
= queue
->page_count
;
6262 r
->size
= queue
->size
;
6263 init_systemtime(&r
->submitted
, t
);
6265 r
->pages_printed
= 0; /* ??? */
6270 /****************************************************************************
6272 ****************************************************************************/
6274 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6275 struct spoolss_JobInfo3
*r
,
6276 const print_queue_struct
*queue
,
6277 const print_queue_struct
*next_queue
,
6278 int position
, int snum
,
6279 struct spoolss_PrinterInfo2
*pinfo2
)
6281 r
->job_id
= queue
->job
;
6284 r
->next_job_id
= next_queue
->job
;
6291 /****************************************************************************
6292 Enumjobs at level 1.
6293 ****************************************************************************/
6295 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6296 const print_queue_struct
*queue
,
6297 uint32_t num_queues
, int snum
,
6298 struct spoolss_PrinterInfo2
*pinfo2
,
6299 union spoolss_JobInfo
**info_p
,
6302 union spoolss_JobInfo
*info
;
6304 WERROR result
= WERR_OK
;
6306 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6307 W_ERROR_HAVE_NO_MEMORY(info
);
6309 *count
= num_queues
;
6311 for (i
=0; i
<*count
; i
++) {
6312 result
= fill_job_info1(info
,
6318 if (!W_ERROR_IS_OK(result
)) {
6324 if (!W_ERROR_IS_OK(result
)) {
6335 /****************************************************************************
6336 Enumjobs at level 2.
6337 ****************************************************************************/
6339 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6340 const print_queue_struct
*queue
,
6341 uint32_t num_queues
, int snum
,
6342 struct spoolss_PrinterInfo2
*pinfo2
,
6343 union spoolss_JobInfo
**info_p
,
6346 union spoolss_JobInfo
*info
;
6348 WERROR result
= WERR_OK
;
6350 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6351 W_ERROR_HAVE_NO_MEMORY(info
);
6353 *count
= num_queues
;
6355 for (i
=0; i
<*count
; i
++) {
6356 struct spoolss_DeviceMode
*devmode
;
6358 result
= spoolss_create_default_devmode(info
,
6359 pinfo2
->printername
,
6361 if (!W_ERROR_IS_OK(result
)) {
6362 DEBUG(3, ("Can't proceed w/o a devmode!"));
6366 result
= fill_job_info2(info
,
6373 if (!W_ERROR_IS_OK(result
)) {
6379 if (!W_ERROR_IS_OK(result
)) {
6390 /****************************************************************************
6391 Enumjobs at level 3.
6392 ****************************************************************************/
6394 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
6395 const print_queue_struct
*queue
,
6396 uint32_t num_queues
, int snum
,
6397 struct spoolss_PrinterInfo2
*pinfo2
,
6398 union spoolss_JobInfo
**info_p
,
6401 union spoolss_JobInfo
*info
;
6403 WERROR result
= WERR_OK
;
6405 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6406 W_ERROR_HAVE_NO_MEMORY(info
);
6408 *count
= num_queues
;
6410 for (i
=0; i
<*count
; i
++) {
6411 const print_queue_struct
*next_queue
= NULL
;
6414 next_queue
= &queue
[i
+1];
6417 result
= fill_job_info3(info
,
6424 if (!W_ERROR_IS_OK(result
)) {
6430 if (!W_ERROR_IS_OK(result
)) {
6441 /****************************************************************
6443 ****************************************************************/
6445 WERROR
_spoolss_EnumJobs(pipes_struct
*p
,
6446 struct spoolss_EnumJobs
*r
)
6449 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6451 print_status_struct prt_status
;
6452 print_queue_struct
*queue
= NULL
;
6455 /* that's an [in out] buffer */
6457 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6458 return WERR_INVALID_PARAM
;
6461 DEBUG(4,("_spoolss_EnumJobs\n"));
6465 *r
->out
.info
= NULL
;
6467 /* lookup the printer snum and tdb entry */
6469 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6473 result
= winreg_get_printer(p
->mem_ctx
, p
->server_info
, NULL
,
6474 lp_servicename(snum
), &pinfo2
);
6475 if (!W_ERROR_IS_OK(result
)) {
6479 count
= print_queue_status(snum
, &queue
, &prt_status
);
6480 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6481 count
, prt_status
.status
, prt_status
.message
));
6485 TALLOC_FREE(pinfo2
);
6489 switch (r
->in
.level
) {
6491 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6492 pinfo2
, r
->out
.info
, r
->out
.count
);
6495 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6496 pinfo2
, r
->out
.info
, r
->out
.count
);
6499 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
6500 pinfo2
, r
->out
.info
, r
->out
.count
);
6503 result
= WERR_UNKNOWN_LEVEL
;
6508 TALLOC_FREE(pinfo2
);
6510 if (!W_ERROR_IS_OK(result
)) {
6514 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6516 *r
->out
.info
, r
->in
.level
,
6518 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6519 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6521 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6524 /****************************************************************
6525 _spoolss_ScheduleJob
6526 ****************************************************************/
6528 WERROR
_spoolss_ScheduleJob(pipes_struct
*p
,
6529 struct spoolss_ScheduleJob
*r
)
6534 /****************************************************************
6535 ****************************************************************/
6537 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
6538 const char *printer_name
,
6540 struct spoolss_SetJobInfo1
*r
)
6544 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
6548 if (strequal(old_doc_name
, r
->document_name
)) {
6552 if (!print_job_set_name(printer_name
, job_id
, r
->document_name
)) {
6559 /****************************************************************
6561 ****************************************************************/
6563 WERROR
_spoolss_SetJob(pipes_struct
*p
,
6564 struct spoolss_SetJob
*r
)
6567 WERROR errcode
= WERR_BADFUNC
;
6569 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6573 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
6574 return WERR_INVALID_PRINTER_NAME
;
6577 switch (r
->in
.command
) {
6578 case SPOOLSS_JOB_CONTROL_CANCEL
:
6579 case SPOOLSS_JOB_CONTROL_DELETE
:
6580 if (print_job_delete(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6584 case SPOOLSS_JOB_CONTROL_PAUSE
:
6585 if (print_job_pause(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6589 case SPOOLSS_JOB_CONTROL_RESTART
:
6590 case SPOOLSS_JOB_CONTROL_RESUME
:
6591 if (print_job_resume(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6599 return WERR_UNKNOWN_LEVEL
;
6602 if (!W_ERROR_IS_OK(errcode
)) {
6606 if (r
->in
.ctr
== NULL
) {
6610 switch (r
->in
.ctr
->level
) {
6612 errcode
= spoolss_setjob_1(p
->mem_ctx
, lp_const_servicename(snum
),
6614 r
->in
.ctr
->info
.info1
);
6620 return WERR_UNKNOWN_LEVEL
;
6626 /****************************************************************************
6627 Enumerates all printer drivers by level and architecture.
6628 ****************************************************************************/
6630 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
6631 struct auth_serversupplied_info
*server_info
,
6632 const char *servername
,
6633 const char *architecture
,
6635 union spoolss_DriverInfo
**info_p
,
6640 struct spoolss_DriverInfo8
*driver
;
6641 union spoolss_DriverInfo
*info
= NULL
;
6643 WERROR result
= WERR_OK
;
6644 uint32_t num_drivers
;
6645 const char **drivers
;
6650 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6651 result
= winreg_get_driver_list(mem_ctx
, server_info
,
6652 architecture
, version
,
6653 &num_drivers
, &drivers
);
6654 if (!W_ERROR_IS_OK(result
)) {
6657 DEBUG(4, ("we have:[%d] drivers in environment"
6658 " [%s] and version [%d]\n",
6659 num_drivers
, architecture
, version
));
6661 if (num_drivers
!= 0) {
6662 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6663 union spoolss_DriverInfo
,
6664 count
+ num_drivers
);
6666 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6667 "failed to enlarge driver info buffer!\n"));
6668 result
= WERR_NOMEM
;
6673 for (i
= 0; i
< num_drivers
; i
++) {
6674 DEBUG(5, ("\tdriver: [%s]\n", drivers
[i
]));
6676 result
= winreg_get_driver(mem_ctx
, server_info
,
6677 architecture
, drivers
[i
],
6679 if (!W_ERROR_IS_OK(result
)) {
6685 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
6686 driver
, servername
);
6689 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
6690 driver
, servername
);
6693 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
6694 driver
, servername
);
6697 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
6698 driver
, servername
);
6701 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
6702 driver
, servername
);
6705 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
6706 driver
, servername
);
6709 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
6710 driver
, servername
);
6713 result
= WERR_UNKNOWN_LEVEL
;
6717 TALLOC_FREE(driver
);
6719 if (!W_ERROR_IS_OK(result
)) {
6724 count
+= num_drivers
;
6725 TALLOC_FREE(drivers
);
6729 TALLOC_FREE(drivers
);
6731 if (!W_ERROR_IS_OK(result
)) {
6742 /****************************************************************************
6743 Enumerates all printer drivers by level.
6744 ****************************************************************************/
6746 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
6747 struct auth_serversupplied_info
*server_info
,
6748 const char *servername
,
6749 const char *architecture
,
6751 union spoolss_DriverInfo
**info_p
,
6755 WERROR result
= WERR_OK
;
6757 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
6759 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
6761 union spoolss_DriverInfo
*info
= NULL
;
6764 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
6767 archi_table
[a
].long_archi
,
6771 if (!W_ERROR_IS_OK(result
)) {
6775 for (i
=0; i
< count
; i
++) {
6776 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
6777 info
[i
], info_p
, count_p
);
6784 return enumprinterdrivers_level_by_architecture(mem_ctx
,
6793 /****************************************************************
6794 _spoolss_EnumPrinterDrivers
6795 ****************************************************************/
6797 WERROR
_spoolss_EnumPrinterDrivers(pipes_struct
*p
,
6798 struct spoolss_EnumPrinterDrivers
*r
)
6800 const char *cservername
;
6803 /* that's an [in out] buffer */
6805 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6806 return WERR_INVALID_PARAM
;
6809 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6813 *r
->out
.info
= NULL
;
6815 cservername
= canon_servername(r
->in
.server
);
6817 if (!is_myname_or_ipaddr(cservername
)) {
6818 return WERR_UNKNOWN_PRINTER_DRIVER
;
6821 result
= enumprinterdrivers_level(p
->mem_ctx
,
6828 if (!W_ERROR_IS_OK(result
)) {
6832 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6833 spoolss_EnumPrinterDrivers
,
6834 *r
->out
.info
, r
->in
.level
,
6836 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6837 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6839 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6842 /****************************************************************
6844 ****************************************************************/
6846 WERROR
_spoolss_EnumForms(pipes_struct
*p
,
6847 struct spoolss_EnumForms
*r
)
6853 *r
->out
.info
= NULL
;
6855 /* that's an [in out] buffer */
6857 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
6858 return WERR_INVALID_PARAM
;
6861 DEBUG(4,("_spoolss_EnumForms\n"));
6862 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6863 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6865 switch (r
->in
.level
) {
6867 result
= winreg_printer_enumforms1(p
->mem_ctx
,
6873 result
= WERR_UNKNOWN_LEVEL
;
6877 if (!W_ERROR_IS_OK(result
)) {
6881 if (*r
->out
.count
== 0) {
6882 return WERR_NO_MORE_ITEMS
;
6885 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6887 *r
->out
.info
, r
->in
.level
,
6889 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6890 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6892 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6895 /****************************************************************
6897 ****************************************************************/
6899 WERROR
_spoolss_GetForm(pipes_struct
*p
,
6900 struct spoolss_GetForm
*r
)
6904 /* that's an [in out] buffer */
6906 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6907 return WERR_INVALID_PARAM
;
6910 DEBUG(4,("_spoolss_GetForm\n"));
6911 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6912 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6914 switch (r
->in
.level
) {
6916 result
= winreg_printer_getform1(p
->mem_ctx
,
6919 &r
->out
.info
->info1
);
6922 result
= WERR_UNKNOWN_LEVEL
;
6926 if (!W_ERROR_IS_OK(result
)) {
6927 TALLOC_FREE(r
->out
.info
);
6931 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
6932 r
->out
.info
, r
->in
.level
);
6933 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
6935 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6938 /****************************************************************************
6939 ****************************************************************************/
6941 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
6942 struct spoolss_PortInfo1
*r
,
6945 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6946 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6951 /****************************************************************************
6952 TODO: This probably needs distinguish between TCP/IP and Local ports
6954 ****************************************************************************/
6956 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
6957 struct spoolss_PortInfo2
*r
,
6960 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6961 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6963 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
6964 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
6966 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
6967 W_ERROR_HAVE_NO_MEMORY(r
->description
);
6969 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
6976 /****************************************************************************
6977 wrapper around the enumer ports command
6978 ****************************************************************************/
6980 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
6982 char *cmd
= lp_enumports_cmd();
6983 char **qlines
= NULL
;
6984 char *command
= NULL
;
6992 /* if no hook then just fill in the default port */
6995 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
6998 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
6999 TALLOC_FREE(qlines
);
7006 /* we have a valid enumport command */
7008 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7013 DEBUG(10,("Running [%s]\n", command
));
7014 ret
= smbrun(command
, &fd
);
7015 DEBUG(10,("Returned [%d]\n", ret
));
7016 TALLOC_FREE(command
);
7021 return WERR_ACCESS_DENIED
;
7025 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7026 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7036 /****************************************************************************
7038 ****************************************************************************/
7040 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7041 union spoolss_PortInfo
**info_p
,
7044 union spoolss_PortInfo
*info
= NULL
;
7046 WERROR result
= WERR_OK
;
7047 char **qlines
= NULL
;
7050 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7051 if (!W_ERROR_IS_OK(result
)) {
7056 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7058 DEBUG(10,("Returning WERR_NOMEM\n"));
7059 result
= WERR_NOMEM
;
7063 for (i
=0; i
<numlines
; i
++) {
7064 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7065 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7066 if (!W_ERROR_IS_OK(result
)) {
7071 TALLOC_FREE(qlines
);
7074 if (!W_ERROR_IS_OK(result
)) {
7076 TALLOC_FREE(qlines
);
7088 /****************************************************************************
7090 ****************************************************************************/
7092 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7093 union spoolss_PortInfo
**info_p
,
7096 union spoolss_PortInfo
*info
= NULL
;
7098 WERROR result
= WERR_OK
;
7099 char **qlines
= NULL
;
7102 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7103 if (!W_ERROR_IS_OK(result
)) {
7108 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7110 DEBUG(10,("Returning WERR_NOMEM\n"));
7111 result
= WERR_NOMEM
;
7115 for (i
=0; i
<numlines
; i
++) {
7116 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7117 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7118 if (!W_ERROR_IS_OK(result
)) {
7123 TALLOC_FREE(qlines
);
7126 if (!W_ERROR_IS_OK(result
)) {
7128 TALLOC_FREE(qlines
);
7140 /****************************************************************
7142 ****************************************************************/
7144 WERROR
_spoolss_EnumPorts(pipes_struct
*p
,
7145 struct spoolss_EnumPorts
*r
)
7149 /* that's an [in out] buffer */
7151 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7152 return WERR_INVALID_PARAM
;
7155 DEBUG(4,("_spoolss_EnumPorts\n"));
7159 *r
->out
.info
= NULL
;
7161 switch (r
->in
.level
) {
7163 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7167 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7171 return WERR_UNKNOWN_LEVEL
;
7174 if (!W_ERROR_IS_OK(result
)) {
7178 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7180 *r
->out
.info
, r
->in
.level
,
7182 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7183 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7185 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7188 /****************************************************************************
7189 ****************************************************************************/
7191 static WERROR
spoolss_addprinterex_level_2(pipes_struct
*p
,
7193 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7194 struct spoolss_DeviceMode
*devmode
,
7195 struct security_descriptor
*secdesc
,
7196 struct spoolss_UserLevelCtr
*user_ctr
,
7197 struct policy_handle
*handle
)
7199 struct spoolss_SetPrinterInfo2
*info2
= info_ctr
->info
.info2
;
7200 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ALL
;
7202 WERROR err
= WERR_OK
;
7204 /* samba does not have a concept of local, non-shared printers yet, so
7205 * make sure we always setup sharename - gd */
7206 if ((info2
->sharename
== NULL
|| info2
->sharename
[0] == '\0') &&
7207 (info2
->printername
!= NULL
&& info2
->printername
[0] != '\0')) {
7208 DEBUG(5, ("spoolss_addprinterex_level_2: "
7209 "no sharename has been set, setting printername %s as sharename\n",
7210 info2
->printername
));
7211 info2
->sharename
= info2
->printername
;
7214 /* check to see if the printer already exists */
7215 if ((snum
= print_queue_snum(info2
->sharename
)) != -1) {
7216 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7218 return WERR_PRINTER_ALREADY_EXISTS
;
7221 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7222 if ((snum
= print_queue_snum(info2
->printername
)) != -1) {
7223 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7224 info2
->printername
));
7225 return WERR_PRINTER_ALREADY_EXISTS
;
7229 /* validate printer info struct */
7230 if (!info2
->printername
|| strlen(info2
->printername
) == 0) {
7231 return WERR_INVALID_PRINTER_NAME
;
7233 if (!info2
->portname
|| strlen(info2
->portname
) == 0) {
7234 return WERR_UNKNOWN_PORT
;
7236 if (!info2
->drivername
|| strlen(info2
->drivername
) == 0) {
7237 return WERR_UNKNOWN_PRINTER_DRIVER
;
7239 if (!info2
->printprocessor
|| strlen(info2
->printprocessor
) == 0) {
7240 return WERR_UNKNOWN_PRINTPROCESSOR
;
7243 /* FIXME!!! smbd should check to see if the driver is installed before
7244 trying to add a printer like this --jerry */
7246 if (*lp_addprinter_cmd() ) {
7247 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7249 return WERR_ACCESS_DENIED
;
7252 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7253 "smb.conf parameter \"addprinter command\" is defined. This"
7254 "parameter must exist for this call to succeed\n",
7255 info2
->sharename
));
7258 if ((snum
= print_queue_snum(info2
->sharename
)) == -1) {
7259 return WERR_ACCESS_DENIED
;
7262 /* you must be a printer admin to add a new printer */
7263 if (!print_access_check(p
->server_info
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7264 return WERR_ACCESS_DENIED
;
7268 * Do sanity check on the requested changes for Samba.
7271 if (!check_printer_ok(p
->mem_ctx
, info2
, snum
)) {
7272 return WERR_INVALID_PARAM
;
7275 if (devmode
== NULL
) {
7276 info2_mask
= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
7279 update_dsspooler(p
->mem_ctx
,
7285 err
= winreg_update_printer(p
->mem_ctx
,
7292 if (!W_ERROR_IS_OK(err
)) {
7296 if (!open_printer_hnd(p
, handle
, info2
->printername
, PRINTER_ACCESS_ADMINISTER
)) {
7297 /* Handle open failed - remove addition. */
7298 ZERO_STRUCTP(handle
);
7299 return WERR_ACCESS_DENIED
;
7305 /****************************************************************
7306 _spoolss_AddPrinterEx
7307 ****************************************************************/
7309 WERROR
_spoolss_AddPrinterEx(pipes_struct
*p
,
7310 struct spoolss_AddPrinterEx
*r
)
7312 switch (r
->in
.info_ctr
->level
) {
7314 /* we don't handle yet */
7315 /* but I know what to do ... */
7316 return WERR_UNKNOWN_LEVEL
;
7318 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7320 r
->in
.devmode_ctr
->devmode
,
7321 r
->in
.secdesc_ctr
->sd
,
7322 r
->in
.userlevel_ctr
,
7325 return WERR_UNKNOWN_LEVEL
;
7329 /****************************************************************
7331 ****************************************************************/
7333 WERROR
_spoolss_AddPrinter(pipes_struct
*p
,
7334 struct spoolss_AddPrinter
*r
)
7336 struct spoolss_AddPrinterEx a
;
7337 struct spoolss_UserLevelCtr userlevel_ctr
;
7339 ZERO_STRUCT(userlevel_ctr
);
7341 userlevel_ctr
.level
= 1;
7343 a
.in
.server
= r
->in
.server
;
7344 a
.in
.info_ctr
= r
->in
.info_ctr
;
7345 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
7346 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
7347 a
.in
.userlevel_ctr
= &userlevel_ctr
;
7348 a
.out
.handle
= r
->out
.handle
;
7350 return _spoolss_AddPrinterEx(p
, &a
);
7353 /****************************************************************
7354 _spoolss_AddPrinterDriverEx
7355 ****************************************************************/
7357 WERROR
_spoolss_AddPrinterDriverEx(pipes_struct
*p
,
7358 struct spoolss_AddPrinterDriverEx
*r
)
7360 WERROR err
= WERR_OK
;
7361 const char *driver_name
= NULL
;
7366 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7367 fn
= "_spoolss_AddPrinterDriver";
7369 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7370 fn
= "_spoolss_AddPrinterDriverEx";
7373 return WERR_INVALID_PARAM
;
7377 * we only support the semantics of AddPrinterDriver()
7378 * i.e. only copy files that are newer than existing ones
7381 if (r
->in
.flags
== 0) {
7382 return WERR_INVALID_PARAM
;
7385 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7386 return WERR_ACCESS_DENIED
;
7390 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
7391 /* Clever hack from Martin Zielinski <mz@seh.de>
7392 * to allow downgrade from level 8 (Vista).
7394 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
7395 r
->in
.info_ctr
->level
));
7396 return WERR_UNKNOWN_LEVEL
;
7399 DEBUG(5,("Cleaning driver's information\n"));
7400 err
= clean_up_driver_struct(p
->mem_ctx
, p
, r
->in
.info_ctr
);
7401 if (!W_ERROR_IS_OK(err
))
7404 DEBUG(5,("Moving driver to final destination\n"));
7405 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, r
->in
.info_ctr
,
7410 err
= winreg_add_driver(p
->mem_ctx
, p
->server_info
,
7411 r
->in
.info_ctr
, &driver_name
, &version
);
7412 if (!W_ERROR_IS_OK(err
)) {
7417 * I think this is where he DrvUpgradePrinter() hook would be
7418 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7419 * server. Right now, we just need to send ourselves a message
7420 * to update each printer bound to this driver. --jerry
7423 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7424 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7432 /****************************************************************
7433 _spoolss_AddPrinterDriver
7434 ****************************************************************/
7436 WERROR
_spoolss_AddPrinterDriver(pipes_struct
*p
,
7437 struct spoolss_AddPrinterDriver
*r
)
7439 struct spoolss_AddPrinterDriverEx a
;
7441 switch (r
->in
.info_ctr
->level
) {
7448 return WERR_UNKNOWN_LEVEL
;
7451 a
.in
.servername
= r
->in
.servername
;
7452 a
.in
.info_ctr
= r
->in
.info_ctr
;
7453 a
.in
.flags
= APD_COPY_NEW_FILES
;
7455 return _spoolss_AddPrinterDriverEx(p
, &a
);
7458 /****************************************************************************
7459 ****************************************************************************/
7461 struct _spoolss_paths
{
7467 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7469 static const struct _spoolss_paths spoolss_paths
[]= {
7470 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7471 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7474 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7475 const char *servername
,
7476 const char *environment
,
7480 const char *pservername
= NULL
;
7481 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7482 const char *short_archi
;
7486 /* environment may be empty */
7487 if (environment
&& strlen(environment
)) {
7488 long_archi
= environment
;
7491 /* servername may be empty */
7492 if (servername
&& strlen(servername
)) {
7493 pservername
= canon_servername(servername
);
7495 if (!is_myname_or_ipaddr(pservername
)) {
7496 return WERR_INVALID_PARAM
;
7500 if (!(short_archi
= get_short_archi(long_archi
))) {
7501 return WERR_INVALID_ENVIRONMENT
;
7504 switch (component
) {
7505 case SPOOLSS_PRTPROCS_PATH
:
7506 case SPOOLSS_DRIVER_PATH
:
7508 *path
= talloc_asprintf(mem_ctx
,
7511 spoolss_paths
[component
].share
,
7514 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7515 SPOOLSS_DEFAULT_SERVER_PATH
,
7516 spoolss_paths
[component
].dir
,
7521 return WERR_INVALID_PARAM
;
7531 /****************************************************************************
7532 ****************************************************************************/
7534 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7535 const char *servername
,
7536 const char *environment
,
7537 struct spoolss_DriverDirectoryInfo1
*r
)
7542 werr
= compose_spoolss_server_path(mem_ctx
,
7545 SPOOLSS_DRIVER_PATH
,
7547 if (!W_ERROR_IS_OK(werr
)) {
7551 DEBUG(4,("printer driver directory: [%s]\n", path
));
7553 r
->directory_name
= path
;
7558 /****************************************************************
7559 _spoolss_GetPrinterDriverDirectory
7560 ****************************************************************/
7562 WERROR
_spoolss_GetPrinterDriverDirectory(pipes_struct
*p
,
7563 struct spoolss_GetPrinterDriverDirectory
*r
)
7567 /* that's an [in out] buffer */
7569 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7570 return WERR_INVALID_PARAM
;
7573 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7578 /* r->in.level is ignored */
7580 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7583 &r
->out
.info
->info1
);
7584 if (!W_ERROR_IS_OK(werror
)) {
7585 TALLOC_FREE(r
->out
.info
);
7589 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
7590 r
->out
.info
, r
->in
.level
);
7591 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7593 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7596 /****************************************************************
7597 _spoolss_EnumPrinterData
7598 ****************************************************************/
7600 WERROR
_spoolss_EnumPrinterData(pipes_struct
*p
,
7601 struct spoolss_EnumPrinterData
*r
)
7604 struct spoolss_EnumPrinterDataEx r2
;
7606 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
7609 r2
.in
.handle
= r
->in
.handle
;
7610 r2
.in
.key_name
= "PrinterDriverData";
7612 r2
.out
.count
= &count
;
7613 r2
.out
.info
= &info
;
7614 r2
.out
.needed
= &needed
;
7616 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7617 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
7618 r2
.in
.offered
= needed
;
7619 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7621 if (!W_ERROR_IS_OK(result
)) {
7626 * The NT machine wants to know the biggest size of value and data
7628 * cf: MSDN EnumPrinterData remark section
7631 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
7632 uint32_t biggest_valuesize
= 0;
7633 uint32_t biggest_datasize
= 0;
7636 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7638 for (i
=0; i
<count
; i
++) {
7640 name_length
= strlen(info
[i
].value_name
);
7641 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
7642 biggest_valuesize
= name_length
;
7645 if (info
[i
].data_length
> biggest_datasize
) {
7646 biggest_datasize
= info
[i
].data_length
;
7649 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7653 /* the value is an UNICODE string but real_value_size is the length
7654 in bytes including the trailing 0 */
7656 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
7657 *r
->out
.data_needed
= biggest_datasize
;
7659 DEBUG(6,("final values: [%d], [%d]\n",
7660 *r
->out
.value_needed
, *r
->out
.data_needed
));
7665 if (r
->in
.enum_index
< count
) {
7666 val
= &info
[r
->in
.enum_index
];
7670 /* out_value should default to "" or else NT4 has
7671 problems unmarshalling the response */
7673 if (r
->in
.value_offered
) {
7674 *r
->out
.value_needed
= 1;
7675 r
->out
.value_name
= talloc_strdup(r
, "");
7676 if (!r
->out
.value_name
) {
7680 r
->out
.value_name
= NULL
;
7681 *r
->out
.value_needed
= 0;
7684 /* the data is counted in bytes */
7686 *r
->out
.data_needed
= r
->in
.data_offered
;
7688 result
= WERR_NO_MORE_ITEMS
;
7692 * - counted in bytes in the request
7693 * - counted in UNICODE chars in the max reply
7694 * - counted in bytes in the real size
7696 * take a pause *before* coding not *during* coding
7700 if (r
->in
.value_offered
) {
7701 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
7702 if (!r
->out
.value_name
) {
7705 *r
->out
.value_needed
= val
->value_name_len
;
7707 r
->out
.value_name
= NULL
;
7708 *r
->out
.value_needed
= 0;
7713 *r
->out
.type
= val
->type
;
7715 /* data - counted in bytes */
7718 * See the section "Dynamically Typed Query Parameters"
7722 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
7723 val
->data_length
&& r
->in
.data_offered
) {
7724 memcpy(r
->out
.data
, val
->data
->data
,
7725 MIN(val
->data_length
,r
->in
.data_offered
));
7728 *r
->out
.data_needed
= val
->data_length
;
7736 /****************************************************************
7737 _spoolss_SetPrinterData
7738 ****************************************************************/
7740 WERROR
_spoolss_SetPrinterData(pipes_struct
*p
,
7741 struct spoolss_SetPrinterData
*r
)
7743 struct spoolss_SetPrinterDataEx r2
;
7745 r2
.in
.handle
= r
->in
.handle
;
7746 r2
.in
.key_name
= "PrinterDriverData";
7747 r2
.in
.value_name
= r
->in
.value_name
;
7748 r2
.in
.type
= r
->in
.type
;
7749 r2
.in
.data
= r
->in
.data
;
7750 r2
.in
.offered
= r
->in
.offered
;
7752 return _spoolss_SetPrinterDataEx(p
, &r2
);
7755 /****************************************************************
7756 _spoolss_ResetPrinter
7757 ****************************************************************/
7759 WERROR
_spoolss_ResetPrinter(pipes_struct
*p
,
7760 struct spoolss_ResetPrinter
*r
)
7762 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7765 DEBUG(5,("_spoolss_ResetPrinter\n"));
7768 * All we do is to check to see if the handle and queue is valid.
7769 * This call really doesn't mean anything to us because we only
7770 * support RAW printing. --jerry
7774 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7775 OUR_HANDLE(r
->in
.handle
)));
7779 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7783 /* blindly return success */
7787 /****************************************************************
7788 _spoolss_DeletePrinterData
7789 ****************************************************************/
7791 WERROR
_spoolss_DeletePrinterData(pipes_struct
*p
,
7792 struct spoolss_DeletePrinterData
*r
)
7794 struct spoolss_DeletePrinterDataEx r2
;
7796 r2
.in
.handle
= r
->in
.handle
;
7797 r2
.in
.key_name
= "PrinterDriverData";
7798 r2
.in
.value_name
= r
->in
.value_name
;
7800 return _spoolss_DeletePrinterDataEx(p
, &r2
);
7803 /****************************************************************
7805 ****************************************************************/
7807 WERROR
_spoolss_AddForm(pipes_struct
*p
,
7808 struct spoolss_AddForm
*r
)
7810 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7812 WERROR status
= WERR_OK
;
7813 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7815 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7817 DEBUG(5,("_spoolss_AddForm\n"));
7820 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7821 OUR_HANDLE(r
->in
.handle
)));
7825 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7826 and not a printer admin, then fail */
7828 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7829 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7830 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7831 p
->server_info
->info3
->base
.domain
.string
,
7833 p
->server_info
->ptok
,
7834 lp_printer_admin(snum
))) {
7835 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7836 return WERR_ACCESS_DENIED
;
7839 switch (form
->flags
) {
7840 case SPOOLSS_FORM_USER
:
7841 case SPOOLSS_FORM_BUILTIN
:
7842 case SPOOLSS_FORM_PRINTER
:
7845 return WERR_INVALID_PARAM
;
7848 status
= winreg_printer_addform1(p
->mem_ctx
, p
->server_info
, form
);
7849 if (!W_ERROR_IS_OK(status
)) {
7854 * ChangeID must always be set if this is a printer
7856 if (Printer
->printer_type
== SPLHND_PRINTER
) {
7857 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7861 status
= winreg_printer_update_changeid(p
->mem_ctx
,
7863 lp_const_servicename(snum
));
7864 if (!W_ERROR_IS_OK(status
)) {
7872 /****************************************************************
7874 ****************************************************************/
7876 WERROR
_spoolss_DeleteForm(pipes_struct
*p
,
7877 struct spoolss_DeleteForm
*r
)
7879 const char *form_name
= r
->in
.form_name
;
7880 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7882 WERROR status
= WERR_OK
;
7883 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7885 DEBUG(5,("_spoolss_DeleteForm\n"));
7888 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7889 OUR_HANDLE(r
->in
.handle
)));
7893 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7894 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7895 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7896 p
->server_info
->info3
->base
.domain
.string
,
7898 p
->server_info
->ptok
,
7899 lp_printer_admin(snum
))) {
7900 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7901 return WERR_ACCESS_DENIED
;
7904 status
= winreg_printer_deleteform1(p
->mem_ctx
,
7907 if (!W_ERROR_IS_OK(status
)) {
7912 * ChangeID must always be set if this is a printer
7914 if (Printer
->printer_type
== SPLHND_PRINTER
) {
7915 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7919 status
= winreg_printer_update_changeid(p
->mem_ctx
,
7921 lp_const_servicename(snum
));
7922 if (!W_ERROR_IS_OK(status
)) {
7930 /****************************************************************
7932 ****************************************************************/
7934 WERROR
_spoolss_SetForm(pipes_struct
*p
,
7935 struct spoolss_SetForm
*r
)
7937 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7938 const char *form_name
= r
->in
.form_name
;
7940 WERROR status
= WERR_OK
;
7941 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7943 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7945 DEBUG(5,("_spoolss_SetForm\n"));
7948 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7949 OUR_HANDLE(r
->in
.handle
)));
7953 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7954 and not a printer admin, then fail */
7956 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7957 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7958 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7959 p
->server_info
->info3
->base
.domain
.string
,
7961 p
->server_info
->ptok
,
7962 lp_printer_admin(snum
))) {
7963 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7964 return WERR_ACCESS_DENIED
;
7967 status
= winreg_printer_setform1(p
->mem_ctx
,
7971 if (!W_ERROR_IS_OK(status
)) {
7976 * ChangeID must always be set if this is a printer
7978 if (Printer
->printer_type
== SPLHND_PRINTER
) {
7979 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7983 status
= winreg_printer_update_changeid(p
->mem_ctx
,
7985 lp_const_servicename(snum
));
7986 if (!W_ERROR_IS_OK(status
)) {
7994 /****************************************************************************
7995 fill_print_processor1
7996 ****************************************************************************/
7998 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
7999 struct spoolss_PrintProcessorInfo1
*r
,
8000 const char *print_processor_name
)
8002 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8003 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8008 /****************************************************************************
8009 enumprintprocessors level 1.
8010 ****************************************************************************/
8012 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8013 union spoolss_PrintProcessorInfo
**info_p
,
8016 union spoolss_PrintProcessorInfo
*info
;
8019 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8020 W_ERROR_HAVE_NO_MEMORY(info
);
8024 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8025 if (!W_ERROR_IS_OK(result
)) {
8030 if (!W_ERROR_IS_OK(result
)) {
8041 /****************************************************************
8042 _spoolss_EnumPrintProcessors
8043 ****************************************************************/
8045 WERROR
_spoolss_EnumPrintProcessors(pipes_struct
*p
,
8046 struct spoolss_EnumPrintProcessors
*r
)
8050 /* that's an [in out] buffer */
8052 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8053 return WERR_INVALID_PARAM
;
8056 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8059 * Enumerate the print processors ...
8061 * Just reply with "winprint", to keep NT happy
8062 * and I can use my nice printer checker.
8067 *r
->out
.info
= NULL
;
8069 switch (r
->in
.level
) {
8071 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8075 return WERR_UNKNOWN_LEVEL
;
8078 if (!W_ERROR_IS_OK(result
)) {
8082 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8083 spoolss_EnumPrintProcessors
,
8084 *r
->out
.info
, r
->in
.level
,
8086 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8087 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8089 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8092 /****************************************************************************
8093 fill_printprocdatatype1
8094 ****************************************************************************/
8096 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8097 struct spoolss_PrintProcDataTypesInfo1
*r
,
8098 const char *name_array
)
8100 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8101 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8106 /****************************************************************************
8107 enumprintprocdatatypes level 1.
8108 ****************************************************************************/
8110 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8111 union spoolss_PrintProcDataTypesInfo
**info_p
,
8115 union spoolss_PrintProcDataTypesInfo
*info
;
8117 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8118 W_ERROR_HAVE_NO_MEMORY(info
);
8122 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8123 if (!W_ERROR_IS_OK(result
)) {
8128 if (!W_ERROR_IS_OK(result
)) {
8139 /****************************************************************
8140 _spoolss_EnumPrintProcDataTypes
8141 ****************************************************************/
8143 WERROR
_spoolss_EnumPrintProcDataTypes(pipes_struct
*p
,
8144 struct spoolss_EnumPrintProcDataTypes
*r
)
8148 /* that's an [in out] buffer */
8150 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8151 return WERR_INVALID_PARAM
;
8154 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8158 *r
->out
.info
= NULL
;
8160 switch (r
->in
.level
) {
8162 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8166 return WERR_UNKNOWN_LEVEL
;
8169 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8170 spoolss_EnumPrintProcDataTypes
,
8171 *r
->out
.info
, r
->in
.level
,
8173 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8174 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8176 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8179 /****************************************************************************
8181 ****************************************************************************/
8183 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8184 struct spoolss_MonitorInfo1
*r
,
8185 const char *monitor_name
)
8187 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8188 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8193 /****************************************************************************
8195 ****************************************************************************/
8197 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8198 struct spoolss_MonitorInfo2
*r
,
8199 const char *monitor_name
,
8200 const char *environment
,
8201 const char *dll_name
)
8203 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8204 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8205 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8206 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8207 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8208 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8213 /****************************************************************************
8214 enumprintmonitors level 1.
8215 ****************************************************************************/
8217 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8218 union spoolss_MonitorInfo
**info_p
,
8221 union spoolss_MonitorInfo
*info
;
8222 WERROR result
= WERR_OK
;
8224 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8225 W_ERROR_HAVE_NO_MEMORY(info
);
8229 result
= fill_monitor_1(info
, &info
[0].info1
,
8231 if (!W_ERROR_IS_OK(result
)) {
8235 result
= fill_monitor_1(info
, &info
[1].info1
,
8237 if (!W_ERROR_IS_OK(result
)) {
8242 if (!W_ERROR_IS_OK(result
)) {
8253 /****************************************************************************
8254 enumprintmonitors level 2.
8255 ****************************************************************************/
8257 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8258 union spoolss_MonitorInfo
**info_p
,
8261 union spoolss_MonitorInfo
*info
;
8262 WERROR result
= WERR_OK
;
8264 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8265 W_ERROR_HAVE_NO_MEMORY(info
);
8269 result
= fill_monitor_2(info
, &info
[0].info2
,
8271 "Windows NT X86", /* FIXME */
8273 if (!W_ERROR_IS_OK(result
)) {
8277 result
= fill_monitor_2(info
, &info
[1].info2
,
8279 "Windows NT X86", /* FIXME */
8281 if (!W_ERROR_IS_OK(result
)) {
8286 if (!W_ERROR_IS_OK(result
)) {
8297 /****************************************************************
8298 _spoolss_EnumMonitors
8299 ****************************************************************/
8301 WERROR
_spoolss_EnumMonitors(pipes_struct
*p
,
8302 struct spoolss_EnumMonitors
*r
)
8306 /* that's an [in out] buffer */
8308 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8309 return WERR_INVALID_PARAM
;
8312 DEBUG(5,("_spoolss_EnumMonitors\n"));
8315 * Enumerate the print monitors ...
8317 * Just reply with "Local Port", to keep NT happy
8318 * and I can use my nice printer checker.
8323 *r
->out
.info
= NULL
;
8325 switch (r
->in
.level
) {
8327 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8331 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8335 return WERR_UNKNOWN_LEVEL
;
8338 if (!W_ERROR_IS_OK(result
)) {
8342 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8343 spoolss_EnumMonitors
,
8344 *r
->out
.info
, r
->in
.level
,
8346 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8347 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8349 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8352 /****************************************************************************
8353 ****************************************************************************/
8355 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8356 const print_queue_struct
*queue
,
8357 int count
, int snum
,
8358 struct spoolss_PrinterInfo2
*pinfo2
,
8360 struct spoolss_JobInfo1
*r
)
8365 for (i
=0; i
<count
; i
++) {
8366 if (queue
[i
].job
== (int)jobid
) {
8372 if (found
== false) {
8373 /* NT treats not found as bad param... yet another bad choice */
8374 return WERR_INVALID_PARAM
;
8377 return fill_job_info1(mem_ctx
,
8385 /****************************************************************************
8386 ****************************************************************************/
8388 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8389 const print_queue_struct
*queue
,
8390 int count
, int snum
,
8391 struct spoolss_PrinterInfo2
*pinfo2
,
8393 struct spoolss_JobInfo2
*r
)
8397 struct spoolss_DeviceMode
*devmode
;
8400 for (i
=0; i
<count
; i
++) {
8401 if (queue
[i
].job
== (int)jobid
) {
8407 if (found
== false) {
8408 /* NT treats not found as bad param... yet another bad
8410 return WERR_INVALID_PARAM
;
8414 * if the print job does not have a DEVMODE associated with it,
8415 * just use the one for the printer. A NULL devicemode is not
8416 * a failure condition
8419 devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8421 result
= spoolss_create_default_devmode(mem_ctx
,
8422 pinfo2
->printername
,
8424 if (!W_ERROR_IS_OK(result
)) {
8425 DEBUG(3, ("Can't proceed w/o a devmode!"));
8430 return fill_job_info2(mem_ctx
,
8439 /****************************************************************
8441 ****************************************************************/
8443 WERROR
_spoolss_GetJob(pipes_struct
*p
,
8444 struct spoolss_GetJob
*r
)
8446 WERROR result
= WERR_OK
;
8447 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
8450 print_queue_struct
*queue
= NULL
;
8451 print_status_struct prt_status
;
8453 /* that's an [in out] buffer */
8455 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8456 return WERR_INVALID_PARAM
;
8459 DEBUG(5,("_spoolss_GetJob\n"));
8463 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8467 result
= winreg_get_printer(p
->mem_ctx
, p
->server_info
, NULL
,
8468 lp_servicename(snum
), &pinfo2
);
8469 if (!W_ERROR_IS_OK(result
)) {
8473 count
= print_queue_status(snum
, &queue
, &prt_status
);
8475 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8476 count
, prt_status
.status
, prt_status
.message
));
8478 switch (r
->in
.level
) {
8480 result
= getjob_level_1(p
->mem_ctx
,
8481 queue
, count
, snum
, pinfo2
,
8482 r
->in
.job_id
, &r
->out
.info
->info1
);
8485 result
= getjob_level_2(p
->mem_ctx
,
8486 queue
, count
, snum
, pinfo2
,
8487 r
->in
.job_id
, &r
->out
.info
->info2
);
8490 result
= WERR_UNKNOWN_LEVEL
;
8495 TALLOC_FREE(pinfo2
);
8497 if (!W_ERROR_IS_OK(result
)) {
8498 TALLOC_FREE(r
->out
.info
);
8502 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
8504 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8506 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8509 /****************************************************************
8510 _spoolss_GetPrinterDataEx
8511 ****************************************************************/
8513 WERROR
_spoolss_GetPrinterDataEx(pipes_struct
*p
,
8514 struct spoolss_GetPrinterDataEx
*r
)
8517 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8518 const char *printer
;
8520 WERROR result
= WERR_OK
;
8522 enum winreg_Type val_type
;
8527 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8529 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8530 r
->in
.key_name
, r
->in
.value_name
));
8532 /* in case of problem, return some default values */
8535 *r
->out
.type
= REG_NONE
;
8538 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8539 OUR_HANDLE(r
->in
.handle
)));
8540 result
= WERR_BADFID
;
8544 /* Is the handle to a printer or to the server? */
8546 if (Printer
->printer_type
== SPLHND_SERVER
) {
8548 union spoolss_PrinterData data
;
8550 result
= getprinterdata_printer_server(p
->mem_ctx
,
8554 if (!W_ERROR_IS_OK(result
)) {
8558 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
8559 *r
->out
.type
, &data
);
8560 if (!W_ERROR_IS_OK(result
)) {
8564 *r
->out
.needed
= blob
.length
;
8566 if (r
->in
.offered
>= *r
->out
.needed
) {
8567 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
8570 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8573 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8576 printer
= lp_const_servicename(snum
);
8578 /* check to see if the keyname is valid */
8579 if (!strlen(r
->in
.key_name
)) {
8580 return WERR_INVALID_PARAM
;
8583 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8584 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
8585 strequal(r
->in
.value_name
, "ChangeId")) {
8586 *r
->out
.type
= REG_DWORD
;
8588 if (r
->in
.offered
>= *r
->out
.needed
) {
8589 uint32_t changeid
= 0;
8591 result
= winreg_printer_get_changeid(p
->mem_ctx
,
8595 if (!W_ERROR_IS_OK(result
)) {
8599 SIVAL(r
->out
.data
, 0, changeid
);
8605 result
= winreg_get_printer_dataex(p
->mem_ctx
,
8613 if (!W_ERROR_IS_OK(result
)) {
8617 *r
->out
.needed
= val_size
;
8618 *r
->out
.type
= val_type
;
8620 if (r
->in
.offered
>= *r
->out
.needed
) {
8621 memcpy(r
->out
.data
, val_data
, val_size
);
8625 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
8626 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
8628 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8631 /****************************************************************
8632 _spoolss_SetPrinterDataEx
8633 ****************************************************************/
8635 WERROR
_spoolss_SetPrinterDataEx(pipes_struct
*p
,
8636 struct spoolss_SetPrinterDataEx
*r
)
8638 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
8640 WERROR result
= WERR_OK
;
8641 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8644 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8646 /* From MSDN documentation of SetPrinterDataEx: pass request to
8647 SetPrinterData if key is "PrinterDriverData" */
8650 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8651 OUR_HANDLE(r
->in
.handle
)));
8655 if (Printer
->printer_type
== SPLHND_SERVER
) {
8656 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8657 "Not implemented for server handles yet\n"));
8658 return WERR_INVALID_PARAM
;
8661 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8666 * Access check : NT returns "access denied" if you make a
8667 * SetPrinterData call without the necessary privildge.
8668 * we were originally returning OK if nothing changed
8669 * which made Win2k issue **a lot** of SetPrinterData
8670 * when connecting to a printer --jerry
8673 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8674 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8675 "change denied by handle access permissions\n"));
8676 return WERR_ACCESS_DENIED
;
8679 result
= winreg_get_printer(Printer
, p
->server_info
,
8680 Printer
->servername
,
8681 lp_servicename(snum
),
8683 if (!W_ERROR_IS_OK(result
)) {
8687 /* check for OID in valuename */
8689 oid_string
= strchr(r
->in
.value_name
, ',');
8695 /* save the registry data */
8697 result
= winreg_set_printer_dataex(p
->mem_ctx
,
8706 if (W_ERROR_IS_OK(result
)) {
8707 /* save the OID if one was specified */
8709 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
8710 r
->in
.key_name
, SPOOL_OID_KEY
);
8712 result
= WERR_NOMEM
;
8717 * I'm not checking the status here on purpose. Don't know
8718 * if this is right, but I'm returning the status from the
8719 * previous set_printer_dataex() call. I have no idea if
8720 * this is right. --jerry
8722 winreg_set_printer_dataex(p
->mem_ctx
,
8728 (uint8_t *) oid_string
,
8729 strlen(oid_string
) + 1);
8732 result
= winreg_printer_update_changeid(p
->mem_ctx
,
8734 lp_const_servicename(snum
));
8739 talloc_free(pinfo2
);
8743 /****************************************************************
8744 _spoolss_DeletePrinterDataEx
8745 ****************************************************************/
8747 WERROR
_spoolss_DeletePrinterDataEx(pipes_struct
*p
,
8748 struct spoolss_DeletePrinterDataEx
*r
)
8750 const char *printer
;
8752 WERROR status
= WERR_OK
;
8753 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8755 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8758 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8759 "Invalid handle (%s:%u:%u).\n",
8760 OUR_HANDLE(r
->in
.handle
)));
8764 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8765 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8766 "printer properties change denied by handle\n"));
8767 return WERR_ACCESS_DENIED
;
8770 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
8774 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8777 printer
= lp_const_servicename(snum
);
8779 status
= winreg_delete_printer_dataex(p
->mem_ctx
,
8784 if (W_ERROR_IS_OK(status
)) {
8785 status
= winreg_printer_update_changeid(p
->mem_ctx
,
8793 /****************************************************************
8794 _spoolss_EnumPrinterKey
8795 ****************************************************************/
8797 WERROR
_spoolss_EnumPrinterKey(pipes_struct
*p
,
8798 struct spoolss_EnumPrinterKey
*r
)
8801 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8803 WERROR result
= WERR_BADFILE
;
8804 const char **array
= NULL
;
8807 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8810 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8811 OUR_HANDLE(r
->in
.handle
)));
8815 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8819 result
= winreg_enum_printer_key(p
->mem_ctx
,
8821 lp_const_servicename(snum
),
8825 if (!W_ERROR_IS_OK(result
)) {
8829 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
8830 result
= WERR_NOMEM
;
8834 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
8835 *r
->out
.needed
= blob
.length
;
8837 if (r
->in
.offered
< *r
->out
.needed
) {
8838 result
= WERR_MORE_DATA
;
8841 r
->out
.key_buffer
->string_array
= array
;
8845 if (!W_ERROR_IS_OK(result
)) {
8847 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8855 /****************************************************************
8856 _spoolss_DeletePrinterKey
8857 ****************************************************************/
8859 WERROR
_spoolss_DeletePrinterKey(pipes_struct
*p
,
8860 struct spoolss_DeletePrinterKey
*r
)
8862 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8865 const char *printer
;
8867 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8870 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8871 OUR_HANDLE(r
->in
.handle
)));
8875 /* if keyname == NULL, return error */
8876 if ( !r
->in
.key_name
)
8877 return WERR_INVALID_PARAM
;
8879 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8883 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8884 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8885 "printer properties change denied by handle\n"));
8886 return WERR_ACCESS_DENIED
;
8889 printer
= lp_const_servicename(snum
);
8891 /* delete the key and all subkeys */
8892 status
= winreg_delete_printer_key(p
->mem_ctx
,
8896 if (W_ERROR_IS_OK(status
)) {
8897 status
= winreg_printer_update_changeid(p
->mem_ctx
,
8905 /****************************************************************
8906 _spoolss_EnumPrinterDataEx
8907 ****************************************************************/
8909 WERROR
_spoolss_EnumPrinterDataEx(pipes_struct
*p
,
8910 struct spoolss_EnumPrinterDataEx
*r
)
8913 struct spoolss_PrinterEnumValues
*info
= NULL
;
8914 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8918 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8922 *r
->out
.info
= NULL
;
8925 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8926 OUR_HANDLE(r
->in
.handle
)));
8931 * first check for a keyname of NULL or "". Win2k seems to send
8932 * this a lot and we should send back WERR_INVALID_PARAM
8933 * no need to spend time looking up the printer in this case.
8937 if (!strlen(r
->in
.key_name
)) {
8938 result
= WERR_INVALID_PARAM
;
8942 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8946 /* now look for a match on the key name */
8947 result
= winreg_enum_printer_dataex(p
->mem_ctx
,
8949 lp_const_servicename(snum
),
8953 if (!W_ERROR_IS_OK(result
)) {
8957 #if 0 /* FIXME - gd */
8958 /* housekeeping information in the reply */
8960 /* Fix from Martin Zielinski <mz@seh.de> - ensure
8961 * the hand marshalled container size is a multiple
8962 * of 4 bytes for RPC alignment.
8966 needed
+= 4-(needed
% 4);
8969 *r
->out
.count
= count
;
8970 *r
->out
.info
= info
;
8973 if (!W_ERROR_IS_OK(result
)) {
8977 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
8978 spoolss_EnumPrinterDataEx
,
8981 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8982 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
8984 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8987 /****************************************************************************
8988 ****************************************************************************/
8990 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
8991 const char *servername
,
8992 const char *environment
,
8993 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
8998 werr
= compose_spoolss_server_path(mem_ctx
,
9001 SPOOLSS_PRTPROCS_PATH
,
9003 if (!W_ERROR_IS_OK(werr
)) {
9007 DEBUG(4,("print processor directory: [%s]\n", path
));
9009 r
->directory_name
= path
;
9014 /****************************************************************
9015 _spoolss_GetPrintProcessorDirectory
9016 ****************************************************************/
9018 WERROR
_spoolss_GetPrintProcessorDirectory(pipes_struct
*p
,
9019 struct spoolss_GetPrintProcessorDirectory
*r
)
9023 /* that's an [in out] buffer */
9025 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9026 return WERR_INVALID_PARAM
;
9029 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9034 /* r->in.level is ignored */
9036 /* We always should reply with a local print processor directory so that
9037 * users are not forced to have a [prnproc$] share on the Samba spoolss
9038 * server - Guenther */
9040 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9041 NULL
, /* r->in.server */
9043 &r
->out
.info
->info1
);
9044 if (!W_ERROR_IS_OK(result
)) {
9045 TALLOC_FREE(r
->out
.info
);
9049 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9050 r
->out
.info
, r
->in
.level
);
9051 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9053 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9056 /*******************************************************************
9057 ********************************************************************/
9059 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9060 const char *dllname
)
9062 enum ndr_err_code ndr_err
;
9063 struct spoolss_MonitorUi ui
;
9065 ui
.dll_name
= dllname
;
9067 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9068 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9069 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9070 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9072 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9075 /*******************************************************************
9076 Streams the monitor UI DLL name in UNICODE
9077 *******************************************************************/
9079 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9080 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9081 DATA_BLOB
*out
, uint32_t *needed
)
9083 const char *dllname
= "tcpmonui.dll";
9085 *needed
= (strlen(dllname
)+1) * 2;
9087 if (out
->length
< *needed
) {
9088 return WERR_INSUFFICIENT_BUFFER
;
9091 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9098 /*******************************************************************
9099 ********************************************************************/
9101 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9102 struct spoolss_PortData1
*port1
,
9103 const DATA_BLOB
*buf
)
9105 enum ndr_err_code ndr_err
;
9106 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9107 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9108 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9109 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9111 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9114 /*******************************************************************
9115 ********************************************************************/
9117 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9118 struct spoolss_PortData2
*port2
,
9119 const DATA_BLOB
*buf
)
9121 enum ndr_err_code ndr_err
;
9122 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9123 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9124 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9125 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9127 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9130 /*******************************************************************
9131 Create a new TCP/IP port
9132 *******************************************************************/
9134 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9135 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9136 DATA_BLOB
*out
, uint32_t *needed
)
9138 struct spoolss_PortData1 port1
;
9139 struct spoolss_PortData2 port2
;
9140 char *device_uri
= NULL
;
9143 const char *portname
;
9144 const char *hostaddress
;
9146 uint32_t port_number
;
9149 /* peek for spoolss_PortData version */
9151 if (!in
|| (in
->length
< (128 + 4))) {
9152 return WERR_GENERAL_FAILURE
;
9155 version
= IVAL(in
->data
, 128);
9161 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9165 portname
= port1
.portname
;
9166 hostaddress
= port1
.hostaddress
;
9167 queue
= port1
.queue
;
9168 protocol
= port1
.protocol
;
9169 port_number
= port1
.port_number
;
9175 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9179 portname
= port2
.portname
;
9180 hostaddress
= port2
.hostaddress
;
9181 queue
= port2
.queue
;
9182 protocol
= port2
.protocol
;
9183 port_number
= port2
.port_number
;
9187 DEBUG(1,("xcvtcp_addport: "
9188 "unknown version of port_data: %d\n", version
));
9189 return WERR_UNKNOWN_PORT
;
9192 /* create the device URI and call the add_port_hook() */
9195 case PROTOCOL_RAWTCP_TYPE
:
9196 device_uri
= talloc_asprintf(mem_ctx
,
9197 "socket://%s:%d/", hostaddress
,
9201 case PROTOCOL_LPR_TYPE
:
9202 device_uri
= talloc_asprintf(mem_ctx
,
9203 "lpr://%s/%s", hostaddress
, queue
);
9207 return WERR_UNKNOWN_PORT
;
9214 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9217 /*******************************************************************
9218 *******************************************************************/
9220 struct xcv_api_table xcvtcp_cmds
[] = {
9221 { "MonitorUI", xcvtcp_monitorui
},
9222 { "AddPort", xcvtcp_addport
},
9226 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9227 NT_USER_TOKEN
*token
, const char *command
,
9234 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9236 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9237 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9238 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9241 return WERR_BADFUNC
;
9244 /*******************************************************************
9245 *******************************************************************/
9246 #if 0 /* don't support management using the "Local Port" monitor */
9248 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9249 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9250 DATA_BLOB
*out
, uint32_t *needed
)
9252 const char *dllname
= "localui.dll";
9254 *needed
= (strlen(dllname
)+1) * 2;
9256 if (out
->length
< *needed
) {
9257 return WERR_INSUFFICIENT_BUFFER
;
9260 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9267 /*******************************************************************
9268 *******************************************************************/
9270 struct xcv_api_table xcvlocal_cmds
[] = {
9271 { "MonitorUI", xcvlocal_monitorui
},
9275 struct xcv_api_table xcvlocal_cmds
[] = {
9282 /*******************************************************************
9283 *******************************************************************/
9285 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9286 NT_USER_TOKEN
*token
, const char *command
,
9287 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9292 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9294 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9295 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9296 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9298 return WERR_BADFUNC
;
9301 /****************************************************************
9303 ****************************************************************/
9305 WERROR
_spoolss_XcvData(pipes_struct
*p
,
9306 struct spoolss_XcvData
*r
)
9308 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9309 DATA_BLOB out_data
= data_blob_null
;
9313 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9314 OUR_HANDLE(r
->in
.handle
)));
9318 /* Has to be a handle to the TCP/IP port monitor */
9320 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9321 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9325 /* requires administrative access to the server */
9327 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9328 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9329 return WERR_ACCESS_DENIED
;
9332 /* Allocate the outgoing buffer */
9334 if (r
->in
.out_data_size
) {
9335 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9336 if (out_data
.data
== NULL
) {
9341 switch ( Printer
->printer_type
) {
9342 case SPLHND_PORTMON_TCP
:
9343 werror
= process_xcvtcp_command(p
->mem_ctx
,
9344 p
->server_info
->ptok
,
9345 r
->in
.function_name
,
9346 &r
->in
.in_data
, &out_data
,
9349 case SPLHND_PORTMON_LOCAL
:
9350 werror
= process_xcvlocal_command(p
->mem_ctx
,
9351 p
->server_info
->ptok
,
9352 r
->in
.function_name
,
9353 &r
->in
.in_data
, &out_data
,
9357 werror
= WERR_INVALID_PRINT_MONITOR
;
9360 if (!W_ERROR_IS_OK(werror
)) {
9364 *r
->out
.status_code
= 0;
9366 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
9367 memcpy(r
->out
.out_data
, out_data
.data
,
9368 MIN(r
->in
.out_data_size
, out_data
.length
));
9374 /****************************************************************
9375 _spoolss_AddPrintProcessor
9376 ****************************************************************/
9378 WERROR
_spoolss_AddPrintProcessor(pipes_struct
*p
,
9379 struct spoolss_AddPrintProcessor
*r
)
9381 /* for now, just indicate success and ignore the add. We'll
9382 automatically set the winprint processor for printer
9383 entries later. Used to debug the LexMark Optra S 1855 PCL
9389 /****************************************************************
9391 ****************************************************************/
9393 WERROR
_spoolss_AddPort(pipes_struct
*p
,
9394 struct spoolss_AddPort
*r
)
9396 /* do what w2k3 does */
9398 return WERR_NOT_SUPPORTED
;
9401 /****************************************************************
9402 _spoolss_GetPrinterDriver
9403 ****************************************************************/
9405 WERROR
_spoolss_GetPrinterDriver(pipes_struct
*p
,
9406 struct spoolss_GetPrinterDriver
*r
)
9408 p
->rng_fault_state
= true;
9409 return WERR_NOT_SUPPORTED
;
9412 /****************************************************************
9413 _spoolss_ReadPrinter
9414 ****************************************************************/
9416 WERROR
_spoolss_ReadPrinter(pipes_struct
*p
,
9417 struct spoolss_ReadPrinter
*r
)
9419 p
->rng_fault_state
= true;
9420 return WERR_NOT_SUPPORTED
;
9423 /****************************************************************
9424 _spoolss_WaitForPrinterChange
9425 ****************************************************************/
9427 WERROR
_spoolss_WaitForPrinterChange(pipes_struct
*p
,
9428 struct spoolss_WaitForPrinterChange
*r
)
9430 p
->rng_fault_state
= true;
9431 return WERR_NOT_SUPPORTED
;
9434 /****************************************************************
9435 _spoolss_ConfigurePort
9436 ****************************************************************/
9438 WERROR
_spoolss_ConfigurePort(pipes_struct
*p
,
9439 struct spoolss_ConfigurePort
*r
)
9441 p
->rng_fault_state
= true;
9442 return WERR_NOT_SUPPORTED
;
9445 /****************************************************************
9447 ****************************************************************/
9449 WERROR
_spoolss_DeletePort(pipes_struct
*p
,
9450 struct spoolss_DeletePort
*r
)
9452 p
->rng_fault_state
= true;
9453 return WERR_NOT_SUPPORTED
;
9456 /****************************************************************
9457 _spoolss_CreatePrinterIC
9458 ****************************************************************/
9460 WERROR
_spoolss_CreatePrinterIC(pipes_struct
*p
,
9461 struct spoolss_CreatePrinterIC
*r
)
9463 p
->rng_fault_state
= true;
9464 return WERR_NOT_SUPPORTED
;
9467 /****************************************************************
9468 _spoolss_PlayGDIScriptOnPrinterIC
9469 ****************************************************************/
9471 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(pipes_struct
*p
,
9472 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
9474 p
->rng_fault_state
= true;
9475 return WERR_NOT_SUPPORTED
;
9478 /****************************************************************
9479 _spoolss_DeletePrinterIC
9480 ****************************************************************/
9482 WERROR
_spoolss_DeletePrinterIC(pipes_struct
*p
,
9483 struct spoolss_DeletePrinterIC
*r
)
9485 p
->rng_fault_state
= true;
9486 return WERR_NOT_SUPPORTED
;
9489 /****************************************************************
9490 _spoolss_AddPrinterConnection
9491 ****************************************************************/
9493 WERROR
_spoolss_AddPrinterConnection(pipes_struct
*p
,
9494 struct spoolss_AddPrinterConnection
*r
)
9496 p
->rng_fault_state
= true;
9497 return WERR_NOT_SUPPORTED
;
9500 /****************************************************************
9501 _spoolss_DeletePrinterConnection
9502 ****************************************************************/
9504 WERROR
_spoolss_DeletePrinterConnection(pipes_struct
*p
,
9505 struct spoolss_DeletePrinterConnection
*r
)
9507 p
->rng_fault_state
= true;
9508 return WERR_NOT_SUPPORTED
;
9511 /****************************************************************
9512 _spoolss_PrinterMessageBox
9513 ****************************************************************/
9515 WERROR
_spoolss_PrinterMessageBox(pipes_struct
*p
,
9516 struct spoolss_PrinterMessageBox
*r
)
9518 p
->rng_fault_state
= true;
9519 return WERR_NOT_SUPPORTED
;
9522 /****************************************************************
9524 ****************************************************************/
9526 WERROR
_spoolss_AddMonitor(pipes_struct
*p
,
9527 struct spoolss_AddMonitor
*r
)
9529 p
->rng_fault_state
= true;
9530 return WERR_NOT_SUPPORTED
;
9533 /****************************************************************
9534 _spoolss_DeleteMonitor
9535 ****************************************************************/
9537 WERROR
_spoolss_DeleteMonitor(pipes_struct
*p
,
9538 struct spoolss_DeleteMonitor
*r
)
9540 p
->rng_fault_state
= true;
9541 return WERR_NOT_SUPPORTED
;
9544 /****************************************************************
9545 _spoolss_DeletePrintProcessor
9546 ****************************************************************/
9548 WERROR
_spoolss_DeletePrintProcessor(pipes_struct
*p
,
9549 struct spoolss_DeletePrintProcessor
*r
)
9551 p
->rng_fault_state
= true;
9552 return WERR_NOT_SUPPORTED
;
9555 /****************************************************************
9556 _spoolss_AddPrintProvidor
9557 ****************************************************************/
9559 WERROR
_spoolss_AddPrintProvidor(pipes_struct
*p
,
9560 struct spoolss_AddPrintProvidor
*r
)
9562 p
->rng_fault_state
= true;
9563 return WERR_NOT_SUPPORTED
;
9566 /****************************************************************
9567 _spoolss_DeletePrintProvidor
9568 ****************************************************************/
9570 WERROR
_spoolss_DeletePrintProvidor(pipes_struct
*p
,
9571 struct spoolss_DeletePrintProvidor
*r
)
9573 p
->rng_fault_state
= true;
9574 return WERR_NOT_SUPPORTED
;
9577 /****************************************************************
9578 _spoolss_FindFirstPrinterChangeNotification
9579 ****************************************************************/
9581 WERROR
_spoolss_FindFirstPrinterChangeNotification(pipes_struct
*p
,
9582 struct spoolss_FindFirstPrinterChangeNotification
*r
)
9584 p
->rng_fault_state
= true;
9585 return WERR_NOT_SUPPORTED
;
9588 /****************************************************************
9589 _spoolss_FindNextPrinterChangeNotification
9590 ****************************************************************/
9592 WERROR
_spoolss_FindNextPrinterChangeNotification(pipes_struct
*p
,
9593 struct spoolss_FindNextPrinterChangeNotification
*r
)
9595 p
->rng_fault_state
= true;
9596 return WERR_NOT_SUPPORTED
;
9599 /****************************************************************
9600 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9601 ****************************************************************/
9603 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct
*p
,
9604 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
9606 p
->rng_fault_state
= true;
9607 return WERR_NOT_SUPPORTED
;
9610 /****************************************************************
9611 _spoolss_ReplyOpenPrinter
9612 ****************************************************************/
9614 WERROR
_spoolss_ReplyOpenPrinter(pipes_struct
*p
,
9615 struct spoolss_ReplyOpenPrinter
*r
)
9617 p
->rng_fault_state
= true;
9618 return WERR_NOT_SUPPORTED
;
9621 /****************************************************************
9622 _spoolss_RouterReplyPrinter
9623 ****************************************************************/
9625 WERROR
_spoolss_RouterReplyPrinter(pipes_struct
*p
,
9626 struct spoolss_RouterReplyPrinter
*r
)
9628 p
->rng_fault_state
= true;
9629 return WERR_NOT_SUPPORTED
;
9632 /****************************************************************
9633 _spoolss_ReplyClosePrinter
9634 ****************************************************************/
9636 WERROR
_spoolss_ReplyClosePrinter(pipes_struct
*p
,
9637 struct spoolss_ReplyClosePrinter
*r
)
9639 p
->rng_fault_state
= true;
9640 return WERR_NOT_SUPPORTED
;
9643 /****************************************************************
9645 ****************************************************************/
9647 WERROR
_spoolss_AddPortEx(pipes_struct
*p
,
9648 struct spoolss_AddPortEx
*r
)
9650 p
->rng_fault_state
= true;
9651 return WERR_NOT_SUPPORTED
;
9654 /****************************************************************
9655 _spoolss_RouterFindFirstPrinterChangeNotification
9656 ****************************************************************/
9658 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct
*p
,
9659 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
9661 p
->rng_fault_state
= true;
9662 return WERR_NOT_SUPPORTED
;
9665 /****************************************************************
9666 _spoolss_SpoolerInit
9667 ****************************************************************/
9669 WERROR
_spoolss_SpoolerInit(pipes_struct
*p
,
9670 struct spoolss_SpoolerInit
*r
)
9672 p
->rng_fault_state
= true;
9673 return WERR_NOT_SUPPORTED
;
9676 /****************************************************************
9677 _spoolss_ResetPrinterEx
9678 ****************************************************************/
9680 WERROR
_spoolss_ResetPrinterEx(pipes_struct
*p
,
9681 struct spoolss_ResetPrinterEx
*r
)
9683 p
->rng_fault_state
= true;
9684 return WERR_NOT_SUPPORTED
;
9687 /****************************************************************
9688 _spoolss_RouterReplyPrinterEx
9689 ****************************************************************/
9691 WERROR
_spoolss_RouterReplyPrinterEx(pipes_struct
*p
,
9692 struct spoolss_RouterReplyPrinterEx
*r
)
9694 p
->rng_fault_state
= true;
9695 return WERR_NOT_SUPPORTED
;
9698 /****************************************************************
9700 ****************************************************************/
9702 WERROR
_spoolss_44(pipes_struct
*p
,
9703 struct spoolss_44
*r
)
9705 p
->rng_fault_state
= true;
9706 return WERR_NOT_SUPPORTED
;
9709 /****************************************************************
9711 ****************************************************************/
9713 WERROR
_spoolss_47(pipes_struct
*p
,
9714 struct spoolss_47
*r
)
9716 p
->rng_fault_state
= true;
9717 return WERR_NOT_SUPPORTED
;
9720 /****************************************************************
9722 ****************************************************************/
9724 WERROR
_spoolss_4a(pipes_struct
*p
,
9725 struct spoolss_4a
*r
)
9727 p
->rng_fault_state
= true;
9728 return WERR_NOT_SUPPORTED
;
9731 /****************************************************************
9733 ****************************************************************/
9735 WERROR
_spoolss_4b(pipes_struct
*p
,
9736 struct spoolss_4b
*r
)
9738 p
->rng_fault_state
= true;
9739 return WERR_NOT_SUPPORTED
;
9742 /****************************************************************
9744 ****************************************************************/
9746 WERROR
_spoolss_4c(pipes_struct
*p
,
9747 struct spoolss_4c
*r
)
9749 p
->rng_fault_state
= true;
9750 return WERR_NOT_SUPPORTED
;
9753 /****************************************************************
9755 ****************************************************************/
9757 WERROR
_spoolss_53(pipes_struct
*p
,
9758 struct spoolss_53
*r
)
9760 p
->rng_fault_state
= true;
9761 return WERR_NOT_SUPPORTED
;
9764 /****************************************************************
9766 ****************************************************************/
9768 WERROR
_spoolss_55(pipes_struct
*p
,
9769 struct spoolss_55
*r
)
9771 p
->rng_fault_state
= true;
9772 return WERR_NOT_SUPPORTED
;
9775 /****************************************************************
9777 ****************************************************************/
9779 WERROR
_spoolss_56(pipes_struct
*p
,
9780 struct spoolss_56
*r
)
9782 p
->rng_fault_state
= true;
9783 return WERR_NOT_SUPPORTED
;
9786 /****************************************************************
9788 ****************************************************************/
9790 WERROR
_spoolss_57(pipes_struct
*p
,
9791 struct spoolss_57
*r
)
9793 p
->rng_fault_state
= true;
9794 return WERR_NOT_SUPPORTED
;
9797 /****************************************************************
9799 ****************************************************************/
9801 WERROR
_spoolss_5a(pipes_struct
*p
,
9802 struct spoolss_5a
*r
)
9804 p
->rng_fault_state
= true;
9805 return WERR_NOT_SUPPORTED
;
9808 /****************************************************************
9810 ****************************************************************/
9812 WERROR
_spoolss_5b(pipes_struct
*p
,
9813 struct spoolss_5b
*r
)
9815 p
->rng_fault_state
= true;
9816 return WERR_NOT_SUPPORTED
;
9819 /****************************************************************
9821 ****************************************************************/
9823 WERROR
_spoolss_5c(pipes_struct
*p
,
9824 struct spoolss_5c
*r
)
9826 p
->rng_fault_state
= true;
9827 return WERR_NOT_SUPPORTED
;
9830 /****************************************************************
9832 ****************************************************************/
9834 WERROR
_spoolss_5d(pipes_struct
*p
,
9835 struct spoolss_5d
*r
)
9837 p
->rng_fault_state
= true;
9838 return WERR_NOT_SUPPORTED
;
9841 /****************************************************************
9843 ****************************************************************/
9845 WERROR
_spoolss_5e(pipes_struct
*p
,
9846 struct spoolss_5e
*r
)
9848 p
->rng_fault_state
= true;
9849 return WERR_NOT_SUPPORTED
;
9852 /****************************************************************
9854 ****************************************************************/
9856 WERROR
_spoolss_5f(pipes_struct
*p
,
9857 struct spoolss_5f
*r
)
9859 p
->rng_fault_state
= true;
9860 return WERR_NOT_SUPPORTED
;
9863 /****************************************************************
9865 ****************************************************************/
9867 WERROR
_spoolss_60(pipes_struct
*p
,
9868 struct spoolss_60
*r
)
9870 p
->rng_fault_state
= true;
9871 return WERR_NOT_SUPPORTED
;
9874 /****************************************************************
9876 ****************************************************************/
9878 WERROR
_spoolss_61(pipes_struct
*p
,
9879 struct spoolss_61
*r
)
9881 p
->rng_fault_state
= true;
9882 return WERR_NOT_SUPPORTED
;
9885 /****************************************************************
9887 ****************************************************************/
9889 WERROR
_spoolss_62(pipes_struct
*p
,
9890 struct spoolss_62
*r
)
9892 p
->rng_fault_state
= true;
9893 return WERR_NOT_SUPPORTED
;
9896 /****************************************************************
9898 ****************************************************************/
9900 WERROR
_spoolss_63(pipes_struct
*p
,
9901 struct spoolss_63
*r
)
9903 p
->rng_fault_state
= true;
9904 return WERR_NOT_SUPPORTED
;
9907 /****************************************************************
9909 ****************************************************************/
9911 WERROR
_spoolss_64(pipes_struct
*p
,
9912 struct spoolss_64
*r
)
9914 p
->rng_fault_state
= true;
9915 return WERR_NOT_SUPPORTED
;
9918 /****************************************************************
9920 ****************************************************************/
9922 WERROR
_spoolss_65(pipes_struct
*p
,
9923 struct spoolss_65
*r
)
9925 p
->rng_fault_state
= true;
9926 return WERR_NOT_SUPPORTED
;
9929 /****************************************************************
9930 _spoolss_GetCorePrinterDrivers
9931 ****************************************************************/
9933 WERROR
_spoolss_GetCorePrinterDrivers(pipes_struct
*p
,
9934 struct spoolss_GetCorePrinterDrivers
*r
)
9936 p
->rng_fault_state
= true;
9937 return WERR_NOT_SUPPORTED
;
9940 /****************************************************************
9942 ****************************************************************/
9944 WERROR
_spoolss_67(pipes_struct
*p
,
9945 struct spoolss_67
*r
)
9947 p
->rng_fault_state
= true;
9948 return WERR_NOT_SUPPORTED
;
9951 /****************************************************************
9952 _spoolss_GetPrinterDriverPackagePath
9953 ****************************************************************/
9955 WERROR
_spoolss_GetPrinterDriverPackagePath(pipes_struct
*p
,
9956 struct spoolss_GetPrinterDriverPackagePath
*r
)
9958 p
->rng_fault_state
= true;
9959 return WERR_NOT_SUPPORTED
;
9962 /****************************************************************
9964 ****************************************************************/
9966 WERROR
_spoolss_69(pipes_struct
*p
,
9967 struct spoolss_69
*r
)
9969 p
->rng_fault_state
= true;
9970 return WERR_NOT_SUPPORTED
;
9973 /****************************************************************
9975 ****************************************************************/
9977 WERROR
_spoolss_6a(pipes_struct
*p
,
9978 struct spoolss_6a
*r
)
9980 p
->rng_fault_state
= true;
9981 return WERR_NOT_SUPPORTED
;
9984 /****************************************************************
9986 ****************************************************************/
9988 WERROR
_spoolss_6b(pipes_struct
*p
,
9989 struct spoolss_6b
*r
)
9991 p
->rng_fault_state
= true;
9992 return WERR_NOT_SUPPORTED
;
9995 /****************************************************************
9997 ****************************************************************/
9999 WERROR
_spoolss_6c(pipes_struct
*p
,
10000 struct spoolss_6c
*r
)
10002 p
->rng_fault_state
= true;
10003 return WERR_NOT_SUPPORTED
;
10006 /****************************************************************
10008 ****************************************************************/
10010 WERROR
_spoolss_6d(pipes_struct
*p
,
10011 struct spoolss_6d
*r
)
10013 p
->rng_fault_state
= true;
10014 return WERR_NOT_SUPPORTED
;