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 "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "librpc/gen_ndr/ndr_security.h"
39 #include "registry/reg_objects.h"
40 #include "include/printing.h"
42 #include "../librpc/gen_ndr/netlogon.h"
45 /* macros stolen from s4 spoolss server */
46 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
47 ((info)?ndr_size_##fn(info, level, 0):0)
49 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
50 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
52 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
53 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
55 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
58 #define DBGC_CLASS DBGC_RPC_SRV
60 static Printer_entry
*printers_list
;
62 typedef struct _counter_printer_0
{
63 struct _counter_printer_0
*next
;
64 struct _counter_printer_0
*prev
;
70 static counter_printer_0
*counter_list
;
72 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
73 static uint32_t smb_connections
= 0;
76 /* Map generic permissions to printer object specific permissions */
78 const struct standard_mapping printer_std_mapping
= {
85 /* Map generic permissions to print server object specific permissions */
87 const struct standard_mapping printserver_std_mapping
= {
94 /* API table for Xcv Monitor functions */
96 struct xcv_api_table
{
98 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, NT_USER_TOKEN
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
101 static void prune_printername_cache(void);
103 /********************************************************************
104 * Canonicalize servername.
105 ********************************************************************/
107 static const char *canon_servername(const char *servername
)
109 const char *pservername
= servername
;
110 while (*pservername
== '\\') {
116 /* translate between internal status numbers and NT status numbers */
117 static int nt_printj_status(int v
)
123 return JOB_STATUS_PAUSED
;
125 return JOB_STATUS_SPOOLING
;
127 return JOB_STATUS_PRINTING
;
129 return JOB_STATUS_ERROR
;
131 return JOB_STATUS_DELETING
;
133 return JOB_STATUS_OFFLINE
;
135 return JOB_STATUS_PAPEROUT
;
137 return JOB_STATUS_PRINTED
;
139 return JOB_STATUS_DELETED
;
141 return JOB_STATUS_BLOCKED_DEVQ
;
142 case LPQ_USER_INTERVENTION
:
143 return JOB_STATUS_USER_INTERVENTION
;
148 static int nt_printq_status(int v
)
152 return PRINTER_STATUS_PAUSED
;
161 /***************************************************************************
162 Disconnect from the client
163 ****************************************************************************/
165 static void srv_spoolss_replycloseprinter(
166 int snum
, struct policy_handle
*handle
,
167 struct messaging_context
*msg_ctx
)
173 * Tell the specific printing tdb we no longer want messages for this printer
174 * by deregistering our PID.
177 if (!print_notify_deregister_pid(snum
))
178 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
180 /* weird if the test succeeds !!! */
181 if (smb_connections
==0) {
182 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
186 status
= rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe
, talloc_tos(),
189 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
190 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
191 win_errstr(result
)));
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections
==1) {
196 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe
) );
198 * The above call shuts down the pipe also.
200 notify_cli_pipe
= NULL
;
202 if (msg_ctx
!= NULL
) {
203 messaging_deregister(msg_ctx
, MSG_PRINTER_NOTIFY2
,
207 * Tell the serverid.tdb we're no longer
208 * interested in printer notify messages.
211 serverid_register_msg_flags(
212 messaging_server_id(msg_ctx
),
213 false, FLAG_MSG_PRINT_NOTIFY
);
220 /****************************************************************************
221 Functions to free a printer entry datastruct.
222 ****************************************************************************/
224 static int printer_entry_destructor(Printer_entry
*Printer
)
226 if (Printer
->notify
.client_connected
== true) {
229 if ( Printer
->printer_type
== SPLHND_SERVER
) {
231 srv_spoolss_replycloseprinter(
232 snum
, &Printer
->notify
.client_hnd
,
233 Printer
->notify
.msg_ctx
);
234 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
235 snum
= print_queue_snum(Printer
->sharename
);
237 srv_spoolss_replycloseprinter(
238 snum
, &Printer
->notify
.client_hnd
,
239 Printer
->notify
.msg_ctx
);
243 Printer
->notify
.flags
=0;
244 Printer
->notify
.options
=0;
245 Printer
->notify
.localmachine
[0]='\0';
246 Printer
->notify
.printerlocal
=0;
247 TALLOC_FREE(Printer
->notify
.option
);
248 Printer
->notify
.client_connected
= false;
250 TALLOC_FREE(Printer
->devmode
);
252 /* Remove from the internal list. */
253 DLIST_REMOVE(printers_list
, Printer
);
257 /****************************************************************************
258 find printer index by handle
259 ****************************************************************************/
261 static Printer_entry
*find_printer_index_by_hnd(struct pipes_struct
*p
,
262 struct policy_handle
*hnd
)
264 Printer_entry
*find_printer
= NULL
;
266 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
267 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
274 /****************************************************************************
275 Close printer index by handle.
276 ****************************************************************************/
278 static bool close_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
280 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
283 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
288 close_policy_hnd(p
, hnd
);
293 /****************************************************************************
294 Delete a printer given a handle.
295 ****************************************************************************/
297 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
,
298 const char *sharename
,
299 struct messaging_context
*msg_ctx
)
301 char *cmd
= lp_deleteprinter_cmd();
302 char *command
= NULL
;
304 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
305 bool is_print_op
= false;
307 /* can't fail if we don't try */
312 command
= talloc_asprintf(ctx
,
319 is_print_op
= user_has_privileges( token
, &se_printop
);
321 DEBUG(10,("Running [%s]\n", command
));
323 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
328 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
329 /* Tell everyone we updated smb.conf. */
330 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
336 /********** END SePrintOperatorPrivlege BLOCK **********/
338 DEBUGADD(10,("returned [%d]\n", ret
));
340 TALLOC_FREE(command
);
343 return WERR_BADFID
; /* What to return here? */
345 /* go ahead and re-read the services immediately */
347 reload_services(msg_ctx
, -1, false);
350 if ( lp_servicenumber( sharename
) > 0 )
351 return WERR_ACCESS_DENIED
;
356 /****************************************************************************
357 Delete a printer given a handle.
358 ****************************************************************************/
360 static WERROR
delete_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
362 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
366 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
372 * It turns out that Windows allows delete printer on a handle
373 * opened by an admin user, then used on a pipe handle created
374 * by an anonymous user..... but they're working on security.... riiight !
378 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
379 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
380 return WERR_ACCESS_DENIED
;
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 result
= winreg_delete_printer_key(p
->mem_ctx
, p
->server_info
,
387 p
->msg_ctx
, Printer
->sharename
, "");
388 if (!W_ERROR_IS_OK(result
)) {
389 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
393 result
= delete_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
394 Printer
->sharename
, p
->msg_ctx
);
395 if (!W_ERROR_IS_OK(result
)) {
398 prune_printername_cache();
402 /****************************************************************************
403 Return the snum of a printer corresponding to an handle.
404 ****************************************************************************/
406 static bool get_printer_snum(struct pipes_struct
*p
, struct policy_handle
*hnd
,
407 int *number
, struct share_params
**params
)
409 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
412 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
417 switch (Printer
->printer_type
) {
419 DEBUG(4,("short name:%s\n", Printer
->sharename
));
420 *number
= print_queue_snum(Printer
->sharename
);
421 return (*number
!= -1);
429 /****************************************************************************
430 Set printer handle type.
431 Check if it's \\server or \\server\printer
432 ****************************************************************************/
434 static bool set_printer_hnd_printertype(Printer_entry
*Printer
, const char *handlename
)
436 DEBUG(3,("Setting printer type=%s\n", handlename
));
438 if ( strlen(handlename
) < 3 ) {
439 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
443 /* it's a print server */
444 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
445 DEBUGADD(4,("Printer is a print server\n"));
446 Printer
->printer_type
= SPLHND_SERVER
;
448 /* it's a printer (set_printer_hnd_name() will handle port monitors */
450 DEBUGADD(4,("Printer is a printer\n"));
451 Printer
->printer_type
= SPLHND_PRINTER
;
457 static void prune_printername_cache_fn(const char *key
, const char *value
,
458 time_t timeout
, void *private_data
)
463 static void prune_printername_cache(void)
465 gencache_iterate(prune_printername_cache_fn
, NULL
, "PRINTERNAME/*");
468 /****************************************************************************
469 Set printer handle name.. Accept names like \\server, \\server\printer,
470 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
471 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
472 XcvDataPort() interface.
473 ****************************************************************************/
475 static bool set_printer_hnd_name(TALLOC_CTX
*mem_ctx
,
476 struct auth_serversupplied_info
*server_info
,
477 struct messaging_context
*msg_ctx
,
478 Printer_entry
*Printer
,
479 const char *handlename
)
482 int n_services
=lp_numservices();
484 const char *printername
;
485 const char *servername
= NULL
;
488 struct spoolss_PrinterInfo2
*info2
= NULL
;
492 * Hopefully nobody names his printers like this. Maybe \ or ,
493 * are illegal in printer names even?
495 const char printer_not_found
[] = "Printer \\, !@#$%^&*( not found";
499 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
500 (unsigned long)strlen(handlename
)));
502 aprinter
= CONST_DISCARD(char *, handlename
);
503 if ( *handlename
== '\\' ) {
504 servername
= canon_servername(handlename
);
505 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
509 if (!is_myname_or_ipaddr(servername
)) {
513 fstrcpy(Printer
->servername
, servername
);
516 if (Printer
->printer_type
== SPLHND_SERVER
) {
520 if (Printer
->printer_type
!= SPLHND_PRINTER
) {
524 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
526 /* check for the Port Monitor Interface */
527 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
528 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
529 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
532 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
533 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
534 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
539 * With hundreds of printers, the "for" loop iterating all
540 * shares can be quite expensive, as it is done on every
541 * OpenPrinter. The loop maps "aprinter" to "sname", the
542 * result of which we cache in gencache.
545 cache_key
= talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
547 if ((cache_key
!= NULL
) && gencache_get(cache_key
, &tmp
, NULL
)) {
549 found
= (strcmp(tmp
, printer_not_found
) != 0);
551 DEBUG(4, ("Printer %s not found\n", aprinter
));
559 /* Search all sharenames first as this is easier than pulling
560 the printer_info_2 off of disk. Don't use find_service() since
561 that calls out to map_username() */
563 /* do another loop to look for printernames */
564 for (snum
= 0; !found
&& snum
< n_services
; snum
++) {
565 const char *printer
= lp_const_servicename(snum
);
567 /* no point going on if this is not a printer */
568 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
))) {
572 /* ignore [printers] share */
573 if (strequal(printer
, "printers")) {
577 fstrcpy(sname
, printer
);
578 if (strequal(aprinter
, printer
)) {
583 /* no point looking up the printer object if
584 we aren't allowing printername != sharename */
585 if (lp_force_printername(snum
)) {
589 result
= winreg_get_printer(mem_ctx
,
595 if ( !W_ERROR_IS_OK(result
) ) {
596 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
597 sname
, win_errstr(result
)));
601 printername
= strrchr(info2
->printername
, '\\');
602 if (printername
== NULL
) {
603 printername
= info2
->printername
;
608 if (strequal(printername
, aprinter
)) {
613 DEBUGADD(10, ("printername: %s\n", printername
));
619 if (cache_key
!= NULL
) {
620 gencache_set(cache_key
, printer_not_found
,
622 TALLOC_FREE(cache_key
);
624 DEBUGADD(4,("Printer not found\n"));
628 if (cache_key
!= NULL
) {
629 gencache_set(cache_key
, sname
, time(NULL
)+300);
630 TALLOC_FREE(cache_key
);
633 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
635 fstrcpy(Printer
->sharename
, sname
);
640 /****************************************************************************
641 Find first available printer slot. creates a printer handle for you.
642 ****************************************************************************/
644 static bool open_printer_hnd(struct pipes_struct
*p
, struct policy_handle
*hnd
,
645 const char *name
, uint32_t access_granted
)
647 Printer_entry
*new_printer
;
649 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
651 new_printer
= TALLOC_ZERO_P(NULL
, Printer_entry
);
652 if (new_printer
== NULL
) {
655 talloc_set_destructor(new_printer
, printer_entry_destructor
);
657 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
658 TALLOC_FREE(new_printer
);
662 /* Add to the internal list. */
663 DLIST_ADD(printers_list
, new_printer
);
665 new_printer
->notify
.option
=NULL
;
667 if (!set_printer_hnd_printertype(new_printer
, name
)) {
668 close_printer_handle(p
, hnd
);
672 if (!set_printer_hnd_name(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
673 new_printer
, name
)) {
674 close_printer_handle(p
, hnd
);
678 new_printer
->access_granted
= access_granted
;
680 DEBUG(5, ("%d printer handles active\n",
681 (int)num_pipe_handles(p
)));
686 /***************************************************************************
687 check to see if the client motify handle is monitoring the notification
688 given by (notify_type, notify_field).
689 **************************************************************************/
691 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
692 uint16_t notify_field
)
697 static bool is_monitoring_event(Printer_entry
*p
, uint16_t notify_type
,
698 uint16_t notify_field
)
700 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
704 * Flags should always be zero when the change notify
705 * is registered by the client's spooler. A user Win32 app
706 * might use the flags though instead of the NOTIFY_OPTION_INFO
715 return is_monitoring_event_flags(
716 p
->notify
.flags
, notify_type
, notify_field
);
718 for (i
= 0; i
< option
->count
; i
++) {
720 /* Check match for notify_type */
722 if (option
->types
[i
].type
!= notify_type
)
725 /* Check match for field */
727 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
728 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
734 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
735 p
->servername
, p
->sharename
, notify_type
, notify_field
));
740 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
741 _data->data.integer[0] = _integer; \
742 _data->data.integer[1] = 0;
745 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
746 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
747 if (!_data->data.string.string) {\
748 _data->data.string.size = 0; \
750 _data->data.string.size = strlen_m_term(_p) * 2;
752 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
753 _data->data.devmode.devmode = _devmode;
755 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
756 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
757 if (!_data->data.sd.sd) { \
758 _data->data.sd.sd_size = 0; \
760 _data->data.sd.sd_size = \
761 ndr_size_security_descriptor(_data->data.sd.sd, 0);
763 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
768 struct spoolss_Time st
;
772 if (!init_systemtime(&st
, t
)) {
776 p
= talloc_array(mem_ctx
, char, len
);
782 * Systemtime must be linearized as a set of UINT16's.
783 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
786 SSVAL(p
, 0, st
.year
);
787 SSVAL(p
, 2, st
.month
);
788 SSVAL(p
, 4, st
.day_of_week
);
790 SSVAL(p
, 8, st
.hour
);
791 SSVAL(p
, 10, st
.minute
);
792 SSVAL(p
, 12, st
.second
);
793 SSVAL(p
, 14, st
.millisecond
);
799 /* Convert a notification message to a struct spoolss_Notify */
801 static void notify_one_value(struct spoolss_notify_msg
*msg
,
802 struct spoolss_Notify
*data
,
805 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
808 static void notify_string(struct spoolss_notify_msg
*msg
,
809 struct spoolss_Notify
*data
,
812 /* The length of the message includes the trailing \0 */
814 data
->data
.string
.size
= msg
->len
* 2;
815 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
816 if (!data
->data
.string
.string
) {
817 data
->data
.string
.size
= 0;
822 static void notify_system_time(struct spoolss_notify_msg
*msg
,
823 struct spoolss_Notify
*data
,
826 data
->data
.string
.string
= NULL
;
827 data
->data
.string
.size
= 0;
829 if (msg
->len
!= sizeof(time_t)) {
830 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
835 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
836 &data
->data
.string
.string
,
837 &data
->data
.string
.size
);
840 struct notify2_message_table
{
842 void (*fn
)(struct spoolss_notify_msg
*msg
,
843 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
846 static struct notify2_message_table printer_notify_table
[] = {
847 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
848 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
849 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
850 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
851 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
852 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
853 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
854 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
855 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
856 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
857 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
858 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
859 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
860 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
861 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
862 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
863 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
864 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
865 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
868 static struct notify2_message_table job_notify_table
[] = {
869 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
870 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
871 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
872 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
873 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
874 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
875 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
876 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
877 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
878 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
879 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
880 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
881 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
882 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
883 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
884 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
885 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
886 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
887 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
888 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
889 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
890 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
891 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
892 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
896 /***********************************************************************
897 Allocate talloc context for container object
898 **********************************************************************/
900 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
905 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
910 /***********************************************************************
911 release all allocated memory and zero out structure
912 **********************************************************************/
914 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
920 talloc_destroy(ctr
->ctx
);
927 /***********************************************************************
928 **********************************************************************/
930 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
938 /***********************************************************************
939 **********************************************************************/
941 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
943 if ( !ctr
|| !ctr
->msg_groups
)
946 if ( idx
>= ctr
->num_groups
)
949 return &ctr
->msg_groups
[idx
];
953 /***********************************************************************
954 How many groups of change messages do we have ?
955 **********************************************************************/
957 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
962 return ctr
->num_groups
;
965 /***********************************************************************
966 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
967 **********************************************************************/
969 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
971 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
972 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
973 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
979 /* loop over all groups looking for a matching printer name */
981 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
982 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
986 /* add a new group? */
988 if ( i
== ctr
->num_groups
) {
991 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
992 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
995 ctr
->msg_groups
= groups
;
997 /* clear the new entry and set the printer name */
999 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
1000 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
1003 /* add the change messages; 'i' is the correct index now regardless */
1005 msg_grp
= &ctr
->msg_groups
[i
];
1007 msg_grp
->num_msgs
++;
1009 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
1010 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
1013 msg_grp
->msgs
= msg_list
;
1015 new_slot
= msg_grp
->num_msgs
-1;
1016 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
1018 /* need to allocate own copy of data */
1020 if ( msg
->len
!= 0 )
1021 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
1022 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
1024 return ctr
->num_groups
;
1027 static void construct_info_data(struct spoolss_Notify
*info_data
,
1028 enum spoolss_NotifyType type
,
1029 uint16_t field
, int id
);
1031 /***********************************************************************
1032 Send a change notication message on all handles which have a call
1034 **********************************************************************/
1036 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1039 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
1040 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
1041 SPOOLSS_NOTIFY_MSG
*messages
;
1042 int sending_msg_count
;
1045 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1049 messages
= msg_group
->msgs
;
1052 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
1056 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
1058 /* loop over all printers */
1060 for (p
= printers_list
; p
; p
= p
->next
) {
1061 struct spoolss_Notify
*notifies
;
1066 /* Is there notification on this handle? */
1068 if ( !p
->notify
.client_connected
)
1071 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
1073 /* For this printer? Print servers always receive
1076 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
1077 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
1080 DEBUG(10,("Our printer\n"));
1082 /* allocate the max entries possible */
1084 notifies
= TALLOC_ZERO_ARRAY(mem_ctx
, struct spoolss_Notify
, msg_group
->num_msgs
);
1089 /* build the array of change notifications */
1091 sending_msg_count
= 0;
1093 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1094 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1096 /* Are we monitoring this event? */
1098 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1101 sending_msg_count
++;
1104 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1105 msg
->type
, msg
->field
, p
->sharename
));
1108 * if the is a printer notification handle and not a job notification
1109 * type, then set the id to 0. Other wise just use what was specified
1112 * When registering change notification on a print server handle
1113 * we always need to send back the id (snum) matching the printer
1114 * for which the change took place. For change notify registered
1115 * on a printer handle, this does not matter and the id should be 0.
1120 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1126 /* Convert unix jobid to smb jobid */
1128 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1129 id
= sysjob_to_jobid(msg
->id
);
1132 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1137 construct_info_data(¬ifies
[count
],
1138 (enum spoolss_NotifyType
) msg
->type
,
1143 case PRINTER_NOTIFY_TYPE
:
1144 if ( printer_notify_table
[msg
->field
].fn
)
1145 printer_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1148 case JOB_NOTIFY_TYPE
:
1149 if ( job_notify_table
[msg
->field
].fn
)
1150 job_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1154 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1161 if ( sending_msg_count
) {
1164 union spoolss_ReplyPrinterInfo info
;
1165 struct spoolss_NotifyInfo info0
;
1166 uint32_t reply_result
;
1168 info0
.version
= 0x2;
1169 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1170 info0
.count
= count
;
1171 info0
.notifies
= notifies
;
1173 info
.info0
= &info0
;
1175 status
= rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe
, mem_ctx
,
1176 &p
->notify
.client_hnd
,
1177 p
->notify
.change
, /* color */
1180 0, /* reply_type, must be 0 */
1183 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
1184 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1185 notify_cli_pipe
->srv_name_slash
,
1188 switch (reply_result
) {
1191 case PRINTER_NOTIFY_INFO_DISCARDED
:
1192 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1193 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1202 DEBUG(8,("send_notify2_changes: Exit...\n"));
1206 /***********************************************************************
1207 **********************************************************************/
1209 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1212 uint32_t tv_sec
, tv_usec
;
1215 /* Unpack message */
1217 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1220 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1222 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1225 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1226 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1228 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1229 &msg
->len
, &msg
->notify
.data
);
1231 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1232 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1234 tv
->tv_sec
= tv_sec
;
1235 tv
->tv_usec
= tv_usec
;
1238 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1239 msg
->notify
.value
[1]));
1241 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1246 /********************************************************************
1247 Receive a notify2 message list
1248 ********************************************************************/
1250 static void receive_notify2_message_list(struct messaging_context
*msg
,
1253 struct server_id server_id
,
1256 size_t msg_count
, i
;
1257 char *buf
= (char *)data
->data
;
1260 SPOOLSS_NOTIFY_MSG notify
;
1261 SPOOLSS_NOTIFY_MSG_CTR messages
;
1264 if (data
->length
< 4) {
1265 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1269 msg_count
= IVAL(buf
, 0);
1272 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1274 if (msg_count
== 0) {
1275 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1279 /* initialize the container */
1281 ZERO_STRUCT( messages
);
1282 notify_msg_ctr_init( &messages
);
1285 * build message groups for each printer identified
1286 * in a change_notify msg. Remember that a PCN message
1287 * includes the handle returned for the srv_spoolss_replyopenprinter()
1288 * call. Therefore messages are grouped according to printer handle.
1291 for ( i
=0; i
<msg_count
; i
++ ) {
1292 struct timeval msg_tv
;
1294 if (msg_ptr
+ 4 - buf
> data
->length
) {
1295 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1299 msg_len
= IVAL(msg_ptr
,0);
1302 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1303 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1307 /* unpack messages */
1309 ZERO_STRUCT( notify
);
1310 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1313 /* add to correct list in container */
1315 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1317 /* free memory that might have been allocated by notify2_unpack_msg() */
1319 if ( notify
.len
!= 0 )
1320 SAFE_FREE( notify
.notify
.data
);
1323 /* process each group of messages */
1325 num_groups
= notify_msg_ctr_numgroups( &messages
);
1326 for ( i
=0; i
<num_groups
; i
++ )
1327 send_notify2_changes( &messages
, i
);
1332 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1333 (uint32_t)msg_count
));
1335 notify_msg_ctr_destroy( &messages
);
1340 /********************************************************************
1341 Send a message to ourself about new driver being installed
1342 so we can upgrade the information for each printer bound to this
1344 ********************************************************************/
1346 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
,
1347 struct messaging_context
*msg_ctx
)
1349 int len
= strlen(drivername
);
1354 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1357 messaging_send_buf(msg_ctx
, messaging_server_id(msg_ctx
),
1358 MSG_PRINTER_DRVUPGRADE
,
1359 (uint8_t *)drivername
, len
+1);
1364 /**********************************************************************
1365 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1366 over all printers, upgrading ones as necessary
1367 **********************************************************************/
1369 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1372 struct server_id server_id
,
1375 TALLOC_CTX
*tmp_ctx
;
1376 struct auth_serversupplied_info
*server_info
= NULL
;
1377 struct spoolss_PrinterInfo2
*pinfo2
;
1380 const char *drivername
;
1382 int n_services
= lp_numservices();
1385 tmp_ctx
= talloc_new(NULL
);
1386 if (!tmp_ctx
) return;
1388 status
= make_server_info_system(tmp_ctx
, &server_info
);
1389 if (!NT_STATUS_IS_OK(status
)) {
1390 DEBUG(0, ("do_drv_upgrade_printer: "
1391 "Could not create system server_info\n"));
1395 len
= MIN(data
->length
,sizeof(drivername
)-1);
1396 drivername
= talloc_strndup(tmp_ctx
, (const char *)data
->data
, len
);
1398 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1402 DEBUG(10, ("do_drv_upgrade_printer: "
1403 "Got message for new driver [%s]\n", drivername
));
1405 /* Iterate the printer list */
1407 for (snum
= 0; snum
< n_services
; snum
++) {
1408 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1412 result
= winreg_get_printer(tmp_ctx
, server_info
, msg
,
1414 lp_const_servicename(snum
),
1417 if (!W_ERROR_IS_OK(result
)) {
1421 if (!pinfo2
->drivername
) {
1425 if (strcmp(drivername
, pinfo2
->drivername
) != 0) {
1429 DEBUG(6,("Updating printer [%s]\n", pinfo2
->printername
));
1431 /* all we care about currently is the change_id */
1432 result
= winreg_printer_update_changeid(tmp_ctx
,
1435 pinfo2
->printername
);
1437 if (!W_ERROR_IS_OK(result
)) {
1438 DEBUG(3, ("do_drv_upgrade_printer: "
1439 "Failed to update changeid [%s]\n",
1440 win_errstr(result
)));
1446 talloc_free(tmp_ctx
);
1449 /********************************************************************
1450 Update the cache for all printq's with a registered client
1452 ********************************************************************/
1454 void update_monitored_printq_cache(struct messaging_context
*msg_ctx
)
1456 Printer_entry
*printer
= printers_list
;
1459 /* loop through all printers and update the cache where
1460 client_connected == true */
1463 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1464 && printer
->notify
.client_connected
)
1466 snum
= print_queue_snum(printer
->sharename
);
1467 print_queue_status(msg_ctx
, snum
, NULL
, NULL
);
1470 printer
= printer
->next
;
1476 /****************************************************************
1477 _spoolss_OpenPrinter
1478 ****************************************************************/
1480 WERROR
_spoolss_OpenPrinter(struct pipes_struct
*p
,
1481 struct spoolss_OpenPrinter
*r
)
1483 struct spoolss_OpenPrinterEx e
;
1486 ZERO_STRUCT(e
.in
.userlevel
);
1488 e
.in
.printername
= r
->in
.printername
;
1489 e
.in
.datatype
= r
->in
.datatype
;
1490 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1491 e
.in
.access_mask
= r
->in
.access_mask
;
1494 e
.out
.handle
= r
->out
.handle
;
1496 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1498 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1499 /* OpenPrinterEx returns this for a bad
1500 * printer name. We must return WERR_INVALID_PRINTER_NAME
1503 werr
= WERR_INVALID_PRINTER_NAME
;
1509 static WERROR
copy_devicemode(TALLOC_CTX
*mem_ctx
,
1510 struct spoolss_DeviceMode
*orig
,
1511 struct spoolss_DeviceMode
**dest
)
1513 struct spoolss_DeviceMode
*dm
;
1515 dm
= talloc(mem_ctx
, struct spoolss_DeviceMode
);
1520 /* copy all values, then duplicate strings and structs */
1523 dm
->devicename
= talloc_strdup(dm
, orig
->devicename
);
1524 if (!dm
->devicename
) {
1527 dm
->formname
= talloc_strdup(dm
, orig
->formname
);
1528 if (!dm
->formname
) {
1531 if (orig
->driverextra_data
.data
) {
1532 dm
->driverextra_data
.data
=
1533 (uint8_t *) talloc_memdup(dm
, orig
->driverextra_data
.data
,
1534 orig
->driverextra_data
.length
);
1535 if (!dm
->driverextra_data
.data
) {
1544 /****************************************************************
1545 _spoolss_OpenPrinterEx
1546 ****************************************************************/
1548 WERROR
_spoolss_OpenPrinterEx(struct pipes_struct
*p
,
1549 struct spoolss_OpenPrinterEx
*r
)
1552 Printer_entry
*Printer
=NULL
;
1554 if (!r
->in
.printername
) {
1555 return WERR_INVALID_PARAM
;
1558 /* some sanity check because you can open a printer or a print server */
1559 /* aka: \\server\printer or \\server */
1561 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1563 if (!open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0)) {
1564 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1565 "for printer %s\n", r
->in
.printername
));
1566 ZERO_STRUCTP(r
->out
.handle
);
1567 return WERR_INVALID_PARAM
;
1570 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1572 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1573 "handle we created for printer %s\n", r
->in
.printername
));
1574 close_printer_handle(p
, r
->out
.handle
);
1575 ZERO_STRUCTP(r
->out
.handle
);
1576 return WERR_INVALID_PARAM
;
1580 * First case: the user is opening the print server:
1582 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1583 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1585 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1586 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1587 * or if the user is listed in the smb.conf printer admin parameter.
1589 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1590 * client view printer folder, but does not show the MSAPW.
1592 * Note: this test needs code to check access rights here too. Jeremy
1593 * could you look at this?
1595 * Second case: the user is opening a printer:
1596 * NT doesn't let us connect to a printer if the connecting user
1597 * doesn't have print permission.
1599 * Third case: user is opening a Port Monitor
1600 * access checks same as opening a handle to the print server.
1603 switch (Printer
->printer_type
)
1606 case SPLHND_PORTMON_TCP
:
1607 case SPLHND_PORTMON_LOCAL
:
1608 /* Printserver handles use global struct... */
1612 /* Map standard access rights to object specific access rights */
1614 se_map_standard(&r
->in
.access_mask
,
1615 &printserver_std_mapping
);
1617 /* Deny any object specific bits that don't apply to print
1618 servers (i.e printer and job specific bits) */
1620 r
->in
.access_mask
&= SEC_MASK_SPECIFIC
;
1622 if (r
->in
.access_mask
&
1623 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1624 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1625 close_printer_handle(p
, r
->out
.handle
);
1626 ZERO_STRUCTP(r
->out
.handle
);
1627 return WERR_ACCESS_DENIED
;
1630 /* Allow admin access */
1632 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1634 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1636 if (!lp_ms_add_printer_wizard()) {
1637 close_printer_handle(p
, r
->out
.handle
);
1638 ZERO_STRUCTP(r
->out
.handle
);
1639 return WERR_ACCESS_DENIED
;
1642 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1643 and not a printer admin, then fail */
1645 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
1646 !user_has_privileges(p
->server_info
->ptok
,
1648 !token_contains_name_in_list(
1649 uidtoname(p
->server_info
->utok
.uid
),
1650 p
->server_info
->info3
->base
.domain
.string
,
1652 p
->server_info
->ptok
,
1653 lp_printer_admin(snum
))) {
1654 close_printer_handle(p
, r
->out
.handle
);
1655 ZERO_STRUCTP(r
->out
.handle
);
1656 return WERR_ACCESS_DENIED
;
1659 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1663 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1666 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1667 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1669 /* We fall through to return WERR_OK */
1672 case SPLHND_PRINTER
:
1673 /* NT doesn't let us connect to a printer if the connecting user
1674 doesn't have print permission. */
1676 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1677 close_printer_handle(p
, r
->out
.handle
);
1678 ZERO_STRUCTP(r
->out
.handle
);
1682 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1683 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1686 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1688 /* map an empty access mask to the minimum access mask */
1689 if (r
->in
.access_mask
== 0x0)
1690 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1693 * If we are not serving the printer driver for this printer,
1694 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1695 * will keep NT clients happy --jerry
1698 if (lp_use_client_driver(snum
)
1699 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1701 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1704 /* check smb.conf parameters and the the sec_desc */
1706 if (!allow_access(lp_hostsdeny(snum
), lp_hostsallow(snum
),
1707 p
->client_id
->name
, p
->client_id
->addr
)) {
1708 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1709 ZERO_STRUCTP(r
->out
.handle
);
1710 return WERR_ACCESS_DENIED
;
1713 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1714 p
->server_info
->ptok
, snum
) ||
1715 !print_access_check(p
->server_info
, p
->msg_ctx
, snum
,
1716 r
->in
.access_mask
)) {
1717 DEBUG(3, ("access DENIED for printer open\n"));
1718 close_printer_handle(p
, r
->out
.handle
);
1719 ZERO_STRUCTP(r
->out
.handle
);
1720 return WERR_ACCESS_DENIED
;
1723 if ((r
->in
.access_mask
& SEC_MASK_SPECIFIC
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1724 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1725 close_printer_handle(p
, r
->out
.handle
);
1726 ZERO_STRUCTP(r
->out
.handle
);
1727 return WERR_ACCESS_DENIED
;
1730 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1731 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1733 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1735 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1736 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1738 winreg_create_printer(p
->mem_ctx
,
1741 Printer
->servername
,
1742 lp_const_servicename(snum
));
1747 /* sanity check to prevent programmer error */
1748 ZERO_STRUCTP(r
->out
.handle
);
1752 Printer
->access_granted
= r
->in
.access_mask
;
1755 * If the client sent a devmode in the OpenPrinter() call, then
1756 * save it here in case we get a job submission on this handle
1759 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1760 r
->in
.devmode_ctr
.devmode
) {
1761 copy_devicemode(NULL
, r
->in
.devmode_ctr
.devmode
,
1765 #if 0 /* JERRY -- I'm doubtful this is really effective */
1766 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1767 optimization in Windows 2000 clients --jerry */
1769 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1770 && (RA_WIN2K
== get_remote_arch()) )
1772 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1773 sys_usleep( 500000 );
1780 /****************************************************************
1781 _spoolss_ClosePrinter
1782 ****************************************************************/
1784 WERROR
_spoolss_ClosePrinter(struct pipes_struct
*p
,
1785 struct spoolss_ClosePrinter
*r
)
1787 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1789 if (Printer
&& Printer
->document_started
) {
1790 struct spoolss_EndDocPrinter e
;
1792 e
.in
.handle
= r
->in
.handle
;
1794 _spoolss_EndDocPrinter(p
, &e
);
1797 if (!close_printer_handle(p
, r
->in
.handle
))
1800 /* clear the returned printer handle. Observed behavior
1801 from Win2k server. Don't think this really matters.
1802 Previous code just copied the value of the closed
1805 ZERO_STRUCTP(r
->out
.handle
);
1810 /****************************************************************
1811 _spoolss_DeletePrinter
1812 ****************************************************************/
1814 WERROR
_spoolss_DeletePrinter(struct pipes_struct
*p
,
1815 struct spoolss_DeletePrinter
*r
)
1817 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1821 if (Printer
&& Printer
->document_started
) {
1822 struct spoolss_EndDocPrinter e
;
1824 e
.in
.handle
= r
->in
.handle
;
1826 _spoolss_EndDocPrinter(p
, &e
);
1829 if (get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
1830 winreg_delete_printer_key(p
->mem_ctx
,
1833 lp_const_servicename(snum
),
1837 result
= delete_printer_handle(p
, r
->in
.handle
);
1842 /*******************************************************************
1843 * static function to lookup the version id corresponding to an
1844 * long architecture string
1845 ******************************************************************/
1847 static const struct print_architecture_table_node archi_table
[]= {
1849 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
1850 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
1851 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
1852 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
1853 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
1854 {"Windows IA64", SPL_ARCH_IA64
, 3 },
1855 {"Windows x64", SPL_ARCH_X64
, 3 },
1859 static int get_version_id(const char *arch
)
1863 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1865 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1866 return (archi_table
[i
].version
);
1872 /****************************************************************
1873 _spoolss_DeletePrinterDriver
1874 ****************************************************************/
1876 WERROR
_spoolss_DeletePrinterDriver(struct pipes_struct
*p
,
1877 struct spoolss_DeletePrinterDriver
*r
)
1880 struct spoolss_DriverInfo8
*info
= NULL
;
1881 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1884 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1886 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1887 and not a printer admin, then fail */
1889 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1890 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1891 && !token_contains_name_in_list(
1892 uidtoname(p
->server_info
->utok
.uid
),
1893 p
->server_info
->info3
->base
.domain
.string
,
1895 p
->server_info
->ptok
,
1896 lp_printer_admin(-1)) )
1898 return WERR_ACCESS_DENIED
;
1901 /* check that we have a valid driver name first */
1903 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
1904 return WERR_INVALID_ENVIRONMENT
;
1906 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
1907 r
->in
.architecture
, r
->in
.driver
,
1909 if (!W_ERROR_IS_OK(status
)) {
1910 /* try for Win2k driver if "Windows NT x86" */
1912 if ( version
== 2 ) {
1915 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
,
1920 if (!W_ERROR_IS_OK(status
)) {
1921 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1925 /* otherwise it was a failure */
1927 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1933 if (printer_driver_in_use(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
1935 status
= WERR_PRINTER_DRIVER_IN_USE
;
1940 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
,
1943 r
->in
.driver
, 3, &info_win2k
);
1944 if (W_ERROR_IS_OK(status
)) {
1945 /* if we get to here, we now have 2 driver info structures to remove */
1946 /* remove the Win2k driver first*/
1948 status
= winreg_del_driver(p
->mem_ctx
,
1952 talloc_free(info_win2k
);
1954 /* this should not have failed---if it did, report to client */
1955 if (!W_ERROR_IS_OK(status
)) {
1961 status
= winreg_del_driver(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
1970 /****************************************************************
1971 _spoolss_DeletePrinterDriverEx
1972 ****************************************************************/
1974 WERROR
_spoolss_DeletePrinterDriverEx(struct pipes_struct
*p
,
1975 struct spoolss_DeletePrinterDriverEx
*r
)
1977 struct spoolss_DriverInfo8
*info
= NULL
;
1978 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1982 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1984 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1985 and not a printer admin, then fail */
1987 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1988 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1989 && !token_contains_name_in_list(
1990 uidtoname(p
->server_info
->utok
.uid
),
1991 p
->server_info
->info3
->base
.domain
.string
,
1993 p
->server_info
->ptok
, lp_printer_admin(-1)) )
1995 return WERR_ACCESS_DENIED
;
1998 /* check that we have a valid driver name first */
1999 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
2000 /* this is what NT returns */
2001 return WERR_INVALID_ENVIRONMENT
;
2004 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2005 version
= r
->in
.version
;
2007 status
= winreg_get_driver(p
->mem_ctx
, p
->server_info
,
2008 p
->msg_ctx
, r
->in
.architecture
,
2009 r
->in
.driver
, version
, &info
);
2010 if (!W_ERROR_IS_OK(status
)) {
2011 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2014 * if the client asked for a specific version,
2015 * or this is something other than Windows NT x86,
2019 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2022 /* try for Win2k driver if "Windows NT x86" */
2025 status
= winreg_get_driver(info
, p
->server_info
, p
->msg_ctx
,
2029 if (!W_ERROR_IS_OK(status
)) {
2030 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2035 if (printer_driver_in_use(info
, p
->server_info
, p
->msg_ctx
, info
)) {
2036 status
= WERR_PRINTER_DRIVER_IN_USE
;
2041 * we have a couple of cases to consider.
2042 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2043 * then the delete should fail if **any** files overlap with
2045 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2046 * non-overlapping files
2047 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2048 * is set, the do not delete any files
2049 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2052 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2054 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2057 (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) &&
2058 printer_driver_files_in_use(info
, p
->server_info
, p
->msg_ctx
,
2060 /* no idea of the correct error here */
2061 status
= WERR_ACCESS_DENIED
;
2066 /* also check for W32X86/3 if necessary; maybe we already have? */
2068 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2069 status
= winreg_get_driver(info
, p
->server_info
, p
->msg_ctx
,
2071 r
->in
.driver
, 3, &info_win2k
);
2072 if (W_ERROR_IS_OK(status
)) {
2075 (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) &&
2076 printer_driver_files_in_use(info
, p
->server_info
,
2079 /* no idea of the correct error here */
2080 talloc_free(info_win2k
);
2081 status
= WERR_ACCESS_DENIED
;
2085 /* if we get to here, we now have 2 driver info structures to remove */
2086 /* remove the Win2k driver first*/
2088 status
= winreg_del_driver(info
, p
->server_info
,
2089 p
->msg_ctx
, info_win2k
, 3);
2091 /* this should not have failed---if it did, report to client */
2093 if (!W_ERROR_IS_OK(status
)) {
2098 * now delete any associated files if delete_files is
2099 * true. Even if this part failes, we return succes
2100 * because the driver doesn not exist any more
2103 delete_driver_files(p
->server_info
,
2109 status
= winreg_del_driver(info
, p
->server_info
, p
->msg_ctx
, info
,
2111 if (!W_ERROR_IS_OK(status
)) {
2116 * now delete any associated files if delete_files is
2117 * true. Even if this part failes, we return succes
2118 * because the driver doesn not exist any more
2121 delete_driver_files(p
->server_info
, info
);
2130 /********************************************************************
2131 GetPrinterData on a printer server Handle.
2132 ********************************************************************/
2134 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2136 enum winreg_Type
*type
,
2137 union spoolss_PrinterData
*data
)
2139 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2141 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2147 if (!StrCaseCmp(value
, "BeepEnabled")) {
2153 if (!StrCaseCmp(value
, "EventLog")) {
2155 /* formally was 0x1b */
2160 if (!StrCaseCmp(value
, "NetPopup")) {
2166 if (!StrCaseCmp(value
, "MajorVersion")) {
2169 /* Windows NT 4.0 seems to not allow uploading of drivers
2170 to a server that reports 0x3 as the MajorVersion.
2171 need to investigate more how Win2k gets around this .
2174 if (RA_WINNT
== get_remote_arch()) {
2183 if (!StrCaseCmp(value
, "MinorVersion")) {
2190 * uint32_t size = 0x114
2191 * uint32_t major = 5
2192 * uint32_t minor = [0|1]
2193 * uint32_t build = [2195|2600]
2194 * extra unicode string = e.g. "Service Pack 3"
2196 if (!StrCaseCmp(value
, "OSVersion")) {
2198 enum ndr_err_code ndr_err
;
2199 struct spoolss_OSVersion os
;
2201 os
.major
= 5; /* Windows 2000 == 5.0 */
2203 os
.build
= 2195; /* build */
2204 os
.extra_string
= ""; /* leave extra string empty */
2206 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2207 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2208 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2209 return WERR_GENERAL_FAILURE
;
2213 data
->binary
= blob
;
2219 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2222 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2223 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2228 if (!StrCaseCmp(value
, "Architecture")) {
2230 data
->string
= talloc_strdup(mem_ctx
,
2231 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2232 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2237 if (!StrCaseCmp(value
, "DsPresent")) {
2240 /* only show the publish check box if we are a
2241 member of a AD domain */
2243 if (lp_security() == SEC_ADS
) {
2251 if (!StrCaseCmp(value
, "DNSMachineName")) {
2252 const char *hostname
= get_mydnsfullname();
2255 return WERR_BADFILE
;
2259 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2260 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2267 return WERR_INVALID_PARAM
;
2270 /****************************************************************
2271 _spoolss_GetPrinterData
2272 ****************************************************************/
2274 WERROR
_spoolss_GetPrinterData(struct pipes_struct
*p
,
2275 struct spoolss_GetPrinterData
*r
)
2277 struct spoolss_GetPrinterDataEx r2
;
2279 r2
.in
.handle
= r
->in
.handle
;
2280 r2
.in
.key_name
= "PrinterDriverData";
2281 r2
.in
.value_name
= r
->in
.value_name
;
2282 r2
.in
.offered
= r
->in
.offered
;
2283 r2
.out
.type
= r
->out
.type
;
2284 r2
.out
.data
= r
->out
.data
;
2285 r2
.out
.needed
= r
->out
.needed
;
2287 return _spoolss_GetPrinterDataEx(p
, &r2
);
2290 /*********************************************************
2291 Connect to the client machine.
2292 **********************************************************/
2294 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2295 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2298 struct cli_state
*the_cli
;
2299 struct sockaddr_storage rm_addr
;
2300 char addr
[INET6_ADDRSTRLEN
];
2302 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2303 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2305 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2306 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2309 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2311 rm_addr
= *client_ss
;
2312 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2313 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2317 if (ismyaddr((struct sockaddr
*)(void *)&rm_addr
)) {
2318 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2323 /* setup the connection */
2324 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2325 &rm_addr
, 0, "IPC$", "IPC",
2329 0, lp_client_signing(), NULL
);
2331 if ( !NT_STATUS_IS_OK( ret
) ) {
2332 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2337 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2338 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2339 cli_shutdown(the_cli
);
2344 * Ok - we have an anonymous connection to the IPC$ share.
2345 * Now start the NT Domain stuff :-).
2348 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2349 if (!NT_STATUS_IS_OK(ret
)) {
2350 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2351 remote_machine
, nt_errstr(ret
)));
2352 cli_shutdown(the_cli
);
2359 /***************************************************************************
2360 Connect to the client.
2361 ****************************************************************************/
2363 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2364 uint32_t localprinter
,
2365 enum winreg_Type type
,
2366 struct policy_handle
*handle
,
2367 struct sockaddr_storage
*client_ss
,
2368 struct messaging_context
*msg_ctx
)
2374 * If it's the first connection, contact the client
2375 * and connect to the IPC$ share anonymously
2377 if (smb_connections
==0) {
2378 fstring unix_printer
;
2380 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2382 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2385 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_NOTIFY2
,
2386 receive_notify2_message_list
);
2387 /* Tell the connections db we're now interested in printer
2388 * notify messages. */
2389 serverid_register_msg_flags(messaging_server_id(msg_ctx
),
2390 true, FLAG_MSG_PRINT_NOTIFY
);
2394 * Tell the specific printing tdb we want messages for this printer
2395 * by registering our PID.
2398 if (!print_notify_register_pid(snum
))
2399 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2403 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2411 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2412 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2413 win_errstr(result
)));
2415 return (W_ERROR_IS_OK(result
));
2418 /****************************************************************
2419 ****************************************************************/
2421 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2422 const struct spoolss_NotifyOption
*r
)
2424 struct spoolss_NotifyOption
*option
;
2431 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2438 if (!option
->count
) {
2442 option
->types
= talloc_zero_array(option
,
2443 struct spoolss_NotifyOptionType
, option
->count
);
2444 if (!option
->types
) {
2445 talloc_free(option
);
2449 for (i
=0; i
< option
->count
; i
++) {
2450 option
->types
[i
] = r
->types
[i
];
2452 if (option
->types
[i
].count
) {
2453 option
->types
[i
].fields
= talloc_zero_array(option
,
2454 union spoolss_Field
, option
->types
[i
].count
);
2455 if (!option
->types
[i
].fields
) {
2456 talloc_free(option
);
2459 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2460 option
->types
[i
].fields
[k
] =
2461 r
->types
[i
].fields
[k
];
2469 /****************************************************************
2470 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2472 * before replying OK: status=0 a rpc call is made to the workstation
2473 * asking ReplyOpenPrinter
2475 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2476 * called from api_spoolss_rffpcnex
2477 ****************************************************************/
2479 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct
*p
,
2480 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2483 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2484 struct sockaddr_storage client_ss
;
2486 /* store the notify value in the printer struct */
2488 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2491 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2492 "Invalid handle (%s:%u:%u).\n",
2493 OUR_HANDLE(r
->in
.handle
)));
2497 Printer
->notify
.flags
= r
->in
.flags
;
2498 Printer
->notify
.options
= r
->in
.options
;
2499 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2500 Printer
->notify
.msg_ctx
= p
->msg_ctx
;
2502 TALLOC_FREE(Printer
->notify
.option
);
2503 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2505 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2507 /* Connect to the client machine and send a ReplyOpenPrinter */
2509 if ( Printer
->printer_type
== SPLHND_SERVER
)
2511 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2512 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2515 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2516 "client_address is %s\n", p
->client_id
->addr
));
2518 if (!interpret_string_addr(&client_ss
, p
->client_id
->addr
,
2520 return WERR_SERVER_UNAVAILABLE
;
2523 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2524 Printer
->notify
.printerlocal
, REG_SZ
,
2525 &Printer
->notify
.client_hnd
,
2526 &client_ss
, p
->msg_ctx
))
2527 return WERR_SERVER_UNAVAILABLE
;
2529 Printer
->notify
.client_connected
= true;
2534 /*******************************************************************
2535 * fill a notify_info_data with the servername
2536 ********************************************************************/
2538 static void spoolss_notify_server_name(struct messaging_context
*msg_ctx
,
2540 struct spoolss_Notify
*data
,
2541 print_queue_struct
*queue
,
2542 struct spoolss_PrinterInfo2
*pinfo2
,
2543 TALLOC_CTX
*mem_ctx
)
2545 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->servername
);
2548 /*******************************************************************
2549 * fill a notify_info_data with the printername (not including the servername).
2550 ********************************************************************/
2552 static void spoolss_notify_printer_name(struct messaging_context
*msg_ctx
,
2554 struct spoolss_Notify
*data
,
2555 print_queue_struct
*queue
,
2556 struct spoolss_PrinterInfo2
*pinfo2
,
2557 TALLOC_CTX
*mem_ctx
)
2559 /* the notify name should not contain the \\server\ part */
2560 const char *p
= strrchr(pinfo2
->printername
, '\\');
2563 p
= pinfo2
->printername
;
2568 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2571 /*******************************************************************
2572 * fill a notify_info_data with the servicename
2573 ********************************************************************/
2575 static void spoolss_notify_share_name(struct messaging_context
*msg_ctx
,
2577 struct spoolss_Notify
*data
,
2578 print_queue_struct
*queue
,
2579 struct spoolss_PrinterInfo2
*pinfo2
,
2580 TALLOC_CTX
*mem_ctx
)
2582 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2585 /*******************************************************************
2586 * fill a notify_info_data with the port name
2587 ********************************************************************/
2589 static void spoolss_notify_port_name(struct messaging_context
*msg_ctx
,
2591 struct spoolss_Notify
*data
,
2592 print_queue_struct
*queue
,
2593 struct spoolss_PrinterInfo2
*pinfo2
,
2594 TALLOC_CTX
*mem_ctx
)
2596 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->portname
);
2599 /*******************************************************************
2600 * fill a notify_info_data with the printername
2601 * but it doesn't exist, have to see what to do
2602 ********************************************************************/
2604 static void spoolss_notify_driver_name(struct messaging_context
*msg_ctx
,
2606 struct spoolss_Notify
*data
,
2607 print_queue_struct
*queue
,
2608 struct spoolss_PrinterInfo2
*pinfo2
,
2609 TALLOC_CTX
*mem_ctx
)
2611 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->drivername
);
2614 /*******************************************************************
2615 * fill a notify_info_data with the comment
2616 ********************************************************************/
2618 static void spoolss_notify_comment(struct messaging_context
*msg_ctx
,
2620 struct spoolss_Notify
*data
,
2621 print_queue_struct
*queue
,
2622 struct spoolss_PrinterInfo2
*pinfo2
,
2623 TALLOC_CTX
*mem_ctx
)
2627 if (*pinfo2
->comment
== '\0') {
2628 p
= lp_comment(snum
);
2630 p
= pinfo2
->comment
;
2633 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2636 /*******************************************************************
2637 * fill a notify_info_data with the comment
2638 * location = "Room 1, floor 2, building 3"
2639 ********************************************************************/
2641 static void spoolss_notify_location(struct messaging_context
*msg_ctx
,
2643 struct spoolss_Notify
*data
,
2644 print_queue_struct
*queue
,
2645 struct spoolss_PrinterInfo2
*pinfo2
,
2646 TALLOC_CTX
*mem_ctx
)
2648 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->location
);
2651 /*******************************************************************
2652 * fill a notify_info_data with the device mode
2653 * jfm:xxxx don't to it for know but that's a real problem !!!
2654 ********************************************************************/
2656 static void spoolss_notify_devmode(struct messaging_context
*msg_ctx
,
2658 struct spoolss_Notify
*data
,
2659 print_queue_struct
*queue
,
2660 struct spoolss_PrinterInfo2
*pinfo2
,
2661 TALLOC_CTX
*mem_ctx
)
2663 /* for a dummy implementation we have to zero the fields */
2664 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2667 /*******************************************************************
2668 * fill a notify_info_data with the separator file name
2669 ********************************************************************/
2671 static void spoolss_notify_sepfile(struct messaging_context
*msg_ctx
,
2673 struct spoolss_Notify
*data
,
2674 print_queue_struct
*queue
,
2675 struct spoolss_PrinterInfo2
*pinfo2
,
2676 TALLOC_CTX
*mem_ctx
)
2678 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->sepfile
);
2681 /*******************************************************************
2682 * fill a notify_info_data with the print processor
2683 * jfm:xxxx return always winprint to indicate we don't do anything to it
2684 ********************************************************************/
2686 static void spoolss_notify_print_processor(struct messaging_context
*msg_ctx
,
2688 struct spoolss_Notify
*data
,
2689 print_queue_struct
*queue
,
2690 struct spoolss_PrinterInfo2
*pinfo2
,
2691 TALLOC_CTX
*mem_ctx
)
2693 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->printprocessor
);
2696 /*******************************************************************
2697 * fill a notify_info_data with the print processor options
2698 * jfm:xxxx send an empty string
2699 ********************************************************************/
2701 static void spoolss_notify_parameters(struct messaging_context
*msg_ctx
,
2703 struct spoolss_Notify
*data
,
2704 print_queue_struct
*queue
,
2705 struct spoolss_PrinterInfo2
*pinfo2
,
2706 TALLOC_CTX
*mem_ctx
)
2708 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->parameters
);
2711 /*******************************************************************
2712 * fill a notify_info_data with the data type
2713 * jfm:xxxx always send RAW as data type
2714 ********************************************************************/
2716 static void spoolss_notify_datatype(struct messaging_context
*msg_ctx
,
2718 struct spoolss_Notify
*data
,
2719 print_queue_struct
*queue
,
2720 struct spoolss_PrinterInfo2
*pinfo2
,
2721 TALLOC_CTX
*mem_ctx
)
2723 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->datatype
);
2726 /*******************************************************************
2727 * fill a notify_info_data with the security descriptor
2728 * jfm:xxxx send an null pointer to say no security desc
2729 * have to implement security before !
2730 ********************************************************************/
2732 static void spoolss_notify_security_desc(struct messaging_context
*msg_ctx
,
2734 struct spoolss_Notify
*data
,
2735 print_queue_struct
*queue
,
2736 struct spoolss_PrinterInfo2
*pinfo2
,
2737 TALLOC_CTX
*mem_ctx
)
2739 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
, pinfo2
->secdesc
);
2742 /*******************************************************************
2743 * fill a notify_info_data with the attributes
2744 * jfm:xxxx a samba printer is always shared
2745 ********************************************************************/
2747 static void spoolss_notify_attributes(struct messaging_context
*msg_ctx
,
2749 struct spoolss_Notify
*data
,
2750 print_queue_struct
*queue
,
2751 struct spoolss_PrinterInfo2
*pinfo2
,
2752 TALLOC_CTX
*mem_ctx
)
2754 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->attributes
);
2757 /*******************************************************************
2758 * fill a notify_info_data with the priority
2759 ********************************************************************/
2761 static void spoolss_notify_priority(struct messaging_context
*msg_ctx
,
2763 struct spoolss_Notify
*data
,
2764 print_queue_struct
*queue
,
2765 struct spoolss_PrinterInfo2
*pinfo2
,
2766 TALLOC_CTX
*mem_ctx
)
2768 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->priority
);
2771 /*******************************************************************
2772 * fill a notify_info_data with the default priority
2773 ********************************************************************/
2775 static void spoolss_notify_default_priority(struct messaging_context
*msg_ctx
,
2777 struct spoolss_Notify
*data
,
2778 print_queue_struct
*queue
,
2779 struct spoolss_PrinterInfo2
*pinfo2
,
2780 TALLOC_CTX
*mem_ctx
)
2782 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->defaultpriority
);
2785 /*******************************************************************
2786 * fill a notify_info_data with the start time
2787 ********************************************************************/
2789 static void spoolss_notify_start_time(struct messaging_context
*msg_ctx
,
2791 struct spoolss_Notify
*data
,
2792 print_queue_struct
*queue
,
2793 struct spoolss_PrinterInfo2
*pinfo2
,
2794 TALLOC_CTX
*mem_ctx
)
2796 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->starttime
);
2799 /*******************************************************************
2800 * fill a notify_info_data with the until time
2801 ********************************************************************/
2803 static void spoolss_notify_until_time(struct messaging_context
*msg_ctx
,
2805 struct spoolss_Notify
*data
,
2806 print_queue_struct
*queue
,
2807 struct spoolss_PrinterInfo2
*pinfo2
,
2808 TALLOC_CTX
*mem_ctx
)
2810 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->untiltime
);
2813 /*******************************************************************
2814 * fill a notify_info_data with the status
2815 ********************************************************************/
2817 static void spoolss_notify_status(struct messaging_context
*msg_ctx
,
2819 struct spoolss_Notify
*data
,
2820 print_queue_struct
*queue
,
2821 struct spoolss_PrinterInfo2
*pinfo2
,
2822 TALLOC_CTX
*mem_ctx
)
2824 print_status_struct status
;
2826 print_queue_length(msg_ctx
, snum
, &status
);
2827 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
2830 /*******************************************************************
2831 * fill a notify_info_data with the number of jobs queued
2832 ********************************************************************/
2834 static void spoolss_notify_cjobs(struct messaging_context
*msg_ctx
,
2836 struct spoolss_Notify
*data
,
2837 print_queue_struct
*queue
,
2838 struct spoolss_PrinterInfo2
*pinfo2
,
2839 TALLOC_CTX
*mem_ctx
)
2841 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
2842 data
, print_queue_length(msg_ctx
, snum
, NULL
));
2845 /*******************************************************************
2846 * fill a notify_info_data with the average ppm
2847 ********************************************************************/
2849 static void spoolss_notify_average_ppm(struct messaging_context
*msg_ctx
,
2851 struct spoolss_Notify
*data
,
2852 print_queue_struct
*queue
,
2853 struct spoolss_PrinterInfo2
*pinfo2
,
2854 TALLOC_CTX
*mem_ctx
)
2856 /* always respond 8 pages per minutes */
2857 /* a little hard ! */
2858 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->averageppm
);
2861 /*******************************************************************
2862 * fill a notify_info_data with username
2863 ********************************************************************/
2865 static void spoolss_notify_username(struct messaging_context
*msg_ctx
,
2867 struct spoolss_Notify
*data
,
2868 print_queue_struct
*queue
,
2869 struct spoolss_PrinterInfo2
*pinfo2
,
2870 TALLOC_CTX
*mem_ctx
)
2872 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
2875 /*******************************************************************
2876 * fill a notify_info_data with job status
2877 ********************************************************************/
2879 static void spoolss_notify_job_status(struct messaging_context
*msg_ctx
,
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
, nt_printj_status(queue
->status
));
2889 /*******************************************************************
2890 * fill a notify_info_data with job name
2891 ********************************************************************/
2893 static void spoolss_notify_job_name(struct messaging_context
*msg_ctx
,
2895 struct spoolss_Notify
*data
,
2896 print_queue_struct
*queue
,
2897 struct spoolss_PrinterInfo2
*pinfo2
,
2898 TALLOC_CTX
*mem_ctx
)
2900 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
2903 /*******************************************************************
2904 * fill a notify_info_data with job status
2905 ********************************************************************/
2907 static void spoolss_notify_job_status_string(struct messaging_context
*msg_ctx
,
2909 struct spoolss_Notify
*data
,
2910 print_queue_struct
*queue
,
2911 struct spoolss_PrinterInfo2
*pinfo2
,
2912 TALLOC_CTX
*mem_ctx
)
2915 * Now we're returning job status codes we just return a "" here. JRA.
2920 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2923 switch (queue
->status
) {
2928 p
= ""; /* NT provides the paused string */
2937 #endif /* NO LONGER NEEDED. */
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2942 /*******************************************************************
2943 * fill a notify_info_data with job time
2944 ********************************************************************/
2946 static void spoolss_notify_job_time(struct messaging_context
*msg_ctx
,
2948 struct spoolss_Notify
*data
,
2949 print_queue_struct
*queue
,
2950 struct spoolss_PrinterInfo2
*pinfo2
,
2951 TALLOC_CTX
*mem_ctx
)
2953 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2956 /*******************************************************************
2957 * fill a notify_info_data with job size
2958 ********************************************************************/
2960 static void spoolss_notify_job_size(struct messaging_context
*msg_ctx
,
2962 struct spoolss_Notify
*data
,
2963 print_queue_struct
*queue
,
2964 struct spoolss_PrinterInfo2
*pinfo2
,
2965 TALLOC_CTX
*mem_ctx
)
2967 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
2970 /*******************************************************************
2971 * fill a notify_info_data with page info
2972 ********************************************************************/
2973 static void spoolss_notify_total_pages(struct messaging_context
*msg_ctx
,
2975 struct spoolss_Notify
*data
,
2976 print_queue_struct
*queue
,
2977 struct spoolss_PrinterInfo2
*pinfo2
,
2978 TALLOC_CTX
*mem_ctx
)
2980 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
2983 /*******************************************************************
2984 * fill a notify_info_data with pages printed info.
2985 ********************************************************************/
2986 static void spoolss_notify_pages_printed(struct messaging_context
*msg_ctx
,
2988 struct spoolss_Notify
*data
,
2989 print_queue_struct
*queue
,
2990 struct spoolss_PrinterInfo2
*pinfo2
,
2991 TALLOC_CTX
*mem_ctx
)
2993 /* Add code when back-end tracks this */
2994 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2997 /*******************************************************************
2998 Fill a notify_info_data with job position.
2999 ********************************************************************/
3001 static void spoolss_notify_job_position(struct messaging_context
*msg_ctx
,
3003 struct spoolss_Notify
*data
,
3004 print_queue_struct
*queue
,
3005 struct spoolss_PrinterInfo2
*pinfo2
,
3006 TALLOC_CTX
*mem_ctx
)
3008 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
3011 /*******************************************************************
3012 Fill a notify_info_data with submitted time.
3013 ********************************************************************/
3015 static void spoolss_notify_submitted_time(struct messaging_context
*msg_ctx
,
3017 struct spoolss_Notify
*data
,
3018 print_queue_struct
*queue
,
3019 struct spoolss_PrinterInfo2
*pinfo2
,
3020 TALLOC_CTX
*mem_ctx
)
3022 data
->data
.string
.string
= NULL
;
3023 data
->data
.string
.size
= 0;
3025 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3026 &data
->data
.string
.string
,
3027 &data
->data
.string
.size
);
3031 struct s_notify_info_data_table
3033 enum spoolss_NotifyType type
;
3036 enum spoolss_NotifyTable variable_type
;
3037 void (*fn
) (struct messaging_context
*msg_ctx
,
3038 int snum
, struct spoolss_Notify
*data
,
3039 print_queue_struct
*queue
,
3040 struct spoolss_PrinterInfo2
*pinfo2
,
3041 TALLOC_CTX
*mem_ctx
);
3044 /* A table describing the various print notification constants and
3045 whether the notification data is a pointer to a variable sized
3046 buffer, a one value uint32_t or a two value uint32_t. */
3048 static const struct s_notify_info_data_table notify_info_data_table
[] =
3050 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3051 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3052 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3053 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3054 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3055 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3056 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3057 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3058 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3059 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3060 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3061 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3062 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3063 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3064 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3065 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3066 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3067 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3068 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3069 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3070 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3071 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3072 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3073 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3074 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3075 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3076 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3077 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3078 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3079 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3080 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3081 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3082 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3083 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3084 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3085 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3086 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3087 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3088 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3089 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3090 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3091 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3092 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3093 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3094 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3095 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3096 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3097 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3098 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3101 /*******************************************************************
3102 Return the variable_type of info_data structure.
3103 ********************************************************************/
3105 static enum spoolss_NotifyTable
variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3110 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3111 if ( (notify_info_data_table
[i
].type
== type
) &&
3112 (notify_info_data_table
[i
].field
== field
) ) {
3113 return notify_info_data_table
[i
].variable_type
;
3117 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3119 return (enum spoolss_NotifyTable
) 0;
3122 /****************************************************************************
3123 ****************************************************************************/
3125 static bool search_notify(enum spoolss_NotifyType type
,
3131 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3132 if (notify_info_data_table
[i
].type
== type
&&
3133 notify_info_data_table
[i
].field
== field
&&
3134 notify_info_data_table
[i
].fn
!= NULL
) {
3143 /****************************************************************************
3144 ****************************************************************************/
3146 static void construct_info_data(struct spoolss_Notify
*info_data
,
3147 enum spoolss_NotifyType type
,
3148 uint16_t field
, int id
)
3150 info_data
->type
= type
;
3151 info_data
->field
.field
= field
;
3152 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3153 info_data
->job_id
= id
;
3156 /*******************************************************************
3158 * fill a notify_info struct with info asked
3160 ********************************************************************/
3162 static bool construct_notify_printer_info(struct messaging_context
*msg_ctx
,
3163 Printer_entry
*print_hnd
,
3164 struct spoolss_NotifyInfo
*info
,
3165 struct spoolss_PrinterInfo2
*pinfo2
,
3167 const struct spoolss_NotifyOptionType
*option_type
,
3169 TALLOC_CTX
*mem_ctx
)
3172 enum spoolss_NotifyType type
;
3175 struct spoolss_Notify
*current_data
;
3176 print_queue_struct
*queue
=NULL
;
3178 type
= option_type
->type
;
3180 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3181 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3182 option_type
->count
, lp_servicename(snum
)));
3184 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3185 field
= option_type
->fields
[field_num
].field
;
3187 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3189 if (!search_notify(type
, field
, &j
) )
3192 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3193 struct spoolss_Notify
,
3195 if (info
->notifies
== NULL
) {
3196 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3200 current_data
= &info
->notifies
[info
->count
];
3202 construct_info_data(current_data
, type
, field
, id
);
3204 DEBUG(10, ("construct_notify_printer_info: "
3205 "calling [%s] snum=%d printername=[%s])\n",
3206 notify_info_data_table
[j
].name
, snum
,
3207 pinfo2
->printername
));
3209 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3210 queue
, pinfo2
, mem_ctx
);
3218 /*******************************************************************
3220 * fill a notify_info struct with info asked
3222 ********************************************************************/
3224 static bool construct_notify_jobs_info(struct messaging_context
*msg_ctx
,
3225 print_queue_struct
*queue
,
3226 struct spoolss_NotifyInfo
*info
,
3227 struct spoolss_PrinterInfo2
*pinfo2
,
3229 const struct spoolss_NotifyOptionType
*option_type
,
3231 TALLOC_CTX
*mem_ctx
)
3234 enum spoolss_NotifyType type
;
3236 struct spoolss_Notify
*current_data
;
3238 DEBUG(4,("construct_notify_jobs_info\n"));
3240 type
= option_type
->type
;
3242 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3243 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3244 option_type
->count
));
3246 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3247 field
= option_type
->fields
[field_num
].field
;
3249 if (!search_notify(type
, field
, &j
) )
3252 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3253 struct spoolss_Notify
,
3255 if (info
->notifies
== NULL
) {
3256 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3260 current_data
=&(info
->notifies
[info
->count
]);
3262 construct_info_data(current_data
, type
, field
, id
);
3263 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3264 queue
, pinfo2
, mem_ctx
);
3272 * JFM: The enumeration is not that simple, it's even non obvious.
3274 * let's take an example: I want to monitor the PRINTER SERVER for
3275 * the printer's name and the number of jobs currently queued.
3276 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3277 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3279 * I have 3 printers on the back of my server.
3281 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3284 * 1 printer 1 name 1
3285 * 2 printer 1 cjob 1
3286 * 3 printer 2 name 2
3287 * 4 printer 2 cjob 2
3288 * 5 printer 3 name 3
3289 * 6 printer 3 name 3
3291 * that's the print server case, the printer case is even worse.
3294 /*******************************************************************
3296 * enumerate all printers on the printserver
3297 * fill a notify_info struct with info asked
3299 ********************************************************************/
3301 static WERROR
printserver_notify_info(struct pipes_struct
*p
,
3302 struct policy_handle
*hnd
,
3303 struct spoolss_NotifyInfo
*info
,
3304 TALLOC_CTX
*mem_ctx
)
3307 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3308 int n_services
=lp_numservices();
3310 struct spoolss_NotifyOption
*option
;
3311 struct spoolss_NotifyOptionType option_type
;
3312 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3315 DEBUG(4,("printserver_notify_info\n"));
3320 option
= Printer
->notify
.option
;
3323 info
->notifies
= NULL
;
3326 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3327 sending a ffpcn() request first */
3332 for (i
=0; i
<option
->count
; i
++) {
3333 option_type
= option
->types
[i
];
3335 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3338 for (snum
= 0; snum
< n_services
; snum
++) {
3339 if (!lp_browseable(snum
) ||
3340 !lp_snum_ok(snum
) ||
3341 !lp_print_ok(snum
)) {
3342 continue; /* skip */
3345 /* Maybe we should use the SYSTEM server_info here... */
3346 result
= winreg_get_printer(mem_ctx
, p
->server_info
,
3348 Printer
->servername
,
3349 lp_servicename(snum
),
3351 if (!W_ERROR_IS_OK(result
)) {
3352 DEBUG(4, ("printserver_notify_info: "
3353 "Failed to get printer [%s]\n",
3354 lp_servicename(snum
)));
3359 construct_notify_printer_info(p
->msg_ctx
,
3365 TALLOC_FREE(pinfo2
);
3371 * Debugging information, don't delete.
3374 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3375 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3376 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3378 for (i
=0; i
<info
->count
; i
++) {
3379 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3380 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3381 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3388 /*******************************************************************
3390 * fill a notify_info struct with info asked
3392 ********************************************************************/
3394 static WERROR
printer_notify_info(struct pipes_struct
*p
,
3395 struct policy_handle
*hnd
,
3396 struct spoolss_NotifyInfo
*info
,
3397 TALLOC_CTX
*mem_ctx
)
3400 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3403 struct spoolss_NotifyOption
*option
;
3404 struct spoolss_NotifyOptionType option_type
;
3406 print_queue_struct
*queue
=NULL
;
3407 print_status_struct status
;
3408 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3411 DEBUG(4,("printer_notify_info\n"));
3416 option
= Printer
->notify
.option
;
3420 info
->notifies
= NULL
;
3423 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3424 sending a ffpcn() request first */
3429 get_printer_snum(p
, hnd
, &snum
, NULL
);
3431 /* Maybe we should use the SYSTEM server_info here... */
3432 result
= winreg_get_printer(mem_ctx
, p
->server_info
, p
->msg_ctx
,
3433 Printer
->servername
,
3434 lp_servicename(snum
), &pinfo2
);
3435 if (!W_ERROR_IS_OK(result
)) {
3439 for (i
=0; i
<option
->count
; i
++) {
3440 option_type
= option
->types
[i
];
3442 switch (option_type
.type
) {
3443 case PRINTER_NOTIFY_TYPE
:
3444 if (construct_notify_printer_info(p
->msg_ctx
,
3453 case JOB_NOTIFY_TYPE
:
3455 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
,
3458 for (j
=0; j
<count
; j
++) {
3459 construct_notify_jobs_info(p
->msg_ctx
,
3473 * Debugging information, don't delete.
3476 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3477 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3478 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3480 for (i=0; i<info->count; i++) {
3481 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3482 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3483 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3487 talloc_free(pinfo2
);
3491 /****************************************************************
3492 _spoolss_RouterRefreshPrinterChangeNotify
3493 ****************************************************************/
3495 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct
*p
,
3496 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3498 struct spoolss_NotifyInfo
*info
;
3500 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3501 WERROR result
= WERR_BADFID
;
3503 /* we always have a spoolss_NotifyInfo struct */
3504 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3506 result
= WERR_NOMEM
;
3510 *r
->out
.info
= info
;
3513 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3514 "Invalid handle (%s:%u:%u).\n",
3515 OUR_HANDLE(r
->in
.handle
)));
3519 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3522 * We are now using the change value, and
3523 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3524 * I don't have a global notification system, I'm sending back all the
3525 * informations even when _NOTHING_ has changed.
3528 /* We need to keep track of the change value to send back in
3529 RRPCN replies otherwise our updates are ignored. */
3531 Printer
->notify
.fnpcn
= true;
3533 if (Printer
->notify
.client_connected
) {
3534 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3535 "Saving change value in request [%x]\n",
3537 Printer
->notify
.change
= r
->in
.change_low
;
3540 /* just ignore the spoolss_NotifyOption */
3542 switch (Printer
->printer_type
) {
3544 result
= printserver_notify_info(p
, r
->in
.handle
,
3548 case SPLHND_PRINTER
:
3549 result
= printer_notify_info(p
, r
->in
.handle
,
3554 Printer
->notify
.fnpcn
= false;
3560 /********************************************************************
3561 * construct_printer_info_0
3562 * fill a printer_info_0 struct
3563 ********************************************************************/
3565 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3566 struct auth_serversupplied_info
*server_info
,
3567 struct messaging_context
*msg_ctx
,
3568 struct spoolss_PrinterInfo2
*info2
,
3569 struct spoolss_PrinterInfo0
*r
,
3573 counter_printer_0
*session_counter
;
3574 struct timeval setuptime
;
3575 print_status_struct status
;
3577 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3578 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3580 r
->servername
= talloc_strdup(mem_ctx
, info2
->servername
);
3581 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3583 count
= print_queue_length(msg_ctx
, snum
, &status
);
3585 /* check if we already have a counter for this printer */
3586 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3587 if (session_counter
->snum
== snum
)
3591 /* it's the first time, add it to the list */
3592 if (session_counter
== NULL
) {
3593 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3594 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3595 ZERO_STRUCTP(session_counter
);
3596 session_counter
->snum
= snum
;
3597 session_counter
->counter
= 0;
3598 DLIST_ADD(counter_list
, session_counter
);
3602 session_counter
->counter
++;
3608 get_startup_time(&setuptime
);
3609 init_systemtime(&r
->time
, gmtime(&setuptime
.tv_sec
));
3612 * the global_counter should be stored in a TDB as it's common to all the clients
3613 * and should be zeroed on samba startup
3615 r
->global_counter
= session_counter
->counter
;
3617 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3618 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3619 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3620 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3622 r
->max_spooling
= 0;
3623 r
->session_counter
= session_counter
->counter
;
3624 r
->num_error_out_of_paper
= 0x0;
3625 r
->num_error_not_ready
= 0x0; /* number of print failure */
3627 r
->number_of_processors
= 0x1;
3628 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3629 r
->high_part_total_bytes
= 0x0;
3631 /* ChangeID in milliseconds*/
3632 winreg_printer_get_changeid(mem_ctx
, server_info
, msg_ctx
,
3633 info2
->sharename
, &r
->change_id
);
3635 r
->last_error
= WERR_OK
;
3636 r
->status
= nt_printq_status(status
.status
);
3637 r
->enumerate_network_printers
= 0x0;
3638 r
->c_setprinter
= 0x0;
3639 r
->processor_architecture
= PROCESSOR_ARCHITECTURE_INTEL
;
3640 r
->processor_level
= 0x6; /* 6 ???*/
3649 /********************************************************************
3650 * construct_printer_info1
3651 * fill a spoolss_PrinterInfo1 struct
3652 ********************************************************************/
3654 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3655 const struct spoolss_PrinterInfo2
*info2
,
3657 struct spoolss_PrinterInfo1
*r
,
3662 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3666 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3668 if (info2
->comment
== NULL
|| info2
->comment
[0] == '\0') {
3669 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3671 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
); /* saved comment */
3673 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3675 r
->name
= talloc_strdup(mem_ctx
, info2
->printername
);
3676 W_ERROR_HAVE_NO_MEMORY(r
->name
);
3681 /********************************************************************
3682 * construct_printer_info2
3683 * fill a spoolss_PrinterInfo2 struct
3684 ********************************************************************/
3686 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3687 struct messaging_context
*msg_ctx
,
3688 const struct spoolss_PrinterInfo2
*info2
,
3689 struct spoolss_PrinterInfo2
*r
,
3693 print_status_struct status
;
3695 count
= print_queue_length(msg_ctx
, snum
, &status
);
3697 r
->servername
= talloc_strdup(mem_ctx
, info2
->servername
);
3698 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3699 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3700 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3701 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
3702 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
3703 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
3704 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3705 r
->drivername
= talloc_strdup(mem_ctx
, info2
->drivername
);
3706 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
3708 if (info2
->comment
[0] == '\0') {
3709 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3711 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
);
3713 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3715 r
->location
= talloc_strdup(mem_ctx
, info2
->location
);
3716 W_ERROR_HAVE_NO_MEMORY(r
->location
);
3717 r
->sepfile
= talloc_strdup(mem_ctx
, info2
->sepfile
);
3718 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
3719 r
->printprocessor
= talloc_strdup(mem_ctx
, info2
->printprocessor
);
3720 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
3721 r
->datatype
= talloc_strdup(mem_ctx
, info2
->datatype
);
3722 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
3723 r
->parameters
= talloc_strdup(mem_ctx
, info2
->parameters
);
3724 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
3726 r
->attributes
= info2
->attributes
;
3728 r
->priority
= info2
->priority
;
3729 r
->defaultpriority
= info2
->defaultpriority
;
3730 r
->starttime
= info2
->starttime
;
3731 r
->untiltime
= info2
->untiltime
;
3732 r
->status
= nt_printq_status(status
.status
);
3734 r
->averageppm
= info2
->averageppm
;
3736 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
3738 DEBUG(8,("Returning NULL Devicemode!\n"));
3743 if (info2
->secdesc
!= NULL
) {
3744 /* don't use talloc_steal() here unless you do a deep steal of all
3745 the SEC_DESC members */
3747 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
3753 /********************************************************************
3754 * construct_printer_info3
3755 * fill a spoolss_PrinterInfo3 struct
3756 ********************************************************************/
3758 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3759 const struct spoolss_PrinterInfo2
*info2
,
3760 struct spoolss_PrinterInfo3
*r
,
3763 /* These are the components of the SD we are returning. */
3765 if (info2
->secdesc
!= NULL
) {
3766 /* don't use talloc_steal() here unless you do a deep steal of all
3767 the SEC_DESC members */
3769 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
3770 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3776 /********************************************************************
3777 * construct_printer_info4
3778 * fill a spoolss_PrinterInfo4 struct
3779 ********************************************************************/
3781 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
3782 const struct spoolss_PrinterInfo2
*info2
,
3783 struct spoolss_PrinterInfo4
*r
,
3786 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3787 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3788 r
->servername
= talloc_strdup(mem_ctx
, info2
->servername
);
3789 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3791 r
->attributes
= info2
->attributes
;
3796 /********************************************************************
3797 * construct_printer_info5
3798 * fill a spoolss_PrinterInfo5 struct
3799 ********************************************************************/
3801 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
3802 const struct spoolss_PrinterInfo2
*info2
,
3803 struct spoolss_PrinterInfo5
*r
,
3806 r
->printername
= talloc_strdup(mem_ctx
, info2
->printername
);
3807 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3808 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
3809 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3811 r
->attributes
= info2
->attributes
;
3813 /* these two are not used by NT+ according to MSDN */
3814 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
3815 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
3820 /********************************************************************
3821 * construct_printer_info_6
3822 * fill a spoolss_PrinterInfo6 struct
3823 ********************************************************************/
3825 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
3826 struct messaging_context
*msg_ctx
,
3827 const struct spoolss_PrinterInfo2
*info2
,
3828 struct spoolss_PrinterInfo6
*r
,
3832 print_status_struct status
;
3834 count
= print_queue_length(msg_ctx
, snum
, &status
);
3836 r
->status
= nt_printq_status(status
.status
);
3841 /********************************************************************
3842 * construct_printer_info7
3843 * fill a spoolss_PrinterInfo7 struct
3844 ********************************************************************/
3846 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
3847 struct messaging_context
*msg_ctx
,
3848 Printer_entry
*print_hnd
,
3849 struct spoolss_PrinterInfo7
*r
,
3852 struct auth_serversupplied_info
*server_info
;
3856 status
= make_server_info_system(mem_ctx
, &server_info
);
3857 if (!NT_STATUS_IS_OK(status
)) {
3858 DEBUG(0, ("construct_printer_info7: "
3859 "Could not create system server_info\n"));
3863 if (is_printer_published(mem_ctx
, server_info
, msg_ctx
,
3864 print_hnd
->servername
,
3865 lp_servicename(snum
), &guid
, NULL
)) {
3866 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
3867 r
->action
= DSPRINT_PUBLISH
;
3869 r
->guid
= talloc_strdup(mem_ctx
, "");
3870 r
->action
= DSPRINT_UNPUBLISH
;
3872 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
3874 TALLOC_FREE(server_info
);
3878 /********************************************************************
3879 * construct_printer_info8
3880 * fill a spoolss_PrinterInfo8 struct
3881 ********************************************************************/
3883 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
3884 const struct spoolss_PrinterInfo2
*info2
,
3885 struct spoolss_DeviceModeInfo
*r
,
3888 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
3890 DEBUG(8,("Returning NULL Devicemode!\n"));
3897 /********************************************************************
3898 ********************************************************************/
3900 static bool snum_is_shared_printer(int snum
)
3902 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
3905 /********************************************************************
3906 Spoolss_enumprinters.
3907 ********************************************************************/
3909 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
3910 struct auth_serversupplied_info
*server_info
,
3911 struct messaging_context
*msg_ctx
,
3914 union spoolss_PrinterInfo
**info_p
,
3918 int n_services
= lp_numservices();
3919 union spoolss_PrinterInfo
*info
= NULL
;
3921 WERROR result
= WERR_OK
;
3926 for (snum
= 0; snum
< n_services
; snum
++) {
3928 const char *printer
;
3929 struct spoolss_PrinterInfo2
*info2
;
3931 if (!snum_is_shared_printer(snum
)) {
3935 printer
= lp_const_servicename(snum
);
3937 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3940 result
= winreg_create_printer(mem_ctx
,
3945 if (!W_ERROR_IS_OK(result
)) {
3949 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
3950 union spoolss_PrinterInfo
,
3953 result
= WERR_NOMEM
;
3957 result
= winreg_get_printer(mem_ctx
, server_info
, msg_ctx
,
3958 NULL
, printer
, &info2
);
3959 if (!W_ERROR_IS_OK(result
)) {
3965 result
= construct_printer_info0(info
, server_info
,
3967 &info
[count
].info0
, snum
);
3970 result
= construct_printer_info1(info
, info2
, flags
,
3971 &info
[count
].info1
, snum
);
3974 result
= construct_printer_info2(info
, msg_ctx
, info2
,
3975 &info
[count
].info2
, snum
);
3978 result
= construct_printer_info4(info
, info2
,
3979 &info
[count
].info4
, snum
);
3982 result
= construct_printer_info5(info
, info2
,
3983 &info
[count
].info5
, snum
);
3987 result
= WERR_UNKNOWN_LEVEL
;
3991 if (!W_ERROR_IS_OK(result
)) {
4002 if (!W_ERROR_IS_OK(result
)) {
4012 /********************************************************************
4013 * handle enumeration of printers at level 0
4014 ********************************************************************/
4016 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4017 struct auth_serversupplied_info
*server_info
,
4018 struct messaging_context
*msg_ctx
,
4020 const char *servername
,
4021 union spoolss_PrinterInfo
**info
,
4024 DEBUG(4,("enum_all_printers_info_0\n"));
4026 return enum_all_printers_info_level(mem_ctx
, server_info
, msg_ctx
,
4027 0, flags
, info
, count
);
4031 /********************************************************************
4032 ********************************************************************/
4034 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4035 struct auth_serversupplied_info
*server_info
,
4036 struct messaging_context
*msg_ctx
,
4038 union spoolss_PrinterInfo
**info
,
4041 DEBUG(4,("enum_all_printers_info_1\n"));
4043 return enum_all_printers_info_level(mem_ctx
, server_info
, msg_ctx
,
4044 1, flags
, info
, count
);
4047 /********************************************************************
4048 enum_all_printers_info_1_local.
4049 *********************************************************************/
4051 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4052 struct auth_serversupplied_info
*server_info
,
4053 struct messaging_context
*msg_ctx
,
4054 union spoolss_PrinterInfo
**info
,
4057 DEBUG(4,("enum_all_printers_info_1_local\n"));
4059 return enum_all_printers_info_1(mem_ctx
, server_info
, msg_ctx
,
4060 PRINTER_ENUM_ICON8
, info
, count
);
4063 /********************************************************************
4064 enum_all_printers_info_1_name.
4065 *********************************************************************/
4067 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4068 struct auth_serversupplied_info
*server_info
,
4069 struct messaging_context
*msg_ctx
,
4071 union spoolss_PrinterInfo
**info
,
4074 const char *s
= name
;
4076 DEBUG(4,("enum_all_printers_info_1_name\n"));
4078 if ((name
[0] == '\\') && (name
[1] == '\\')) {
4082 if (!is_myname_or_ipaddr(s
)) {
4083 return WERR_INVALID_NAME
;
4086 return enum_all_printers_info_1(mem_ctx
, server_info
, msg_ctx
,
4087 PRINTER_ENUM_ICON8
, info
, count
);
4090 /********************************************************************
4091 enum_all_printers_info_1_network.
4092 *********************************************************************/
4094 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4095 struct auth_serversupplied_info
*server_info
,
4096 struct messaging_context
*msg_ctx
,
4098 union spoolss_PrinterInfo
**info
,
4101 const char *s
= name
;
4103 DEBUG(4,("enum_all_printers_info_1_network\n"));
4105 /* If we respond to a enum_printers level 1 on our name with flags
4106 set to PRINTER_ENUM_REMOTE with a list of printers then these
4107 printers incorrectly appear in the APW browse list.
4108 Specifically the printers for the server appear at the workgroup
4109 level where all the other servers in the domain are
4110 listed. Windows responds to this call with a
4111 WERR_CAN_NOT_COMPLETE so we should do the same. */
4113 if (name
[0] == '\\' && name
[1] == '\\') {
4117 if (is_myname_or_ipaddr(s
)) {
4118 return WERR_CAN_NOT_COMPLETE
;
4121 return enum_all_printers_info_1(mem_ctx
, server_info
, msg_ctx
,
4122 PRINTER_ENUM_NAME
, info
, count
);
4125 /********************************************************************
4126 * api_spoolss_enumprinters
4128 * called from api_spoolss_enumprinters (see this to understand)
4129 ********************************************************************/
4131 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4132 struct auth_serversupplied_info
*server_info
,
4133 struct messaging_context
*msg_ctx
,
4134 union spoolss_PrinterInfo
**info
,
4137 DEBUG(4,("enum_all_printers_info_2\n"));
4139 return enum_all_printers_info_level(mem_ctx
, server_info
, msg_ctx
,
4143 /********************************************************************
4144 * handle enumeration of printers at level 1
4145 ********************************************************************/
4147 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4148 struct auth_serversupplied_info
*server_info
,
4149 struct messaging_context
*msg_ctx
,
4152 union spoolss_PrinterInfo
**info
,
4155 /* Not all the flags are equals */
4157 if (flags
& PRINTER_ENUM_LOCAL
) {
4158 return enum_all_printers_info_1_local(mem_ctx
, server_info
,
4159 msg_ctx
, info
, count
);
4162 if (flags
& PRINTER_ENUM_NAME
) {
4163 return enum_all_printers_info_1_name(mem_ctx
, server_info
,
4164 msg_ctx
, name
, info
,
4168 if (flags
& PRINTER_ENUM_NETWORK
) {
4169 return enum_all_printers_info_1_network(mem_ctx
, server_info
,
4170 msg_ctx
, name
, info
,
4174 return WERR_OK
; /* NT4sp5 does that */
4177 /********************************************************************
4178 * handle enumeration of printers at level 2
4179 ********************************************************************/
4181 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4182 struct auth_serversupplied_info
*server_info
,
4183 struct messaging_context
*msg_ctx
,
4185 const char *servername
,
4186 union spoolss_PrinterInfo
**info
,
4189 if (flags
& PRINTER_ENUM_LOCAL
) {
4190 return enum_all_printers_info_2(mem_ctx
, server_info
, msg_ctx
,
4194 if (flags
& PRINTER_ENUM_NAME
) {
4195 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4196 return WERR_INVALID_NAME
;
4199 return enum_all_printers_info_2(mem_ctx
, server_info
, msg_ctx
,
4203 if (flags
& PRINTER_ENUM_REMOTE
) {
4204 return WERR_UNKNOWN_LEVEL
;
4210 /********************************************************************
4211 * handle enumeration of printers at level 4
4212 ********************************************************************/
4214 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4215 struct auth_serversupplied_info
*server_info
,
4216 struct messaging_context
*msg_ctx
,
4218 const char *servername
,
4219 union spoolss_PrinterInfo
**info
,
4222 DEBUG(4,("enum_all_printers_info_4\n"));
4224 return enum_all_printers_info_level(mem_ctx
, server_info
, msg_ctx
,
4225 4, flags
, info
, count
);
4229 /********************************************************************
4230 * handle enumeration of printers at level 5
4231 ********************************************************************/
4233 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4234 struct auth_serversupplied_info
*server_info
,
4235 struct messaging_context
*msg_ctx
,
4237 const char *servername
,
4238 union spoolss_PrinterInfo
**info
,
4241 DEBUG(4,("enum_all_printers_info_5\n"));
4243 return enum_all_printers_info_level(mem_ctx
, server_info
, msg_ctx
,
4244 5, flags
, info
, count
);
4247 /****************************************************************
4248 _spoolss_EnumPrinters
4249 ****************************************************************/
4251 WERROR
_spoolss_EnumPrinters(struct pipes_struct
*p
,
4252 struct spoolss_EnumPrinters
*r
)
4254 const char *name
= NULL
;
4257 /* that's an [in out] buffer */
4259 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4260 return WERR_INVALID_PARAM
;
4263 DEBUG(4,("_spoolss_EnumPrinters\n"));
4267 *r
->out
.info
= NULL
;
4271 * flags==PRINTER_ENUM_NAME
4272 * if name=="" then enumerates all printers
4273 * if name!="" then enumerate the printer
4274 * flags==PRINTER_ENUM_REMOTE
4275 * name is NULL, enumerate printers
4276 * Level 2: name!="" enumerates printers, name can't be NULL
4277 * Level 3: doesn't exist
4278 * Level 4: does a local registry lookup
4279 * Level 5: same as Level 2
4283 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4284 W_ERROR_HAVE_NO_MEMORY(name
);
4287 switch (r
->in
.level
) {
4289 result
= enumprinters_level0(p
->mem_ctx
, p
->server_info
,
4290 p
->msg_ctx
, r
->in
.flags
, name
,
4291 r
->out
.info
, r
->out
.count
);
4294 result
= enumprinters_level1(p
->mem_ctx
, p
->server_info
,
4295 p
->msg_ctx
, r
->in
.flags
, name
,
4296 r
->out
.info
, r
->out
.count
);
4299 result
= enumprinters_level2(p
->mem_ctx
, p
->server_info
,
4300 p
->msg_ctx
, r
->in
.flags
, name
,
4301 r
->out
.info
, r
->out
.count
);
4304 result
= enumprinters_level4(p
->mem_ctx
, p
->server_info
,
4305 p
->msg_ctx
, r
->in
.flags
, name
,
4306 r
->out
.info
, r
->out
.count
);
4309 result
= enumprinters_level5(p
->mem_ctx
, p
->server_info
,
4310 p
->msg_ctx
, r
->in
.flags
, name
,
4311 r
->out
.info
, r
->out
.count
);
4314 return WERR_UNKNOWN_LEVEL
;
4317 if (!W_ERROR_IS_OK(result
)) {
4321 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4322 spoolss_EnumPrinters
,
4323 *r
->out
.info
, r
->in
.level
,
4325 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4326 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4328 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4331 /****************************************************************
4333 ****************************************************************/
4335 WERROR
_spoolss_GetPrinter(struct pipes_struct
*p
,
4336 struct spoolss_GetPrinter
*r
)
4338 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4339 struct spoolss_PrinterInfo2
*info2
= NULL
;
4340 WERROR result
= WERR_OK
;
4341 const char *servername
= NULL
;
4344 /* that's an [in out] buffer */
4346 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4347 return WERR_INVALID_PARAM
;
4352 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4356 if (Printer
!= NULL
|| Printer
->servername
!= NULL
) {
4357 servername
= Printer
->servername
;
4360 result
= winreg_get_printer(p
->mem_ctx
,
4364 lp_const_servicename(snum
),
4366 if (!W_ERROR_IS_OK(result
)) {
4370 switch (r
->in
.level
) {
4372 result
= construct_printer_info0(p
->mem_ctx
, p
->server_info
,
4374 &r
->out
.info
->info0
, snum
);
4377 result
= construct_printer_info1(p
->mem_ctx
, info2
,
4379 &r
->out
.info
->info1
, snum
);
4382 result
= construct_printer_info2(p
->mem_ctx
, p
->msg_ctx
, info2
,
4383 &r
->out
.info
->info2
, snum
);
4386 result
= construct_printer_info3(p
->mem_ctx
, info2
,
4387 &r
->out
.info
->info3
, snum
);
4390 result
= construct_printer_info4(p
->mem_ctx
, info2
,
4391 &r
->out
.info
->info4
, snum
);
4394 result
= construct_printer_info5(p
->mem_ctx
, info2
,
4395 &r
->out
.info
->info5
, snum
);
4398 result
= construct_printer_info6(p
->mem_ctx
, p
->msg_ctx
, info2
,
4399 &r
->out
.info
->info6
, snum
);
4402 result
= construct_printer_info7(p
->mem_ctx
, p
->msg_ctx
,
4404 &r
->out
.info
->info7
, snum
);
4407 result
= construct_printer_info8(p
->mem_ctx
, info2
,
4408 &r
->out
.info
->info8
, snum
);
4411 result
= WERR_UNKNOWN_LEVEL
;
4415 if (!W_ERROR_IS_OK(result
)) {
4416 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4417 r
->in
.level
, win_errstr(result
)));
4418 TALLOC_FREE(r
->out
.info
);
4422 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4423 r
->out
.info
, r
->in
.level
);
4424 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4426 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4429 /********************************************************************
4430 ********************************************************************/
4432 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4434 if (in && strlen(in)) { \
4435 out = talloc_strdup(mem_ctx, in); \
4437 out = talloc_strdup(mem_ctx, ""); \
4439 W_ERROR_HAVE_NO_MEMORY(out); \
4442 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4444 if (in && strlen(in)) { \
4445 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4447 out = talloc_strdup(mem_ctx, ""); \
4449 W_ERROR_HAVE_NO_MEMORY(out); \
4452 static WERROR
string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4453 const char **string_array
,
4454 const char ***presult
,
4455 const char *cservername
,
4459 int i
, num_strings
= 0;
4460 const char **array
= NULL
;
4462 if (string_array
== NULL
) {
4463 return WERR_INVALID_PARAMETER
;;
4466 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4467 const char *str
= NULL
;
4469 if (cservername
== NULL
|| arch
== NULL
) {
4470 FILL_DRIVER_STRING(mem_ctx
, string_array
[i
], str
);
4472 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
, arch
, version
, string_array
[i
], str
);
4475 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4482 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4483 &array
, &num_strings
);
4493 /********************************************************************
4494 * fill a spoolss_DriverInfo1 struct
4495 ********************************************************************/
4497 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4498 struct spoolss_DriverInfo1
*r
,
4499 const struct spoolss_DriverInfo8
*driver
,
4500 const char *servername
)
4502 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4503 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4508 /********************************************************************
4509 * fill a spoolss_DriverInfo2 struct
4510 ********************************************************************/
4512 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4513 struct spoolss_DriverInfo2
*r
,
4514 const struct spoolss_DriverInfo8
*driver
,
4515 const char *servername
)
4518 const char *cservername
= canon_servername(servername
);
4520 r
->version
= driver
->version
;
4522 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4523 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4524 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4525 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4527 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4528 driver
->architecture
,
4530 driver
->driver_path
,
4533 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4534 driver
->architecture
,
4539 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4540 driver
->architecture
,
4542 driver
->config_file
,
4548 /********************************************************************
4549 * fill a spoolss_DriverInfo3 struct
4550 ********************************************************************/
4552 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4553 struct spoolss_DriverInfo3
*r
,
4554 const struct spoolss_DriverInfo8
*driver
,
4555 const char *servername
)
4557 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 return string_array_from_driver_info(mem_ctx
,
4599 driver
->dependent_files
,
4600 &r
->dependent_files
,
4602 driver
->architecture
,
4606 /********************************************************************
4607 * fill a spoolss_DriverInfo4 struct
4608 ********************************************************************/
4610 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4611 struct spoolss_DriverInfo4
*r
,
4612 const struct spoolss_DriverInfo8
*driver
,
4613 const char *servername
)
4615 const char *cservername
= canon_servername(servername
);
4618 r
->version
= driver
->version
;
4620 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4621 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4622 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4623 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4625 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4626 driver
->architecture
,
4628 driver
->driver_path
,
4631 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4632 driver
->architecture
,
4637 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4638 driver
->architecture
,
4640 driver
->config_file
,
4643 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4644 driver
->architecture
,
4649 result
= string_array_from_driver_info(mem_ctx
,
4650 driver
->dependent_files
,
4651 &r
->dependent_files
,
4653 driver
->architecture
,
4655 if (!W_ERROR_IS_OK(result
)) {
4659 FILL_DRIVER_STRING(mem_ctx
,
4660 driver
->monitor_name
,
4663 FILL_DRIVER_STRING(mem_ctx
,
4664 driver
->default_datatype
,
4665 r
->default_datatype
);
4668 result
= string_array_from_driver_info(mem_ctx
,
4669 driver
->previous_names
,
4676 /********************************************************************
4677 * fill a spoolss_DriverInfo5 struct
4678 ********************************************************************/
4680 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
4681 struct spoolss_DriverInfo5
*r
,
4682 const struct spoolss_DriverInfo8
*driver
,
4683 const char *servername
)
4685 const char *cservername
= canon_servername(servername
);
4687 r
->version
= driver
->version
;
4689 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4690 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4691 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4692 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4694 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4695 driver
->architecture
,
4697 driver
->driver_path
,
4700 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4701 driver
->architecture
,
4706 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4707 driver
->architecture
,
4709 driver
->config_file
,
4712 r
->driver_attributes
= 0;
4713 r
->config_version
= 0;
4714 r
->driver_version
= 0;
4718 /********************************************************************
4719 * fill a spoolss_DriverInfo6 struct
4720 ********************************************************************/
4722 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4723 struct spoolss_DriverInfo6
*r
,
4724 const struct spoolss_DriverInfo8
*driver
,
4725 const char *servername
)
4727 const char *cservername
= canon_servername(servername
);
4730 r
->version
= driver
->version
;
4732 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4733 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4734 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4735 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4737 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4738 driver
->architecture
,
4740 driver
->driver_path
,
4743 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4744 driver
->architecture
,
4749 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4750 driver
->architecture
,
4752 driver
->config_file
,
4755 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4756 driver
->architecture
,
4761 FILL_DRIVER_STRING(mem_ctx
,
4762 driver
->monitor_name
,
4765 FILL_DRIVER_STRING(mem_ctx
,
4766 driver
->default_datatype
,
4767 r
->default_datatype
);
4769 result
= string_array_from_driver_info(mem_ctx
,
4770 driver
->dependent_files
,
4771 &r
->dependent_files
,
4773 driver
->architecture
,
4775 if (!W_ERROR_IS_OK(result
)) {
4779 result
= string_array_from_driver_info(mem_ctx
,
4780 driver
->previous_names
,
4783 if (!W_ERROR_IS_OK(result
)) {
4787 r
->driver_date
= driver
->driver_date
;
4788 r
->driver_version
= driver
->driver_version
;
4790 FILL_DRIVER_STRING(mem_ctx
,
4791 driver
->manufacturer_name
,
4792 r
->manufacturer_name
);
4793 FILL_DRIVER_STRING(mem_ctx
,
4794 driver
->manufacturer_url
,
4795 r
->manufacturer_url
);
4796 FILL_DRIVER_STRING(mem_ctx
,
4797 driver
->hardware_id
,
4799 FILL_DRIVER_STRING(mem_ctx
,
4806 /********************************************************************
4807 * fill a spoolss_DriverInfo8 struct
4808 ********************************************************************/
4810 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
4811 struct spoolss_DriverInfo8
*r
,
4812 const struct spoolss_DriverInfo8
*driver
,
4813 const char *servername
)
4815 const char *cservername
= canon_servername(servername
);
4818 r
->version
= driver
->version
;
4820 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4821 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4822 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4823 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4825 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4826 driver
->architecture
,
4828 driver
->driver_path
,
4831 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4832 driver
->architecture
,
4837 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4838 driver
->architecture
,
4840 driver
->config_file
,
4843 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4844 driver
->architecture
,
4849 FILL_DRIVER_STRING(mem_ctx
,
4850 driver
->monitor_name
,
4853 FILL_DRIVER_STRING(mem_ctx
,
4854 driver
->default_datatype
,
4855 r
->default_datatype
);
4857 result
= string_array_from_driver_info(mem_ctx
,
4858 driver
->dependent_files
,
4859 &r
->dependent_files
,
4861 driver
->architecture
,
4863 if (!W_ERROR_IS_OK(result
)) {
4867 result
= string_array_from_driver_info(mem_ctx
,
4868 driver
->previous_names
,
4871 if (!W_ERROR_IS_OK(result
)) {
4875 r
->driver_date
= driver
->driver_date
;
4876 r
->driver_version
= driver
->driver_version
;
4878 FILL_DRIVER_STRING(mem_ctx
,
4879 driver
->manufacturer_name
,
4880 r
->manufacturer_name
);
4881 FILL_DRIVER_STRING(mem_ctx
,
4882 driver
->manufacturer_url
,
4883 r
->manufacturer_url
);
4884 FILL_DRIVER_STRING(mem_ctx
,
4885 driver
->hardware_id
,
4887 FILL_DRIVER_STRING(mem_ctx
,
4891 FILL_DRIVER_STRING(mem_ctx
,
4892 driver
->print_processor
,
4893 r
->print_processor
);
4894 FILL_DRIVER_STRING(mem_ctx
,
4895 driver
->vendor_setup
,
4898 result
= string_array_from_driver_info(mem_ctx
,
4899 driver
->color_profiles
,
4902 if (!W_ERROR_IS_OK(result
)) {
4906 FILL_DRIVER_STRING(mem_ctx
,
4910 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
4912 result
= string_array_from_driver_info(mem_ctx
,
4913 driver
->core_driver_dependencies
,
4914 &r
->core_driver_dependencies
,
4916 if (!W_ERROR_IS_OK(result
)) {
4920 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
4921 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
4926 #if 0 /* disabled until marshalling issues are resolved - gd */
4927 /********************************************************************
4928 ********************************************************************/
4930 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
4931 struct spoolss_DriverFileInfo
*r
,
4932 const char *cservername
,
4933 const char *file_name
,
4934 enum spoolss_DriverFileType file_type
,
4935 uint32_t file_version
)
4937 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4938 cservername
, file_name
);
4939 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
4940 r
->file_type
= file_type
;
4941 r
->file_version
= file_version
;
4946 /********************************************************************
4947 ********************************************************************/
4949 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
4950 const struct spoolss_DriverInfo8
*driver
,
4951 const char *cservername
,
4952 struct spoolss_DriverFileInfo
**info_p
,
4955 struct spoolss_DriverFileInfo
*info
= NULL
;
4963 if (strlen(driver
->driver_path
)) {
4964 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4965 struct spoolss_DriverFileInfo
,
4967 W_ERROR_HAVE_NO_MEMORY(info
);
4968 result
= fill_spoolss_DriverFileInfo(info
,
4971 driver
->driver_path
,
4972 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
4974 W_ERROR_NOT_OK_RETURN(result
);
4978 if (strlen(driver
->config_file
)) {
4979 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4980 struct spoolss_DriverFileInfo
,
4982 W_ERROR_HAVE_NO_MEMORY(info
);
4983 result
= fill_spoolss_DriverFileInfo(info
,
4986 driver
->config_file
,
4987 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
4989 W_ERROR_NOT_OK_RETURN(result
);
4993 if (strlen(driver
->data_file
)) {
4994 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4995 struct spoolss_DriverFileInfo
,
4997 W_ERROR_HAVE_NO_MEMORY(info
);
4998 result
= fill_spoolss_DriverFileInfo(info
,
5002 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5004 W_ERROR_NOT_OK_RETURN(result
);
5008 if (strlen(driver
->help_file
)) {
5009 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5010 struct spoolss_DriverFileInfo
,
5012 W_ERROR_HAVE_NO_MEMORY(info
);
5013 result
= fill_spoolss_DriverFileInfo(info
,
5017 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5019 W_ERROR_NOT_OK_RETURN(result
);
5023 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
5024 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5025 struct spoolss_DriverFileInfo
,
5027 W_ERROR_HAVE_NO_MEMORY(info
);
5028 result
= fill_spoolss_DriverFileInfo(info
,
5031 driver
->dependent_files
[i
],
5032 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5034 W_ERROR_NOT_OK_RETURN(result
);
5044 /********************************************************************
5045 * fill a spoolss_DriverInfo101 struct
5046 ********************************************************************/
5048 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5049 struct spoolss_DriverInfo101
*r
,
5050 const struct spoolss_DriverInfo8
*driver
,
5051 const char *servername
)
5053 const char *cservername
= canon_servername(servername
);
5056 r
->version
= driver
->version
;
5058 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5059 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5060 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5061 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5063 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5067 if (!W_ERROR_IS_OK(result
)) {
5071 FILL_DRIVER_STRING(mem_ctx
,
5072 driver
->monitor_name
,
5075 FILL_DRIVER_STRING(mem_ctx
,
5076 driver
->default_datatype
,
5077 r
->default_datatype
);
5079 result
= string_array_from_driver_info(mem_ctx
,
5080 driver
->previous_names
,
5083 if (!W_ERROR_IS_OK(result
)) {
5087 r
->driver_date
= driver
->driver_date
;
5088 r
->driver_version
= driver
->driver_version
;
5090 FILL_DRIVER_STRING(mem_ctx
,
5091 driver
->manufacturer_name
,
5092 r
->manufacturer_name
);
5093 FILL_DRIVER_STRING(mem_ctx
,
5094 driver
->manufacturer_url
,
5095 r
->manufacturer_url
);
5096 FILL_DRIVER_STRING(mem_ctx
,
5097 driver
->hardware_id
,
5099 FILL_DRIVER_STRING(mem_ctx
,
5106 /********************************************************************
5107 ********************************************************************/
5109 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
5110 struct auth_serversupplied_info
*server_info
,
5111 struct messaging_context
*msg_ctx
,
5113 union spoolss_DriverInfo
*r
,
5115 const char *servername
,
5116 const char *architecture
,
5119 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
5120 struct spoolss_DriverInfo8
*driver
;
5123 result
= winreg_get_printer(mem_ctx
,
5127 lp_const_servicename(snum
),
5130 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5131 win_errstr(result
)));
5133 if (!W_ERROR_IS_OK(result
)) {
5134 return WERR_INVALID_PRINTER_NAME
;
5137 result
= winreg_get_driver(mem_ctx
, server_info
, msg_ctx
,
5139 pinfo2
->drivername
, version
, &driver
);
5141 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5142 win_errstr(result
)));
5144 if (!W_ERROR_IS_OK(result
)) {
5146 * Is this a W2k client ?
5150 talloc_free(pinfo2
);
5151 return WERR_UNKNOWN_PRINTER_DRIVER
;
5154 /* Yes - try again with a WinNT driver. */
5156 result
= winreg_get_driver(mem_ctx
, server_info
, msg_ctx
,
5160 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5161 win_errstr(result
)));
5162 if (!W_ERROR_IS_OK(result
)) {
5163 talloc_free(pinfo2
);
5164 return WERR_UNKNOWN_PRINTER_DRIVER
;
5170 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
5173 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
5176 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
5179 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
5182 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
5185 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5188 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5190 #if 0 /* disabled until marshalling issues are resolved - gd */
5192 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5196 result
= WERR_UNKNOWN_LEVEL
;
5200 talloc_free(pinfo2
);
5201 talloc_free(driver
);
5206 /****************************************************************
5207 _spoolss_GetPrinterDriver2
5208 ****************************************************************/
5210 WERROR
_spoolss_GetPrinterDriver2(struct pipes_struct
*p
,
5211 struct spoolss_GetPrinterDriver2
*r
)
5213 Printer_entry
*printer
;
5218 /* that's an [in out] buffer */
5220 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5221 return WERR_INVALID_PARAM
;
5224 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5226 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5227 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5228 return WERR_INVALID_PRINTER_NAME
;
5232 *r
->out
.server_major_version
= 0;
5233 *r
->out
.server_minor_version
= 0;
5235 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5239 result
= construct_printer_driver_info_level(p
->mem_ctx
,
5242 r
->in
.level
, r
->out
.info
,
5243 snum
, printer
->servername
,
5245 r
->in
.client_major_version
);
5246 if (!W_ERROR_IS_OK(result
)) {
5247 TALLOC_FREE(r
->out
.info
);
5251 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5252 r
->out
.info
, r
->in
.level
);
5253 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5255 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5259 /****************************************************************
5260 _spoolss_StartPagePrinter
5261 ****************************************************************/
5263 WERROR
_spoolss_StartPagePrinter(struct pipes_struct
*p
,
5264 struct spoolss_StartPagePrinter
*r
)
5266 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5269 DEBUG(3,("_spoolss_StartPagePrinter: "
5270 "Error in startpageprinter printer handle\n"));
5274 Printer
->page_started
= true;
5278 /****************************************************************
5279 _spoolss_EndPagePrinter
5280 ****************************************************************/
5282 WERROR
_spoolss_EndPagePrinter(struct pipes_struct
*p
,
5283 struct spoolss_EndPagePrinter
*r
)
5287 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5290 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5291 OUR_HANDLE(r
->in
.handle
)));
5295 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5298 Printer
->page_started
= false;
5299 print_job_endpage(p
->msg_ctx
, snum
, Printer
->jobid
);
5304 /****************************************************************
5305 _spoolss_StartDocPrinter
5306 ****************************************************************/
5308 WERROR
_spoolss_StartDocPrinter(struct pipes_struct
*p
,
5309 struct spoolss_StartDocPrinter
*r
)
5311 struct spoolss_DocumentInfo1
*info_1
;
5313 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5317 DEBUG(2,("_spoolss_StartDocPrinter: "
5318 "Invalid handle (%s:%u:%u)\n",
5319 OUR_HANDLE(r
->in
.handle
)));
5323 if (Printer
->jobid
) {
5324 DEBUG(2, ("_spoolss_StartDocPrinter: "
5325 "StartDocPrinter called twice! "
5326 "(existing jobid = %d)\n", Printer
->jobid
));
5327 return WERR_INVALID_HANDLE
;
5330 if (r
->in
.level
!= 1) {
5331 return WERR_UNKNOWN_LEVEL
;
5334 info_1
= r
->in
.info
.info1
;
5337 * a nice thing with NT is it doesn't listen to what you tell it.
5338 * when asked to send _only_ RAW datas, it tries to send datas
5341 * So I add checks like in NT Server ...
5344 if (info_1
->datatype
) {
5345 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5347 return WERR_INVALID_DATATYPE
;
5351 /* get the share number of the printer */
5352 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5356 werr
= print_job_start(p
->server_info
, p
->msg_ctx
,
5357 p
->client_id
->name
, snum
,
5358 info_1
->document_name
, info_1
->output_file
,
5359 Printer
->devmode
, &Printer
->jobid
);
5361 /* An error occured in print_job_start() so return an appropriate
5364 if (!W_ERROR_IS_OK(werr
)) {
5368 Printer
->document_started
= true;
5369 *r
->out
.job_id
= Printer
->jobid
;
5374 /****************************************************************
5375 _spoolss_EndDocPrinter
5376 ****************************************************************/
5378 WERROR
_spoolss_EndDocPrinter(struct pipes_struct
*p
,
5379 struct spoolss_EndDocPrinter
*r
)
5381 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5386 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5387 OUR_HANDLE(r
->in
.handle
)));
5391 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5395 Printer
->document_started
= false;
5396 status
= print_job_end(p
->msg_ctx
, snum
, Printer
->jobid
, NORMAL_CLOSE
);
5397 if (!NT_STATUS_IS_OK(status
)) {
5398 DEBUG(2, ("_spoolss_EndDocPrinter: "
5399 "print_job_end failed [%s]\n",
5400 nt_errstr(status
)));
5404 return ntstatus_to_werror(status
);
5407 /****************************************************************
5408 _spoolss_WritePrinter
5409 ****************************************************************/
5411 WERROR
_spoolss_WritePrinter(struct pipes_struct
*p
,
5412 struct spoolss_WritePrinter
*r
)
5414 ssize_t buffer_written
;
5416 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5419 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5420 OUR_HANDLE(r
->in
.handle
)));
5421 *r
->out
.num_written
= r
->in
._data_size
;
5425 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5428 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5429 buffer_written
= print_job_write(server_event_context(),p
->msg_ctx
,
5430 snum
, Printer
->jobid
,
5431 (const char *)r
->in
.data
.data
,
5432 (size_t)r
->in
._data_size
);
5433 if (buffer_written
== (ssize_t
)-1) {
5434 *r
->out
.num_written
= 0;
5435 if (errno
== ENOSPC
)
5436 return WERR_NO_SPOOL_SPACE
;
5438 return WERR_ACCESS_DENIED
;
5441 *r
->out
.num_written
= r
->in
._data_size
;
5446 /********************************************************************
5447 * api_spoolss_getprinter
5448 * called from the spoolss dispatcher
5450 ********************************************************************/
5452 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5453 struct pipes_struct
*p
)
5456 WERROR errcode
= WERR_BADFUNC
;
5457 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5460 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5461 OUR_HANDLE(handle
)));
5465 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5469 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5470 errcode
= print_queue_pause(p
->server_info
, p
->msg_ctx
, snum
);
5472 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5473 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5474 errcode
= print_queue_resume(p
->server_info
, p
->msg_ctx
, snum
);
5476 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5477 errcode
= print_queue_purge(p
->server_info
, p
->msg_ctx
, snum
);
5480 return WERR_UNKNOWN_LEVEL
;
5487 /****************************************************************
5488 _spoolss_AbortPrinter
5489 * From MSDN: "Deletes printer's spool file if printer is configured
5491 ****************************************************************/
5493 WERROR
_spoolss_AbortPrinter(struct pipes_struct
*p
,
5494 struct spoolss_AbortPrinter
*r
)
5496 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5498 WERROR errcode
= WERR_OK
;
5501 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5502 OUR_HANDLE(r
->in
.handle
)));
5506 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5509 if (!Printer
->document_started
) {
5510 return WERR_SPL_NO_STARTDOC
;
5513 errcode
= print_job_delete(p
->server_info
, p
->msg_ctx
, snum
,
5519 /********************************************************************
5520 * called by spoolss_api_setprinter
5521 * when updating a printer description
5522 ********************************************************************/
5524 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5525 struct pipes_struct
*p
,
5526 struct sec_desc_buf
*secdesc_ctr
)
5528 struct spoolss_security_descriptor
*new_secdesc
= NULL
;
5529 struct spoolss_security_descriptor
*old_secdesc
= NULL
;
5530 const char *printer
;
5534 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5536 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5537 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5538 OUR_HANDLE(handle
)));
5540 result
= WERR_BADFID
;
5544 if (secdesc_ctr
== NULL
) {
5545 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5546 result
= WERR_INVALID_PARAM
;
5549 printer
= lp_const_servicename(snum
);
5551 /* Check the user has permissions to change the security
5552 descriptor. By experimentation with two NT machines, the user
5553 requires Full Access to the printer to change security
5556 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5557 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5558 result
= WERR_ACCESS_DENIED
;
5562 /* NT seems to like setting the security descriptor even though
5563 nothing may have actually changed. */
5564 result
= winreg_get_printer_secdesc(p
->mem_ctx
,
5569 if (!W_ERROR_IS_OK(result
)) {
5570 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5571 result
= WERR_BADFID
;
5575 if (DEBUGLEVEL
>= 10) {
5576 struct security_acl
*the_acl
;
5579 the_acl
= old_secdesc
->dacl
;
5580 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5581 printer
, the_acl
->num_aces
));
5583 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5584 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5585 &the_acl
->aces
[i
].trustee
),
5586 the_acl
->aces
[i
].access_mask
));
5589 the_acl
= secdesc_ctr
->sd
->dacl
;
5592 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5593 printer
, the_acl
->num_aces
));
5595 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5596 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5597 &the_acl
->aces
[i
].trustee
),
5598 the_acl
->aces
[i
].access_mask
));
5601 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5605 new_secdesc
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
->sd
, old_secdesc
);
5606 if (new_secdesc
== NULL
) {
5607 result
= WERR_NOMEM
;
5611 if (security_descriptor_equal(new_secdesc
, old_secdesc
)) {
5616 result
= winreg_set_printer_secdesc(p
->mem_ctx
,
5626 /********************************************************************
5627 Canonicalize printer info from a client
5628 ********************************************************************/
5630 static bool check_printer_ok(TALLOC_CTX
*mem_ctx
,
5631 struct spoolss_SetPrinterInfo2
*info2
,
5634 fstring printername
;
5637 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5638 "portname=%s drivername=%s comment=%s location=%s\n",
5639 info2
->servername
, info2
->printername
, info2
->sharename
,
5640 info2
->portname
, info2
->drivername
, info2
->comment
,
5643 /* we force some elements to "correct" values */
5644 info2
->servername
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
5645 if (info2
->servername
== NULL
) {
5648 info2
->sharename
= talloc_strdup(mem_ctx
, lp_const_servicename(snum
));
5649 if (info2
->sharename
== NULL
) {
5653 /* check to see if we allow printername != sharename */
5654 if (lp_force_printername(snum
)) {
5655 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
5656 global_myname(), info2
->sharename
);
5658 /* make sure printername is in \\server\printername format */
5659 fstrcpy(printername
, info2
->printername
);
5661 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5662 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5666 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
5667 global_myname(), p
);
5669 if (info2
->printername
== NULL
) {
5673 info2
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5674 info2
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5679 /****************************************************************************
5680 ****************************************************************************/
5682 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5684 char *cmd
= lp_addport_cmd();
5685 char *command
= NULL
;
5687 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5688 bool is_print_op
= false;
5691 return WERR_ACCESS_DENIED
;
5694 command
= talloc_asprintf(ctx
,
5695 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5701 is_print_op
= user_has_privileges( token
, &se_printop
);
5703 DEBUG(10,("Running [%s]\n", command
));
5705 /********* BEGIN SePrintOperatorPrivilege **********/
5710 ret
= smbrun(command
, NULL
);
5715 /********* END SePrintOperatorPrivilege **********/
5717 DEBUGADD(10,("returned [%d]\n", ret
));
5719 TALLOC_FREE(command
);
5722 return WERR_ACCESS_DENIED
;
5728 /****************************************************************************
5729 ****************************************************************************/
5731 static bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
,
5732 struct spoolss_SetPrinterInfo2
*info2
,
5733 const char *remote_machine
,
5734 struct messaging_context
*msg_ctx
)
5736 char *cmd
= lp_addprinter_cmd();
5738 char *command
= NULL
;
5742 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5743 bool is_print_op
= false;
5745 if (!remote_machine
) {
5749 command
= talloc_asprintf(ctx
,
5750 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5751 cmd
, info2
->printername
, info2
->sharename
,
5752 info2
->portname
, info2
->drivername
,
5753 info2
->location
, info2
->comment
, remote_machine
);
5759 is_print_op
= user_has_privileges( token
, &se_printop
);
5761 DEBUG(10,("Running [%s]\n", command
));
5763 /********* BEGIN SePrintOperatorPrivilege **********/
5768 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5769 /* Tell everyone we updated smb.conf. */
5770 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
5776 /********* END SePrintOperatorPrivilege **********/
5778 DEBUGADD(10,("returned [%d]\n", ret
));
5780 TALLOC_FREE(command
);
5788 /* reload our services immediately */
5790 reload_services(msg_ctx
, -1, false);
5794 /* Get lines and convert them back to dos-codepage */
5795 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
5796 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5799 /* Set the portname to what the script says the portname should be. */
5800 /* but don't require anything to be return from the script exit a good error code */
5803 /* Set the portname to what the script says the portname should be. */
5804 info2
->portname
= talloc_strdup(ctx
, qlines
[0]);
5805 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5808 TALLOC_FREE(qlines
);
5812 static WERROR
update_dsspooler(TALLOC_CTX
*mem_ctx
,
5813 struct auth_serversupplied_info
*server_info
,
5814 struct messaging_context
*msg_ctx
,
5816 struct spoolss_SetPrinterInfo2
*printer
,
5817 struct spoolss_PrinterInfo2
*old_printer
)
5819 bool force_update
= (old_printer
== NULL
);
5820 const char *dnsdomname
;
5821 const char *longname
;
5822 const char *uncname
;
5823 const char *spooling
;
5825 WERROR result
= WERR_OK
;
5827 if (force_update
|| !strequal(printer
->drivername
, old_printer
->drivername
)) {
5828 push_reg_sz(mem_ctx
, &buffer
, printer
->drivername
);
5829 winreg_set_printer_dataex(mem_ctx
,
5833 SPOOL_DSSPOOLER_KEY
,
5834 SPOOL_REG_DRIVERNAME
,
5839 if (!force_update
) {
5840 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5841 printer
->drivername
));
5843 notify_printer_driver(server_event_context(), msg_ctx
,
5844 snum
, printer
->drivername
);
5848 if (force_update
|| !strequal(printer
->comment
, old_printer
->comment
)) {
5849 push_reg_sz(mem_ctx
, &buffer
, printer
->comment
);
5850 winreg_set_printer_dataex(mem_ctx
,
5854 SPOOL_DSSPOOLER_KEY
,
5855 SPOOL_REG_DESCRIPTION
,
5860 if (!force_update
) {
5861 notify_printer_comment(server_event_context(), msg_ctx
,
5862 snum
, printer
->comment
);
5866 if (force_update
|| !strequal(printer
->sharename
, old_printer
->sharename
)) {
5867 push_reg_sz(mem_ctx
, &buffer
, printer
->sharename
);
5868 winreg_set_printer_dataex(mem_ctx
,
5872 SPOOL_DSSPOOLER_KEY
,
5873 SPOOL_REG_PRINTSHARENAME
,
5878 if (!force_update
) {
5879 notify_printer_sharename(server_event_context(),
5881 snum
, printer
->sharename
);
5885 if (force_update
|| !strequal(printer
->printername
, old_printer
->printername
)) {
5888 p
= strrchr(printer
->printername
, '\\' );
5892 p
= printer
->printername
;
5895 push_reg_sz(mem_ctx
, &buffer
, p
);
5896 winreg_set_printer_dataex(mem_ctx
,
5900 SPOOL_DSSPOOLER_KEY
,
5901 SPOOL_REG_PRINTERNAME
,
5906 if (!force_update
) {
5907 notify_printer_printername(server_event_context(),
5912 if (force_update
|| !strequal(printer
->portname
, old_printer
->portname
)) {
5913 push_reg_sz(mem_ctx
, &buffer
, printer
->portname
);
5914 winreg_set_printer_dataex(mem_ctx
,
5918 SPOOL_DSSPOOLER_KEY
,
5924 if (!force_update
) {
5925 notify_printer_port(server_event_context(),
5926 msg_ctx
, snum
, printer
->portname
);
5930 if (force_update
|| !strequal(printer
->location
, old_printer
->location
)) {
5931 push_reg_sz(mem_ctx
, &buffer
, printer
->location
);
5932 winreg_set_printer_dataex(mem_ctx
,
5936 SPOOL_DSSPOOLER_KEY
,
5942 if (!force_update
) {
5943 notify_printer_location(server_event_context(),
5949 if (force_update
|| !strequal(printer
->sepfile
, old_printer
->sepfile
)) {
5950 push_reg_sz(mem_ctx
, &buffer
, printer
->sepfile
);
5951 winreg_set_printer_dataex(mem_ctx
,
5955 SPOOL_DSSPOOLER_KEY
,
5956 SPOOL_REG_PRINTSEPARATORFILE
,
5961 if (!force_update
) {
5962 notify_printer_location(server_event_context(),
5968 if (force_update
|| printer
->starttime
!= old_printer
->starttime
) {
5969 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
5970 SIVAL(buffer
.data
, 0, printer
->starttime
);
5971 winreg_set_printer_dataex(mem_ctx
,
5975 SPOOL_DSSPOOLER_KEY
,
5976 SPOOL_REG_PRINTSTARTTIME
,
5982 if (force_update
|| printer
->untiltime
!= old_printer
->untiltime
) {
5983 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
5984 SIVAL(buffer
.data
, 0, printer
->untiltime
);
5985 winreg_set_printer_dataex(mem_ctx
,
5989 SPOOL_DSSPOOLER_KEY
,
5990 SPOOL_REG_PRINTENDTIME
,
5996 if (force_update
|| printer
->priority
!= old_printer
->priority
) {
5997 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
5998 SIVAL(buffer
.data
, 0, printer
->priority
);
5999 winreg_set_printer_dataex(mem_ctx
,
6003 SPOOL_DSSPOOLER_KEY
,
6010 if (force_update
|| printer
->attributes
!= old_printer
->attributes
) {
6011 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6012 SIVAL(buffer
.data
, 0, (printer
->attributes
&
6013 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
6014 winreg_set_printer_dataex(mem_ctx
,
6018 SPOOL_DSSPOOLER_KEY
,
6019 SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
6024 switch (printer
->attributes
& 0x3) {
6026 spooling
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
6029 spooling
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
6032 spooling
= SPOOL_REGVAL_PRINTDIRECT
;
6035 spooling
= "unknown";
6037 push_reg_sz(mem_ctx
, &buffer
, spooling
);
6038 winreg_set_printer_dataex(mem_ctx
,
6042 SPOOL_DSSPOOLER_KEY
,
6043 SPOOL_REG_PRINTSPOOLING
,
6049 push_reg_sz(mem_ctx
, &buffer
, global_myname());
6050 winreg_set_printer_dataex(mem_ctx
,
6054 SPOOL_DSSPOOLER_KEY
,
6055 SPOOL_REG_SHORTSERVERNAME
,
6060 dnsdomname
= get_mydnsfullname();
6061 if (dnsdomname
!= NULL
&& dnsdomname
[0] != '\0') {
6062 longname
= talloc_strdup(mem_ctx
, dnsdomname
);
6064 longname
= talloc_strdup(mem_ctx
, global_myname());
6066 if (longname
== NULL
) {
6067 result
= WERR_NOMEM
;
6071 push_reg_sz(mem_ctx
, &buffer
, longname
);
6072 winreg_set_printer_dataex(mem_ctx
,
6076 SPOOL_DSSPOOLER_KEY
,
6077 SPOOL_REG_SERVERNAME
,
6082 uncname
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6083 global_myname(), printer
->sharename
);
6084 push_reg_sz(mem_ctx
, &buffer
, uncname
);
6085 winreg_set_printer_dataex(mem_ctx
,
6089 SPOOL_DSSPOOLER_KEY
,
6099 /********************************************************************
6100 * Called by spoolss_api_setprinter
6101 * when updating a printer description.
6102 ********************************************************************/
6104 static WERROR
update_printer(struct pipes_struct
*p
,
6105 struct policy_handle
*handle
,
6106 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6107 struct spoolss_DeviceMode
*devmode
)
6109 uint32_t printer_mask
= SPOOLSS_PRINTER_INFO_ALL
;
6110 struct spoolss_SetPrinterInfo2
*printer
= info_ctr
->info
.info2
;
6111 struct spoolss_PrinterInfo2
*old_printer
;
6112 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6113 const char *servername
= NULL
;
6115 WERROR result
= WERR_OK
;
6116 TALLOC_CTX
*tmp_ctx
;
6118 DEBUG(8,("update_printer\n"));
6120 tmp_ctx
= talloc_new(p
->mem_ctx
);
6121 if (tmp_ctx
== NULL
) {
6126 result
= WERR_BADFID
;
6130 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6131 result
= WERR_BADFID
;
6135 if (Printer
!= NULL
|| Printer
->servername
!= NULL
) {
6136 servername
= Printer
->servername
;
6139 result
= winreg_get_printer(tmp_ctx
,
6143 lp_const_servicename(snum
),
6145 if (!W_ERROR_IS_OK(result
)) {
6146 result
= WERR_BADFID
;
6150 /* Do sanity check on the requested changes for Samba */
6151 if (!check_printer_ok(tmp_ctx
, printer
, snum
)) {
6152 result
= WERR_INVALID_PARAM
;
6156 /* FIXME!!! If the driver has changed we really should verify that
6157 it is installed before doing much else --jerry */
6159 /* Check calling user has permission to update printer description */
6160 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6161 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6162 result
= WERR_ACCESS_DENIED
;
6166 /* Call addprinter hook */
6167 /* Check changes to see if this is really needed */
6169 if (*lp_addprinter_cmd() &&
6170 (!strequal(printer
->drivername
, old_printer
->drivername
) ||
6171 !strequal(printer
->comment
, old_printer
->comment
) ||
6172 !strequal(printer
->portname
, old_printer
->portname
) ||
6173 !strequal(printer
->location
, old_printer
->location
)) )
6175 /* add_printer_hook() will call reload_services() */
6176 if (!add_printer_hook(tmp_ctx
, p
->server_info
->ptok
,
6177 printer
, p
->client_id
->addr
,
6179 result
= WERR_ACCESS_DENIED
;
6184 update_dsspooler(tmp_ctx
,
6191 printer_mask
&= ~SPOOLSS_PRINTER_INFO_SECDESC
;
6193 if (devmode
== NULL
) {
6194 printer_mask
&= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
6196 result
= winreg_update_printer(tmp_ctx
,
6206 talloc_free(tmp_ctx
);
6211 /****************************************************************************
6212 ****************************************************************************/
6213 static WERROR
publish_or_unpublish_printer(struct pipes_struct
*p
,
6214 struct policy_handle
*handle
,
6215 struct spoolss_SetPrinterInfo7
*info7
)
6218 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6221 Printer_entry
*Printer
;
6223 if ( lp_security() != SEC_ADS
) {
6224 return WERR_UNKNOWN_LEVEL
;
6227 Printer
= find_printer_index_by_hnd(p
, handle
);
6229 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6234 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6237 result
= winreg_get_printer(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
6238 Printer
->servername
,
6239 lp_servicename(snum
), &pinfo2
);
6240 if (!W_ERROR_IS_OK(result
)) {
6244 nt_printer_publish(pinfo2
, p
->server_info
, p
->msg_ctx
, pinfo2
,
6247 TALLOC_FREE(pinfo2
);
6250 return WERR_UNKNOWN_LEVEL
;
6254 /********************************************************************
6255 ********************************************************************/
6257 static WERROR
update_printer_devmode(struct pipes_struct
*p
,
6258 struct policy_handle
*handle
,
6259 struct spoolss_DeviceMode
*devmode
)
6262 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6263 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_DEVMODE
;
6265 DEBUG(8,("update_printer_devmode\n"));
6271 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6275 /* Check calling user has permission to update printer description */
6276 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6277 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6278 return WERR_ACCESS_DENIED
;
6281 return winreg_update_printer(p
->mem_ctx
,
6284 lp_const_servicename(snum
),
6292 /****************************************************************
6294 ****************************************************************/
6296 WERROR
_spoolss_SetPrinter(struct pipes_struct
*p
,
6297 struct spoolss_SetPrinter
*r
)
6301 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6304 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6305 OUR_HANDLE(r
->in
.handle
)));
6309 /* check the level */
6310 switch (r
->in
.info_ctr
->level
) {
6312 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6314 result
= update_printer(p
, r
->in
.handle
,
6316 r
->in
.devmode_ctr
->devmode
);
6317 if (!W_ERROR_IS_OK(result
))
6319 if (r
->in
.secdesc_ctr
->sd
)
6320 result
= update_printer_sec(r
->in
.handle
, p
,
6324 return update_printer_sec(r
->in
.handle
, p
,
6327 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6328 r
->in
.info_ctr
->info
.info7
);
6330 return update_printer_devmode(p
, r
->in
.handle
,
6331 r
->in
.devmode_ctr
->devmode
);
6333 return WERR_UNKNOWN_LEVEL
;
6337 /****************************************************************
6338 _spoolss_FindClosePrinterNotify
6339 ****************************************************************/
6341 WERROR
_spoolss_FindClosePrinterNotify(struct pipes_struct
*p
,
6342 struct spoolss_FindClosePrinterNotify
*r
)
6344 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6347 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6348 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6352 if (Printer
->notify
.client_connected
== true) {
6355 if ( Printer
->printer_type
== SPLHND_SERVER
)
6357 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6358 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
6361 srv_spoolss_replycloseprinter(
6362 snum
, &Printer
->notify
.client_hnd
, p
->msg_ctx
);
6365 Printer
->notify
.flags
=0;
6366 Printer
->notify
.options
=0;
6367 Printer
->notify
.localmachine
[0]='\0';
6368 Printer
->notify
.printerlocal
=0;
6369 TALLOC_FREE(Printer
->notify
.option
);
6370 Printer
->notify
.client_connected
= false;
6375 /****************************************************************
6377 ****************************************************************/
6379 WERROR
_spoolss_AddJob(struct pipes_struct
*p
,
6380 struct spoolss_AddJob
*r
)
6382 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6383 return WERR_INVALID_PARAM
;
6386 /* this is what a NT server returns for AddJob. AddJob must fail on
6387 * non-local printers */
6389 if (r
->in
.level
!= 1) {
6390 return WERR_UNKNOWN_LEVEL
;
6393 return WERR_INVALID_PARAM
;
6396 /****************************************************************************
6398 ****************************************************************************/
6400 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
6401 struct spoolss_JobInfo1
*r
,
6402 const print_queue_struct
*queue
,
6403 int position
, int snum
,
6404 struct spoolss_PrinterInfo2
*pinfo2
)
6408 t
= gmtime(&queue
->time
);
6410 r
->job_id
= queue
->job
;
6412 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6413 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6414 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6415 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6416 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6417 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6418 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6419 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6420 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6421 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6422 r
->text_status
= talloc_strdup(mem_ctx
, "");
6423 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6425 r
->status
= nt_printj_status(queue
->status
);
6426 r
->priority
= queue
->priority
;
6427 r
->position
= position
;
6428 r
->total_pages
= queue
->page_count
;
6429 r
->pages_printed
= 0; /* ??? */
6431 init_systemtime(&r
->submitted
, t
);
6436 /****************************************************************************
6438 ****************************************************************************/
6440 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6441 struct spoolss_JobInfo2
*r
,
6442 const print_queue_struct
*queue
,
6443 int position
, int snum
,
6444 struct spoolss_PrinterInfo2
*pinfo2
,
6445 struct spoolss_DeviceMode
*devmode
)
6449 t
= gmtime(&queue
->time
);
6451 r
->job_id
= queue
->job
;
6453 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6454 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6455 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6456 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6457 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6458 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6459 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6460 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6461 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6462 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6463 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6464 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6465 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6466 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6467 r
->parameters
= talloc_strdup(mem_ctx
, "");
6468 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6469 r
->driver_name
= talloc_strdup(mem_ctx
, pinfo2
->drivername
);
6470 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6472 r
->devmode
= devmode
;
6474 r
->text_status
= talloc_strdup(mem_ctx
, "");
6475 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6479 r
->status
= nt_printj_status(queue
->status
);
6480 r
->priority
= queue
->priority
;
6481 r
->position
= position
;
6484 r
->total_pages
= queue
->page_count
;
6485 r
->size
= queue
->size
;
6486 init_systemtime(&r
->submitted
, t
);
6488 r
->pages_printed
= 0; /* ??? */
6493 /****************************************************************************
6495 ****************************************************************************/
6497 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6498 struct spoolss_JobInfo3
*r
,
6499 const print_queue_struct
*queue
,
6500 const print_queue_struct
*next_queue
,
6501 int position
, int snum
,
6502 struct spoolss_PrinterInfo2
*pinfo2
)
6504 r
->job_id
= queue
->job
;
6507 r
->next_job_id
= next_queue
->job
;
6514 /****************************************************************************
6515 Enumjobs at level 1.
6516 ****************************************************************************/
6518 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6519 const print_queue_struct
*queue
,
6520 uint32_t num_queues
, int snum
,
6521 struct spoolss_PrinterInfo2
*pinfo2
,
6522 union spoolss_JobInfo
**info_p
,
6525 union spoolss_JobInfo
*info
;
6527 WERROR result
= WERR_OK
;
6529 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6530 W_ERROR_HAVE_NO_MEMORY(info
);
6532 *count
= num_queues
;
6534 for (i
=0; i
<*count
; i
++) {
6535 result
= fill_job_info1(info
,
6541 if (!W_ERROR_IS_OK(result
)) {
6547 if (!W_ERROR_IS_OK(result
)) {
6558 /****************************************************************************
6559 Enumjobs at level 2.
6560 ****************************************************************************/
6562 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6563 const print_queue_struct
*queue
,
6564 uint32_t num_queues
, int snum
,
6565 struct spoolss_PrinterInfo2
*pinfo2
,
6566 union spoolss_JobInfo
**info_p
,
6569 union spoolss_JobInfo
*info
;
6571 WERROR result
= WERR_OK
;
6573 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6574 W_ERROR_HAVE_NO_MEMORY(info
);
6576 *count
= num_queues
;
6578 for (i
=0; i
<*count
; i
++) {
6579 struct spoolss_DeviceMode
*devmode
;
6581 result
= spoolss_create_default_devmode(info
,
6582 pinfo2
->printername
,
6584 if (!W_ERROR_IS_OK(result
)) {
6585 DEBUG(3, ("Can't proceed w/o a devmode!"));
6589 result
= fill_job_info2(info
,
6596 if (!W_ERROR_IS_OK(result
)) {
6602 if (!W_ERROR_IS_OK(result
)) {
6613 /****************************************************************************
6614 Enumjobs at level 3.
6615 ****************************************************************************/
6617 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
6618 const print_queue_struct
*queue
,
6619 uint32_t num_queues
, int snum
,
6620 struct spoolss_PrinterInfo2
*pinfo2
,
6621 union spoolss_JobInfo
**info_p
,
6624 union spoolss_JobInfo
*info
;
6626 WERROR result
= WERR_OK
;
6628 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6629 W_ERROR_HAVE_NO_MEMORY(info
);
6631 *count
= num_queues
;
6633 for (i
=0; i
<*count
; i
++) {
6634 const print_queue_struct
*next_queue
= NULL
;
6637 next_queue
= &queue
[i
+1];
6640 result
= fill_job_info3(info
,
6647 if (!W_ERROR_IS_OK(result
)) {
6653 if (!W_ERROR_IS_OK(result
)) {
6664 /****************************************************************
6666 ****************************************************************/
6668 WERROR
_spoolss_EnumJobs(struct pipes_struct
*p
,
6669 struct spoolss_EnumJobs
*r
)
6672 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6674 print_status_struct prt_status
;
6675 print_queue_struct
*queue
= NULL
;
6678 /* that's an [in out] buffer */
6680 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6681 return WERR_INVALID_PARAM
;
6684 DEBUG(4,("_spoolss_EnumJobs\n"));
6688 *r
->out
.info
= NULL
;
6690 /* lookup the printer snum and tdb entry */
6692 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6696 result
= winreg_get_printer(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
6697 NULL
, lp_servicename(snum
), &pinfo2
);
6698 if (!W_ERROR_IS_OK(result
)) {
6702 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
6703 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6704 count
, prt_status
.status
, prt_status
.message
));
6708 TALLOC_FREE(pinfo2
);
6712 switch (r
->in
.level
) {
6714 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6715 pinfo2
, r
->out
.info
, r
->out
.count
);
6718 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6719 pinfo2
, r
->out
.info
, r
->out
.count
);
6722 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
6723 pinfo2
, r
->out
.info
, r
->out
.count
);
6726 result
= WERR_UNKNOWN_LEVEL
;
6731 TALLOC_FREE(pinfo2
);
6733 if (!W_ERROR_IS_OK(result
)) {
6737 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6739 *r
->out
.info
, r
->in
.level
,
6741 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6742 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6744 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6747 /****************************************************************
6748 _spoolss_ScheduleJob
6749 ****************************************************************/
6751 WERROR
_spoolss_ScheduleJob(struct pipes_struct
*p
,
6752 struct spoolss_ScheduleJob
*r
)
6757 /****************************************************************
6758 ****************************************************************/
6760 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
6761 struct messaging_context
*msg_ctx
,
6762 const char *printer_name
,
6764 struct spoolss_SetJobInfo1
*r
)
6768 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
6772 if (strequal(old_doc_name
, r
->document_name
)) {
6776 if (!print_job_set_name(server_event_context(), msg_ctx
,
6777 printer_name
, job_id
, r
->document_name
)) {
6784 /****************************************************************
6786 ****************************************************************/
6788 WERROR
_spoolss_SetJob(struct pipes_struct
*p
,
6789 struct spoolss_SetJob
*r
)
6792 WERROR errcode
= WERR_BADFUNC
;
6794 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6798 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
6799 return WERR_INVALID_PRINTER_NAME
;
6802 switch (r
->in
.command
) {
6803 case SPOOLSS_JOB_CONTROL_CANCEL
:
6804 case SPOOLSS_JOB_CONTROL_DELETE
:
6805 errcode
= print_job_delete(p
->server_info
, p
->msg_ctx
,
6806 snum
, r
->in
.job_id
);
6807 if (W_ERROR_EQUAL(errcode
, WERR_PRINTER_HAS_JOBS_QUEUED
)) {
6811 case SPOOLSS_JOB_CONTROL_PAUSE
:
6812 if (print_job_pause(p
->server_info
, p
->msg_ctx
,
6813 snum
, r
->in
.job_id
, &errcode
)) {
6817 case SPOOLSS_JOB_CONTROL_RESTART
:
6818 case SPOOLSS_JOB_CONTROL_RESUME
:
6819 if (print_job_resume(p
->server_info
, p
->msg_ctx
,
6820 snum
, r
->in
.job_id
, &errcode
)) {
6828 return WERR_UNKNOWN_LEVEL
;
6831 if (!W_ERROR_IS_OK(errcode
)) {
6835 if (r
->in
.ctr
== NULL
) {
6839 switch (r
->in
.ctr
->level
) {
6841 errcode
= spoolss_setjob_1(p
->mem_ctx
, p
->msg_ctx
,
6842 lp_const_servicename(snum
),
6844 r
->in
.ctr
->info
.info1
);
6850 return WERR_UNKNOWN_LEVEL
;
6856 /****************************************************************************
6857 Enumerates all printer drivers by level and architecture.
6858 ****************************************************************************/
6860 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
6861 struct auth_serversupplied_info
*server_info
,
6862 struct messaging_context
*msg_ctx
,
6863 const char *servername
,
6864 const char *architecture
,
6866 union spoolss_DriverInfo
**info_p
,
6871 struct spoolss_DriverInfo8
*driver
;
6872 union spoolss_DriverInfo
*info
= NULL
;
6874 WERROR result
= WERR_OK
;
6875 uint32_t num_drivers
;
6876 const char **drivers
;
6881 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6882 result
= winreg_get_driver_list(mem_ctx
, server_info
, msg_ctx
,
6883 architecture
, version
,
6884 &num_drivers
, &drivers
);
6885 if (!W_ERROR_IS_OK(result
)) {
6888 DEBUG(4, ("we have:[%d] drivers in environment"
6889 " [%s] and version [%d]\n",
6890 num_drivers
, architecture
, version
));
6892 if (num_drivers
!= 0) {
6893 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6894 union spoolss_DriverInfo
,
6895 count
+ num_drivers
);
6897 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6898 "failed to enlarge driver info buffer!\n"));
6899 result
= WERR_NOMEM
;
6904 for (i
= 0; i
< num_drivers
; i
++) {
6905 DEBUG(5, ("\tdriver: [%s]\n", drivers
[i
]));
6907 result
= winreg_get_driver(mem_ctx
, server_info
,
6909 architecture
, drivers
[i
],
6911 if (!W_ERROR_IS_OK(result
)) {
6917 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
6918 driver
, servername
);
6921 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
6922 driver
, servername
);
6925 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
6926 driver
, servername
);
6929 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
6930 driver
, servername
);
6933 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
6934 driver
, servername
);
6937 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
6938 driver
, servername
);
6941 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
6942 driver
, servername
);
6945 result
= WERR_UNKNOWN_LEVEL
;
6949 TALLOC_FREE(driver
);
6951 if (!W_ERROR_IS_OK(result
)) {
6956 count
+= num_drivers
;
6957 TALLOC_FREE(drivers
);
6961 TALLOC_FREE(drivers
);
6963 if (!W_ERROR_IS_OK(result
)) {
6974 /****************************************************************************
6975 Enumerates all printer drivers by level.
6976 ****************************************************************************/
6978 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
6979 struct auth_serversupplied_info
*server_info
,
6980 struct messaging_context
*msg_ctx
,
6981 const char *servername
,
6982 const char *architecture
,
6984 union spoolss_DriverInfo
**info_p
,
6988 WERROR result
= WERR_OK
;
6990 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
6992 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
6994 union spoolss_DriverInfo
*info
= NULL
;
6997 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
7001 archi_table
[a
].long_archi
,
7005 if (!W_ERROR_IS_OK(result
)) {
7009 for (i
=0; i
< count
; i
++) {
7010 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
7011 info
[i
], info_p
, count_p
);
7018 return enumprinterdrivers_level_by_architecture(mem_ctx
,
7028 /****************************************************************
7029 _spoolss_EnumPrinterDrivers
7030 ****************************************************************/
7032 WERROR
_spoolss_EnumPrinterDrivers(struct pipes_struct
*p
,
7033 struct spoolss_EnumPrinterDrivers
*r
)
7035 const char *cservername
;
7038 /* that's an [in out] buffer */
7040 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7041 return WERR_INVALID_PARAM
;
7044 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7048 *r
->out
.info
= NULL
;
7050 cservername
= canon_servername(r
->in
.server
);
7052 if (!is_myname_or_ipaddr(cservername
)) {
7053 return WERR_UNKNOWN_PRINTER_DRIVER
;
7056 result
= enumprinterdrivers_level(p
->mem_ctx
,
7064 if (!W_ERROR_IS_OK(result
)) {
7068 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7069 spoolss_EnumPrinterDrivers
,
7070 *r
->out
.info
, r
->in
.level
,
7072 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7073 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7075 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7078 /****************************************************************
7080 ****************************************************************/
7082 WERROR
_spoolss_EnumForms(struct pipes_struct
*p
,
7083 struct spoolss_EnumForms
*r
)
7089 *r
->out
.info
= NULL
;
7091 /* that's an [in out] buffer */
7093 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7094 return WERR_INVALID_PARAM
;
7097 DEBUG(4,("_spoolss_EnumForms\n"));
7098 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7099 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7101 switch (r
->in
.level
) {
7103 result
= winreg_printer_enumforms1(p
->mem_ctx
,
7110 result
= WERR_UNKNOWN_LEVEL
;
7114 if (!W_ERROR_IS_OK(result
)) {
7118 if (*r
->out
.count
== 0) {
7119 return WERR_NO_MORE_ITEMS
;
7122 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7124 *r
->out
.info
, r
->in
.level
,
7126 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7127 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7129 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7132 /****************************************************************
7134 ****************************************************************/
7136 WERROR
_spoolss_GetForm(struct pipes_struct
*p
,
7137 struct spoolss_GetForm
*r
)
7141 /* that's an [in out] buffer */
7143 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7144 return WERR_INVALID_PARAM
;
7147 DEBUG(4,("_spoolss_GetForm\n"));
7148 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7149 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7151 switch (r
->in
.level
) {
7153 result
= winreg_printer_getform1(p
->mem_ctx
,
7157 &r
->out
.info
->info1
);
7160 result
= WERR_UNKNOWN_LEVEL
;
7164 if (!W_ERROR_IS_OK(result
)) {
7165 TALLOC_FREE(r
->out
.info
);
7169 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
7170 r
->out
.info
, r
->in
.level
);
7171 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7173 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7176 /****************************************************************************
7177 ****************************************************************************/
7179 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7180 struct spoolss_PortInfo1
*r
,
7183 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7184 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7189 /****************************************************************************
7190 TODO: This probably needs distinguish between TCP/IP and Local ports
7192 ****************************************************************************/
7194 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7195 struct spoolss_PortInfo2
*r
,
7198 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7199 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7201 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7202 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7204 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7205 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7207 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7214 /****************************************************************************
7215 wrapper around the enumer ports command
7216 ****************************************************************************/
7218 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7220 char *cmd
= lp_enumports_cmd();
7221 char **qlines
= NULL
;
7222 char *command
= NULL
;
7230 /* if no hook then just fill in the default port */
7233 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
7236 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7237 TALLOC_FREE(qlines
);
7244 /* we have a valid enumport command */
7246 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7251 DEBUG(10,("Running [%s]\n", command
));
7252 ret
= smbrun(command
, &fd
);
7253 DEBUG(10,("Returned [%d]\n", ret
));
7254 TALLOC_FREE(command
);
7259 return WERR_ACCESS_DENIED
;
7263 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7264 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7274 /****************************************************************************
7276 ****************************************************************************/
7278 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7279 union spoolss_PortInfo
**info_p
,
7282 union spoolss_PortInfo
*info
= NULL
;
7284 WERROR result
= WERR_OK
;
7285 char **qlines
= NULL
;
7288 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7289 if (!W_ERROR_IS_OK(result
)) {
7294 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7296 DEBUG(10,("Returning WERR_NOMEM\n"));
7297 result
= WERR_NOMEM
;
7301 for (i
=0; i
<numlines
; i
++) {
7302 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7303 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7304 if (!W_ERROR_IS_OK(result
)) {
7309 TALLOC_FREE(qlines
);
7312 if (!W_ERROR_IS_OK(result
)) {
7314 TALLOC_FREE(qlines
);
7326 /****************************************************************************
7328 ****************************************************************************/
7330 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7331 union spoolss_PortInfo
**info_p
,
7334 union spoolss_PortInfo
*info
= NULL
;
7336 WERROR result
= WERR_OK
;
7337 char **qlines
= NULL
;
7340 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7341 if (!W_ERROR_IS_OK(result
)) {
7346 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7348 DEBUG(10,("Returning WERR_NOMEM\n"));
7349 result
= WERR_NOMEM
;
7353 for (i
=0; i
<numlines
; i
++) {
7354 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7355 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7356 if (!W_ERROR_IS_OK(result
)) {
7361 TALLOC_FREE(qlines
);
7364 if (!W_ERROR_IS_OK(result
)) {
7366 TALLOC_FREE(qlines
);
7378 /****************************************************************
7380 ****************************************************************/
7382 WERROR
_spoolss_EnumPorts(struct pipes_struct
*p
,
7383 struct spoolss_EnumPorts
*r
)
7387 /* that's an [in out] buffer */
7389 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7390 return WERR_INVALID_PARAM
;
7393 DEBUG(4,("_spoolss_EnumPorts\n"));
7397 *r
->out
.info
= NULL
;
7399 switch (r
->in
.level
) {
7401 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7405 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7409 return WERR_UNKNOWN_LEVEL
;
7412 if (!W_ERROR_IS_OK(result
)) {
7416 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7418 *r
->out
.info
, r
->in
.level
,
7420 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7421 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7423 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7426 /****************************************************************************
7427 ****************************************************************************/
7429 static WERROR
spoolss_addprinterex_level_2(struct pipes_struct
*p
,
7431 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7432 struct spoolss_DeviceMode
*devmode
,
7433 struct security_descriptor
*secdesc
,
7434 struct spoolss_UserLevelCtr
*user_ctr
,
7435 struct policy_handle
*handle
)
7437 struct spoolss_SetPrinterInfo2
*info2
= info_ctr
->info
.info2
;
7438 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ALL
;
7440 WERROR err
= WERR_OK
;
7442 /* samba does not have a concept of local, non-shared printers yet, so
7443 * make sure we always setup sharename - gd */
7444 if ((info2
->sharename
== NULL
|| info2
->sharename
[0] == '\0') &&
7445 (info2
->printername
!= NULL
&& info2
->printername
[0] != '\0')) {
7446 DEBUG(5, ("spoolss_addprinterex_level_2: "
7447 "no sharename has been set, setting printername %s as sharename\n",
7448 info2
->printername
));
7449 info2
->sharename
= info2
->printername
;
7452 /* check to see if the printer already exists */
7453 if ((snum
= print_queue_snum(info2
->sharename
)) != -1) {
7454 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7456 return WERR_PRINTER_ALREADY_EXISTS
;
7459 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7460 if ((snum
= print_queue_snum(info2
->printername
)) != -1) {
7461 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7462 info2
->printername
));
7463 return WERR_PRINTER_ALREADY_EXISTS
;
7467 /* validate printer info struct */
7468 if (!info2
->printername
|| strlen(info2
->printername
) == 0) {
7469 return WERR_INVALID_PRINTER_NAME
;
7471 if (!info2
->portname
|| strlen(info2
->portname
) == 0) {
7472 return WERR_UNKNOWN_PORT
;
7474 if (!info2
->drivername
|| strlen(info2
->drivername
) == 0) {
7475 return WERR_UNKNOWN_PRINTER_DRIVER
;
7477 if (!info2
->printprocessor
|| strlen(info2
->printprocessor
) == 0) {
7478 return WERR_UNKNOWN_PRINTPROCESSOR
;
7481 /* FIXME!!! smbd should check to see if the driver is installed before
7482 trying to add a printer like this --jerry */
7484 if (*lp_addprinter_cmd() ) {
7485 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7486 info2
, p
->client_id
->addr
,
7488 return WERR_ACCESS_DENIED
;
7491 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7492 "smb.conf parameter \"addprinter command\" is defined. This"
7493 "parameter must exist for this call to succeed\n",
7494 info2
->sharename
));
7497 if ((snum
= print_queue_snum(info2
->sharename
)) == -1) {
7498 return WERR_ACCESS_DENIED
;
7501 /* you must be a printer admin to add a new printer */
7502 if (!print_access_check(p
->server_info
, p
->msg_ctx
, snum
,
7503 PRINTER_ACCESS_ADMINISTER
)) {
7504 return WERR_ACCESS_DENIED
;
7508 * Do sanity check on the requested changes for Samba.
7511 if (!check_printer_ok(p
->mem_ctx
, info2
, snum
)) {
7512 return WERR_INVALID_PARAM
;
7515 if (devmode
== NULL
) {
7516 info2_mask
= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
7519 update_dsspooler(p
->mem_ctx
,
7526 err
= winreg_update_printer(p
->mem_ctx
,
7534 if (!W_ERROR_IS_OK(err
)) {
7538 if (!open_printer_hnd(p
, handle
, info2
->printername
, PRINTER_ACCESS_ADMINISTER
)) {
7539 /* Handle open failed - remove addition. */
7540 ZERO_STRUCTP(handle
);
7541 return WERR_ACCESS_DENIED
;
7547 /****************************************************************
7548 _spoolss_AddPrinterEx
7549 ****************************************************************/
7551 WERROR
_spoolss_AddPrinterEx(struct pipes_struct
*p
,
7552 struct spoolss_AddPrinterEx
*r
)
7554 switch (r
->in
.info_ctr
->level
) {
7556 /* we don't handle yet */
7557 /* but I know what to do ... */
7558 return WERR_UNKNOWN_LEVEL
;
7560 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7562 r
->in
.devmode_ctr
->devmode
,
7563 r
->in
.secdesc_ctr
->sd
,
7564 r
->in
.userlevel_ctr
,
7567 return WERR_UNKNOWN_LEVEL
;
7571 /****************************************************************
7573 ****************************************************************/
7575 WERROR
_spoolss_AddPrinter(struct pipes_struct
*p
,
7576 struct spoolss_AddPrinter
*r
)
7578 struct spoolss_AddPrinterEx a
;
7579 struct spoolss_UserLevelCtr userlevel_ctr
;
7581 ZERO_STRUCT(userlevel_ctr
);
7583 userlevel_ctr
.level
= 1;
7585 a
.in
.server
= r
->in
.server
;
7586 a
.in
.info_ctr
= r
->in
.info_ctr
;
7587 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
7588 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
7589 a
.in
.userlevel_ctr
= &userlevel_ctr
;
7590 a
.out
.handle
= r
->out
.handle
;
7592 return _spoolss_AddPrinterEx(p
, &a
);
7595 /****************************************************************
7596 _spoolss_AddPrinterDriverEx
7597 ****************************************************************/
7599 WERROR
_spoolss_AddPrinterDriverEx(struct pipes_struct
*p
,
7600 struct spoolss_AddPrinterDriverEx
*r
)
7602 WERROR err
= WERR_OK
;
7603 const char *driver_name
= NULL
;
7608 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7609 fn
= "_spoolss_AddPrinterDriver";
7611 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7612 fn
= "_spoolss_AddPrinterDriverEx";
7615 return WERR_INVALID_PARAM
;
7619 * we only support the semantics of AddPrinterDriver()
7620 * i.e. only copy files that are newer than existing ones
7623 if (r
->in
.flags
== 0) {
7624 return WERR_INVALID_PARAM
;
7627 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7628 return WERR_ACCESS_DENIED
;
7632 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
7633 /* Clever hack from Martin Zielinski <mz@seh.de>
7634 * to allow downgrade from level 8 (Vista).
7636 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
7637 r
->in
.info_ctr
->level
));
7638 return WERR_UNKNOWN_LEVEL
;
7641 DEBUG(5,("Cleaning driver's information\n"));
7642 err
= clean_up_driver_struct(p
->mem_ctx
, p
, r
->in
.info_ctr
);
7643 if (!W_ERROR_IS_OK(err
))
7646 DEBUG(5,("Moving driver to final destination\n"));
7647 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, r
->in
.info_ctr
,
7652 err
= winreg_add_driver(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
7653 r
->in
.info_ctr
, &driver_name
, &version
);
7654 if (!W_ERROR_IS_OK(err
)) {
7659 * I think this is where he DrvUpgradePrinter() hook would be
7660 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7661 * server. Right now, we just need to send ourselves a message
7662 * to update each printer bound to this driver. --jerry
7665 if (!srv_spoolss_drv_upgrade_printer(driver_name
, p
->msg_ctx
)) {
7666 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7674 /****************************************************************
7675 _spoolss_AddPrinterDriver
7676 ****************************************************************/
7678 WERROR
_spoolss_AddPrinterDriver(struct pipes_struct
*p
,
7679 struct spoolss_AddPrinterDriver
*r
)
7681 struct spoolss_AddPrinterDriverEx a
;
7683 switch (r
->in
.info_ctr
->level
) {
7690 return WERR_UNKNOWN_LEVEL
;
7693 a
.in
.servername
= r
->in
.servername
;
7694 a
.in
.info_ctr
= r
->in
.info_ctr
;
7695 a
.in
.flags
= APD_COPY_NEW_FILES
;
7697 return _spoolss_AddPrinterDriverEx(p
, &a
);
7700 /****************************************************************************
7701 ****************************************************************************/
7703 struct _spoolss_paths
{
7709 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7711 static const struct _spoolss_paths spoolss_paths
[]= {
7712 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7713 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7716 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7717 const char *servername
,
7718 const char *environment
,
7722 const char *pservername
= NULL
;
7723 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7724 const char *short_archi
;
7728 /* environment may be empty */
7729 if (environment
&& strlen(environment
)) {
7730 long_archi
= environment
;
7733 /* servername may be empty */
7734 if (servername
&& strlen(servername
)) {
7735 pservername
= canon_servername(servername
);
7737 if (!is_myname_or_ipaddr(pservername
)) {
7738 return WERR_INVALID_PARAM
;
7742 if (!(short_archi
= get_short_archi(long_archi
))) {
7743 return WERR_INVALID_ENVIRONMENT
;
7746 switch (component
) {
7747 case SPOOLSS_PRTPROCS_PATH
:
7748 case SPOOLSS_DRIVER_PATH
:
7750 *path
= talloc_asprintf(mem_ctx
,
7753 spoolss_paths
[component
].share
,
7756 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7757 SPOOLSS_DEFAULT_SERVER_PATH
,
7758 spoolss_paths
[component
].dir
,
7763 return WERR_INVALID_PARAM
;
7773 /****************************************************************************
7774 ****************************************************************************/
7776 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7777 const char *servername
,
7778 const char *environment
,
7779 struct spoolss_DriverDirectoryInfo1
*r
)
7784 werr
= compose_spoolss_server_path(mem_ctx
,
7787 SPOOLSS_DRIVER_PATH
,
7789 if (!W_ERROR_IS_OK(werr
)) {
7793 DEBUG(4,("printer driver directory: [%s]\n", path
));
7795 r
->directory_name
= path
;
7800 /****************************************************************
7801 _spoolss_GetPrinterDriverDirectory
7802 ****************************************************************/
7804 WERROR
_spoolss_GetPrinterDriverDirectory(struct pipes_struct
*p
,
7805 struct spoolss_GetPrinterDriverDirectory
*r
)
7809 /* that's an [in out] buffer */
7811 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7812 return WERR_INVALID_PARAM
;
7815 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7820 /* r->in.level is ignored */
7822 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7825 &r
->out
.info
->info1
);
7826 if (!W_ERROR_IS_OK(werror
)) {
7827 TALLOC_FREE(r
->out
.info
);
7831 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
7832 r
->out
.info
, r
->in
.level
);
7833 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7835 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7838 /****************************************************************
7839 _spoolss_EnumPrinterData
7840 ****************************************************************/
7842 WERROR
_spoolss_EnumPrinterData(struct pipes_struct
*p
,
7843 struct spoolss_EnumPrinterData
*r
)
7846 struct spoolss_EnumPrinterDataEx r2
;
7848 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
7851 r2
.in
.handle
= r
->in
.handle
;
7852 r2
.in
.key_name
= "PrinterDriverData";
7854 r2
.out
.count
= &count
;
7855 r2
.out
.info
= &info
;
7856 r2
.out
.needed
= &needed
;
7858 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7859 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
7860 r2
.in
.offered
= needed
;
7861 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7863 if (!W_ERROR_IS_OK(result
)) {
7868 * The NT machine wants to know the biggest size of value and data
7870 * cf: MSDN EnumPrinterData remark section
7873 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
7874 uint32_t biggest_valuesize
= 0;
7875 uint32_t biggest_datasize
= 0;
7878 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7880 for (i
=0; i
<count
; i
++) {
7882 name_length
= strlen(info
[i
].value_name
);
7883 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
7884 biggest_valuesize
= name_length
;
7887 if (info
[i
].data_length
> biggest_datasize
) {
7888 biggest_datasize
= info
[i
].data_length
;
7891 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7895 /* the value is an UNICODE string but real_value_size is the length
7896 in bytes including the trailing 0 */
7898 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
7899 *r
->out
.data_needed
= biggest_datasize
;
7901 DEBUG(6,("final values: [%d], [%d]\n",
7902 *r
->out
.value_needed
, *r
->out
.data_needed
));
7907 if (r
->in
.enum_index
< count
) {
7908 val
= &info
[r
->in
.enum_index
];
7912 /* out_value should default to "" or else NT4 has
7913 problems unmarshalling the response */
7915 if (r
->in
.value_offered
) {
7916 *r
->out
.value_needed
= 1;
7917 r
->out
.value_name
= talloc_strdup(r
, "");
7918 if (!r
->out
.value_name
) {
7922 r
->out
.value_name
= NULL
;
7923 *r
->out
.value_needed
= 0;
7926 /* the data is counted in bytes */
7928 *r
->out
.data_needed
= r
->in
.data_offered
;
7930 result
= WERR_NO_MORE_ITEMS
;
7934 * - counted in bytes in the request
7935 * - counted in UNICODE chars in the max reply
7936 * - counted in bytes in the real size
7938 * take a pause *before* coding not *during* coding
7942 if (r
->in
.value_offered
) {
7943 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
7944 if (!r
->out
.value_name
) {
7947 *r
->out
.value_needed
= val
->value_name_len
;
7949 r
->out
.value_name
= NULL
;
7950 *r
->out
.value_needed
= 0;
7955 *r
->out
.type
= val
->type
;
7957 /* data - counted in bytes */
7960 * See the section "Dynamically Typed Query Parameters"
7964 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
7965 val
->data_length
&& r
->in
.data_offered
) {
7966 memcpy(r
->out
.data
, val
->data
->data
,
7967 MIN(val
->data_length
,r
->in
.data_offered
));
7970 *r
->out
.data_needed
= val
->data_length
;
7978 /****************************************************************
7979 _spoolss_SetPrinterData
7980 ****************************************************************/
7982 WERROR
_spoolss_SetPrinterData(struct pipes_struct
*p
,
7983 struct spoolss_SetPrinterData
*r
)
7985 struct spoolss_SetPrinterDataEx r2
;
7987 r2
.in
.handle
= r
->in
.handle
;
7988 r2
.in
.key_name
= "PrinterDriverData";
7989 r2
.in
.value_name
= r
->in
.value_name
;
7990 r2
.in
.type
= r
->in
.type
;
7991 r2
.in
.data
= r
->in
.data
;
7992 r2
.in
.offered
= r
->in
.offered
;
7994 return _spoolss_SetPrinterDataEx(p
, &r2
);
7997 /****************************************************************
7998 _spoolss_ResetPrinter
7999 ****************************************************************/
8001 WERROR
_spoolss_ResetPrinter(struct pipes_struct
*p
,
8002 struct spoolss_ResetPrinter
*r
)
8004 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8007 DEBUG(5,("_spoolss_ResetPrinter\n"));
8010 * All we do is to check to see if the handle and queue is valid.
8011 * This call really doesn't mean anything to us because we only
8012 * support RAW printing. --jerry
8016 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8017 OUR_HANDLE(r
->in
.handle
)));
8021 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8025 /* blindly return success */
8029 /****************************************************************
8030 _spoolss_DeletePrinterData
8031 ****************************************************************/
8033 WERROR
_spoolss_DeletePrinterData(struct pipes_struct
*p
,
8034 struct spoolss_DeletePrinterData
*r
)
8036 struct spoolss_DeletePrinterDataEx r2
;
8038 r2
.in
.handle
= r
->in
.handle
;
8039 r2
.in
.key_name
= "PrinterDriverData";
8040 r2
.in
.value_name
= r
->in
.value_name
;
8042 return _spoolss_DeletePrinterDataEx(p
, &r2
);
8045 /****************************************************************
8047 ****************************************************************/
8049 WERROR
_spoolss_AddForm(struct pipes_struct
*p
,
8050 struct spoolss_AddForm
*r
)
8052 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8054 WERROR status
= WERR_OK
;
8055 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8057 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8059 DEBUG(5,("_spoolss_AddForm\n"));
8062 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8063 OUR_HANDLE(r
->in
.handle
)));
8067 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8068 and not a printer admin, then fail */
8070 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8071 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8072 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8073 p
->server_info
->info3
->base
.domain
.string
,
8075 p
->server_info
->ptok
,
8076 lp_printer_admin(snum
))) {
8077 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8078 return WERR_ACCESS_DENIED
;
8081 switch (form
->flags
) {
8082 case SPOOLSS_FORM_USER
:
8083 case SPOOLSS_FORM_BUILTIN
:
8084 case SPOOLSS_FORM_PRINTER
:
8087 return WERR_INVALID_PARAM
;
8090 status
= winreg_printer_addform1(p
->mem_ctx
, p
->server_info
,
8092 if (!W_ERROR_IS_OK(status
)) {
8097 * ChangeID must always be set if this is a printer
8099 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8100 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8104 status
= winreg_printer_update_changeid(p
->mem_ctx
,
8107 lp_const_servicename(snum
));
8108 if (!W_ERROR_IS_OK(status
)) {
8116 /****************************************************************
8118 ****************************************************************/
8120 WERROR
_spoolss_DeleteForm(struct pipes_struct
*p
,
8121 struct spoolss_DeleteForm
*r
)
8123 const char *form_name
= r
->in
.form_name
;
8124 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8126 WERROR status
= WERR_OK
;
8127 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8129 DEBUG(5,("_spoolss_DeleteForm\n"));
8132 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8133 OUR_HANDLE(r
->in
.handle
)));
8137 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8138 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8139 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8140 p
->server_info
->info3
->base
.domain
.string
,
8142 p
->server_info
->ptok
,
8143 lp_printer_admin(snum
))) {
8144 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8145 return WERR_ACCESS_DENIED
;
8148 status
= winreg_printer_deleteform1(p
->mem_ctx
,
8152 if (!W_ERROR_IS_OK(status
)) {
8157 * ChangeID must always be set if this is a printer
8159 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8160 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8164 status
= winreg_printer_update_changeid(p
->mem_ctx
,
8167 lp_const_servicename(snum
));
8168 if (!W_ERROR_IS_OK(status
)) {
8176 /****************************************************************
8178 ****************************************************************/
8180 WERROR
_spoolss_SetForm(struct pipes_struct
*p
,
8181 struct spoolss_SetForm
*r
)
8183 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8184 const char *form_name
= r
->in
.form_name
;
8186 WERROR status
= WERR_OK
;
8187 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
8189 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8191 DEBUG(5,("_spoolss_SetForm\n"));
8194 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8195 OUR_HANDLE(r
->in
.handle
)));
8199 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8200 and not a printer admin, then fail */
8202 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8203 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8204 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8205 p
->server_info
->info3
->base
.domain
.string
,
8207 p
->server_info
->ptok
,
8208 lp_printer_admin(snum
))) {
8209 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8210 return WERR_ACCESS_DENIED
;
8213 status
= winreg_printer_setform1(p
->mem_ctx
,
8218 if (!W_ERROR_IS_OK(status
)) {
8223 * ChangeID must always be set if this is a printer
8225 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8226 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8230 status
= winreg_printer_update_changeid(p
->mem_ctx
,
8233 lp_const_servicename(snum
));
8234 if (!W_ERROR_IS_OK(status
)) {
8242 /****************************************************************************
8243 fill_print_processor1
8244 ****************************************************************************/
8246 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8247 struct spoolss_PrintProcessorInfo1
*r
,
8248 const char *print_processor_name
)
8250 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8251 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8256 /****************************************************************************
8257 enumprintprocessors level 1.
8258 ****************************************************************************/
8260 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8261 union spoolss_PrintProcessorInfo
**info_p
,
8264 union spoolss_PrintProcessorInfo
*info
;
8267 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8268 W_ERROR_HAVE_NO_MEMORY(info
);
8272 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8273 if (!W_ERROR_IS_OK(result
)) {
8278 if (!W_ERROR_IS_OK(result
)) {
8289 /****************************************************************
8290 _spoolss_EnumPrintProcessors
8291 ****************************************************************/
8293 WERROR
_spoolss_EnumPrintProcessors(struct pipes_struct
*p
,
8294 struct spoolss_EnumPrintProcessors
*r
)
8298 /* that's an [in out] buffer */
8300 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8301 return WERR_INVALID_PARAM
;
8304 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8307 * Enumerate the print processors ...
8309 * Just reply with "winprint", to keep NT happy
8310 * and I can use my nice printer checker.
8315 *r
->out
.info
= NULL
;
8317 switch (r
->in
.level
) {
8319 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8323 return WERR_UNKNOWN_LEVEL
;
8326 if (!W_ERROR_IS_OK(result
)) {
8330 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8331 spoolss_EnumPrintProcessors
,
8332 *r
->out
.info
, r
->in
.level
,
8334 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8335 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8337 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8340 /****************************************************************************
8341 fill_printprocdatatype1
8342 ****************************************************************************/
8344 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8345 struct spoolss_PrintProcDataTypesInfo1
*r
,
8346 const char *name_array
)
8348 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8349 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8354 /****************************************************************************
8355 enumprintprocdatatypes level 1.
8356 ****************************************************************************/
8358 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8359 union spoolss_PrintProcDataTypesInfo
**info_p
,
8363 union spoolss_PrintProcDataTypesInfo
*info
;
8365 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8366 W_ERROR_HAVE_NO_MEMORY(info
);
8370 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8371 if (!W_ERROR_IS_OK(result
)) {
8376 if (!W_ERROR_IS_OK(result
)) {
8387 /****************************************************************
8388 _spoolss_EnumPrintProcDataTypes
8389 ****************************************************************/
8391 WERROR
_spoolss_EnumPrintProcDataTypes(struct pipes_struct
*p
,
8392 struct spoolss_EnumPrintProcDataTypes
*r
)
8396 /* that's an [in out] buffer */
8398 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8399 return WERR_INVALID_PARAM
;
8402 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8406 *r
->out
.info
= NULL
;
8408 switch (r
->in
.level
) {
8410 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8414 return WERR_UNKNOWN_LEVEL
;
8417 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8418 spoolss_EnumPrintProcDataTypes
,
8419 *r
->out
.info
, r
->in
.level
,
8421 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8422 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8424 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8427 /****************************************************************************
8429 ****************************************************************************/
8431 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8432 struct spoolss_MonitorInfo1
*r
,
8433 const char *monitor_name
)
8435 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8436 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8441 /****************************************************************************
8443 ****************************************************************************/
8445 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8446 struct spoolss_MonitorInfo2
*r
,
8447 const char *monitor_name
,
8448 const char *environment
,
8449 const char *dll_name
)
8451 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8452 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8453 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8454 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8455 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8456 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8461 /****************************************************************************
8462 enumprintmonitors level 1.
8463 ****************************************************************************/
8465 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8466 union spoolss_MonitorInfo
**info_p
,
8469 union spoolss_MonitorInfo
*info
;
8470 WERROR result
= WERR_OK
;
8472 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8473 W_ERROR_HAVE_NO_MEMORY(info
);
8477 result
= fill_monitor_1(info
, &info
[0].info1
,
8479 if (!W_ERROR_IS_OK(result
)) {
8483 result
= fill_monitor_1(info
, &info
[1].info1
,
8485 if (!W_ERROR_IS_OK(result
)) {
8490 if (!W_ERROR_IS_OK(result
)) {
8501 /****************************************************************************
8502 enumprintmonitors level 2.
8503 ****************************************************************************/
8505 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8506 union spoolss_MonitorInfo
**info_p
,
8509 union spoolss_MonitorInfo
*info
;
8510 WERROR result
= WERR_OK
;
8512 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8513 W_ERROR_HAVE_NO_MEMORY(info
);
8517 result
= fill_monitor_2(info
, &info
[0].info2
,
8519 "Windows NT X86", /* FIXME */
8521 if (!W_ERROR_IS_OK(result
)) {
8525 result
= fill_monitor_2(info
, &info
[1].info2
,
8527 "Windows NT X86", /* FIXME */
8529 if (!W_ERROR_IS_OK(result
)) {
8534 if (!W_ERROR_IS_OK(result
)) {
8545 /****************************************************************
8546 _spoolss_EnumMonitors
8547 ****************************************************************/
8549 WERROR
_spoolss_EnumMonitors(struct pipes_struct
*p
,
8550 struct spoolss_EnumMonitors
*r
)
8554 /* that's an [in out] buffer */
8556 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8557 return WERR_INVALID_PARAM
;
8560 DEBUG(5,("_spoolss_EnumMonitors\n"));
8563 * Enumerate the print monitors ...
8565 * Just reply with "Local Port", to keep NT happy
8566 * and I can use my nice printer checker.
8571 *r
->out
.info
= NULL
;
8573 switch (r
->in
.level
) {
8575 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8579 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8583 return WERR_UNKNOWN_LEVEL
;
8586 if (!W_ERROR_IS_OK(result
)) {
8590 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8591 spoolss_EnumMonitors
,
8592 *r
->out
.info
, r
->in
.level
,
8594 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8595 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8597 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8600 /****************************************************************************
8601 ****************************************************************************/
8603 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8604 const print_queue_struct
*queue
,
8605 int count
, int snum
,
8606 struct spoolss_PrinterInfo2
*pinfo2
,
8608 struct spoolss_JobInfo1
*r
)
8613 for (i
=0; i
<count
; i
++) {
8614 if (queue
[i
].job
== (int)jobid
) {
8620 if (found
== false) {
8621 /* NT treats not found as bad param... yet another bad choice */
8622 return WERR_INVALID_PARAM
;
8625 return fill_job_info1(mem_ctx
,
8633 /****************************************************************************
8634 ****************************************************************************/
8636 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8637 const print_queue_struct
*queue
,
8638 int count
, int snum
,
8639 struct spoolss_PrinterInfo2
*pinfo2
,
8641 struct spoolss_JobInfo2
*r
)
8645 struct spoolss_DeviceMode
*devmode
;
8648 for (i
=0; i
<count
; i
++) {
8649 if (queue
[i
].job
== (int)jobid
) {
8655 if (found
== false) {
8656 /* NT treats not found as bad param... yet another bad
8658 return WERR_INVALID_PARAM
;
8662 * if the print job does not have a DEVMODE associated with it,
8663 * just use the one for the printer. A NULL devicemode is not
8664 * a failure condition
8667 devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8669 result
= spoolss_create_default_devmode(mem_ctx
,
8670 pinfo2
->printername
,
8672 if (!W_ERROR_IS_OK(result
)) {
8673 DEBUG(3, ("Can't proceed w/o a devmode!"));
8678 return fill_job_info2(mem_ctx
,
8687 /****************************************************************
8689 ****************************************************************/
8691 WERROR
_spoolss_GetJob(struct pipes_struct
*p
,
8692 struct spoolss_GetJob
*r
)
8694 WERROR result
= WERR_OK
;
8695 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
8698 print_queue_struct
*queue
= NULL
;
8699 print_status_struct prt_status
;
8701 /* that's an [in out] buffer */
8703 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8704 return WERR_INVALID_PARAM
;
8707 DEBUG(5,("_spoolss_GetJob\n"));
8711 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8715 result
= winreg_get_printer(p
->mem_ctx
, p
->server_info
, p
->msg_ctx
,
8716 NULL
, lp_servicename(snum
), &pinfo2
);
8717 if (!W_ERROR_IS_OK(result
)) {
8721 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
8723 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8724 count
, prt_status
.status
, prt_status
.message
));
8726 switch (r
->in
.level
) {
8728 result
= getjob_level_1(p
->mem_ctx
,
8729 queue
, count
, snum
, pinfo2
,
8730 r
->in
.job_id
, &r
->out
.info
->info1
);
8733 result
= getjob_level_2(p
->mem_ctx
,
8734 queue
, count
, snum
, pinfo2
,
8735 r
->in
.job_id
, &r
->out
.info
->info2
);
8738 result
= WERR_UNKNOWN_LEVEL
;
8743 TALLOC_FREE(pinfo2
);
8745 if (!W_ERROR_IS_OK(result
)) {
8746 TALLOC_FREE(r
->out
.info
);
8750 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
8752 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8754 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8757 /****************************************************************
8758 _spoolss_GetPrinterDataEx
8759 ****************************************************************/
8761 WERROR
_spoolss_GetPrinterDataEx(struct pipes_struct
*p
,
8762 struct spoolss_GetPrinterDataEx
*r
)
8765 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8766 const char *printer
;
8768 WERROR result
= WERR_OK
;
8770 enum winreg_Type val_type
;
8775 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8777 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8778 r
->in
.key_name
, r
->in
.value_name
));
8780 /* in case of problem, return some default values */
8783 *r
->out
.type
= REG_NONE
;
8786 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8787 OUR_HANDLE(r
->in
.handle
)));
8788 result
= WERR_BADFID
;
8792 /* Is the handle to a printer or to the server? */
8794 if (Printer
->printer_type
== SPLHND_SERVER
) {
8796 union spoolss_PrinterData data
;
8798 result
= getprinterdata_printer_server(p
->mem_ctx
,
8802 if (!W_ERROR_IS_OK(result
)) {
8806 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
8807 *r
->out
.type
, &data
);
8808 if (!W_ERROR_IS_OK(result
)) {
8812 *r
->out
.needed
= blob
.length
;
8814 if (r
->in
.offered
>= *r
->out
.needed
) {
8815 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
8818 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8821 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8824 printer
= lp_const_servicename(snum
);
8826 /* check to see if the keyname is valid */
8827 if (!strlen(r
->in
.key_name
)) {
8828 return WERR_INVALID_PARAM
;
8831 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8832 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
8833 strequal(r
->in
.value_name
, "ChangeId")) {
8834 *r
->out
.type
= REG_DWORD
;
8836 if (r
->in
.offered
>= *r
->out
.needed
) {
8837 uint32_t changeid
= 0;
8839 result
= winreg_printer_get_changeid(p
->mem_ctx
,
8844 if (!W_ERROR_IS_OK(result
)) {
8848 SIVAL(r
->out
.data
, 0, changeid
);
8854 result
= winreg_get_printer_dataex(p
->mem_ctx
,
8863 if (!W_ERROR_IS_OK(result
)) {
8867 *r
->out
.needed
= val_size
;
8868 *r
->out
.type
= val_type
;
8870 if (r
->in
.offered
>= *r
->out
.needed
) {
8871 memcpy(r
->out
.data
, val_data
, val_size
);
8875 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
8876 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
8878 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8881 /****************************************************************
8882 _spoolss_SetPrinterDataEx
8883 ****************************************************************/
8885 WERROR
_spoolss_SetPrinterDataEx(struct pipes_struct
*p
,
8886 struct spoolss_SetPrinterDataEx
*r
)
8888 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
8890 WERROR result
= WERR_OK
;
8891 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8894 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8896 /* From MSDN documentation of SetPrinterDataEx: pass request to
8897 SetPrinterData if key is "PrinterDriverData" */
8900 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8901 OUR_HANDLE(r
->in
.handle
)));
8905 if (Printer
->printer_type
== SPLHND_SERVER
) {
8906 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8907 "Not implemented for server handles yet\n"));
8908 return WERR_INVALID_PARAM
;
8911 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8916 * Access check : NT returns "access denied" if you make a
8917 * SetPrinterData call without the necessary privildge.
8918 * we were originally returning OK if nothing changed
8919 * which made Win2k issue **a lot** of SetPrinterData
8920 * when connecting to a printer --jerry
8923 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8924 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8925 "change denied by handle access permissions\n"));
8926 return WERR_ACCESS_DENIED
;
8929 result
= winreg_get_printer(Printer
, p
->server_info
, p
->msg_ctx
,
8930 Printer
->servername
,
8931 lp_servicename(snum
),
8933 if (!W_ERROR_IS_OK(result
)) {
8937 /* check for OID in valuename */
8939 oid_string
= strchr(r
->in
.value_name
, ',');
8945 /* save the registry data */
8947 result
= winreg_set_printer_dataex(p
->mem_ctx
,
8957 if (W_ERROR_IS_OK(result
)) {
8958 /* save the OID if one was specified */
8960 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
8961 r
->in
.key_name
, SPOOL_OID_KEY
);
8963 result
= WERR_NOMEM
;
8968 * I'm not checking the status here on purpose. Don't know
8969 * if this is right, but I'm returning the status from the
8970 * previous set_printer_dataex() call. I have no idea if
8971 * this is right. --jerry
8973 winreg_set_printer_dataex(p
->mem_ctx
,
8980 (uint8_t *) oid_string
,
8981 strlen(oid_string
) + 1);
8984 result
= winreg_printer_update_changeid(p
->mem_ctx
,
8987 lp_const_servicename(snum
));
8992 talloc_free(pinfo2
);
8996 /****************************************************************
8997 _spoolss_DeletePrinterDataEx
8998 ****************************************************************/
9000 WERROR
_spoolss_DeletePrinterDataEx(struct pipes_struct
*p
,
9001 struct spoolss_DeletePrinterDataEx
*r
)
9003 const char *printer
;
9005 WERROR status
= WERR_OK
;
9006 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9008 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9011 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9012 "Invalid handle (%s:%u:%u).\n",
9013 OUR_HANDLE(r
->in
.handle
)));
9017 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9018 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9019 "printer properties change denied by handle\n"));
9020 return WERR_ACCESS_DENIED
;
9023 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9027 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9030 printer
= lp_const_servicename(snum
);
9032 status
= winreg_delete_printer_dataex(p
->mem_ctx
,
9038 if (W_ERROR_IS_OK(status
)) {
9039 status
= winreg_printer_update_changeid(p
->mem_ctx
,
9048 /****************************************************************
9049 _spoolss_EnumPrinterKey
9050 ****************************************************************/
9052 WERROR
_spoolss_EnumPrinterKey(struct pipes_struct
*p
,
9053 struct spoolss_EnumPrinterKey
*r
)
9056 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9058 WERROR result
= WERR_BADFILE
;
9059 const char **array
= NULL
;
9062 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9065 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9066 OUR_HANDLE(r
->in
.handle
)));
9070 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9074 result
= winreg_enum_printer_key(p
->mem_ctx
,
9077 lp_const_servicename(snum
),
9081 if (!W_ERROR_IS_OK(result
)) {
9085 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9086 result
= WERR_NOMEM
;
9090 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
9091 *r
->out
.needed
= blob
.length
;
9093 if (r
->in
.offered
< *r
->out
.needed
) {
9094 result
= WERR_MORE_DATA
;
9097 r
->out
.key_buffer
->string_array
= array
;
9101 if (!W_ERROR_IS_OK(result
)) {
9103 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9111 /****************************************************************
9112 _spoolss_DeletePrinterKey
9113 ****************************************************************/
9115 WERROR
_spoolss_DeletePrinterKey(struct pipes_struct
*p
,
9116 struct spoolss_DeletePrinterKey
*r
)
9118 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9121 const char *printer
;
9123 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9126 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9127 OUR_HANDLE(r
->in
.handle
)));
9131 /* if keyname == NULL, return error */
9132 if ( !r
->in
.key_name
)
9133 return WERR_INVALID_PARAM
;
9135 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9139 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9140 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9141 "printer properties change denied by handle\n"));
9142 return WERR_ACCESS_DENIED
;
9145 printer
= lp_const_servicename(snum
);
9147 /* delete the key and all subkeys */
9148 status
= winreg_delete_printer_key(p
->mem_ctx
,
9153 if (W_ERROR_IS_OK(status
)) {
9154 status
= winreg_printer_update_changeid(p
->mem_ctx
,
9163 /****************************************************************
9164 _spoolss_EnumPrinterDataEx
9165 ****************************************************************/
9167 WERROR
_spoolss_EnumPrinterDataEx(struct pipes_struct
*p
,
9168 struct spoolss_EnumPrinterDataEx
*r
)
9171 struct spoolss_PrinterEnumValues
*info
= NULL
;
9172 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9176 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9180 *r
->out
.info
= NULL
;
9183 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9184 OUR_HANDLE(r
->in
.handle
)));
9189 * first check for a keyname of NULL or "". Win2k seems to send
9190 * this a lot and we should send back WERR_INVALID_PARAM
9191 * no need to spend time looking up the printer in this case.
9195 if (!strlen(r
->in
.key_name
)) {
9196 result
= WERR_INVALID_PARAM
;
9200 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9204 /* now look for a match on the key name */
9205 result
= winreg_enum_printer_dataex(p
->mem_ctx
,
9208 lp_const_servicename(snum
),
9212 if (!W_ERROR_IS_OK(result
)) {
9216 #if 0 /* FIXME - gd */
9217 /* housekeeping information in the reply */
9219 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9220 * the hand marshalled container size is a multiple
9221 * of 4 bytes for RPC alignment.
9225 needed
+= 4-(needed
% 4);
9228 *r
->out
.count
= count
;
9229 *r
->out
.info
= info
;
9232 if (!W_ERROR_IS_OK(result
)) {
9236 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9237 spoolss_EnumPrinterDataEx
,
9240 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9241 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9243 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9246 /****************************************************************************
9247 ****************************************************************************/
9249 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9250 const char *servername
,
9251 const char *environment
,
9252 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9257 werr
= compose_spoolss_server_path(mem_ctx
,
9260 SPOOLSS_PRTPROCS_PATH
,
9262 if (!W_ERROR_IS_OK(werr
)) {
9266 DEBUG(4,("print processor directory: [%s]\n", path
));
9268 r
->directory_name
= path
;
9273 /****************************************************************
9274 _spoolss_GetPrintProcessorDirectory
9275 ****************************************************************/
9277 WERROR
_spoolss_GetPrintProcessorDirectory(struct pipes_struct
*p
,
9278 struct spoolss_GetPrintProcessorDirectory
*r
)
9282 /* that's an [in out] buffer */
9284 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9285 return WERR_INVALID_PARAM
;
9288 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9293 /* r->in.level is ignored */
9295 /* We always should reply with a local print processor directory so that
9296 * users are not forced to have a [prnproc$] share on the Samba spoolss
9297 * server - Guenther */
9299 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9300 NULL
, /* r->in.server */
9302 &r
->out
.info
->info1
);
9303 if (!W_ERROR_IS_OK(result
)) {
9304 TALLOC_FREE(r
->out
.info
);
9308 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9309 r
->out
.info
, r
->in
.level
);
9310 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9312 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9315 /*******************************************************************
9316 ********************************************************************/
9318 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9319 const char *dllname
)
9321 enum ndr_err_code ndr_err
;
9322 struct spoolss_MonitorUi ui
;
9324 ui
.dll_name
= dllname
;
9326 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9327 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9328 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9329 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9331 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9334 /*******************************************************************
9335 Streams the monitor UI DLL name in UNICODE
9336 *******************************************************************/
9338 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9339 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9340 DATA_BLOB
*out
, uint32_t *needed
)
9342 const char *dllname
= "tcpmonui.dll";
9344 *needed
= (strlen(dllname
)+1) * 2;
9346 if (out
->length
< *needed
) {
9347 return WERR_INSUFFICIENT_BUFFER
;
9350 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9357 /*******************************************************************
9358 ********************************************************************/
9360 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9361 struct spoolss_PortData1
*port1
,
9362 const DATA_BLOB
*buf
)
9364 enum ndr_err_code ndr_err
;
9365 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9366 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9367 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9368 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9370 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9373 /*******************************************************************
9374 ********************************************************************/
9376 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9377 struct spoolss_PortData2
*port2
,
9378 const DATA_BLOB
*buf
)
9380 enum ndr_err_code ndr_err
;
9381 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9382 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9383 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9384 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9386 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9389 /*******************************************************************
9390 Create a new TCP/IP port
9391 *******************************************************************/
9393 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9394 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9395 DATA_BLOB
*out
, uint32_t *needed
)
9397 struct spoolss_PortData1 port1
;
9398 struct spoolss_PortData2 port2
;
9399 char *device_uri
= NULL
;
9402 const char *portname
;
9403 const char *hostaddress
;
9405 uint32_t port_number
;
9408 /* peek for spoolss_PortData version */
9410 if (!in
|| (in
->length
< (128 + 4))) {
9411 return WERR_GENERAL_FAILURE
;
9414 version
= IVAL(in
->data
, 128);
9420 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9424 portname
= port1
.portname
;
9425 hostaddress
= port1
.hostaddress
;
9426 queue
= port1
.queue
;
9427 protocol
= port1
.protocol
;
9428 port_number
= port1
.port_number
;
9434 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9438 portname
= port2
.portname
;
9439 hostaddress
= port2
.hostaddress
;
9440 queue
= port2
.queue
;
9441 protocol
= port2
.protocol
;
9442 port_number
= port2
.port_number
;
9446 DEBUG(1,("xcvtcp_addport: "
9447 "unknown version of port_data: %d\n", version
));
9448 return WERR_UNKNOWN_PORT
;
9451 /* create the device URI and call the add_port_hook() */
9454 case PROTOCOL_RAWTCP_TYPE
:
9455 device_uri
= talloc_asprintf(mem_ctx
,
9456 "socket://%s:%d/", hostaddress
,
9460 case PROTOCOL_LPR_TYPE
:
9461 device_uri
= talloc_asprintf(mem_ctx
,
9462 "lpr://%s/%s", hostaddress
, queue
);
9466 return WERR_UNKNOWN_PORT
;
9473 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9476 /*******************************************************************
9477 *******************************************************************/
9479 struct xcv_api_table xcvtcp_cmds
[] = {
9480 { "MonitorUI", xcvtcp_monitorui
},
9481 { "AddPort", xcvtcp_addport
},
9485 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9486 NT_USER_TOKEN
*token
, const char *command
,
9493 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9495 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9496 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9497 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9500 return WERR_BADFUNC
;
9503 /*******************************************************************
9504 *******************************************************************/
9505 #if 0 /* don't support management using the "Local Port" monitor */
9507 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9508 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9509 DATA_BLOB
*out
, uint32_t *needed
)
9511 const char *dllname
= "localui.dll";
9513 *needed
= (strlen(dllname
)+1) * 2;
9515 if (out
->length
< *needed
) {
9516 return WERR_INSUFFICIENT_BUFFER
;
9519 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9526 /*******************************************************************
9527 *******************************************************************/
9529 struct xcv_api_table xcvlocal_cmds
[] = {
9530 { "MonitorUI", xcvlocal_monitorui
},
9534 struct xcv_api_table xcvlocal_cmds
[] = {
9541 /*******************************************************************
9542 *******************************************************************/
9544 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9545 NT_USER_TOKEN
*token
, const char *command
,
9546 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9551 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9553 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9554 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9555 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9557 return WERR_BADFUNC
;
9560 /****************************************************************
9562 ****************************************************************/
9564 WERROR
_spoolss_XcvData(struct pipes_struct
*p
,
9565 struct spoolss_XcvData
*r
)
9567 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9568 DATA_BLOB out_data
= data_blob_null
;
9572 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9573 OUR_HANDLE(r
->in
.handle
)));
9577 /* Has to be a handle to the TCP/IP port monitor */
9579 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9580 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9584 /* requires administrative access to the server */
9586 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9587 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9588 return WERR_ACCESS_DENIED
;
9591 /* Allocate the outgoing buffer */
9593 if (r
->in
.out_data_size
) {
9594 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9595 if (out_data
.data
== NULL
) {
9600 switch ( Printer
->printer_type
) {
9601 case SPLHND_PORTMON_TCP
:
9602 werror
= process_xcvtcp_command(p
->mem_ctx
,
9603 p
->server_info
->ptok
,
9604 r
->in
.function_name
,
9605 &r
->in
.in_data
, &out_data
,
9608 case SPLHND_PORTMON_LOCAL
:
9609 werror
= process_xcvlocal_command(p
->mem_ctx
,
9610 p
->server_info
->ptok
,
9611 r
->in
.function_name
,
9612 &r
->in
.in_data
, &out_data
,
9616 werror
= WERR_INVALID_PRINT_MONITOR
;
9619 if (!W_ERROR_IS_OK(werror
)) {
9623 *r
->out
.status_code
= 0;
9625 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
9626 memcpy(r
->out
.out_data
, out_data
.data
,
9627 MIN(r
->in
.out_data_size
, out_data
.length
));
9633 /****************************************************************
9634 _spoolss_AddPrintProcessor
9635 ****************************************************************/
9637 WERROR
_spoolss_AddPrintProcessor(struct pipes_struct
*p
,
9638 struct spoolss_AddPrintProcessor
*r
)
9640 /* for now, just indicate success and ignore the add. We'll
9641 automatically set the winprint processor for printer
9642 entries later. Used to debug the LexMark Optra S 1855 PCL
9648 /****************************************************************
9650 ****************************************************************/
9652 WERROR
_spoolss_AddPort(struct pipes_struct
*p
,
9653 struct spoolss_AddPort
*r
)
9655 /* do what w2k3 does */
9657 return WERR_NOT_SUPPORTED
;
9660 /****************************************************************
9661 _spoolss_GetPrinterDriver
9662 ****************************************************************/
9664 WERROR
_spoolss_GetPrinterDriver(struct pipes_struct
*p
,
9665 struct spoolss_GetPrinterDriver
*r
)
9667 p
->rng_fault_state
= true;
9668 return WERR_NOT_SUPPORTED
;
9671 /****************************************************************
9672 _spoolss_ReadPrinter
9673 ****************************************************************/
9675 WERROR
_spoolss_ReadPrinter(struct pipes_struct
*p
,
9676 struct spoolss_ReadPrinter
*r
)
9678 p
->rng_fault_state
= true;
9679 return WERR_NOT_SUPPORTED
;
9682 /****************************************************************
9683 _spoolss_WaitForPrinterChange
9684 ****************************************************************/
9686 WERROR
_spoolss_WaitForPrinterChange(struct pipes_struct
*p
,
9687 struct spoolss_WaitForPrinterChange
*r
)
9689 p
->rng_fault_state
= true;
9690 return WERR_NOT_SUPPORTED
;
9693 /****************************************************************
9694 _spoolss_ConfigurePort
9695 ****************************************************************/
9697 WERROR
_spoolss_ConfigurePort(struct pipes_struct
*p
,
9698 struct spoolss_ConfigurePort
*r
)
9700 p
->rng_fault_state
= true;
9701 return WERR_NOT_SUPPORTED
;
9704 /****************************************************************
9706 ****************************************************************/
9708 WERROR
_spoolss_DeletePort(struct pipes_struct
*p
,
9709 struct spoolss_DeletePort
*r
)
9711 p
->rng_fault_state
= true;
9712 return WERR_NOT_SUPPORTED
;
9715 /****************************************************************
9716 _spoolss_CreatePrinterIC
9717 ****************************************************************/
9719 WERROR
_spoolss_CreatePrinterIC(struct pipes_struct
*p
,
9720 struct spoolss_CreatePrinterIC
*r
)
9722 p
->rng_fault_state
= true;
9723 return WERR_NOT_SUPPORTED
;
9726 /****************************************************************
9727 _spoolss_PlayGDIScriptOnPrinterIC
9728 ****************************************************************/
9730 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct
*p
,
9731 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
9733 p
->rng_fault_state
= true;
9734 return WERR_NOT_SUPPORTED
;
9737 /****************************************************************
9738 _spoolss_DeletePrinterIC
9739 ****************************************************************/
9741 WERROR
_spoolss_DeletePrinterIC(struct pipes_struct
*p
,
9742 struct spoolss_DeletePrinterIC
*r
)
9744 p
->rng_fault_state
= true;
9745 return WERR_NOT_SUPPORTED
;
9748 /****************************************************************
9749 _spoolss_AddPrinterConnection
9750 ****************************************************************/
9752 WERROR
_spoolss_AddPrinterConnection(struct pipes_struct
*p
,
9753 struct spoolss_AddPrinterConnection
*r
)
9755 p
->rng_fault_state
= true;
9756 return WERR_NOT_SUPPORTED
;
9759 /****************************************************************
9760 _spoolss_DeletePrinterConnection
9761 ****************************************************************/
9763 WERROR
_spoolss_DeletePrinterConnection(struct pipes_struct
*p
,
9764 struct spoolss_DeletePrinterConnection
*r
)
9766 p
->rng_fault_state
= true;
9767 return WERR_NOT_SUPPORTED
;
9770 /****************************************************************
9771 _spoolss_PrinterMessageBox
9772 ****************************************************************/
9774 WERROR
_spoolss_PrinterMessageBox(struct pipes_struct
*p
,
9775 struct spoolss_PrinterMessageBox
*r
)
9777 p
->rng_fault_state
= true;
9778 return WERR_NOT_SUPPORTED
;
9781 /****************************************************************
9783 ****************************************************************/
9785 WERROR
_spoolss_AddMonitor(struct pipes_struct
*p
,
9786 struct spoolss_AddMonitor
*r
)
9788 p
->rng_fault_state
= true;
9789 return WERR_NOT_SUPPORTED
;
9792 /****************************************************************
9793 _spoolss_DeleteMonitor
9794 ****************************************************************/
9796 WERROR
_spoolss_DeleteMonitor(struct pipes_struct
*p
,
9797 struct spoolss_DeleteMonitor
*r
)
9799 p
->rng_fault_state
= true;
9800 return WERR_NOT_SUPPORTED
;
9803 /****************************************************************
9804 _spoolss_DeletePrintProcessor
9805 ****************************************************************/
9807 WERROR
_spoolss_DeletePrintProcessor(struct pipes_struct
*p
,
9808 struct spoolss_DeletePrintProcessor
*r
)
9810 p
->rng_fault_state
= true;
9811 return WERR_NOT_SUPPORTED
;
9814 /****************************************************************
9815 _spoolss_AddPrintProvidor
9816 ****************************************************************/
9818 WERROR
_spoolss_AddPrintProvidor(struct pipes_struct
*p
,
9819 struct spoolss_AddPrintProvidor
*r
)
9821 p
->rng_fault_state
= true;
9822 return WERR_NOT_SUPPORTED
;
9825 /****************************************************************
9826 _spoolss_DeletePrintProvidor
9827 ****************************************************************/
9829 WERROR
_spoolss_DeletePrintProvidor(struct pipes_struct
*p
,
9830 struct spoolss_DeletePrintProvidor
*r
)
9832 p
->rng_fault_state
= true;
9833 return WERR_NOT_SUPPORTED
;
9836 /****************************************************************
9837 _spoolss_FindFirstPrinterChangeNotification
9838 ****************************************************************/
9840 WERROR
_spoolss_FindFirstPrinterChangeNotification(struct pipes_struct
*p
,
9841 struct spoolss_FindFirstPrinterChangeNotification
*r
)
9843 p
->rng_fault_state
= true;
9844 return WERR_NOT_SUPPORTED
;
9847 /****************************************************************
9848 _spoolss_FindNextPrinterChangeNotification
9849 ****************************************************************/
9851 WERROR
_spoolss_FindNextPrinterChangeNotification(struct pipes_struct
*p
,
9852 struct spoolss_FindNextPrinterChangeNotification
*r
)
9854 p
->rng_fault_state
= true;
9855 return WERR_NOT_SUPPORTED
;
9858 /****************************************************************
9859 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9860 ****************************************************************/
9862 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct
*p
,
9863 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
9865 p
->rng_fault_state
= true;
9866 return WERR_NOT_SUPPORTED
;
9869 /****************************************************************
9870 _spoolss_ReplyOpenPrinter
9871 ****************************************************************/
9873 WERROR
_spoolss_ReplyOpenPrinter(struct pipes_struct
*p
,
9874 struct spoolss_ReplyOpenPrinter
*r
)
9876 p
->rng_fault_state
= true;
9877 return WERR_NOT_SUPPORTED
;
9880 /****************************************************************
9881 _spoolss_RouterReplyPrinter
9882 ****************************************************************/
9884 WERROR
_spoolss_RouterReplyPrinter(struct pipes_struct
*p
,
9885 struct spoolss_RouterReplyPrinter
*r
)
9887 p
->rng_fault_state
= true;
9888 return WERR_NOT_SUPPORTED
;
9891 /****************************************************************
9892 _spoolss_ReplyClosePrinter
9893 ****************************************************************/
9895 WERROR
_spoolss_ReplyClosePrinter(struct pipes_struct
*p
,
9896 struct spoolss_ReplyClosePrinter
*r
)
9898 p
->rng_fault_state
= true;
9899 return WERR_NOT_SUPPORTED
;
9902 /****************************************************************
9904 ****************************************************************/
9906 WERROR
_spoolss_AddPortEx(struct pipes_struct
*p
,
9907 struct spoolss_AddPortEx
*r
)
9909 p
->rng_fault_state
= true;
9910 return WERR_NOT_SUPPORTED
;
9913 /****************************************************************
9914 _spoolss_RouterFindFirstPrinterChangeNotification
9915 ****************************************************************/
9917 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct
*p
,
9918 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
9920 p
->rng_fault_state
= true;
9921 return WERR_NOT_SUPPORTED
;
9924 /****************************************************************
9925 _spoolss_SpoolerInit
9926 ****************************************************************/
9928 WERROR
_spoolss_SpoolerInit(struct pipes_struct
*p
,
9929 struct spoolss_SpoolerInit
*r
)
9931 p
->rng_fault_state
= true;
9932 return WERR_NOT_SUPPORTED
;
9935 /****************************************************************
9936 _spoolss_ResetPrinterEx
9937 ****************************************************************/
9939 WERROR
_spoolss_ResetPrinterEx(struct pipes_struct
*p
,
9940 struct spoolss_ResetPrinterEx
*r
)
9942 p
->rng_fault_state
= true;
9943 return WERR_NOT_SUPPORTED
;
9946 /****************************************************************
9947 _spoolss_RouterReplyPrinterEx
9948 ****************************************************************/
9950 WERROR
_spoolss_RouterReplyPrinterEx(struct pipes_struct
*p
,
9951 struct spoolss_RouterReplyPrinterEx
*r
)
9953 p
->rng_fault_state
= true;
9954 return WERR_NOT_SUPPORTED
;
9957 /****************************************************************
9959 ****************************************************************/
9961 WERROR
_spoolss_44(struct pipes_struct
*p
,
9962 struct spoolss_44
*r
)
9964 p
->rng_fault_state
= true;
9965 return WERR_NOT_SUPPORTED
;
9968 /****************************************************************
9970 ****************************************************************/
9972 WERROR
_spoolss_47(struct pipes_struct
*p
,
9973 struct spoolss_47
*r
)
9975 p
->rng_fault_state
= true;
9976 return WERR_NOT_SUPPORTED
;
9979 /****************************************************************
9981 ****************************************************************/
9983 WERROR
_spoolss_4a(struct pipes_struct
*p
,
9984 struct spoolss_4a
*r
)
9986 p
->rng_fault_state
= true;
9987 return WERR_NOT_SUPPORTED
;
9990 /****************************************************************
9992 ****************************************************************/
9994 WERROR
_spoolss_4b(struct pipes_struct
*p
,
9995 struct spoolss_4b
*r
)
9997 p
->rng_fault_state
= true;
9998 return WERR_NOT_SUPPORTED
;
10001 /****************************************************************
10003 ****************************************************************/
10005 WERROR
_spoolss_4c(struct pipes_struct
*p
,
10006 struct spoolss_4c
*r
)
10008 p
->rng_fault_state
= true;
10009 return WERR_NOT_SUPPORTED
;
10012 /****************************************************************
10014 ****************************************************************/
10016 WERROR
_spoolss_53(struct pipes_struct
*p
,
10017 struct spoolss_53
*r
)
10019 p
->rng_fault_state
= true;
10020 return WERR_NOT_SUPPORTED
;
10023 /****************************************************************
10025 ****************************************************************/
10027 WERROR
_spoolss_55(struct pipes_struct
*p
,
10028 struct spoolss_55
*r
)
10030 p
->rng_fault_state
= true;
10031 return WERR_NOT_SUPPORTED
;
10034 /****************************************************************
10036 ****************************************************************/
10038 WERROR
_spoolss_56(struct pipes_struct
*p
,
10039 struct spoolss_56
*r
)
10041 p
->rng_fault_state
= true;
10042 return WERR_NOT_SUPPORTED
;
10045 /****************************************************************
10047 ****************************************************************/
10049 WERROR
_spoolss_57(struct pipes_struct
*p
,
10050 struct spoolss_57
*r
)
10052 p
->rng_fault_state
= true;
10053 return WERR_NOT_SUPPORTED
;
10056 /****************************************************************
10058 ****************************************************************/
10060 WERROR
_spoolss_5a(struct pipes_struct
*p
,
10061 struct spoolss_5a
*r
)
10063 p
->rng_fault_state
= true;
10064 return WERR_NOT_SUPPORTED
;
10067 /****************************************************************
10069 ****************************************************************/
10071 WERROR
_spoolss_5b(struct pipes_struct
*p
,
10072 struct spoolss_5b
*r
)
10074 p
->rng_fault_state
= true;
10075 return WERR_NOT_SUPPORTED
;
10078 /****************************************************************
10080 ****************************************************************/
10082 WERROR
_spoolss_5c(struct pipes_struct
*p
,
10083 struct spoolss_5c
*r
)
10085 p
->rng_fault_state
= true;
10086 return WERR_NOT_SUPPORTED
;
10089 /****************************************************************
10091 ****************************************************************/
10093 WERROR
_spoolss_5d(struct pipes_struct
*p
,
10094 struct spoolss_5d
*r
)
10096 p
->rng_fault_state
= true;
10097 return WERR_NOT_SUPPORTED
;
10100 /****************************************************************
10102 ****************************************************************/
10104 WERROR
_spoolss_5e(struct pipes_struct
*p
,
10105 struct spoolss_5e
*r
)
10107 p
->rng_fault_state
= true;
10108 return WERR_NOT_SUPPORTED
;
10111 /****************************************************************
10113 ****************************************************************/
10115 WERROR
_spoolss_5f(struct pipes_struct
*p
,
10116 struct spoolss_5f
*r
)
10118 p
->rng_fault_state
= true;
10119 return WERR_NOT_SUPPORTED
;
10122 /****************************************************************
10124 ****************************************************************/
10126 WERROR
_spoolss_60(struct pipes_struct
*p
,
10127 struct spoolss_60
*r
)
10129 p
->rng_fault_state
= true;
10130 return WERR_NOT_SUPPORTED
;
10133 /****************************************************************
10135 ****************************************************************/
10137 WERROR
_spoolss_61(struct pipes_struct
*p
,
10138 struct spoolss_61
*r
)
10140 p
->rng_fault_state
= true;
10141 return WERR_NOT_SUPPORTED
;
10144 /****************************************************************
10146 ****************************************************************/
10148 WERROR
_spoolss_62(struct pipes_struct
*p
,
10149 struct spoolss_62
*r
)
10151 p
->rng_fault_state
= true;
10152 return WERR_NOT_SUPPORTED
;
10155 /****************************************************************
10157 ****************************************************************/
10159 WERROR
_spoolss_63(struct pipes_struct
*p
,
10160 struct spoolss_63
*r
)
10162 p
->rng_fault_state
= true;
10163 return WERR_NOT_SUPPORTED
;
10166 /****************************************************************
10168 ****************************************************************/
10170 WERROR
_spoolss_64(struct pipes_struct
*p
,
10171 struct spoolss_64
*r
)
10173 p
->rng_fault_state
= true;
10174 return WERR_NOT_SUPPORTED
;
10177 /****************************************************************
10179 ****************************************************************/
10181 WERROR
_spoolss_65(struct pipes_struct
*p
,
10182 struct spoolss_65
*r
)
10184 p
->rng_fault_state
= true;
10185 return WERR_NOT_SUPPORTED
;
10188 /****************************************************************
10189 _spoolss_GetCorePrinterDrivers
10190 ****************************************************************/
10192 WERROR
_spoolss_GetCorePrinterDrivers(struct pipes_struct
*p
,
10193 struct spoolss_GetCorePrinterDrivers
*r
)
10195 p
->rng_fault_state
= true;
10196 return WERR_NOT_SUPPORTED
;
10199 /****************************************************************
10201 ****************************************************************/
10203 WERROR
_spoolss_67(struct pipes_struct
*p
,
10204 struct spoolss_67
*r
)
10206 p
->rng_fault_state
= true;
10207 return WERR_NOT_SUPPORTED
;
10210 /****************************************************************
10211 _spoolss_GetPrinterDriverPackagePath
10212 ****************************************************************/
10214 WERROR
_spoolss_GetPrinterDriverPackagePath(struct pipes_struct
*p
,
10215 struct spoolss_GetPrinterDriverPackagePath
*r
)
10217 p
->rng_fault_state
= true;
10218 return WERR_NOT_SUPPORTED
;
10221 /****************************************************************
10223 ****************************************************************/
10225 WERROR
_spoolss_69(struct pipes_struct
*p
,
10226 struct spoolss_69
*r
)
10228 p
->rng_fault_state
= true;
10229 return WERR_NOT_SUPPORTED
;
10232 /****************************************************************
10234 ****************************************************************/
10236 WERROR
_spoolss_6a(struct pipes_struct
*p
,
10237 struct spoolss_6a
*r
)
10239 p
->rng_fault_state
= true;
10240 return WERR_NOT_SUPPORTED
;
10243 /****************************************************************
10245 ****************************************************************/
10247 WERROR
_spoolss_6b(struct pipes_struct
*p
,
10248 struct spoolss_6b
*r
)
10250 p
->rng_fault_state
= true;
10251 return WERR_NOT_SUPPORTED
;
10254 /****************************************************************
10256 ****************************************************************/
10258 WERROR
_spoolss_6c(struct pipes_struct
*p
,
10259 struct spoolss_6c
*r
)
10261 p
->rng_fault_state
= true;
10262 return WERR_NOT_SUPPORTED
;
10265 /****************************************************************
10267 ****************************************************************/
10269 WERROR
_spoolss_6d(struct pipes_struct
*p
,
10270 struct spoolss_6d
*r
)
10272 p
->rng_fault_state
= true;
10273 return WERR_NOT_SUPPORTED
;