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. */
32
#include "nt_printing.h"
33
#include "srv_spoolss_util.h"
34
#include "../librpc/gen_ndr/srv_spoolss.h"
35
#include "../librpc/gen_ndr/ndr_spoolss_c.h"
36
#include "rpc_client/init_spoolss.h"
37
#include "rpc_client/cli_pipe.h"
38
#include "../libcli/security/security.h"
39
#include "librpc/gen_ndr/ndr_security.h"
41
#include "registry/reg_objects.h"
42
#include "include/printing.h"
44
#include "../librpc/gen_ndr/netlogon.h"
46
#include "printing/notify.h"
48
#include "../libcli/registry/util_reg.h"
49
#include "smbd/smbd.h"
52
#include "rpc_server/spoolss/srv_spoolss_nt.h"
54
#include "libsmb/libsmb.h"
55
#include "printing/printer_list.h"
56
#include "rpc_client/cli_winreg_spoolss.h"
58
/* macros stolen from s4 spoolss server */
59
#define SPOOLSS_BUFFER_UNION(fn,info,level) \
60
((info)?ndr_size_##fn(info, level, 0):0)
62
#define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
63
((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
65
#define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
66
((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
68
#define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
#define DBGC_CLASS DBGC_RPC_SRV
73
#ifndef MAX_OPEN_PRINTER_EXS
74
#define MAX_OPEN_PRINTER_EXS 50
77
struct notify_back_channel;
79
/* structure to store the printer handles */
80
/* and a reference to what it's pointing to */
81
/* and the notify info asked about */
82
/* that's the central struct */
83
struct printer_handle {
84
struct printer_handle *prev, *next;
85
bool document_started;
87
uint32 jobid; /* jobid in printing backend */
89
const char *servername;
92
uint32 access_granted;
98
struct spoolss_NotifyOption *option;
99
struct policy_handle cli_hnd;
100
struct notify_back_channel *cli_chan;
102
/* are we in a FindNextPrinterChangeNotify() call? */
104
struct messaging_context *msg_ctx;
111
/* devmode sent in the OpenPrinter() call */
112
struct spoolss_DeviceMode *devmode;
114
/* TODO cache the printer info2 structure */
115
struct spoolss_PrinterInfo2 *info2;
119
static struct printer_handle *printers_list;
121
struct printer_session_counter {
122
struct printer_session_counter *next;
123
struct printer_session_counter *prev;
129
static struct printer_session_counter *counter_list;
131
struct notify_back_channel {
132
struct notify_back_channel *prev, *next;
134
/* associated client */
135
struct sockaddr_storage client_address;
137
/* print notify back-channel pipe handle*/
138
struct rpc_pipe_client *cli_pipe;
139
struct dcerpc_binding_handle *binding_handle;
140
uint32_t active_connections;
143
static struct notify_back_channel *back_channels;
145
/* Map generic permissions to printer object specific permissions */
147
const struct standard_mapping printer_std_mapping = {
154
/* Map generic permissions to print server object specific permissions */
156
const struct standard_mapping printserver_std_mapping = {
163
/* API table for Xcv Monitor functions */
165
struct xcv_api_table {
167
WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170
static void prune_printername_cache(void);
172
/********************************************************************
173
* Canonicalize servername.
174
********************************************************************/
176
static const char *canon_servername(const char *servername)
178
const char *pservername = servername;
179
while (*pservername == '\\') {
185
/* translate between internal status numbers and NT status numbers */
186
static int nt_printj_status(int v)
192
return JOB_STATUS_PAUSED;
194
return JOB_STATUS_SPOOLING;
196
return JOB_STATUS_PRINTING;
198
return JOB_STATUS_ERROR;
200
return JOB_STATUS_DELETING;
202
return JOB_STATUS_OFFLINE;
204
return JOB_STATUS_PAPEROUT;
206
return JOB_STATUS_PRINTED;
208
return JOB_STATUS_DELETED;
210
return JOB_STATUS_BLOCKED_DEVQ;
211
case LPQ_USER_INTERVENTION:
212
return JOB_STATUS_USER_INTERVENTION;
217
static int nt_printq_status(int v)
221
return PRINTER_STATUS_PAUSED;
230
/***************************************************************************
231
Disconnect from the client
232
****************************************************************************/
234
static void srv_spoolss_replycloseprinter(int snum,
235
struct printer_handle *prn_hnd)
241
* Tell the specific printing tdb we no longer want messages for this printer
242
* by deregistering our PID.
245
if (!print_notify_deregister_pid(snum)) {
246
DEBUG(0, ("Failed to register our pid for printer %s\n",
247
lp_const_servicename(snum)));
250
/* weird if the test succeeds !!! */
251
if (prn_hnd->notify.cli_chan == NULL ||
252
prn_hnd->notify.cli_chan->active_connections == 0) {
253
DEBUG(0, ("Trying to close unexisting backchannel!\n"));
254
DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
255
TALLOC_FREE(prn_hnd->notify.cli_chan);
259
status = dcerpc_spoolss_ReplyClosePrinter(
260
prn_hnd->notify.cli_chan->binding_handle,
262
&prn_hnd->notify.cli_hnd,
264
if (!NT_STATUS_IS_OK(status)) {
265
DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
267
result = ntstatus_to_werror(status);
268
} else if (!W_ERROR_IS_OK(result)) {
269
DEBUG(0, ("reply_close_printer failed [%s].\n",
270
win_errstr(result)));
273
/* if it's the last connection, deconnect the IPC$ share */
274
if (prn_hnd->notify.cli_chan->active_connections == 1) {
276
prn_hnd->notify.cli_chan->binding_handle = NULL;
277
cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
278
DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
279
TALLOC_FREE(prn_hnd->notify.cli_chan);
281
if (prn_hnd->notify.msg_ctx != NULL) {
282
messaging_deregister(prn_hnd->notify.msg_ctx,
283
MSG_PRINTER_NOTIFY2, NULL);
286
* Tell the serverid.tdb we're no longer
287
* interested in printer notify messages.
290
serverid_register_msg_flags(
291
messaging_server_id(prn_hnd->notify.msg_ctx),
292
false, FLAG_MSG_PRINT_NOTIFY);
296
if (prn_hnd->notify.cli_chan) {
297
prn_hnd->notify.cli_chan->active_connections--;
301
/****************************************************************************
302
Functions to free a printer entry datastruct.
303
****************************************************************************/
305
static int printer_entry_destructor(struct printer_handle *Printer)
307
if (Printer->notify.cli_chan != NULL &&
308
Printer->notify.cli_chan->active_connections > 0) {
311
switch(Printer->printer_type) {
313
srv_spoolss_replycloseprinter(snum, Printer);
317
snum = print_queue_snum(Printer->sharename);
319
srv_spoolss_replycloseprinter(snum, Printer);
327
Printer->notify.flags=0;
328
Printer->notify.options=0;
329
Printer->notify.localmachine[0]='\0';
330
Printer->notify.printerlocal=0;
331
TALLOC_FREE(Printer->notify.option);
332
TALLOC_FREE(Printer->devmode);
334
/* Remove from the internal list. */
335
DLIST_REMOVE(printers_list, Printer);
339
/****************************************************************************
340
find printer index by handle
341
****************************************************************************/
343
static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
344
struct policy_handle *hnd)
346
struct printer_handle *find_printer = NULL;
348
if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
349
DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
356
/****************************************************************************
357
Close printer index by handle.
358
****************************************************************************/
360
static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
362
struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
365
DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
370
close_policy_hnd(p, hnd);
375
/****************************************************************************
376
Delete a printer given a handle.
377
****************************************************************************/
379
static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
380
const char *sharename,
381
struct messaging_context *msg_ctx)
383
char *cmd = lp_deleteprinter_cmd();
384
char *command = NULL;
386
bool is_print_op = false;
388
/* can't fail if we don't try */
393
command = talloc_asprintf(ctx,
400
is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
402
DEBUG(10,("Running [%s]\n", command));
404
/********** BEGIN SePrintOperatorPrivlege BLOCK **********/
409
if ( (ret = smbrun(command, NULL)) == 0 ) {
410
/* Tell everyone we updated smb.conf. */
411
message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
417
/********** END SePrintOperatorPrivlege BLOCK **********/
419
DEBUGADD(10,("returned [%d]\n", ret));
421
TALLOC_FREE(command);
424
return WERR_BADFID; /* What to return here? */
426
/* go ahead and re-read the services immediately */
428
reload_services(msg_ctx, -1, false);
431
if ( lp_servicenumber( sharename ) >= 0 )
432
return WERR_ACCESS_DENIED;
437
/****************************************************************************
438
Delete a printer given a handle.
439
****************************************************************************/
441
static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
443
struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
447
DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
453
* It turns out that Windows allows delete printer on a handle
454
* opened by an admin user, then used on a pipe handle created
455
* by an anonymous user..... but they're working on security.... riiight !
459
if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
460
DEBUG(3, ("delete_printer_handle: denied by handle\n"));
461
return WERR_ACCESS_DENIED;
464
/* this does not need a become root since the access check has been
465
done on the handle already */
467
result = winreg_delete_printer_key_internal(p->mem_ctx,
468
get_session_info_system(),
472
if (!W_ERROR_IS_OK(result)) {
473
DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
477
result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
478
Printer->sharename, p->msg_ctx);
479
if (!W_ERROR_IS_OK(result)) {
482
prune_printername_cache();
486
/****************************************************************************
487
Return the snum of a printer corresponding to an handle.
488
****************************************************************************/
490
static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
491
int *number, struct share_params **params)
493
struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
496
DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
501
switch (Printer->printer_type) {
503
DEBUG(4,("short name:%s\n", Printer->sharename));
504
*number = print_queue_snum(Printer->sharename);
505
return (*number != -1);
513
/****************************************************************************
514
Set printer handle type.
515
Check if it's \\server or \\server\printer
516
****************************************************************************/
518
static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
520
DEBUG(3,("Setting printer type=%s\n", handlename));
522
/* it's a print server */
523
if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
524
DEBUGADD(4,("Printer is a print server\n"));
525
Printer->printer_type = SPLHND_SERVER;
527
/* it's a printer (set_printer_hnd_name() will handle port monitors */
529
DEBUGADD(4,("Printer is a printer\n"));
530
Printer->printer_type = SPLHND_PRINTER;
536
static void prune_printername_cache_fn(const char *key, const char *value,
537
time_t timeout, void *private_data)
542
static void prune_printername_cache(void)
544
gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
547
/****************************************************************************
548
Set printer handle name.. Accept names like \\server, \\server\printer,
549
\\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
550
the MSDN docs regarding OpenPrinter() for details on the XcvData() and
551
XcvDataPort() interface.
552
****************************************************************************/
554
static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
555
const struct auth_serversupplied_info *session_info,
556
struct messaging_context *msg_ctx,
557
struct printer_handle *Printer,
558
const char *handlename)
561
int n_services=lp_numservices();
563
const char *printername;
564
const char *servername = NULL;
567
struct spoolss_PrinterInfo2 *info2 = NULL;
572
* Hopefully nobody names his printers like this. Maybe \ or ,
573
* are illegal in printer names even?
575
const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
579
DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
580
(unsigned long)strlen(handlename)));
582
aprinter = CONST_DISCARD(char *, handlename);
583
if ( *handlename == '\\' ) {
584
servername = canon_servername(handlename);
585
if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
589
if (!is_myname_or_ipaddr(servername)) {
590
return WERR_INVALID_PRINTER_NAME;
592
Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
593
if (Printer->servername == NULL) {
598
if (Printer->printer_type == SPLHND_SERVER) {
602
if (Printer->printer_type != SPLHND_PRINTER) {
603
return WERR_INVALID_HANDLE;
606
DEBUGADD(5, ("searching for [%s]\n", aprinter));
608
p = strchr(aprinter, ',');
615
if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
617
} else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
623
DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
626
/* check for the Port Monitor Interface */
627
if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
628
Printer->printer_type = SPLHND_PORTMON_TCP;
629
fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
632
else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
633
Printer->printer_type = SPLHND_PORTMON_LOCAL;
634
fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
639
* With hundreds of printers, the "for" loop iterating all
640
* shares can be quite expensive, as it is done on every
641
* OpenPrinter. The loop maps "aprinter" to "sname", the
642
* result of which we cache in gencache.
645
cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
647
if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
649
found = (strcmp(tmp, printer_not_found) != 0);
651
DEBUG(4, ("Printer %s not found\n", aprinter));
653
return WERR_INVALID_PRINTER_NAME;
659
/* Search all sharenames first as this is easier than pulling
660
the printer_info_2 off of disk. Don't use find_service() since
661
that calls out to map_username() */
663
/* do another loop to look for printernames */
664
for (snum = 0; !found && snum < n_services; snum++) {
665
const char *printer = lp_const_servicename(snum);
667
/* no point going on if this is not a printer */
668
if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
672
/* ignore [printers] share */
673
if (strequal(printer, "printers")) {
677
fstrcpy(sname, printer);
678
if (strequal(aprinter, printer)) {
683
/* no point looking up the printer object if
684
we aren't allowing printername != sharename */
685
if (lp_force_printername(snum)) {
689
result = winreg_get_printer_internal(mem_ctx,
694
if ( !W_ERROR_IS_OK(result) ) {
695
DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
696
sname, win_errstr(result)));
700
printername = strrchr(info2->printername, '\\');
701
if (printername == NULL) {
702
printername = info2->printername;
707
if (strequal(printername, aprinter)) {
712
DEBUGADD(10, ("printername: %s\n", printername));
718
if (cache_key != NULL) {
719
gencache_set(cache_key, printer_not_found,
721
TALLOC_FREE(cache_key);
723
DEBUGADD(4,("Printer not found\n"));
724
return WERR_INVALID_PRINTER_NAME;
727
if (cache_key != NULL) {
728
gencache_set(cache_key, sname, time(NULL)+300);
729
TALLOC_FREE(cache_key);
732
DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
734
fstrcpy(Printer->sharename, sname);
739
/****************************************************************************
740
Find first available printer slot. creates a printer handle for you.
741
****************************************************************************/
743
static WERROR open_printer_hnd(struct pipes_struct *p,
744
struct policy_handle *hnd,
746
uint32_t access_granted)
748
struct printer_handle *new_printer;
751
DEBUG(10,("open_printer_hnd: name [%s]\n", name));
753
new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
754
if (new_printer == NULL) {
757
talloc_set_destructor(new_printer, printer_entry_destructor);
759
/* This also steals the printer_handle on the policy_handle */
760
if (!create_policy_hnd(p, hnd, new_printer)) {
761
TALLOC_FREE(new_printer);
762
return WERR_INVALID_HANDLE;
765
/* Add to the internal list. */
766
DLIST_ADD(printers_list, new_printer);
768
new_printer->notify.option=NULL;
770
if (!set_printer_hnd_printertype(new_printer, name)) {
771
close_printer_handle(p, hnd);
772
return WERR_INVALID_HANDLE;
775
result = set_printer_hnd_name(p->mem_ctx,
776
get_session_info_system(),
779
if (!W_ERROR_IS_OK(result)) {
780
close_printer_handle(p, hnd);
784
new_printer->access_granted = access_granted;
786
DEBUG(5, ("%d printer handles active\n",
787
(int)num_pipe_handles(p)));
792
/***************************************************************************
793
check to see if the client motify handle is monitoring the notification
794
given by (notify_type, notify_field).
795
**************************************************************************/
797
static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
798
uint16_t notify_field)
803
static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
804
uint16_t notify_field)
806
struct spoolss_NotifyOption *option = p->notify.option;
810
* Flags should always be zero when the change notify
811
* is registered by the client's spooler. A user Win32 app
812
* might use the flags though instead of the NOTIFY_OPTION_INFO
821
return is_monitoring_event_flags(
822
p->notify.flags, notify_type, notify_field);
824
for (i = 0; i < option->count; i++) {
826
/* Check match for notify_type */
828
if (option->types[i].type != notify_type)
831
/* Check match for field */
833
for (j = 0; j < option->types[i].count; j++) {
834
if (option->types[i].fields[j].field == notify_field) {
840
DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
841
p->servername, p->sharename, notify_type, notify_field));
846
#define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
847
_data->data.integer[0] = _integer; \
848
_data->data.integer[1] = 0;
851
#define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
852
_data->data.string.string = talloc_strdup(mem_ctx, _p); \
853
if (!_data->data.string.string) {\
854
_data->data.string.size = 0; \
856
_data->data.string.size = strlen_m_term(_p) * 2;
858
#define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
859
_data->data.devmode.devmode = _devmode;
861
#define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
862
_data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
863
if (!_data->data.sd.sd) { \
864
_data->data.sd.sd_size = 0; \
866
_data->data.sd.sd_size = \
867
ndr_size_security_descriptor(_data->data.sd.sd, 0);
869
static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
874
struct spoolss_Time st;
878
if (!init_systemtime(&st, t)) {
882
p = talloc_array(mem_ctx, char, len);
888
* Systemtime must be linearized as a set of UINT16's.
889
* Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
892
SSVAL(p, 0, st.year);
893
SSVAL(p, 2, st.month);
894
SSVAL(p, 4, st.day_of_week);
896
SSVAL(p, 8, st.hour);
897
SSVAL(p, 10, st.minute);
898
SSVAL(p, 12, st.second);
899
SSVAL(p, 14, st.millisecond);
905
/* Convert a notification message to a struct spoolss_Notify */
907
static void notify_one_value(struct spoolss_notify_msg *msg,
908
struct spoolss_Notify *data,
911
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
914
static void notify_string(struct spoolss_notify_msg *msg,
915
struct spoolss_Notify *data,
918
/* The length of the message includes the trailing \0 */
920
data->data.string.size = msg->len * 2;
921
data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
922
if (!data->data.string.string) {
923
data->data.string.size = 0;
928
static void notify_system_time(struct spoolss_notify_msg *msg,
929
struct spoolss_Notify *data,
932
data->data.string.string = NULL;
933
data->data.string.size = 0;
935
if (msg->len != sizeof(time_t)) {
936
DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
941
init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
942
&data->data.string.string,
943
&data->data.string.size);
946
struct notify2_message_table {
948
void (*fn)(struct spoolss_notify_msg *msg,
949
struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
952
static struct notify2_message_table printer_notify_table[] = {
953
/* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
954
/* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
955
/* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
956
/* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
957
/* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
958
/* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
959
/* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
960
/* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
961
/* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
962
/* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
963
/* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
964
/* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
965
/* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
966
/* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
967
/* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
968
/* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
969
/* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
970
/* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
971
/* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
974
static struct notify2_message_table job_notify_table[] = {
975
/* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
976
/* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
977
/* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
978
/* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
979
/* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
980
/* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
981
/* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
982
/* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
983
/* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
984
/* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
985
/* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
986
/* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
987
/* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
988
/* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
989
/* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
990
/* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
991
/* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
992
/* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
993
/* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
994
/* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
995
/* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
996
/* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
997
/* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
998
/* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1002
/***********************************************************************
1003
Allocate talloc context for container object
1004
**********************************************************************/
1006
static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1011
ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1016
/***********************************************************************
1017
release all allocated memory and zero out structure
1018
**********************************************************************/
1020
static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1026
talloc_destroy(ctr->ctx);
1033
/***********************************************************************
1034
**********************************************************************/
1036
static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1044
/***********************************************************************
1045
**********************************************************************/
1047
static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1049
if ( !ctr || !ctr->msg_groups )
1052
if ( idx >= ctr->num_groups )
1055
return &ctr->msg_groups[idx];
1059
/***********************************************************************
1060
How many groups of change messages do we have ?
1061
**********************************************************************/
1063
static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1068
return ctr->num_groups;
1071
/***********************************************************************
1072
Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1073
**********************************************************************/
1075
static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1077
SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1078
SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1079
SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1085
/* loop over all groups looking for a matching printer name */
1087
for ( i=0; i<ctr->num_groups; i++ ) {
1088
if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1092
/* add a new group? */
1094
if ( i == ctr->num_groups ) {
1097
if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1098
DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1101
ctr->msg_groups = groups;
1103
/* clear the new entry and set the printer name */
1105
ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1106
fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1109
/* add the change messages; 'i' is the correct index now regardless */
1111
msg_grp = &ctr->msg_groups[i];
1113
msg_grp->num_msgs++;
1115
if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1116
DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1119
msg_grp->msgs = msg_list;
1121
new_slot = msg_grp->num_msgs-1;
1122
memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1124
/* need to allocate own copy of data */
1126
if ( msg->len != 0 )
1127
msg_grp->msgs[new_slot].notify.data = (char *)
1128
TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1130
return ctr->num_groups;
1133
static void construct_info_data(struct spoolss_Notify *info_data,
1134
enum spoolss_NotifyType type,
1135
uint16_t field, int id);
1137
/***********************************************************************
1138
Send a change notication message on all handles which have a call
1140
**********************************************************************/
1142
static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1143
struct printer_handle *prn_hnd,
1144
SPOOLSS_NOTIFY_MSG *messages,
1146
struct spoolss_Notify **_notifies,
1149
struct spoolss_Notify *notifies;
1150
SPOOLSS_NOTIFY_MSG *msg;
1155
notifies = talloc_zero_array(mem_ctx,
1156
struct spoolss_Notify, num_msgs);
1161
for (i = 0; i < num_msgs; i++) {
1165
/* Are we monitoring this event? */
1167
if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1171
DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1172
"for printer [%s]\n",
1173
msg->type, msg->field, prn_hnd->sharename));
1176
* if the is a printer notification handle and not a job
1177
* notification type, then set the id to 0.
1178
* Otherwise just use what was specified in the message.
1180
* When registering change notification on a print server
1181
* handle we always need to send back the id (snum) matching
1182
* the printer for which the change took place.
1183
* For change notify registered on a printer handle,
1184
* this does not matter and the id should be 0.
1189
if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1190
(prn_hnd->printer_type == SPLHND_PRINTER)) {
1196
/* Convert unix jobid to smb jobid */
1198
if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1199
id = sysjob_to_jobid(msg->id);
1202
DEBUG(3, ("no such unix jobid %d\n",
1208
construct_info_data(¬ifies[count],
1209
msg->type, msg->field, id);
1212
case PRINTER_NOTIFY_TYPE:
1213
if (printer_notify_table[msg->field].fn) {
1214
printer_notify_table[msg->field].fn(msg,
1215
¬ifies[count], mem_ctx);
1219
case JOB_NOTIFY_TYPE:
1220
if (job_notify_table[msg->field].fn) {
1221
job_notify_table[msg->field].fn(msg,
1222
¬ifies[count], mem_ctx);
1227
DEBUG(5, ("Unknown notification type %d\n",
1235
*_notifies = notifies;
1241
static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1242
struct printer_handle *prn_hnd,
1243
SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1245
struct spoolss_Notify *notifies;
1247
union spoolss_ReplyPrinterInfo info;
1248
struct spoolss_NotifyInfo info0;
1249
uint32_t reply_result;
1254
/* Is there notification on this handle? */
1255
if (prn_hnd->notify.cli_chan == NULL ||
1256
prn_hnd->notify.cli_chan->active_connections == 0) {
1260
DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1261
prn_hnd->servername, prn_hnd->sharename));
1263
/* For this printer? Print servers always receive notifications. */
1264
if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1265
(!strequal(msg_group->printername, prn_hnd->sharename))) {
1269
DEBUG(10,("Our printer\n"));
1271
/* build the array of change notifications */
1272
ret = build_notify2_messages(mem_ctx, prn_hnd,
1274
msg_group->num_msgs,
1280
info0.version = 0x2;
1281
info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1282
info0.count = count;
1283
info0.notifies = notifies;
1285
info.info0 = &info0;
1287
status = dcerpc_spoolss_RouterReplyPrinterEx(
1288
prn_hnd->notify.cli_chan->binding_handle,
1290
&prn_hnd->notify.cli_hnd,
1291
prn_hnd->notify.change, /* color */
1292
prn_hnd->notify.flags,
1294
0, /* reply_type, must be 0 */
1296
if (!NT_STATUS_IS_OK(status)) {
1297
DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1299
prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1300
nt_errstr(status)));
1301
werr = ntstatus_to_werror(status);
1302
} else if (!W_ERROR_IS_OK(werr)) {
1303
DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1305
prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1308
switch (reply_result) {
1311
case PRINTER_NOTIFY_INFO_DISCARDED:
1312
case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1313
case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1322
static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1324
struct printer_handle *p;
1325
TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1326
SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1330
DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1334
if (!msg_group->msgs) {
1335
DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1339
DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1341
/* loop over all printers */
1343
for (p = printers_list; p; p = p->next) {
1344
ret = send_notify2_printer(mem_ctx, p, msg_group);
1351
DEBUG(8,("send_notify2_changes: Exit...\n"));
1355
/***********************************************************************
1356
**********************************************************************/
1358
static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1361
uint32_t tv_sec, tv_usec;
1364
/* Unpack message */
1366
offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1369
offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1371
&msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1374
tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1375
&msg->notify.value[0], &msg->notify.value[1]);
1377
tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1378
&msg->len, &msg->notify.data);
1380
DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1381
msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1383
tv->tv_sec = tv_sec;
1384
tv->tv_usec = tv_usec;
1387
DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1388
msg->notify.value[1]));
1390
dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1395
/********************************************************************
1396
Receive a notify2 message list
1397
********************************************************************/
1399
static void receive_notify2_message_list(struct messaging_context *msg,
1402
struct server_id server_id,
1405
size_t msg_count, i;
1406
char *buf = (char *)data->data;
1409
SPOOLSS_NOTIFY_MSG notify;
1410
SPOOLSS_NOTIFY_MSG_CTR messages;
1413
if (data->length < 4) {
1414
DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1418
msg_count = IVAL(buf, 0);
1421
DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1423
if (msg_count == 0) {
1424
DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1428
/* initialize the container */
1430
ZERO_STRUCT( messages );
1431
notify_msg_ctr_init( &messages );
1434
* build message groups for each printer identified
1435
* in a change_notify msg. Remember that a PCN message
1436
* includes the handle returned for the srv_spoolss_replyopenprinter()
1437
* call. Therefore messages are grouped according to printer handle.
1440
for ( i=0; i<msg_count; i++ ) {
1441
struct timeval msg_tv;
1443
if (msg_ptr + 4 - buf > data->length) {
1444
DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1448
msg_len = IVAL(msg_ptr,0);
1451
if (msg_ptr + msg_len - buf > data->length) {
1452
DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1456
/* unpack messages */
1458
ZERO_STRUCT( notify );
1459
notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1462
/* add to correct list in container */
1464
notify_msg_ctr_addmsg( &messages, ¬ify );
1466
/* free memory that might have been allocated by notify2_unpack_msg() */
1468
if ( notify.len != 0 )
1469
SAFE_FREE( notify.notify.data );
1472
/* process each group of messages */
1474
num_groups = notify_msg_ctr_numgroups( &messages );
1475
for ( i=0; i<num_groups; i++ )
1476
send_notify2_changes( &messages, i );
1481
DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1482
(uint32_t)msg_count ));
1484
notify_msg_ctr_destroy( &messages );
1489
/********************************************************************
1490
Send a message to ourself about new driver being installed
1491
so we can upgrade the information for each printer bound to this
1493
********************************************************************/
1495
static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1496
struct messaging_context *msg_ctx)
1498
int len = strlen(drivername);
1503
DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1506
messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1507
MSG_PRINTER_DRVUPGRADE,
1508
(uint8_t *)drivername, len+1);
1513
void srv_spoolss_cleanup(void)
1515
struct printer_session_counter *session_counter;
1517
for (session_counter = counter_list;
1518
session_counter != NULL;
1519
session_counter = counter_list) {
1520
DLIST_REMOVE(counter_list, session_counter);
1521
TALLOC_FREE(session_counter);
1525
/**********************************************************************
1526
callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1527
over all printers, upgrading ones as necessary
1528
**********************************************************************/
1530
void do_drv_upgrade_printer(struct messaging_context *msg,
1533
struct server_id server_id,
1536
TALLOC_CTX *tmp_ctx;
1537
struct auth_serversupplied_info *session_info = NULL;
1538
struct spoolss_PrinterInfo2 *pinfo2;
1541
const char *drivername;
1543
int n_services = lp_numservices();
1544
struct dcerpc_binding_handle *b = NULL;
1546
tmp_ctx = talloc_new(NULL);
1547
if (!tmp_ctx) return;
1549
status = make_session_info_system(tmp_ctx, &session_info);
1550
if (!NT_STATUS_IS_OK(status)) {
1551
DEBUG(0, ("do_drv_upgrade_printer: "
1552
"Could not create system session_info\n"));
1556
drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1558
DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1562
DEBUG(10, ("do_drv_upgrade_printer: "
1563
"Got message for new driver [%s]\n", drivername));
1565
/* Iterate the printer list */
1567
for (snum = 0; snum < n_services; snum++) {
1568
if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1572
/* ignore [printers] share */
1573
if (strequal(lp_const_servicename(snum), "printers")) {
1578
result = winreg_printer_binding_handle(tmp_ctx,
1582
if (!W_ERROR_IS_OK(result)) {
1587
result = winreg_get_printer(tmp_ctx, b,
1588
lp_const_servicename(snum),
1591
if (!W_ERROR_IS_OK(result)) {
1595
if (!pinfo2->drivername) {
1599
if (strcmp(drivername, pinfo2->drivername) != 0) {
1603
DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1605
/* all we care about currently is the change_id */
1606
result = winreg_printer_update_changeid(tmp_ctx, b,
1607
pinfo2->printername);
1609
if (!W_ERROR_IS_OK(result)) {
1610
DEBUG(3, ("do_drv_upgrade_printer: "
1611
"Failed to update changeid [%s]\n",
1612
win_errstr(result)));
1618
talloc_free(tmp_ctx);
1621
/********************************************************************
1622
Update the cache for all printq's with a registered client
1624
********************************************************************/
1626
void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1628
struct printer_handle *printer = printers_list;
1631
/* loop through all printers and update the cache where
1632
a client is connected */
1634
if ((printer->printer_type == SPLHND_PRINTER) &&
1635
((printer->notify.cli_chan != NULL) &&
1636
(printer->notify.cli_chan->active_connections > 0))) {
1637
snum = print_queue_snum(printer->sharename);
1638
print_queue_status(msg_ctx, snum, NULL, NULL);
1641
printer = printer->next;
1647
/****************************************************************
1648
_spoolss_OpenPrinter
1649
****************************************************************/
1651
WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1652
struct spoolss_OpenPrinter *r)
1654
struct spoolss_OpenPrinterEx e;
1657
ZERO_STRUCT(e.in.userlevel);
1659
e.in.printername = r->in.printername;
1660
e.in.datatype = r->in.datatype;
1661
e.in.devmode_ctr = r->in.devmode_ctr;
1662
e.in.access_mask = r->in.access_mask;
1665
e.out.handle = r->out.handle;
1667
werr = _spoolss_OpenPrinterEx(p, &e);
1669
if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1670
/* OpenPrinterEx returns this for a bad
1671
* printer name. We must return WERR_INVALID_PRINTER_NAME
1674
werr = WERR_INVALID_PRINTER_NAME;
1680
static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1681
struct spoolss_DeviceMode *orig,
1682
struct spoolss_DeviceMode **dest)
1684
struct spoolss_DeviceMode *dm;
1686
dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1691
/* copy all values, then duplicate strings and structs */
1694
dm->devicename = talloc_strdup(dm, orig->devicename);
1695
if (!dm->devicename) {
1698
dm->formname = talloc_strdup(dm, orig->formname);
1699
if (!dm->formname) {
1702
if (orig->driverextra_data.data) {
1703
dm->driverextra_data.data =
1704
(uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1705
orig->driverextra_data.length);
1706
if (!dm->driverextra_data.data) {
1715
/****************************************************************
1716
_spoolss_OpenPrinterEx
1717
****************************************************************/
1719
WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1720
struct spoolss_OpenPrinterEx *r)
1723
struct printer_handle *Printer=NULL;
1726
if (!r->in.printername) {
1727
return WERR_INVALID_PARAM;
1730
if (r->in.level > 3) {
1731
return WERR_INVALID_PARAM;
1733
if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1734
(r->in.level == 2 && !r->in.userlevel.level2) ||
1735
(r->in.level == 3 && !r->in.userlevel.level3)) {
1736
return WERR_INVALID_PARAM;
1739
/* some sanity check because you can open a printer or a print server */
1740
/* aka: \\server\printer or \\server */
1742
DEBUGADD(3,("checking name: %s\n", r->in.printername));
1744
result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1745
if (!W_ERROR_IS_OK(result)) {
1746
DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1747
"for printer %s\n", r->in.printername));
1748
ZERO_STRUCTP(r->out.handle);
1752
Printer = find_printer_index_by_hnd(p, r->out.handle);
1754
DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1755
"handle we created for printer %s\n", r->in.printername));
1756
close_printer_handle(p, r->out.handle);
1757
ZERO_STRUCTP(r->out.handle);
1758
return WERR_INVALID_PARAM;
1762
* First case: the user is opening the print server:
1764
* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1765
* client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1767
* Then both Win2k and WinNT clients try an OpenPrinterEx with
1768
* SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1769
* or if the user is listed in the smb.conf printer admin parameter.
1771
* Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1772
* client view printer folder, but does not show the MSAPW.
1774
* Note: this test needs code to check access rights here too. Jeremy
1775
* could you look at this?
1777
* Second case: the user is opening a printer:
1778
* NT doesn't let us connect to a printer if the connecting user
1779
* doesn't have print permission.
1781
* Third case: user is opening a Port Monitor
1782
* access checks same as opening a handle to the print server.
1785
switch (Printer->printer_type )
1788
case SPLHND_PORTMON_TCP:
1789
case SPLHND_PORTMON_LOCAL:
1790
/* Printserver handles use global struct... */
1794
/* Map standard access rights to object specific access rights */
1796
se_map_standard(&r->in.access_mask,
1797
&printserver_std_mapping);
1799
/* Deny any object specific bits that don't apply to print
1800
servers (i.e printer and job specific bits) */
1802
r->in.access_mask &= SEC_MASK_SPECIFIC;
1804
if (r->in.access_mask &
1805
~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1806
DEBUG(3, ("access DENIED for non-printserver bits\n"));
1807
close_printer_handle(p, r->out.handle);
1808
ZERO_STRUCTP(r->out.handle);
1809
return WERR_ACCESS_DENIED;
1812
/* Allow admin access */
1814
if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1816
if (!lp_ms_add_printer_wizard()) {
1817
close_printer_handle(p, r->out.handle);
1818
ZERO_STRUCTP(r->out.handle);
1819
return WERR_ACCESS_DENIED;
1822
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1823
and not a printer admin, then fail */
1825
if ((p->session_info->utok.uid != sec_initial_uid()) &&
1826
!security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1827
!nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1828
!token_contains_name_in_list(
1829
uidtoname(p->session_info->utok.uid),
1830
p->session_info->info3->base.domain.string,
1832
p->session_info->security_token,
1833
lp_printer_admin(snum))) {
1834
close_printer_handle(p, r->out.handle);
1835
ZERO_STRUCTP(r->out.handle);
1836
DEBUG(3,("access DENIED as user is not root, "
1837
"has no printoperator privilege, "
1838
"not a member of the printoperator builtin group and "
1839
"is not in printer admin list"));
1840
return WERR_ACCESS_DENIED;
1843
r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1847
r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1850
DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1851
? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1853
/* We fall through to return WERR_OK */
1856
case SPLHND_PRINTER:
1857
/* NT doesn't let us connect to a printer if the connecting user
1858
doesn't have print permission. */
1860
if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1861
close_printer_handle(p, r->out.handle);
1862
ZERO_STRUCTP(r->out.handle);
1866
if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1867
r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1870
se_map_standard(&r->in.access_mask, &printer_std_mapping);
1872
/* map an empty access mask to the minimum access mask */
1873
if (r->in.access_mask == 0x0)
1874
r->in.access_mask = PRINTER_ACCESS_USE;
1877
* If we are not serving the printer driver for this printer,
1878
* map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1879
* will keep NT clients happy --jerry
1882
if (lp_use_client_driver(snum)
1883
&& (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1885
r->in.access_mask = PRINTER_ACCESS_USE;
1888
/* check smb.conf parameters and the the sec_desc */
1890
if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1891
p->client_id->name, p->client_id->addr)) {
1892
DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1893
ZERO_STRUCTP(r->out.handle);
1894
return WERR_ACCESS_DENIED;
1897
if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1898
p->session_info->security_token, snum) ||
1899
!print_access_check(p->session_info,
1902
r->in.access_mask)) {
1903
DEBUG(3, ("access DENIED for printer open\n"));
1904
close_printer_handle(p, r->out.handle);
1905
ZERO_STRUCTP(r->out.handle);
1906
return WERR_ACCESS_DENIED;
1909
if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1910
DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1911
close_printer_handle(p, r->out.handle);
1912
ZERO_STRUCTP(r->out.handle);
1913
return WERR_ACCESS_DENIED;
1916
if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1917
r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919
r->in.access_mask = PRINTER_ACCESS_USE;
1921
DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1922
? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924
winreg_create_printer_internal(p->mem_ctx,
1925
get_session_info_system(),
1927
lp_const_servicename(snum));
1932
/* sanity check to prevent programmer error */
1933
ZERO_STRUCTP(r->out.handle);
1937
Printer->access_granted = r->in.access_mask;
1940
* If the client sent a devmode in the OpenPrinter() call, then
1941
* save it here in case we get a job submission on this handle
1944
if ((Printer->printer_type != SPLHND_SERVER) &&
1945
r->in.devmode_ctr.devmode) {
1946
copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1950
#if 0 /* JERRY -- I'm doubtful this is really effective */
1951
/* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1952
optimization in Windows 2000 clients --jerry */
1954
if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1955
&& (RA_WIN2K == get_remote_arch()) )
1957
DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1958
sys_usleep( 500000 );
1965
/****************************************************************
1966
_spoolss_ClosePrinter
1967
****************************************************************/
1969
WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1970
struct spoolss_ClosePrinter *r)
1972
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1974
if (Printer && Printer->document_started) {
1975
struct spoolss_EndDocPrinter e;
1977
e.in.handle = r->in.handle;
1979
_spoolss_EndDocPrinter(p, &e);
1982
if (!close_printer_handle(p, r->in.handle))
1985
/* clear the returned printer handle. Observed behavior
1986
from Win2k server. Don't think this really matters.
1987
Previous code just copied the value of the closed
1990
ZERO_STRUCTP(r->out.handle);
1995
/****************************************************************
1996
_spoolss_DeletePrinter
1997
****************************************************************/
1999
WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2000
struct spoolss_DeletePrinter *r)
2002
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2006
if (Printer && Printer->document_started) {
2007
struct spoolss_EndDocPrinter e;
2009
e.in.handle = r->in.handle;
2011
_spoolss_EndDocPrinter(p, &e);
2014
if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2015
winreg_delete_printer_key_internal(p->mem_ctx,
2016
get_session_info_system(),
2018
lp_const_servicename(snum),
2022
result = delete_printer_handle(p, r->in.handle);
2027
/*******************************************************************
2028
* static function to lookup the version id corresponding to an
2029
* long architecture string
2030
******************************************************************/
2032
static const struct print_architecture_table_node archi_table[]= {
2034
{"Windows 4.0", SPL_ARCH_WIN40, 0 },
2035
{"Windows NT x86", SPL_ARCH_W32X86, 2 },
2036
{"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2037
{"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2038
{"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2039
{"Windows IA64", SPL_ARCH_IA64, 3 },
2040
{"Windows x64", SPL_ARCH_X64, 3 },
2044
static int get_version_id(const char *arch)
2048
for (i=0; archi_table[i].long_archi != NULL; i++)
2050
if (strcmp(arch, archi_table[i].long_archi) == 0)
2051
return (archi_table[i].version);
2057
/****************************************************************
2058
_spoolss_DeletePrinterDriver
2059
****************************************************************/
2061
WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2062
struct spoolss_DeletePrinterDriver *r)
2065
struct spoolss_DriverInfo8 *info = NULL;
2066
struct spoolss_DriverInfo8 *info_win2k = NULL;
2069
struct dcerpc_binding_handle *b;
2071
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2072
and not a printer admin, then fail */
2074
if ( (p->session_info->utok.uid != sec_initial_uid())
2075
&& !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2076
&& !token_contains_name_in_list(
2077
uidtoname(p->session_info->utok.uid),
2078
p->session_info->info3->base.domain.string,
2080
p->session_info->security_token,
2081
lp_printer_admin(-1)) )
2083
return WERR_ACCESS_DENIED;
2086
/* check that we have a valid driver name first */
2088
if ((version = get_version_id(r->in.architecture)) == -1)
2089
return WERR_INVALID_ENVIRONMENT;
2091
status = winreg_printer_binding_handle(p->mem_ctx,
2092
get_session_info_system(),
2095
if (!W_ERROR_IS_OK(status)) {
2099
status = winreg_get_driver(p->mem_ctx, b,
2100
r->in.architecture, r->in.driver,
2102
if (!W_ERROR_IS_OK(status)) {
2103
/* try for Win2k driver if "Windows NT x86" */
2105
if ( version == 2 ) {
2108
status = winreg_get_driver(p->mem_ctx, b,
2112
if (!W_ERROR_IS_OK(status)) {
2113
status = WERR_UNKNOWN_PRINTER_DRIVER;
2117
/* otherwise it was a failure */
2119
status = WERR_UNKNOWN_PRINTER_DRIVER;
2125
if (printer_driver_in_use(p->mem_ctx,
2126
get_session_info_system(),
2129
status = WERR_PRINTER_DRIVER_IN_USE;
2134
status = winreg_get_driver(p->mem_ctx, b,
2136
r->in.driver, 3, &info_win2k);
2137
if (W_ERROR_IS_OK(status)) {
2138
/* if we get to here, we now have 2 driver info structures to remove */
2139
/* remove the Win2k driver first*/
2141
status = winreg_del_driver(p->mem_ctx, b,
2143
talloc_free(info_win2k);
2145
/* this should not have failed---if it did, report to client */
2146
if (!W_ERROR_IS_OK(status)) {
2152
status = winreg_del_driver(p->mem_ctx, b,
2161
/****************************************************************
2162
_spoolss_DeletePrinterDriverEx
2163
****************************************************************/
2165
WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2166
struct spoolss_DeletePrinterDriverEx *r)
2168
struct spoolss_DriverInfo8 *info = NULL;
2169
struct spoolss_DriverInfo8 *info_win2k = NULL;
2173
struct dcerpc_binding_handle *b;
2175
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2176
and not a printer admin, then fail */
2178
if ( (p->session_info->utok.uid != sec_initial_uid())
2179
&& !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2180
&& !token_contains_name_in_list(
2181
uidtoname(p->session_info->utok.uid),
2182
p->session_info->info3->base.domain.string,
2184
p->session_info->security_token, lp_printer_admin(-1)) )
2186
return WERR_ACCESS_DENIED;
2189
/* check that we have a valid driver name first */
2190
if ((version = get_version_id(r->in.architecture)) == -1) {
2191
/* this is what NT returns */
2192
return WERR_INVALID_ENVIRONMENT;
2195
if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2196
version = r->in.version;
2198
status = winreg_printer_binding_handle(p->mem_ctx,
2199
get_session_info_system(),
2202
if (!W_ERROR_IS_OK(status)) {
2206
status = winreg_get_driver(p->mem_ctx, b,
2211
if (!W_ERROR_IS_OK(status)) {
2212
status = WERR_UNKNOWN_PRINTER_DRIVER;
2215
* if the client asked for a specific version,
2216
* or this is something other than Windows NT x86,
2220
if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2223
/* try for Win2k driver if "Windows NT x86" */
2226
status = winreg_get_driver(info, b,
2230
if (!W_ERROR_IS_OK(status)) {
2231
status = WERR_UNKNOWN_PRINTER_DRIVER;
2236
if (printer_driver_in_use(info,
2237
get_session_info_system(),
2240
status = WERR_PRINTER_DRIVER_IN_USE;
2245
* we have a couple of cases to consider.
2246
* (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2247
* then the delete should fail if **any** files overlap with
2249
* (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2250
* non-overlapping files
2251
* (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2252
* is set, the do not delete any files
2253
* Refer to MSDN docs on DeletePrinterDriverEx() for details.
2256
delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2258
/* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2261
(r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2262
printer_driver_files_in_use(info,
2263
get_session_info_system(),
2266
/* no idea of the correct error here */
2267
status = WERR_ACCESS_DENIED;
2272
/* also check for W32X86/3 if necessary; maybe we already have? */
2274
if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2275
status = winreg_get_driver(info, b,
2277
r->in.driver, 3, &info_win2k);
2278
if (W_ERROR_IS_OK(status)) {
2281
(r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2282
printer_driver_files_in_use(info,
2283
get_session_info_system(),
2286
/* no idea of the correct error here */
2287
talloc_free(info_win2k);
2288
status = WERR_ACCESS_DENIED;
2292
/* if we get to here, we now have 2 driver info structures to remove */
2293
/* remove the Win2k driver first*/
2295
status = winreg_del_driver(info, b,
2299
/* this should not have failed---if it did, report to client */
2301
if (!W_ERROR_IS_OK(status)) {
2306
* now delete any associated files if delete_files is
2307
* true. Even if this part failes, we return succes
2308
* because the driver doesn not exist any more
2311
delete_driver_files(get_session_info_system(),
2317
status = winreg_del_driver(info, b,
2320
if (!W_ERROR_IS_OK(status)) {
2325
* now delete any associated files if delete_files is
2326
* true. Even if this part failes, we return succes
2327
* because the driver doesn not exist any more
2330
delete_driver_files(get_session_info_system(), info);
2339
/********************************************************************
2340
GetPrinterData on a printer server Handle.
2341
********************************************************************/
2343
static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2345
enum winreg_Type *type,
2346
union spoolss_PrinterData *data)
2348
DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2350
if (!StrCaseCmp(value, "W3SvcInstalled")) {
2356
if (!StrCaseCmp(value, "BeepEnabled")) {
2362
if (!StrCaseCmp(value, "EventLog")) {
2364
/* formally was 0x1b */
2369
if (!StrCaseCmp(value, "NetPopup")) {
2375
if (!StrCaseCmp(value, "MajorVersion")) {
2378
/* Windows NT 4.0 seems to not allow uploading of drivers
2379
to a server that reports 0x3 as the MajorVersion.
2380
need to investigate more how Win2k gets around this .
2383
if (RA_WINNT == get_remote_arch()) {
2392
if (!StrCaseCmp(value, "MinorVersion")) {
2399
* uint32_t size = 0x114
2400
* uint32_t major = 5
2401
* uint32_t minor = [0|1]
2402
* uint32_t build = [2195|2600]
2403
* extra unicode string = e.g. "Service Pack 3"
2405
if (!StrCaseCmp(value, "OSVersion")) {
2407
enum ndr_err_code ndr_err;
2408
struct spoolss_OSVersion os;
2410
os.major = 5; /* Windows 2000 == 5.0 */
2412
os.build = 2195; /* build */
2413
os.extra_string = ""; /* leave extra string empty */
2415
ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2416
(ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2417
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2418
return WERR_GENERAL_FAILURE;
2422
data->binary = blob;
2428
if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2431
data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2432
W_ERROR_HAVE_NO_MEMORY(data->string);
2437
if (!StrCaseCmp(value, "Architecture")) {
2439
data->string = talloc_strdup(mem_ctx,
2440
lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2441
W_ERROR_HAVE_NO_MEMORY(data->string);
2446
if (!StrCaseCmp(value, "DsPresent")) {
2449
/* only show the publish check box if we are a
2450
member of a AD domain */
2452
if (lp_security() == SEC_ADS) {
2460
if (!StrCaseCmp(value, "DNSMachineName")) {
2461
const char *hostname = get_mydnsfullname();
2464
return WERR_BADFILE;
2468
data->string = talloc_strdup(mem_ctx, hostname);
2469
W_ERROR_HAVE_NO_MEMORY(data->string);
2476
return WERR_INVALID_PARAM;
2479
/****************************************************************
2480
_spoolss_GetPrinterData
2481
****************************************************************/
2483
WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2484
struct spoolss_GetPrinterData *r)
2486
struct spoolss_GetPrinterDataEx r2;
2488
r2.in.handle = r->in.handle;
2489
r2.in.key_name = "PrinterDriverData";
2490
r2.in.value_name = r->in.value_name;
2491
r2.in.offered = r->in.offered;
2492
r2.out.type = r->out.type;
2493
r2.out.data = r->out.data;
2494
r2.out.needed = r->out.needed;
2496
return _spoolss_GetPrinterDataEx(p, &r2);
2499
/*********************************************************
2500
Connect to the client machine.
2501
**********************************************************/
2503
static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2504
struct sockaddr_storage *client_ss, const char *remote_machine)
2507
struct cli_state *the_cli;
2508
struct sockaddr_storage rm_addr;
2509
char addr[INET6_ADDRSTRLEN];
2511
if ( is_zero_addr(client_ss) ) {
2512
DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2514
if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2515
DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2518
print_sockaddr(addr, sizeof(addr), &rm_addr);
2520
rm_addr = *client_ss;
2521
print_sockaddr(addr, sizeof(addr), &rm_addr);
2522
DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2526
if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2527
DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2532
/* setup the connection */
2533
ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2534
&rm_addr, 0, "IPC$", "IPC",
2538
0, lp_client_signing());
2540
if ( !NT_STATUS_IS_OK( ret ) ) {
2541
DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2546
if ( the_cli->protocol != PROTOCOL_NT1 ) {
2547
DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2548
cli_shutdown(the_cli);
2553
* Ok - we have an anonymous connection to the IPC$ share.
2554
* Now start the NT Domain stuff :-).
2557
ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2558
if (!NT_STATUS_IS_OK(ret)) {
2559
DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2560
remote_machine, nt_errstr(ret)));
2561
cli_shutdown(the_cli);
2568
/***************************************************************************
2569
Connect to the client.
2570
****************************************************************************/
2572
static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2573
uint32_t localprinter,
2574
enum winreg_Type type,
2575
struct policy_handle *handle,
2576
struct notify_back_channel **_chan,
2577
struct sockaddr_storage *client_ss,
2578
struct messaging_context *msg_ctx)
2582
struct notify_back_channel *chan;
2584
for (chan = back_channels; chan; chan = chan->next) {
2585
if (memcmp(&chan->client_address, client_ss,
2586
sizeof(struct sockaddr_storage)) == 0) {
2592
* If it's the first connection, contact the client
2593
* and connect to the IPC$ share anonymously
2596
fstring unix_printer;
2598
/* the +2 is to strip the leading 2 backslashs */
2599
fstrcpy(unix_printer, printer + 2);
2601
chan = talloc_zero(back_channels, struct notify_back_channel);
2605
chan->client_address = *client_ss;
2607
if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2611
chan->binding_handle = chan->cli_pipe->binding_handle;
2613
DLIST_ADD(back_channels, chan);
2615
messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2616
receive_notify2_message_list);
2617
/* Tell the connections db we're now interested in printer
2618
* notify messages. */
2619
serverid_register_msg_flags(messaging_server_id(msg_ctx),
2620
true, FLAG_MSG_PRINT_NOTIFY);
2624
* Tell the specific printing tdb we want messages for this printer
2625
* by registering our PID.
2628
if (!print_notify_register_pid(snum)) {
2629
DEBUG(0, ("Failed to register our pid for printer %s\n",
2633
status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2642
if (!NT_STATUS_IS_OK(status)) {
2643
DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2644
result = ntstatus_to_werror(status);
2645
} else if (!W_ERROR_IS_OK(result)) {
2646
DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2649
chan->active_connections++;
2652
return (W_ERROR_IS_OK(result));
2655
/****************************************************************
2656
****************************************************************/
2658
static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2659
const struct spoolss_NotifyOption *r)
2661
struct spoolss_NotifyOption *option;
2668
option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2675
if (!option->count) {
2679
option->types = talloc_zero_array(option,
2680
struct spoolss_NotifyOptionType, option->count);
2681
if (!option->types) {
2682
talloc_free(option);
2686
for (i=0; i < option->count; i++) {
2687
option->types[i] = r->types[i];
2689
if (option->types[i].count) {
2690
option->types[i].fields = talloc_zero_array(option,
2691
union spoolss_Field, option->types[i].count);
2692
if (!option->types[i].fields) {
2693
talloc_free(option);
2696
for (k=0; k<option->types[i].count; k++) {
2697
option->types[i].fields[k] =
2698
r->types[i].fields[k];
2706
/****************************************************************
2707
* _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2709
* before replying OK: status=0 a rpc call is made to the workstation
2710
* asking ReplyOpenPrinter
2712
* in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2713
* called from api_spoolss_rffpcnex
2714
****************************************************************/
2716
WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2717
struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2720
struct spoolss_NotifyOption *option = r->in.notify_options;
2721
struct sockaddr_storage client_ss;
2723
/* store the notify value in the printer struct */
2725
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2728
DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2729
"Invalid handle (%s:%u:%u).\n",
2730
OUR_HANDLE(r->in.handle)));
2734
Printer->notify.flags = r->in.flags;
2735
Printer->notify.options = r->in.options;
2736
Printer->notify.printerlocal = r->in.printer_local;
2737
Printer->notify.msg_ctx = p->msg_ctx;
2739
TALLOC_FREE(Printer->notify.option);
2740
Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2742
fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2744
/* Connect to the client machine and send a ReplyOpenPrinter */
2746
if ( Printer->printer_type == SPLHND_SERVER)
2748
else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2749
!get_printer_snum(p, r->in.handle, &snum, NULL) )
2752
DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2753
"client_address is %s\n", p->client_id->addr));
2755
if (!lp_print_notify_backchannel(snum)) {
2756
DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2757
"backchannel disabled\n"));
2758
return WERR_SERVER_UNAVAILABLE;
2761
if (!interpret_string_addr(&client_ss, p->client_id->addr,
2763
return WERR_SERVER_UNAVAILABLE;
2766
if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2767
Printer->notify.printerlocal, REG_SZ,
2768
&Printer->notify.cli_hnd,
2769
&Printer->notify.cli_chan,
2770
&client_ss, p->msg_ctx)) {
2771
return WERR_SERVER_UNAVAILABLE;
2777
/*******************************************************************
2778
* fill a notify_info_data with the servername
2779
********************************************************************/
2781
static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2783
struct spoolss_Notify *data,
2784
print_queue_struct *queue,
2785
struct spoolss_PrinterInfo2 *pinfo2,
2786
TALLOC_CTX *mem_ctx)
2788
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2791
/*******************************************************************
2792
* fill a notify_info_data with the printername (not including the servername).
2793
********************************************************************/
2795
static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2797
struct spoolss_Notify *data,
2798
print_queue_struct *queue,
2799
struct spoolss_PrinterInfo2 *pinfo2,
2800
TALLOC_CTX *mem_ctx)
2802
/* the notify name should not contain the \\server\ part */
2803
const char *p = strrchr(pinfo2->printername, '\\');
2806
p = pinfo2->printername;
2811
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2814
/*******************************************************************
2815
* fill a notify_info_data with the servicename
2816
********************************************************************/
2818
static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2820
struct spoolss_Notify *data,
2821
print_queue_struct *queue,
2822
struct spoolss_PrinterInfo2 *pinfo2,
2823
TALLOC_CTX *mem_ctx)
2825
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2828
/*******************************************************************
2829
* fill a notify_info_data with the port name
2830
********************************************************************/
2832
static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2834
struct spoolss_Notify *data,
2835
print_queue_struct *queue,
2836
struct spoolss_PrinterInfo2 *pinfo2,
2837
TALLOC_CTX *mem_ctx)
2839
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2842
/*******************************************************************
2843
* fill a notify_info_data with the printername
2844
* but it doesn't exist, have to see what to do
2845
********************************************************************/
2847
static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2849
struct spoolss_Notify *data,
2850
print_queue_struct *queue,
2851
struct spoolss_PrinterInfo2 *pinfo2,
2852
TALLOC_CTX *mem_ctx)
2854
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2857
/*******************************************************************
2858
* fill a notify_info_data with the comment
2859
********************************************************************/
2861
static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2863
struct spoolss_Notify *data,
2864
print_queue_struct *queue,
2865
struct spoolss_PrinterInfo2 *pinfo2,
2866
TALLOC_CTX *mem_ctx)
2870
if (*pinfo2->comment == '\0') {
2871
p = lp_comment(snum);
2873
p = pinfo2->comment;
2876
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2879
/*******************************************************************
2880
* fill a notify_info_data with the comment
2881
* location = "Room 1, floor 2, building 3"
2882
********************************************************************/
2884
static void spoolss_notify_location(struct messaging_context *msg_ctx,
2886
struct spoolss_Notify *data,
2887
print_queue_struct *queue,
2888
struct spoolss_PrinterInfo2 *pinfo2,
2889
TALLOC_CTX *mem_ctx)
2891
const char *loc = pinfo2->location;
2894
status = printer_list_get_printer(mem_ctx,
2899
if (NT_STATUS_IS_OK(status)) {
2901
loc = pinfo2->location;
2905
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2908
/*******************************************************************
2909
* fill a notify_info_data with the device mode
2910
* jfm:xxxx don't to it for know but that's a real problem !!!
2911
********************************************************************/
2913
static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2915
struct spoolss_Notify *data,
2916
print_queue_struct *queue,
2917
struct spoolss_PrinterInfo2 *pinfo2,
2918
TALLOC_CTX *mem_ctx)
2920
/* for a dummy implementation we have to zero the fields */
2921
SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2924
/*******************************************************************
2925
* fill a notify_info_data with the separator file name
2926
********************************************************************/
2928
static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2930
struct spoolss_Notify *data,
2931
print_queue_struct *queue,
2932
struct spoolss_PrinterInfo2 *pinfo2,
2933
TALLOC_CTX *mem_ctx)
2935
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2938
/*******************************************************************
2939
* fill a notify_info_data with the print processor
2940
* jfm:xxxx return always winprint to indicate we don't do anything to it
2941
********************************************************************/
2943
static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2945
struct spoolss_Notify *data,
2946
print_queue_struct *queue,
2947
struct spoolss_PrinterInfo2 *pinfo2,
2948
TALLOC_CTX *mem_ctx)
2950
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2953
/*******************************************************************
2954
* fill a notify_info_data with the print processor options
2955
* jfm:xxxx send an empty string
2956
********************************************************************/
2958
static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2960
struct spoolss_Notify *data,
2961
print_queue_struct *queue,
2962
struct spoolss_PrinterInfo2 *pinfo2,
2963
TALLOC_CTX *mem_ctx)
2965
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2968
/*******************************************************************
2969
* fill a notify_info_data with the data type
2970
* jfm:xxxx always send RAW as data type
2971
********************************************************************/
2973
static void spoolss_notify_datatype(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_STRING(data, pinfo2->datatype);
2983
/*******************************************************************
2984
* fill a notify_info_data with the security descriptor
2985
* jfm:xxxx send an null pointer to say no security desc
2986
* have to implement security before !
2987
********************************************************************/
2989
static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2991
struct spoolss_Notify *data,
2992
print_queue_struct *queue,
2993
struct spoolss_PrinterInfo2 *pinfo2,
2994
TALLOC_CTX *mem_ctx)
2996
SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2999
/*******************************************************************
3000
* fill a notify_info_data with the attributes
3001
* jfm:xxxx a samba printer is always shared
3002
********************************************************************/
3004
static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3006
struct spoolss_Notify *data,
3007
print_queue_struct *queue,
3008
struct spoolss_PrinterInfo2 *pinfo2,
3009
TALLOC_CTX *mem_ctx)
3011
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3014
/*******************************************************************
3015
* fill a notify_info_data with the priority
3016
********************************************************************/
3018
static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3020
struct spoolss_Notify *data,
3021
print_queue_struct *queue,
3022
struct spoolss_PrinterInfo2 *pinfo2,
3023
TALLOC_CTX *mem_ctx)
3025
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3028
/*******************************************************************
3029
* fill a notify_info_data with the default priority
3030
********************************************************************/
3032
static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3034
struct spoolss_Notify *data,
3035
print_queue_struct *queue,
3036
struct spoolss_PrinterInfo2 *pinfo2,
3037
TALLOC_CTX *mem_ctx)
3039
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3042
/*******************************************************************
3043
* fill a notify_info_data with the start time
3044
********************************************************************/
3046
static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3048
struct spoolss_Notify *data,
3049
print_queue_struct *queue,
3050
struct spoolss_PrinterInfo2 *pinfo2,
3051
TALLOC_CTX *mem_ctx)
3053
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3056
/*******************************************************************
3057
* fill a notify_info_data with the until time
3058
********************************************************************/
3060
static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3062
struct spoolss_Notify *data,
3063
print_queue_struct *queue,
3064
struct spoolss_PrinterInfo2 *pinfo2,
3065
TALLOC_CTX *mem_ctx)
3067
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3070
/*******************************************************************
3071
* fill a notify_info_data with the status
3072
********************************************************************/
3074
static void spoolss_notify_status(struct messaging_context *msg_ctx,
3076
struct spoolss_Notify *data,
3077
print_queue_struct *queue,
3078
struct spoolss_PrinterInfo2 *pinfo2,
3079
TALLOC_CTX *mem_ctx)
3081
print_status_struct status;
3083
print_queue_length(msg_ctx, snum, &status);
3084
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3087
/*******************************************************************
3088
* fill a notify_info_data with the number of jobs queued
3089
********************************************************************/
3091
static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3093
struct spoolss_Notify *data,
3094
print_queue_struct *queue,
3095
struct spoolss_PrinterInfo2 *pinfo2,
3096
TALLOC_CTX *mem_ctx)
3098
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3099
data, print_queue_length(msg_ctx, snum, NULL));
3102
/*******************************************************************
3103
* fill a notify_info_data with the average ppm
3104
********************************************************************/
3106
static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3108
struct spoolss_Notify *data,
3109
print_queue_struct *queue,
3110
struct spoolss_PrinterInfo2 *pinfo2,
3111
TALLOC_CTX *mem_ctx)
3113
/* always respond 8 pages per minutes */
3114
/* a little hard ! */
3115
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3118
/*******************************************************************
3119
* fill a notify_info_data with username
3120
********************************************************************/
3122
static void spoolss_notify_username(struct messaging_context *msg_ctx,
3124
struct spoolss_Notify *data,
3125
print_queue_struct *queue,
3126
struct spoolss_PrinterInfo2 *pinfo2,
3127
TALLOC_CTX *mem_ctx)
3129
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3132
/*******************************************************************
3133
* fill a notify_info_data with job status
3134
********************************************************************/
3136
static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3138
struct spoolss_Notify *data,
3139
print_queue_struct *queue,
3140
struct spoolss_PrinterInfo2 *pinfo2,
3141
TALLOC_CTX *mem_ctx)
3143
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3146
/*******************************************************************
3147
* fill a notify_info_data with job name
3148
********************************************************************/
3150
static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3152
struct spoolss_Notify *data,
3153
print_queue_struct *queue,
3154
struct spoolss_PrinterInfo2 *pinfo2,
3155
TALLOC_CTX *mem_ctx)
3157
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3160
/*******************************************************************
3161
* fill a notify_info_data with job status
3162
********************************************************************/
3164
static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3166
struct spoolss_Notify *data,
3167
print_queue_struct *queue,
3168
struct spoolss_PrinterInfo2 *pinfo2,
3169
TALLOC_CTX *mem_ctx)
3172
* Now we're returning job status codes we just return a "" here. JRA.
3177
#if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3180
switch (queue->status) {
3185
p = ""; /* NT provides the paused string */
3194
#endif /* NO LONGER NEEDED. */
3196
SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3199
/*******************************************************************
3200
* fill a notify_info_data with job time
3201
********************************************************************/
3203
static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3205
struct spoolss_Notify *data,
3206
print_queue_struct *queue,
3207
struct spoolss_PrinterInfo2 *pinfo2,
3208
TALLOC_CTX *mem_ctx)
3210
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3213
/*******************************************************************
3214
* fill a notify_info_data with job size
3215
********************************************************************/
3217
static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3219
struct spoolss_Notify *data,
3220
print_queue_struct *queue,
3221
struct spoolss_PrinterInfo2 *pinfo2,
3222
TALLOC_CTX *mem_ctx)
3224
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3227
/*******************************************************************
3228
* fill a notify_info_data with page info
3229
********************************************************************/
3230
static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3232
struct spoolss_Notify *data,
3233
print_queue_struct *queue,
3234
struct spoolss_PrinterInfo2 *pinfo2,
3235
TALLOC_CTX *mem_ctx)
3237
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3240
/*******************************************************************
3241
* fill a notify_info_data with pages printed info.
3242
********************************************************************/
3243
static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3245
struct spoolss_Notify *data,
3246
print_queue_struct *queue,
3247
struct spoolss_PrinterInfo2 *pinfo2,
3248
TALLOC_CTX *mem_ctx)
3250
/* Add code when back-end tracks this */
3251
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3254
/*******************************************************************
3255
Fill a notify_info_data with job position.
3256
********************************************************************/
3258
static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3260
struct spoolss_Notify *data,
3261
print_queue_struct *queue,
3262
struct spoolss_PrinterInfo2 *pinfo2,
3263
TALLOC_CTX *mem_ctx)
3265
SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3268
/*******************************************************************
3269
Fill a notify_info_data with submitted time.
3270
********************************************************************/
3272
static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3274
struct spoolss_Notify *data,
3275
print_queue_struct *queue,
3276
struct spoolss_PrinterInfo2 *pinfo2,
3277
TALLOC_CTX *mem_ctx)
3279
data->data.string.string = NULL;
3280
data->data.string.size = 0;
3282
init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3283
&data->data.string.string,
3284
&data->data.string.size);
3288
struct s_notify_info_data_table
3290
enum spoolss_NotifyType type;
3293
enum spoolss_NotifyTable variable_type;
3294
void (*fn) (struct messaging_context *msg_ctx,
3295
int snum, struct spoolss_Notify *data,
3296
print_queue_struct *queue,
3297
struct spoolss_PrinterInfo2 *pinfo2,
3298
TALLOC_CTX *mem_ctx);
3301
/* A table describing the various print notification constants and
3302
whether the notification data is a pointer to a variable sized
3303
buffer, a one value uint32_t or a two value uint32_t. */
3305
static const struct s_notify_info_data_table notify_info_data_table[] =
3307
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3308
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3309
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3310
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3311
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3312
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3313
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3314
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3315
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3316
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3317
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3318
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3319
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3320
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3321
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3322
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3323
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3324
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3325
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3326
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3327
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3328
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3329
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3330
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3331
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3332
{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3333
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3334
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3335
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3336
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3337
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3338
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3339
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3340
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3341
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3342
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3343
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3344
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3345
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3346
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3347
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3348
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3349
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3350
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3351
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3352
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3353
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3354
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3355
{ JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3358
/*******************************************************************
3359
Return the variable_type of info_data structure.
3360
********************************************************************/
3362
static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3367
for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3368
if ( (notify_info_data_table[i].type == type) &&
3369
(notify_info_data_table[i].field == field) ) {
3370
return notify_info_data_table[i].variable_type;
3374
DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3376
return (enum spoolss_NotifyTable) 0;
3379
/****************************************************************************
3380
****************************************************************************/
3382
static bool search_notify(enum spoolss_NotifyType type,
3388
for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3389
if (notify_info_data_table[i].type == type &&
3390
notify_info_data_table[i].field == field &&
3391
notify_info_data_table[i].fn != NULL) {
3400
/****************************************************************************
3401
****************************************************************************/
3403
static void construct_info_data(struct spoolss_Notify *info_data,
3404
enum spoolss_NotifyType type,
3405
uint16_t field, int id)
3407
info_data->type = type;
3408
info_data->field.field = field;
3409
info_data->variable_type = variable_type_of_notify_info_data(type, field);
3410
info_data->job_id = id;
3413
/*******************************************************************
3415
* fill a notify_info struct with info asked
3417
********************************************************************/
3419
static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3420
struct printer_handle *print_hnd,
3421
struct spoolss_NotifyInfo *info,
3422
struct spoolss_PrinterInfo2 *pinfo2,
3424
const struct spoolss_NotifyOptionType *option_type,
3426
TALLOC_CTX *mem_ctx)
3429
enum spoolss_NotifyType type;
3432
struct spoolss_Notify *current_data;
3434
type = option_type->type;
3436
DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3437
(type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3438
option_type->count, lp_servicename(snum)));
3440
for(field_num=0; field_num < option_type->count; field_num++) {
3441
field = option_type->fields[field_num].field;
3443
DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3445
if (!search_notify(type, field, &j) )
3448
info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3449
struct spoolss_Notify,
3451
if (info->notifies == NULL) {
3452
DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3456
current_data = &info->notifies[info->count];
3458
construct_info_data(current_data, type, field, id);
3460
DEBUG(10, ("construct_notify_printer_info: "
3461
"calling [%s] snum=%d printername=[%s])\n",
3462
notify_info_data_table[j].name, snum,
3463
pinfo2->printername));
3465
notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3466
NULL, pinfo2, mem_ctx);
3474
/*******************************************************************
3476
* fill a notify_info struct with info asked
3478
********************************************************************/
3480
static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3481
print_queue_struct *queue,
3482
struct spoolss_NotifyInfo *info,
3483
struct spoolss_PrinterInfo2 *pinfo2,
3485
const struct spoolss_NotifyOptionType *option_type,
3487
TALLOC_CTX *mem_ctx)
3490
enum spoolss_NotifyType type;
3492
struct spoolss_Notify *current_data;
3494
DEBUG(4,("construct_notify_jobs_info\n"));
3496
type = option_type->type;
3498
DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3499
(type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3500
option_type->count));
3502
for(field_num=0; field_num<option_type->count; field_num++) {
3503
field = option_type->fields[field_num].field;
3505
if (!search_notify(type, field, &j) )
3508
info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3509
struct spoolss_Notify,
3511
if (info->notifies == NULL) {
3512
DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3516
current_data=&(info->notifies[info->count]);
3518
construct_info_data(current_data, type, field, id);
3519
notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3520
queue, pinfo2, mem_ctx);
3528
* JFM: The enumeration is not that simple, it's even non obvious.
3530
* let's take an example: I want to monitor the PRINTER SERVER for
3531
* the printer's name and the number of jobs currently queued.
3532
* So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3533
* Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3535
* I have 3 printers on the back of my server.
3537
* Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3540
* 1 printer 1 name 1
3541
* 2 printer 1 cjob 1
3542
* 3 printer 2 name 2
3543
* 4 printer 2 cjob 2
3544
* 5 printer 3 name 3
3545
* 6 printer 3 name 3
3547
* that's the print server case, the printer case is even worse.
3550
/*******************************************************************
3552
* enumerate all printers on the printserver
3553
* fill a notify_info struct with info asked
3555
********************************************************************/
3557
static WERROR printserver_notify_info(struct pipes_struct *p,
3558
struct policy_handle *hnd,
3559
struct spoolss_NotifyInfo *info,
3560
TALLOC_CTX *mem_ctx)
3563
struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3564
int n_services=lp_numservices();
3566
struct spoolss_NotifyOption *option;
3567
struct spoolss_NotifyOptionType option_type;
3568
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3571
DEBUG(4,("printserver_notify_info\n"));
3576
option = Printer->notify.option;
3579
info->notifies = NULL;
3582
/* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3583
sending a ffpcn() request first */
3588
for (i=0; i<option->count; i++) {
3589
option_type = option->types[i];
3591
if (option_type.type != PRINTER_NOTIFY_TYPE)
3594
for (snum = 0; snum < n_services; snum++) {
3595
if (!lp_browseable(snum) ||
3596
!lp_snum_ok(snum) ||
3597
!lp_print_ok(snum)) {
3598
continue; /* skip */
3601
/* Maybe we should use the SYSTEM session_info here... */
3602
result = winreg_get_printer_internal(mem_ctx,
3603
get_session_info_system(),
3605
lp_servicename(snum),
3607
if (!W_ERROR_IS_OK(result)) {
3608
DEBUG(4, ("printserver_notify_info: "
3609
"Failed to get printer [%s]\n",
3610
lp_servicename(snum)));
3615
construct_notify_printer_info(p->msg_ctx,
3621
TALLOC_FREE(pinfo2);
3627
* Debugging information, don't delete.
3630
DEBUG(1,("dumping the NOTIFY_INFO\n"));
3631
DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3632
DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3634
for (i=0; i<info->count; i++) {
3635
DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3636
i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3637
info->data[i].id, info->data[i].size, info->data[i].enc_type));
3644
/*******************************************************************
3646
* fill a notify_info struct with info asked
3648
********************************************************************/
3650
static WERROR printer_notify_info(struct pipes_struct *p,
3651
struct policy_handle *hnd,
3652
struct spoolss_NotifyInfo *info,
3653
TALLOC_CTX *mem_ctx)
3656
struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3659
struct spoolss_NotifyOption *option;
3660
struct spoolss_NotifyOptionType option_type;
3662
print_queue_struct *queue=NULL;
3663
print_status_struct status;
3664
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3667
DEBUG(4,("printer_notify_info\n"));
3672
option = Printer->notify.option;
3676
info->notifies = NULL;
3679
/* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3680
sending a ffpcn() request first */
3685
if (!get_printer_snum(p, hnd, &snum, NULL)) {
3689
/* Maybe we should use the SYSTEM session_info here... */
3690
result = winreg_get_printer_internal(mem_ctx,
3691
get_session_info_system(),
3693
lp_servicename(snum), &pinfo2);
3694
if (!W_ERROR_IS_OK(result)) {
3699
* When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3700
* correct servername.
3702
pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3703
if (pinfo2->servername == NULL) {
3707
for (i=0; i<option->count; i++) {
3708
option_type = option->types[i];
3710
switch (option_type.type) {
3711
case PRINTER_NOTIFY_TYPE:
3712
if (construct_notify_printer_info(p->msg_ctx,
3721
case JOB_NOTIFY_TYPE:
3723
count = print_queue_status(p->msg_ctx, snum, &queue,
3726
for (j=0; j<count; j++) {
3727
construct_notify_jobs_info(p->msg_ctx,
3741
* Debugging information, don't delete.
3744
DEBUG(1,("dumping the NOTIFY_INFO\n"));
3745
DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3746
DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3748
for (i=0; i<info->count; i++) {
3749
DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3750
i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3751
info->data[i].id, info->data[i].size, info->data[i].enc_type));
3755
talloc_free(pinfo2);
3759
/****************************************************************
3760
_spoolss_RouterRefreshPrinterChangeNotify
3761
****************************************************************/
3763
WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3764
struct spoolss_RouterRefreshPrinterChangeNotify *r)
3766
struct spoolss_NotifyInfo *info;
3768
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3769
WERROR result = WERR_BADFID;
3771
/* we always have a spoolss_NotifyInfo struct */
3772
info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3774
result = WERR_NOMEM;
3778
*r->out.info = info;
3781
DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3782
"Invalid handle (%s:%u:%u).\n",
3783
OUR_HANDLE(r->in.handle)));
3787
DEBUG(4,("Printer type %x\n",Printer->printer_type));
3790
* We are now using the change value, and
3791
* I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3792
* I don't have a global notification system, I'm sending back all the
3793
* information even when _NOTHING_ has changed.
3796
/* We need to keep track of the change value to send back in
3797
RRPCN replies otherwise our updates are ignored. */
3799
Printer->notify.fnpcn = true;
3801
if (Printer->notify.cli_chan != NULL &&
3802
Printer->notify.cli_chan->active_connections > 0) {
3803
DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3804
"Saving change value in request [%x]\n",
3806
Printer->notify.change = r->in.change_low;
3809
/* just ignore the spoolss_NotifyOption */
3811
switch (Printer->printer_type) {
3813
result = printserver_notify_info(p, r->in.handle,
3817
case SPLHND_PRINTER:
3818
result = printer_notify_info(p, r->in.handle,
3823
Printer->notify.fnpcn = false;
3829
/********************************************************************
3830
********************************************************************/
3832
static WERROR create_printername(TALLOC_CTX *mem_ctx,
3833
const char *servername,
3834
const char *printername,
3835
const char **printername_p)
3837
/* FIXME: add lp_force_printername() */
3839
if (servername == NULL) {
3840
*printername_p = talloc_strdup(mem_ctx, printername);
3841
W_ERROR_HAVE_NO_MEMORY(*printername_p);
3845
if (servername[0] == '\\' && servername[1] == '\\') {
3849
*printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3850
W_ERROR_HAVE_NO_MEMORY(*printername_p);
3855
/********************************************************************
3856
********************************************************************/
3858
static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3859
const char *printername)
3865
dm->devicename = talloc_strndup(dm, printername,
3866
MIN(strlen(printername), 31));
3869
/********************************************************************
3870
* construct_printer_info_0
3871
* fill a printer_info_0 struct
3872
********************************************************************/
3874
static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3875
const struct auth_serversupplied_info *session_info,
3876
struct messaging_context *msg_ctx,
3877
struct spoolss_PrinterInfo2 *info2,
3878
const char *servername,
3879
struct spoolss_PrinterInfo0 *r,
3883
struct printer_session_counter *session_counter;
3884
struct timeval setuptime;
3885
print_status_struct status;
3888
result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3889
if (!W_ERROR_IS_OK(result)) {
3894
r->servername = talloc_strdup(mem_ctx, servername);
3895
W_ERROR_HAVE_NO_MEMORY(r->servername);
3897
r->servername = NULL;
3900
count = print_queue_length(msg_ctx, snum, &status);
3902
/* check if we already have a counter for this printer */
3903
for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3904
if (session_counter->snum == snum)
3908
/* it's the first time, add it to the list */
3909
if (session_counter == NULL) {
3910
session_counter = talloc_zero(counter_list, struct printer_session_counter);
3911
W_ERROR_HAVE_NO_MEMORY(session_counter);
3912
session_counter->snum = snum;
3913
session_counter->counter = 0;
3914
DLIST_ADD(counter_list, session_counter);
3918
session_counter->counter++;
3924
get_startup_time(&setuptime);
3925
init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3928
* the global_counter should be stored in a TDB as it's common to all the clients
3929
* and should be zeroed on samba startup
3931
r->global_counter = session_counter->counter;
3933
/* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3934
SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3935
SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3936
r->free_build = SPOOLSS_RELEASE_BUILD;
3938
r->max_spooling = 0;
3939
r->session_counter = session_counter->counter;
3940
r->num_error_out_of_paper = 0x0;
3941
r->num_error_not_ready = 0x0; /* number of print failure */
3943
r->number_of_processors = 0x1;
3944
r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3945
r->high_part_total_bytes = 0x0;
3947
/* ChangeID in milliseconds*/
3948
winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3949
info2->sharename, &r->change_id);
3951
r->last_error = WERR_OK;
3952
r->status = nt_printq_status(status.status);
3953
r->enumerate_network_printers = 0x0;
3954
r->c_setprinter = 0x0;
3955
r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3956
r->processor_level = 0x6; /* 6 ???*/
3965
/********************************************************************
3966
* construct_printer_info1
3967
* fill a spoolss_PrinterInfo1 struct
3968
********************************************************************/
3970
static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3971
const struct spoolss_PrinterInfo2 *info2,
3973
const char *servername,
3974
struct spoolss_PrinterInfo1 *r,
3981
if (info2->comment == NULL || info2->comment[0] == '\0') {
3982
r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3984
r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3986
W_ERROR_HAVE_NO_MEMORY(r->comment);
3988
result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3989
if (!W_ERROR_IS_OK(result)) {
3993
r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3997
W_ERROR_HAVE_NO_MEMORY(r->description);
4002
/********************************************************************
4003
* construct_printer_info2
4004
* fill a spoolss_PrinterInfo2 struct
4005
********************************************************************/
4007
static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4008
struct messaging_context *msg_ctx,
4009
const struct spoolss_PrinterInfo2 *info2,
4010
const char *servername,
4011
struct spoolss_PrinterInfo2 *r,
4015
print_status_struct status;
4018
count = print_queue_length(msg_ctx, snum, &status);
4021
r->servername = talloc_strdup(mem_ctx, servername);
4022
W_ERROR_HAVE_NO_MEMORY(r->servername);
4024
r->servername = NULL;
4027
result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4028
if (!W_ERROR_IS_OK(result)) {
4032
r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4033
W_ERROR_HAVE_NO_MEMORY(r->sharename);
4034
r->portname = talloc_strdup(mem_ctx, info2->portname);
4035
W_ERROR_HAVE_NO_MEMORY(r->portname);
4036
r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4037
W_ERROR_HAVE_NO_MEMORY(r->drivername);
4039
if (info2->comment[0] == '\0') {
4040
r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4042
r->comment = talloc_strdup(mem_ctx, info2->comment);
4044
W_ERROR_HAVE_NO_MEMORY(r->comment);
4046
r->location = talloc_strdup(mem_ctx, info2->location);
4047
if (info2->location[0] == '\0') {
4048
const char *loc = NULL;
4051
nt_status = printer_list_get_printer(mem_ctx,
4056
if (NT_STATUS_IS_OK(nt_status)) {
4058
r->location = talloc_strdup(mem_ctx, loc);
4062
W_ERROR_HAVE_NO_MEMORY(r->location);
4064
r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4065
W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4066
r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4067
W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4068
r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4069
W_ERROR_HAVE_NO_MEMORY(r->datatype);
4070
r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4071
W_ERROR_HAVE_NO_MEMORY(r->parameters);
4073
r->attributes = info2->attributes;
4075
r->priority = info2->priority;
4076
r->defaultpriority = info2->defaultpriority;
4077
r->starttime = info2->starttime;
4078
r->untiltime = info2->untiltime;
4079
r->status = nt_printq_status(status.status);
4081
r->averageppm = info2->averageppm;
4083
copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4085
DEBUG(8,("Returning NULL Devicemode!\n"));
4088
compose_devicemode_devicename(r->devmode, r->printername);
4092
if (info2->secdesc != NULL) {
4093
/* don't use talloc_steal() here unless you do a deep steal of all
4094
the SEC_DESC members */
4096
r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4102
/********************************************************************
4103
* construct_printer_info3
4104
* fill a spoolss_PrinterInfo3 struct
4105
********************************************************************/
4107
static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4108
const struct spoolss_PrinterInfo2 *info2,
4109
const char *servername,
4110
struct spoolss_PrinterInfo3 *r,
4113
/* These are the components of the SD we are returning. */
4115
if (info2->secdesc != NULL) {
4116
/* don't use talloc_steal() here unless you do a deep steal of all
4117
the SEC_DESC members */
4119
r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4120
W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4126
/********************************************************************
4127
* construct_printer_info4
4128
* fill a spoolss_PrinterInfo4 struct
4129
********************************************************************/
4131
static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4132
const struct spoolss_PrinterInfo2 *info2,
4133
const char *servername,
4134
struct spoolss_PrinterInfo4 *r,
4139
result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4140
if (!W_ERROR_IS_OK(result)) {
4145
r->servername = talloc_strdup(mem_ctx, servername);
4146
W_ERROR_HAVE_NO_MEMORY(r->servername);
4148
r->servername = NULL;
4151
r->attributes = info2->attributes;
4156
/********************************************************************
4157
* construct_printer_info5
4158
* fill a spoolss_PrinterInfo5 struct
4159
********************************************************************/
4161
static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4162
const struct spoolss_PrinterInfo2 *info2,
4163
const char *servername,
4164
struct spoolss_PrinterInfo5 *r,
4169
result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4170
if (!W_ERROR_IS_OK(result)) {
4174
r->portname = talloc_strdup(mem_ctx, info2->portname);
4175
W_ERROR_HAVE_NO_MEMORY(r->portname);
4177
r->attributes = info2->attributes;
4179
/* these two are not used by NT+ according to MSDN */
4180
r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4181
r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4186
/********************************************************************
4187
* construct_printer_info_6
4188
* fill a spoolss_PrinterInfo6 struct
4189
********************************************************************/
4191
static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4192
struct messaging_context *msg_ctx,
4193
const struct spoolss_PrinterInfo2 *info2,
4194
const char *servername,
4195
struct spoolss_PrinterInfo6 *r,
4199
print_status_struct status;
4201
count = print_queue_length(msg_ctx, snum, &status);
4203
r->status = nt_printq_status(status.status);
4208
/********************************************************************
4209
* construct_printer_info7
4210
* fill a spoolss_PrinterInfo7 struct
4211
********************************************************************/
4213
static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4214
struct messaging_context *msg_ctx,
4215
const char *servername,
4216
struct spoolss_PrinterInfo7 *r,
4219
struct auth_serversupplied_info *session_info;
4223
status = make_session_info_system(mem_ctx, &session_info);
4224
if (!NT_STATUS_IS_OK(status)) {
4225
DEBUG(0, ("construct_printer_info7: "
4226
"Could not create system session_info\n"));
4230
if (is_printer_published(mem_ctx, session_info, msg_ctx,
4232
lp_servicename(snum), &guid, NULL)) {
4233
r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4234
r->action = DSPRINT_PUBLISH;
4236
r->guid = talloc_strdup(mem_ctx, "");
4237
r->action = DSPRINT_UNPUBLISH;
4239
W_ERROR_HAVE_NO_MEMORY(r->guid);
4241
TALLOC_FREE(session_info);
4245
/********************************************************************
4246
* construct_printer_info8
4247
* fill a spoolss_PrinterInfo8 struct
4248
********************************************************************/
4250
static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4251
const struct spoolss_PrinterInfo2 *info2,
4252
const char *servername,
4253
struct spoolss_DeviceModeInfo *r,
4257
const char *printername;
4259
result = create_printername(mem_ctx, servername, info2->printername, &printername);
4260
if (!W_ERROR_IS_OK(result)) {
4264
copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4266
DEBUG(8,("Returning NULL Devicemode!\n"));
4269
compose_devicemode_devicename(r->devmode, printername);
4275
/********************************************************************
4276
********************************************************************/
4278
static bool snum_is_shared_printer(int snum)
4280
return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4283
/********************************************************************
4284
Spoolss_enumprinters.
4285
********************************************************************/
4287
static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4288
const struct auth_serversupplied_info *session_info,
4289
struct messaging_context *msg_ctx,
4290
const char *servername,
4293
union spoolss_PrinterInfo **info_p,
4297
int n_services = lp_numservices();
4298
union spoolss_PrinterInfo *info = NULL;
4300
WERROR result = WERR_OK;
4301
struct dcerpc_binding_handle *b = NULL;
4306
for (snum = 0; snum < n_services; snum++) {
4308
const char *printer;
4309
struct spoolss_PrinterInfo2 *info2;
4311
if (!snum_is_shared_printer(snum)) {
4315
printer = lp_const_servicename(snum);
4317
DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4321
result = winreg_printer_binding_handle(mem_ctx,
4325
if (!W_ERROR_IS_OK(result)) {
4330
result = winreg_create_printer(mem_ctx, b,
4332
if (!W_ERROR_IS_OK(result)) {
4336
info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4337
union spoolss_PrinterInfo,
4340
result = WERR_NOMEM;
4344
result = winreg_get_printer(mem_ctx, b,
4346
if (!W_ERROR_IS_OK(result)) {
4352
result = construct_printer_info0(info, session_info,
4355
&info[count].info0, snum);
4358
result = construct_printer_info1(info, info2, flags,
4360
&info[count].info1, snum);
4363
result = construct_printer_info2(info, msg_ctx, info2,
4365
&info[count].info2, snum);
4368
result = construct_printer_info4(info, info2,
4370
&info[count].info4, snum);
4373
result = construct_printer_info5(info, info2,
4375
&info[count].info5, snum);
4379
result = WERR_UNKNOWN_LEVEL;
4383
if (!W_ERROR_IS_OK(result)) {
4394
if (!W_ERROR_IS_OK(result)) {
4404
/********************************************************************
4405
* handle enumeration of printers at level 0
4406
********************************************************************/
4408
static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4409
const struct auth_serversupplied_info *session_info,
4410
struct messaging_context *msg_ctx,
4412
const char *servername,
4413
union spoolss_PrinterInfo **info,
4416
DEBUG(4,("enum_all_printers_info_0\n"));
4418
return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4419
servername, 0, flags, info, count);
4423
/********************************************************************
4424
********************************************************************/
4426
static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4427
const struct auth_serversupplied_info *session_info,
4428
struct messaging_context *msg_ctx,
4429
const char *servername,
4431
union spoolss_PrinterInfo **info,
4434
DEBUG(4,("enum_all_printers_info_1\n"));
4436
return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4437
servername, 1, flags, info, count);
4440
/********************************************************************
4441
enum_all_printers_info_1_local.
4442
*********************************************************************/
4444
static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4445
const struct auth_serversupplied_info *session_info,
4446
struct messaging_context *msg_ctx,
4447
const char *servername,
4448
union spoolss_PrinterInfo **info,
4451
DEBUG(4,("enum_all_printers_info_1_local\n"));
4453
return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4454
servername, PRINTER_ENUM_ICON8, info, count);
4457
/********************************************************************
4458
enum_all_printers_info_1_name.
4459
*********************************************************************/
4461
static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4462
const struct auth_serversupplied_info *session_info,
4463
struct messaging_context *msg_ctx,
4464
const char *servername,
4465
union spoolss_PrinterInfo **info,
4468
const char *s = servername;
4470
DEBUG(4,("enum_all_printers_info_1_name\n"));
4472
if ((servername[0] == '\\') && (servername[1] == '\\')) {
4476
if (!is_myname_or_ipaddr(s)) {
4477
return WERR_INVALID_NAME;
4480
return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4481
servername, PRINTER_ENUM_ICON8, info, count);
4484
/********************************************************************
4485
enum_all_printers_info_1_network.
4486
*********************************************************************/
4488
static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4489
const struct auth_serversupplied_info *session_info,
4490
struct messaging_context *msg_ctx,
4491
const char *servername,
4492
union spoolss_PrinterInfo **info,
4495
const char *s = servername;
4497
DEBUG(4,("enum_all_printers_info_1_network\n"));
4499
/* If we respond to a enum_printers level 1 on our name with flags
4500
set to PRINTER_ENUM_REMOTE with a list of printers then these
4501
printers incorrectly appear in the APW browse list.
4502
Specifically the printers for the server appear at the workgroup
4503
level where all the other servers in the domain are
4504
listed. Windows responds to this call with a
4505
WERR_CAN_NOT_COMPLETE so we should do the same. */
4507
if (servername[0] == '\\' && servername[1] == '\\') {
4511
if (is_myname_or_ipaddr(s)) {
4512
return WERR_CAN_NOT_COMPLETE;
4515
return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4516
servername, PRINTER_ENUM_NAME, info, count);
4519
/********************************************************************
4520
* api_spoolss_enumprinters
4522
* called from api_spoolss_enumprinters (see this to understand)
4523
********************************************************************/
4525
static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4526
const struct auth_serversupplied_info *session_info,
4527
struct messaging_context *msg_ctx,
4528
const char *servername,
4529
union spoolss_PrinterInfo **info,
4532
DEBUG(4,("enum_all_printers_info_2\n"));
4534
return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4535
servername, 2, 0, info, count);
4538
/********************************************************************
4539
* handle enumeration of printers at level 1
4540
********************************************************************/
4542
static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4543
const struct auth_serversupplied_info *session_info,
4544
struct messaging_context *msg_ctx,
4546
const char *servername,
4547
union spoolss_PrinterInfo **info,
4550
/* Not all the flags are equals */
4552
if (flags & PRINTER_ENUM_LOCAL) {
4553
return enum_all_printers_info_1_local(mem_ctx, session_info,
4554
msg_ctx, servername, info, count);
4557
if (flags & PRINTER_ENUM_NAME) {
4558
return enum_all_printers_info_1_name(mem_ctx, session_info,
4559
msg_ctx, servername, info,
4563
if (flags & PRINTER_ENUM_NETWORK) {
4564
return enum_all_printers_info_1_network(mem_ctx, session_info,
4565
msg_ctx, servername, info,
4569
return WERR_OK; /* NT4sp5 does that */
4572
/********************************************************************
4573
* handle enumeration of printers at level 2
4574
********************************************************************/
4576
static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4577
const struct auth_serversupplied_info *session_info,
4578
struct messaging_context *msg_ctx,
4580
const char *servername,
4581
union spoolss_PrinterInfo **info,
4584
if (flags & PRINTER_ENUM_LOCAL) {
4586
return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4591
if (flags & PRINTER_ENUM_NAME) {
4592
if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4593
return WERR_INVALID_NAME;
4596
return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4601
if (flags & PRINTER_ENUM_REMOTE) {
4602
return WERR_UNKNOWN_LEVEL;
4608
/********************************************************************
4609
* handle enumeration of printers at level 4
4610
********************************************************************/
4612
static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4613
const struct auth_serversupplied_info *session_info,
4614
struct messaging_context *msg_ctx,
4616
const char *servername,
4617
union spoolss_PrinterInfo **info,
4620
DEBUG(4,("enum_all_printers_info_4\n"));
4622
return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4623
servername, 4, flags, info, count);
4627
/********************************************************************
4628
* handle enumeration of printers at level 5
4629
********************************************************************/
4631
static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4632
const struct auth_serversupplied_info *session_info,
4633
struct messaging_context *msg_ctx,
4635
const char *servername,
4636
union spoolss_PrinterInfo **info,
4639
DEBUG(4,("enum_all_printers_info_5\n"));
4641
return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4642
servername, 5, flags, info, count);
4645
/****************************************************************
4646
_spoolss_EnumPrinters
4647
****************************************************************/
4649
WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4650
struct spoolss_EnumPrinters *r)
4652
const struct auth_serversupplied_info *session_info = get_session_info_system();
4655
/* that's an [in out] buffer */
4657
if (!r->in.buffer && (r->in.offered != 0)) {
4658
return WERR_INVALID_PARAM;
4661
DEBUG(4,("_spoolss_EnumPrinters\n"));
4665
*r->out.info = NULL;
4669
* flags==PRINTER_ENUM_NAME
4670
* if name=="" then enumerates all printers
4671
* if name!="" then enumerate the printer
4672
* flags==PRINTER_ENUM_REMOTE
4673
* name is NULL, enumerate printers
4674
* Level 2: name!="" enumerates printers, name can't be NULL
4675
* Level 3: doesn't exist
4676
* Level 4: does a local registry lookup
4677
* Level 5: same as Level 2
4680
if (r->in.server && r->in.server[0] == '\0') {
4681
r->in.server = NULL;
4684
switch (r->in.level) {
4686
result = enumprinters_level0(p->mem_ctx, session_info,
4687
p->msg_ctx, r->in.flags,
4689
r->out.info, r->out.count);
4692
result = enumprinters_level1(p->mem_ctx, session_info,
4693
p->msg_ctx, r->in.flags,
4695
r->out.info, r->out.count);
4698
result = enumprinters_level2(p->mem_ctx, session_info,
4699
p->msg_ctx, r->in.flags,
4701
r->out.info, r->out.count);
4704
result = enumprinters_level4(p->mem_ctx, session_info,
4705
p->msg_ctx, r->in.flags,
4707
r->out.info, r->out.count);
4710
result = enumprinters_level5(p->mem_ctx, session_info,
4711
p->msg_ctx, r->in.flags,
4713
r->out.info, r->out.count);
4716
return WERR_UNKNOWN_LEVEL;
4719
if (!W_ERROR_IS_OK(result)) {
4723
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4724
spoolss_EnumPrinters,
4725
*r->out.info, r->in.level,
4727
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4728
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4730
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4733
/****************************************************************
4735
****************************************************************/
4737
WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4738
struct spoolss_GetPrinter *r)
4740
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4741
struct spoolss_PrinterInfo2 *info2 = NULL;
4742
WERROR result = WERR_OK;
4745
/* that's an [in out] buffer */
4747
if (!r->in.buffer && (r->in.offered != 0)) {
4748
return WERR_INVALID_PARAM;
4753
if (Printer == NULL) {
4757
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4761
result = winreg_get_printer_internal(p->mem_ctx,
4762
get_session_info_system(),
4764
lp_const_servicename(snum),
4766
if (!W_ERROR_IS_OK(result)) {
4770
switch (r->in.level) {
4772
result = construct_printer_info0(p->mem_ctx,
4773
get_session_info_system(),
4776
Printer->servername,
4777
&r->out.info->info0,
4781
result = construct_printer_info1(p->mem_ctx, info2,
4783
Printer->servername,
4784
&r->out.info->info1, snum);
4787
result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4788
Printer->servername,
4789
&r->out.info->info2, snum);
4792
result = construct_printer_info3(p->mem_ctx, info2,
4793
Printer->servername,
4794
&r->out.info->info3, snum);
4797
result = construct_printer_info4(p->mem_ctx, info2,
4798
Printer->servername,
4799
&r->out.info->info4, snum);
4802
result = construct_printer_info5(p->mem_ctx, info2,
4803
Printer->servername,
4804
&r->out.info->info5, snum);
4807
result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4808
Printer->servername,
4809
&r->out.info->info6, snum);
4812
result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4813
Printer->servername,
4814
&r->out.info->info7, snum);
4817
result = construct_printer_info8(p->mem_ctx, info2,
4818
Printer->servername,
4819
&r->out.info->info8, snum);
4822
result = WERR_UNKNOWN_LEVEL;
4827
if (!W_ERROR_IS_OK(result)) {
4828
DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4829
r->in.level, win_errstr(result)));
4830
TALLOC_FREE(r->out.info);
4834
*r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4835
r->out.info, r->in.level);
4836
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4838
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4841
/********************************************************************
4842
********************************************************************/
4844
#define FILL_DRIVER_STRING(mem_ctx, in, out) \
4846
if (in && strlen(in)) { \
4847
out = talloc_strdup(mem_ctx, in); \
4849
out = talloc_strdup(mem_ctx, ""); \
4851
W_ERROR_HAVE_NO_MEMORY(out); \
4854
#define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4856
if (in && strlen(in)) { \
4857
out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4859
out = talloc_strdup(mem_ctx, ""); \
4861
W_ERROR_HAVE_NO_MEMORY(out); \
4864
static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4865
const char **string_array,
4866
const char ***presult,
4867
const char *cservername,
4871
int i, num_strings = 0;
4872
const char **array = NULL;
4874
if (string_array == NULL) {
4875
return WERR_INVALID_PARAMETER;
4878
for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4879
const char *str = NULL;
4881
if (cservername == NULL || arch == NULL) {
4882
FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4884
FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4887
if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4894
ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4895
&array, &num_strings);
4905
/********************************************************************
4906
* fill a spoolss_DriverInfo1 struct
4907
********************************************************************/
4909
static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4910
struct spoolss_DriverInfo1 *r,
4911
const struct spoolss_DriverInfo8 *driver,
4912
const char *servername)
4914
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4915
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4920
/********************************************************************
4921
* fill a spoolss_DriverInfo2 struct
4922
********************************************************************/
4924
static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4925
struct spoolss_DriverInfo2 *r,
4926
const struct spoolss_DriverInfo8 *driver,
4927
const char *servername)
4930
const char *cservername = canon_servername(servername);
4932
r->version = driver->version;
4934
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4935
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4936
r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4937
W_ERROR_HAVE_NO_MEMORY(r->architecture);
4939
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4940
driver->architecture,
4942
driver->driver_path,
4945
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4946
driver->architecture,
4951
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4952
driver->architecture,
4954
driver->config_file,
4960
/********************************************************************
4961
* fill a spoolss_DriverInfo3 struct
4962
********************************************************************/
4964
static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4965
struct spoolss_DriverInfo3 *r,
4966
const struct spoolss_DriverInfo8 *driver,
4967
const char *servername)
4969
const char *cservername = canon_servername(servername);
4971
r->version = driver->version;
4973
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4974
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4975
r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4976
W_ERROR_HAVE_NO_MEMORY(r->architecture);
4978
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979
driver->architecture,
4981
driver->driver_path,
4984
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985
driver->architecture,
4990
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4991
driver->architecture,
4993
driver->config_file,
4996
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997
driver->architecture,
5002
FILL_DRIVER_STRING(mem_ctx,
5003
driver->monitor_name,
5006
FILL_DRIVER_STRING(mem_ctx,
5007
driver->default_datatype,
5008
r->default_datatype);
5010
return string_array_from_driver_info(mem_ctx,
5011
driver->dependent_files,
5012
&r->dependent_files,
5014
driver->architecture,
5018
/********************************************************************
5019
* fill a spoolss_DriverInfo4 struct
5020
********************************************************************/
5022
static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5023
struct spoolss_DriverInfo4 *r,
5024
const struct spoolss_DriverInfo8 *driver,
5025
const char *servername)
5027
const char *cservername = canon_servername(servername);
5030
r->version = driver->version;
5032
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5033
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5034
r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5035
W_ERROR_HAVE_NO_MEMORY(r->architecture);
5037
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5038
driver->architecture,
5040
driver->driver_path,
5043
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5044
driver->architecture,
5049
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050
driver->architecture,
5052
driver->config_file,
5055
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056
driver->architecture,
5061
result = string_array_from_driver_info(mem_ctx,
5062
driver->dependent_files,
5063
&r->dependent_files,
5065
driver->architecture,
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);
5080
result = string_array_from_driver_info(mem_ctx,
5081
driver->previous_names,
5088
/********************************************************************
5089
* fill a spoolss_DriverInfo5 struct
5090
********************************************************************/
5092
static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5093
struct spoolss_DriverInfo5 *r,
5094
const struct spoolss_DriverInfo8 *driver,
5095
const char *servername)
5097
const char *cservername = canon_servername(servername);
5099
r->version = driver->version;
5101
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5102
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5103
r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5104
W_ERROR_HAVE_NO_MEMORY(r->architecture);
5106
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107
driver->architecture,
5109
driver->driver_path,
5112
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113
driver->architecture,
5118
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119
driver->architecture,
5121
driver->config_file,
5124
r->driver_attributes = 0;
5125
r->config_version = 0;
5126
r->driver_version = 0;
5130
/********************************************************************
5131
* fill a spoolss_DriverInfo6 struct
5132
********************************************************************/
5134
static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5135
struct spoolss_DriverInfo6 *r,
5136
const struct spoolss_DriverInfo8 *driver,
5137
const char *servername)
5139
const char *cservername = canon_servername(servername);
5142
r->version = driver->version;
5144
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5145
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5146
r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5147
W_ERROR_HAVE_NO_MEMORY(r->architecture);
5149
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5150
driver->architecture,
5152
driver->driver_path,
5155
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5156
driver->architecture,
5161
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5162
driver->architecture,
5164
driver->config_file,
5167
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5168
driver->architecture,
5173
FILL_DRIVER_STRING(mem_ctx,
5174
driver->monitor_name,
5177
FILL_DRIVER_STRING(mem_ctx,
5178
driver->default_datatype,
5179
r->default_datatype);
5181
result = string_array_from_driver_info(mem_ctx,
5182
driver->dependent_files,
5183
&r->dependent_files,
5185
driver->architecture,
5187
if (!W_ERROR_IS_OK(result)) {
5191
result = string_array_from_driver_info(mem_ctx,
5192
driver->previous_names,
5195
if (!W_ERROR_IS_OK(result)) {
5199
r->driver_date = driver->driver_date;
5200
r->driver_version = driver->driver_version;
5202
FILL_DRIVER_STRING(mem_ctx,
5203
driver->manufacturer_name,
5204
r->manufacturer_name);
5205
FILL_DRIVER_STRING(mem_ctx,
5206
driver->manufacturer_url,
5207
r->manufacturer_url);
5208
FILL_DRIVER_STRING(mem_ctx,
5209
driver->hardware_id,
5211
FILL_DRIVER_STRING(mem_ctx,
5218
/********************************************************************
5219
* fill a spoolss_DriverInfo8 struct
5220
********************************************************************/
5222
static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5223
struct spoolss_DriverInfo8 *r,
5224
const struct spoolss_DriverInfo8 *driver,
5225
const char *servername)
5227
const char *cservername = canon_servername(servername);
5230
r->version = driver->version;
5232
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5233
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5234
r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5235
W_ERROR_HAVE_NO_MEMORY(r->architecture);
5237
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5238
driver->architecture,
5240
driver->driver_path,
5243
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5244
driver->architecture,
5249
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5250
driver->architecture,
5252
driver->config_file,
5255
FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5256
driver->architecture,
5261
FILL_DRIVER_STRING(mem_ctx,
5262
driver->monitor_name,
5265
FILL_DRIVER_STRING(mem_ctx,
5266
driver->default_datatype,
5267
r->default_datatype);
5269
result = string_array_from_driver_info(mem_ctx,
5270
driver->dependent_files,
5271
&r->dependent_files,
5273
driver->architecture,
5275
if (!W_ERROR_IS_OK(result)) {
5279
result = string_array_from_driver_info(mem_ctx,
5280
driver->previous_names,
5283
if (!W_ERROR_IS_OK(result)) {
5287
r->driver_date = driver->driver_date;
5288
r->driver_version = driver->driver_version;
5290
FILL_DRIVER_STRING(mem_ctx,
5291
driver->manufacturer_name,
5292
r->manufacturer_name);
5293
FILL_DRIVER_STRING(mem_ctx,
5294
driver->manufacturer_url,
5295
r->manufacturer_url);
5296
FILL_DRIVER_STRING(mem_ctx,
5297
driver->hardware_id,
5299
FILL_DRIVER_STRING(mem_ctx,
5303
FILL_DRIVER_STRING(mem_ctx,
5304
driver->print_processor,
5305
r->print_processor);
5306
FILL_DRIVER_STRING(mem_ctx,
5307
driver->vendor_setup,
5310
result = string_array_from_driver_info(mem_ctx,
5311
driver->color_profiles,
5314
if (!W_ERROR_IS_OK(result)) {
5318
FILL_DRIVER_STRING(mem_ctx,
5322
r->printer_driver_attributes = driver->printer_driver_attributes;
5324
result = string_array_from_driver_info(mem_ctx,
5325
driver->core_driver_dependencies,
5326
&r->core_driver_dependencies,
5328
if (!W_ERROR_IS_OK(result)) {
5332
r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5333
r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5338
#if 0 /* disabled until marshalling issues are resolved - gd */
5339
/********************************************************************
5340
********************************************************************/
5342
static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5343
struct spoolss_DriverFileInfo *r,
5344
const char *cservername,
5345
const char *file_name,
5346
enum spoolss_DriverFileType file_type,
5347
uint32_t file_version)
5349
r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5350
cservername, file_name);
5351
W_ERROR_HAVE_NO_MEMORY(r->file_name);
5352
r->file_type = file_type;
5353
r->file_version = file_version;
5358
/********************************************************************
5359
********************************************************************/
5361
static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5362
const struct spoolss_DriverInfo8 *driver,
5363
const char *cservername,
5364
struct spoolss_DriverFileInfo **info_p,
5367
struct spoolss_DriverFileInfo *info = NULL;
5375
if (strlen(driver->driver_path)) {
5376
info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5377
struct spoolss_DriverFileInfo,
5379
W_ERROR_HAVE_NO_MEMORY(info);
5380
result = fill_spoolss_DriverFileInfo(info,
5383
driver->driver_path,
5384
SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5386
W_ERROR_NOT_OK_RETURN(result);
5390
if (strlen(driver->config_file)) {
5391
info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5392
struct spoolss_DriverFileInfo,
5394
W_ERROR_HAVE_NO_MEMORY(info);
5395
result = fill_spoolss_DriverFileInfo(info,
5398
driver->config_file,
5399
SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5401
W_ERROR_NOT_OK_RETURN(result);
5405
if (strlen(driver->data_file)) {
5406
info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5407
struct spoolss_DriverFileInfo,
5409
W_ERROR_HAVE_NO_MEMORY(info);
5410
result = fill_spoolss_DriverFileInfo(info,
5414
SPOOLSS_DRIVER_FILE_TYPE_DATA,
5416
W_ERROR_NOT_OK_RETURN(result);
5420
if (strlen(driver->help_file)) {
5421
info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5422
struct spoolss_DriverFileInfo,
5424
W_ERROR_HAVE_NO_MEMORY(info);
5425
result = fill_spoolss_DriverFileInfo(info,
5429
SPOOLSS_DRIVER_FILE_TYPE_HELP,
5431
W_ERROR_NOT_OK_RETURN(result);
5435
for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5436
info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5437
struct spoolss_DriverFileInfo,
5439
W_ERROR_HAVE_NO_MEMORY(info);
5440
result = fill_spoolss_DriverFileInfo(info,
5443
driver->dependent_files[i],
5444
SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5446
W_ERROR_NOT_OK_RETURN(result);
5456
/********************************************************************
5457
* fill a spoolss_DriverInfo101 struct
5458
********************************************************************/
5460
static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5461
struct spoolss_DriverInfo101 *r,
5462
const struct spoolss_DriverInfo8 *driver,
5463
const char *servername)
5465
const char *cservername = canon_servername(servername);
5468
r->version = driver->version;
5470
r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5471
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5472
r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5473
W_ERROR_HAVE_NO_MEMORY(r->architecture);
5475
result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5479
if (!W_ERROR_IS_OK(result)) {
5483
FILL_DRIVER_STRING(mem_ctx,
5484
driver->monitor_name,
5487
FILL_DRIVER_STRING(mem_ctx,
5488
driver->default_datatype,
5489
r->default_datatype);
5491
result = string_array_from_driver_info(mem_ctx,
5492
driver->previous_names,
5495
if (!W_ERROR_IS_OK(result)) {
5499
r->driver_date = driver->driver_date;
5500
r->driver_version = driver->driver_version;
5502
FILL_DRIVER_STRING(mem_ctx,
5503
driver->manufacturer_name,
5504
r->manufacturer_name);
5505
FILL_DRIVER_STRING(mem_ctx,
5506
driver->manufacturer_url,
5507
r->manufacturer_url);
5508
FILL_DRIVER_STRING(mem_ctx,
5509
driver->hardware_id,
5511
FILL_DRIVER_STRING(mem_ctx,
5518
/********************************************************************
5519
********************************************************************/
5521
static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5522
const struct auth_serversupplied_info *session_info,
5523
struct messaging_context *msg_ctx,
5525
union spoolss_DriverInfo *r,
5527
const char *servername,
5528
const char *architecture,
5531
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5532
struct spoolss_DriverInfo8 *driver;
5534
struct dcerpc_binding_handle *b;
5537
return WERR_UNKNOWN_LEVEL;
5540
result = winreg_printer_binding_handle(mem_ctx,
5544
if (!W_ERROR_IS_OK(result)) {
5548
result = winreg_get_printer(mem_ctx, b,
5549
lp_const_servicename(snum),
5552
DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5553
win_errstr(result)));
5555
if (!W_ERROR_IS_OK(result)) {
5556
return WERR_INVALID_PRINTER_NAME;
5559
result = winreg_get_driver(mem_ctx, b,
5561
pinfo2->drivername, version, &driver);
5563
DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5564
win_errstr(result)));
5566
if (!W_ERROR_IS_OK(result)) {
5568
* Is this a W2k client ?
5572
talloc_free(pinfo2);
5573
return WERR_UNKNOWN_PRINTER_DRIVER;
5576
/* Yes - try again with a WinNT driver. */
5578
result = winreg_get_driver(mem_ctx, b,
5582
DEBUG(8,("construct_printer_driver_level: status: %s\n",
5583
win_errstr(result)));
5584
if (!W_ERROR_IS_OK(result)) {
5585
talloc_free(pinfo2);
5586
return WERR_UNKNOWN_PRINTER_DRIVER;
5592
result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5595
result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5598
result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5601
result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5604
result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5607
result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5610
result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5612
#if 0 /* disabled until marshalling issues are resolved - gd */
5614
result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5618
result = WERR_UNKNOWN_LEVEL;
5622
talloc_free(pinfo2);
5623
talloc_free(driver);
5628
/****************************************************************
5629
_spoolss_GetPrinterDriver2
5630
****************************************************************/
5632
WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5633
struct spoolss_GetPrinterDriver2 *r)
5635
struct printer_handle *printer;
5640
/* that's an [in out] buffer */
5642
if (!r->in.buffer && (r->in.offered != 0)) {
5643
return WERR_INVALID_PARAM;
5646
DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5648
if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5649
DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5650
return WERR_INVALID_PRINTER_NAME;
5654
*r->out.server_major_version = 0;
5655
*r->out.server_minor_version = 0;
5657
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5661
result = construct_printer_driver_info_level(p->mem_ctx,
5662
get_session_info_system(),
5664
r->in.level, r->out.info,
5665
snum, printer->servername,
5667
r->in.client_major_version);
5668
if (!W_ERROR_IS_OK(result)) {
5669
TALLOC_FREE(r->out.info);
5673
*r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5674
r->out.info, r->in.level);
5675
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5677
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5681
/****************************************************************
5682
_spoolss_StartPagePrinter
5683
****************************************************************/
5685
WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5686
struct spoolss_StartPagePrinter *r)
5688
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5691
DEBUG(3,("_spoolss_StartPagePrinter: "
5692
"Error in startpageprinter printer handle\n"));
5696
Printer->page_started = true;
5700
/****************************************************************
5701
_spoolss_EndPagePrinter
5702
****************************************************************/
5704
WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5705
struct spoolss_EndPagePrinter *r)
5709
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5712
DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5713
OUR_HANDLE(r->in.handle)));
5717
if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5720
Printer->page_started = false;
5721
print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5726
/****************************************************************
5727
_spoolss_StartDocPrinter
5728
****************************************************************/
5730
WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5731
struct spoolss_StartDocPrinter *r)
5733
struct spoolss_DocumentInfo1 *info_1;
5735
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5739
DEBUG(2,("_spoolss_StartDocPrinter: "
5740
"Invalid handle (%s:%u:%u)\n",
5741
OUR_HANDLE(r->in.handle)));
5745
if (Printer->jobid) {
5746
DEBUG(2, ("_spoolss_StartDocPrinter: "
5747
"StartDocPrinter called twice! "
5748
"(existing jobid = %d)\n", Printer->jobid));
5749
return WERR_INVALID_HANDLE;
5752
if (r->in.level != 1) {
5753
return WERR_UNKNOWN_LEVEL;
5756
info_1 = r->in.info.info1;
5759
* a nice thing with NT is it doesn't listen to what you tell it.
5760
* when asked to send _only_ RAW datas, it tries to send datas
5763
* So I add checks like in NT Server ...
5766
if (info_1->datatype) {
5767
if (strcmp(info_1->datatype, "RAW") != 0) {
5769
return WERR_INVALID_DATATYPE;
5773
/* get the share number of the printer */
5774
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5778
werr = print_job_start(p->session_info,
5782
info_1->document_name,
5783
info_1->output_file,
5787
/* An error occured in print_job_start() so return an appropriate
5790
if (!W_ERROR_IS_OK(werr)) {
5794
Printer->document_started = true;
5795
*r->out.job_id = Printer->jobid;
5800
/****************************************************************
5801
_spoolss_EndDocPrinter
5802
****************************************************************/
5804
WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5805
struct spoolss_EndDocPrinter *r)
5807
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5812
DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5813
OUR_HANDLE(r->in.handle)));
5817
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5821
Printer->document_started = false;
5822
status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5823
if (!NT_STATUS_IS_OK(status)) {
5824
DEBUG(2, ("_spoolss_EndDocPrinter: "
5825
"print_job_end failed [%s]\n",
5826
nt_errstr(status)));
5830
return ntstatus_to_werror(status);
5833
/****************************************************************
5834
_spoolss_WritePrinter
5835
****************************************************************/
5837
WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5838
struct spoolss_WritePrinter *r)
5840
ssize_t buffer_written;
5842
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5845
DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5846
OUR_HANDLE(r->in.handle)));
5847
*r->out.num_written = r->in._data_size;
5851
if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5854
/* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5855
buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5856
snum, Printer->jobid,
5857
(const char *)r->in.data.data,
5858
(size_t)r->in._data_size);
5859
if (buffer_written == (ssize_t)-1) {
5860
*r->out.num_written = 0;
5861
if (errno == ENOSPC)
5862
return WERR_NO_SPOOL_SPACE;
5864
return WERR_ACCESS_DENIED;
5867
*r->out.num_written = r->in._data_size;
5872
/********************************************************************
5873
* api_spoolss_getprinter
5874
* called from the spoolss dispatcher
5876
********************************************************************/
5878
static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5879
struct pipes_struct *p)
5881
const struct auth_serversupplied_info *session_info = p->session_info;
5883
WERROR errcode = WERR_BADFUNC;
5884
struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5887
DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5888
OUR_HANDLE(handle)));
5892
if (!get_printer_snum(p, handle, &snum, NULL))
5896
case SPOOLSS_PRINTER_CONTROL_PAUSE:
5897
errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5899
case SPOOLSS_PRINTER_CONTROL_RESUME:
5900
case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5901
errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5903
case SPOOLSS_PRINTER_CONTROL_PURGE:
5904
errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5907
return WERR_UNKNOWN_LEVEL;
5914
/****************************************************************
5915
_spoolss_AbortPrinter
5916
* From MSDN: "Deletes printer's spool file if printer is configured
5918
****************************************************************/
5920
WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5921
struct spoolss_AbortPrinter *r)
5923
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5925
WERROR errcode = WERR_OK;
5928
DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5929
OUR_HANDLE(r->in.handle)));
5933
if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5936
if (!Printer->document_started) {
5937
return WERR_SPL_NO_STARTDOC;
5940
errcode = print_job_delete(p->session_info,
5948
/********************************************************************
5949
* called by spoolss_api_setprinter
5950
* when updating a printer description
5951
********************************************************************/
5953
static WERROR update_printer_sec(struct policy_handle *handle,
5954
struct pipes_struct *p,
5955
struct sec_desc_buf *secdesc_ctr)
5957
struct spoolss_security_descriptor *new_secdesc = NULL;
5958
struct spoolss_security_descriptor *old_secdesc = NULL;
5959
const char *printer;
5962
struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5963
struct dcerpc_binding_handle *b;
5965
if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5966
DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5967
OUR_HANDLE(handle)));
5969
result = WERR_BADFID;
5973
if (secdesc_ctr == NULL) {
5974
DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5975
result = WERR_INVALID_PARAM;
5978
printer = lp_const_servicename(snum);
5980
/* Check the user has permissions to change the security
5981
descriptor. By experimentation with two NT machines, the user
5982
requires Full Access to the printer to change security
5985
if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5986
DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5987
result = WERR_ACCESS_DENIED;
5991
result = winreg_printer_binding_handle(p->mem_ctx,
5992
get_session_info_system(),
5995
if (!W_ERROR_IS_OK(result)) {
5999
/* NT seems to like setting the security descriptor even though
6000
nothing may have actually changed. */
6001
result = winreg_get_printer_secdesc(p->mem_ctx, b,
6004
if (!W_ERROR_IS_OK(result)) {
6005
DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6006
result = WERR_BADFID;
6010
if (DEBUGLEVEL >= 10) {
6011
struct security_acl *the_acl;
6014
the_acl = old_secdesc->dacl;
6015
DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6016
printer, the_acl->num_aces));
6018
for (i = 0; i < the_acl->num_aces; i++) {
6019
DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6020
&the_acl->aces[i].trustee),
6021
the_acl->aces[i].access_mask));
6024
the_acl = secdesc_ctr->sd->dacl;
6027
DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6028
printer, the_acl->num_aces));
6030
for (i = 0; i < the_acl->num_aces; i++) {
6031
DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6032
&the_acl->aces[i].trustee),
6033
the_acl->aces[i].access_mask));
6036
DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6040
new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
6041
if (new_secdesc == NULL) {
6042
result = WERR_NOMEM;
6046
if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6051
result = winreg_set_printer_secdesc(p->mem_ctx, b,
6059
/********************************************************************
6060
Canonicalize printer info from a client
6061
********************************************************************/
6063
static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6064
struct spoolss_SetPrinterInfo2 *info2,
6067
fstring printername;
6070
DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6071
"portname=%s drivername=%s comment=%s location=%s\n",
6072
info2->servername, info2->printername, info2->sharename,
6073
info2->portname, info2->drivername, info2->comment,
6076
/* we force some elements to "correct" values */
6077
info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6078
if (info2->servername == NULL) {
6081
info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6082
if (info2->sharename == NULL) {
6086
/* check to see if we allow printername != sharename */
6087
if (lp_force_printername(snum)) {
6088
info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6089
global_myname(), info2->sharename);
6091
/* make sure printername is in \\server\printername format */
6092
fstrcpy(printername, info2->printername);
6094
if ( printername[0] == '\\' && printername[1] == '\\' ) {
6095
if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6099
info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6100
global_myname(), p);
6102
if (info2->printername == NULL) {
6106
info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6107
info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6112
/****************************************************************************
6113
****************************************************************************/
6115
static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6117
char *cmd = lp_addport_cmd();
6118
char *command = NULL;
6120
bool is_print_op = false;
6123
return WERR_ACCESS_DENIED;
6126
command = talloc_asprintf(ctx,
6127
"%s \"%s\" \"%s\"", cmd, portname, uri );
6133
is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6135
DEBUG(10,("Running [%s]\n", command));
6137
/********* BEGIN SePrintOperatorPrivilege **********/
6142
ret = smbrun(command, NULL);
6147
/********* END SePrintOperatorPrivilege **********/
6149
DEBUGADD(10,("returned [%d]\n", ret));
6151
TALLOC_FREE(command);
6154
return WERR_ACCESS_DENIED;
6160
/****************************************************************************
6161
****************************************************************************/
6163
static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6164
struct spoolss_SetPrinterInfo2 *info2,
6165
const char *remote_machine,
6166
struct messaging_context *msg_ctx)
6168
char *cmd = lp_addprinter_cmd();
6170
char *command = NULL;
6174
bool is_print_op = false;
6176
if (!remote_machine) {
6180
command = talloc_asprintf(ctx,
6181
"%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6182
cmd, info2->printername, info2->sharename,
6183
info2->portname, info2->drivername,
6184
info2->location, info2->comment, remote_machine);
6190
is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6192
DEBUG(10,("Running [%s]\n", command));
6194
/********* BEGIN SePrintOperatorPrivilege **********/
6199
if ( (ret = smbrun(command, &fd)) == 0 ) {
6200
/* Tell everyone we updated smb.conf. */
6201
message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6207
/********* END SePrintOperatorPrivilege **********/
6209
DEBUGADD(10,("returned [%d]\n", ret));
6211
TALLOC_FREE(command);
6219
/* reload our services immediately */
6221
reload_services(msg_ctx, -1, false);
6225
/* Get lines and convert them back to dos-codepage */
6226
qlines = fd_lines_load(fd, &numlines, 0, NULL);
6227
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6230
/* Set the portname to what the script says the portname should be. */
6231
/* but don't require anything to be return from the script exit a good error code */
6234
/* Set the portname to what the script says the portname should be. */
6235
info2->portname = talloc_strdup(ctx, qlines[0]);
6236
DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6239
TALLOC_FREE(qlines);
6243
static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6244
const struct auth_serversupplied_info *session_info,
6245
struct messaging_context *msg_ctx,
6247
struct spoolss_SetPrinterInfo2 *printer,
6248
struct spoolss_PrinterInfo2 *old_printer)
6250
bool force_update = (old_printer == NULL);
6251
const char *dnsdomname;
6252
const char *longname;
6253
const char *uncname;
6254
const char *spooling;
6256
WERROR result = WERR_OK;
6257
struct dcerpc_binding_handle *b;
6259
result = winreg_printer_binding_handle(mem_ctx,
6263
if (!W_ERROR_IS_OK(result)) {
6267
if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6268
push_reg_sz(mem_ctx, &buffer, printer->drivername);
6269
winreg_set_printer_dataex(mem_ctx, b,
6271
SPOOL_DSSPOOLER_KEY,
6272
SPOOL_REG_DRIVERNAME,
6277
if (!force_update) {
6278
DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6279
printer->drivername));
6281
notify_printer_driver(server_event_context(), msg_ctx,
6282
snum, printer->drivername ?
6283
printer->drivername : "");
6287
if (force_update || !strequal(printer->comment, old_printer->comment)) {
6288
push_reg_sz(mem_ctx, &buffer, printer->comment);
6289
winreg_set_printer_dataex(mem_ctx, b,
6291
SPOOL_DSSPOOLER_KEY,
6292
SPOOL_REG_DESCRIPTION,
6297
if (!force_update) {
6298
notify_printer_comment(server_event_context(), msg_ctx,
6299
snum, printer->comment ?
6300
printer->comment : "");
6304
if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6305
push_reg_sz(mem_ctx, &buffer, printer->sharename);
6306
winreg_set_printer_dataex(mem_ctx, b,
6308
SPOOL_DSSPOOLER_KEY,
6309
SPOOL_REG_PRINTSHARENAME,
6314
if (!force_update) {
6315
notify_printer_sharename(server_event_context(),
6317
snum, printer->sharename ?
6318
printer->sharename : "");
6322
if (force_update || !strequal(printer->printername, old_printer->printername)) {
6325
p = strrchr(printer->printername, '\\' );
6329
p = printer->printername;
6332
push_reg_sz(mem_ctx, &buffer, p);
6333
winreg_set_printer_dataex(mem_ctx, b,
6335
SPOOL_DSSPOOLER_KEY,
6336
SPOOL_REG_PRINTERNAME,
6341
if (!force_update) {
6342
notify_printer_printername(server_event_context(),
6343
msg_ctx, snum, p ? p : "");
6347
if (force_update || !strequal(printer->portname, old_printer->portname)) {
6348
push_reg_sz(mem_ctx, &buffer, printer->portname);
6349
winreg_set_printer_dataex(mem_ctx, b,
6351
SPOOL_DSSPOOLER_KEY,
6357
if (!force_update) {
6358
notify_printer_port(server_event_context(),
6359
msg_ctx, snum, printer->portname ?
6360
printer->portname : "");
6364
if (force_update || !strequal(printer->location, old_printer->location)) {
6365
push_reg_sz(mem_ctx, &buffer, printer->location);
6366
winreg_set_printer_dataex(mem_ctx, b,
6368
SPOOL_DSSPOOLER_KEY,
6374
if (!force_update) {
6375
notify_printer_location(server_event_context(),
6378
printer->location : "");
6382
if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6383
push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6384
winreg_set_printer_dataex(mem_ctx, b,
6386
SPOOL_DSSPOOLER_KEY,
6387
SPOOL_REG_PRINTSEPARATORFILE,
6392
if (!force_update) {
6393
notify_printer_sepfile(server_event_context(),
6396
printer->sepfile : "");
6400
if (force_update || printer->starttime != old_printer->starttime) {
6401
buffer = data_blob_talloc(mem_ctx, NULL, 4);
6402
SIVAL(buffer.data, 0, printer->starttime);
6403
winreg_set_printer_dataex(mem_ctx, b,
6405
SPOOL_DSSPOOLER_KEY,
6406
SPOOL_REG_PRINTSTARTTIME,
6412
if (force_update || printer->untiltime != old_printer->untiltime) {
6413
buffer = data_blob_talloc(mem_ctx, NULL, 4);
6414
SIVAL(buffer.data, 0, printer->untiltime);
6415
winreg_set_printer_dataex(mem_ctx, b,
6417
SPOOL_DSSPOOLER_KEY,
6418
SPOOL_REG_PRINTENDTIME,
6424
if (force_update || printer->priority != old_printer->priority) {
6425
buffer = data_blob_talloc(mem_ctx, NULL, 4);
6426
SIVAL(buffer.data, 0, printer->priority);
6427
winreg_set_printer_dataex(mem_ctx, b,
6429
SPOOL_DSSPOOLER_KEY,
6436
if (force_update || printer->attributes != old_printer->attributes) {
6437
buffer = data_blob_talloc(mem_ctx, NULL, 4);
6438
SIVAL(buffer.data, 0, (printer->attributes &
6439
PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6440
winreg_set_printer_dataex(mem_ctx, b,
6442
SPOOL_DSSPOOLER_KEY,
6443
SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6448
switch (printer->attributes & 0x3) {
6450
spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6453
spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6456
spooling = SPOOL_REGVAL_PRINTDIRECT;
6459
spooling = "unknown";
6461
push_reg_sz(mem_ctx, &buffer, spooling);
6462
winreg_set_printer_dataex(mem_ctx, b,
6464
SPOOL_DSSPOOLER_KEY,
6465
SPOOL_REG_PRINTSPOOLING,
6471
push_reg_sz(mem_ctx, &buffer, global_myname());
6472
winreg_set_printer_dataex(mem_ctx, b,
6474
SPOOL_DSSPOOLER_KEY,
6475
SPOOL_REG_SHORTSERVERNAME,
6480
dnsdomname = get_mydnsfullname();
6481
if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6482
longname = talloc_strdup(mem_ctx, dnsdomname);
6484
longname = talloc_strdup(mem_ctx, global_myname());
6486
if (longname == NULL) {
6487
result = WERR_NOMEM;
6491
push_reg_sz(mem_ctx, &buffer, longname);
6492
winreg_set_printer_dataex(mem_ctx, b,
6494
SPOOL_DSSPOOLER_KEY,
6495
SPOOL_REG_SERVERNAME,
6500
uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6501
global_myname(), printer->sharename);
6502
push_reg_sz(mem_ctx, &buffer, uncname);
6503
winreg_set_printer_dataex(mem_ctx, b,
6505
SPOOL_DSSPOOLER_KEY,
6515
/********************************************************************
6516
* Called by spoolss_api_setprinter
6517
* when updating a printer description.
6518
********************************************************************/
6520
static WERROR update_printer(struct pipes_struct *p,
6521
struct policy_handle *handle,
6522
struct spoolss_SetPrinterInfoCtr *info_ctr,
6523
struct spoolss_DeviceMode *devmode)
6525
uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6526
struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6527
struct spoolss_PrinterInfo2 *old_printer;
6528
struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6530
WERROR result = WERR_OK;
6531
TALLOC_CTX *tmp_ctx;
6532
struct dcerpc_binding_handle *b;
6534
DEBUG(8,("update_printer\n"));
6536
tmp_ctx = talloc_new(p->mem_ctx);
6537
if (tmp_ctx == NULL) {
6542
result = WERR_BADFID;
6546
if (!get_printer_snum(p, handle, &snum, NULL)) {
6547
result = WERR_BADFID;
6551
result = winreg_printer_binding_handle(tmp_ctx,
6552
get_session_info_system(),
6555
if (!W_ERROR_IS_OK(result)) {
6559
result = winreg_get_printer(tmp_ctx, b,
6560
lp_const_servicename(snum),
6562
if (!W_ERROR_IS_OK(result)) {
6563
result = WERR_BADFID;
6567
/* Do sanity check on the requested changes for Samba */
6568
if (!check_printer_ok(tmp_ctx, printer, snum)) {
6569
result = WERR_INVALID_PARAM;
6573
/* FIXME!!! If the driver has changed we really should verify that
6574
it is installed before doing much else --jerry */
6576
/* Check calling user has permission to update printer description */
6577
if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6578
DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6579
result = WERR_ACCESS_DENIED;
6583
/* Call addprinter hook */
6584
/* Check changes to see if this is really needed */
6586
if (*lp_addprinter_cmd() &&
6587
(!strequal(printer->drivername, old_printer->drivername) ||
6588
!strequal(printer->comment, old_printer->comment) ||
6589
!strequal(printer->portname, old_printer->portname) ||
6590
!strequal(printer->location, old_printer->location)) )
6592
/* add_printer_hook() will call reload_services() */
6593
if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6594
printer, p->client_id->addr,
6596
result = WERR_ACCESS_DENIED;
6601
update_dsspooler(tmp_ctx,
6602
get_session_info_system(),
6608
printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6610
if (devmode == NULL) {
6611
printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6613
result = winreg_update_printer(tmp_ctx, b,
6621
talloc_free(tmp_ctx);
6626
/****************************************************************************
6627
****************************************************************************/
6628
static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6629
struct policy_handle *handle,
6630
struct spoolss_SetPrinterInfo7 *info7)
6633
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6636
struct printer_handle *Printer;
6638
if ( lp_security() != SEC_ADS ) {
6639
return WERR_UNKNOWN_LEVEL;
6642
Printer = find_printer_index_by_hnd(p, handle);
6644
DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6649
if (!get_printer_snum(p, handle, &snum, NULL))
6652
result = winreg_get_printer_internal(p->mem_ctx,
6653
get_session_info_system(),
6655
lp_servicename(snum),
6657
if (!W_ERROR_IS_OK(result)) {
6661
nt_printer_publish(pinfo2,
6662
get_session_info_system(),
6667
TALLOC_FREE(pinfo2);
6670
return WERR_UNKNOWN_LEVEL;
6674
/********************************************************************
6675
********************************************************************/
6677
static WERROR update_printer_devmode(struct pipes_struct *p,
6678
struct policy_handle *handle,
6679
struct spoolss_DeviceMode *devmode)
6682
struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6683
uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6685
DEBUG(8,("update_printer_devmode\n"));
6691
if (!get_printer_snum(p, handle, &snum, NULL)) {
6695
/* Check calling user has permission to update printer description */
6696
if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6697
DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6698
return WERR_ACCESS_DENIED;
6701
return winreg_update_printer_internal(p->mem_ctx,
6702
get_session_info_system(),
6704
lp_const_servicename(snum),
6712
/****************************************************************
6714
****************************************************************/
6716
WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6717
struct spoolss_SetPrinter *r)
6721
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6724
DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6725
OUR_HANDLE(r->in.handle)));
6729
/* check the level */
6730
switch (r->in.info_ctr->level) {
6732
return control_printer(r->in.handle, r->in.command, p);
6734
result = update_printer(p, r->in.handle,
6736
r->in.devmode_ctr->devmode);
6737
if (!W_ERROR_IS_OK(result))
6739
if (r->in.secdesc_ctr->sd)
6740
result = update_printer_sec(r->in.handle, p,
6744
return update_printer_sec(r->in.handle, p,
6747
return publish_or_unpublish_printer(p, r->in.handle,
6748
r->in.info_ctr->info.info7);
6750
return update_printer_devmode(p, r->in.handle,
6751
r->in.devmode_ctr->devmode);
6753
return WERR_UNKNOWN_LEVEL;
6757
/****************************************************************
6758
_spoolss_FindClosePrinterNotify
6759
****************************************************************/
6761
WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6762
struct spoolss_FindClosePrinterNotify *r)
6764
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6767
DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6768
"Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6772
if (Printer->notify.cli_chan != NULL &&
6773
Printer->notify.cli_chan->active_connections > 0) {
6776
if (Printer->printer_type == SPLHND_PRINTER) {
6777
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6782
srv_spoolss_replycloseprinter(snum, Printer);
6785
Printer->notify.flags=0;
6786
Printer->notify.options=0;
6787
Printer->notify.localmachine[0]='\0';
6788
Printer->notify.printerlocal=0;
6789
TALLOC_FREE(Printer->notify.option);
6794
/****************************************************************
6796
****************************************************************/
6798
WERROR _spoolss_AddJob(struct pipes_struct *p,
6799
struct spoolss_AddJob *r)
6801
if (!r->in.buffer && (r->in.offered != 0)) {
6802
return WERR_INVALID_PARAM;
6805
/* this is what a NT server returns for AddJob. AddJob must fail on
6806
* non-local printers */
6808
if (r->in.level != 1) {
6809
return WERR_UNKNOWN_LEVEL;
6812
return WERR_INVALID_PARAM;
6815
/****************************************************************************
6817
****************************************************************************/
6819
static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6820
struct spoolss_JobInfo1 *r,
6821
const print_queue_struct *queue,
6822
int position, int snum,
6823
struct spoolss_PrinterInfo2 *pinfo2)
6827
t = gmtime(&queue->time);
6829
r->job_id = queue->job;
6831
r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6832
W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6833
r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6834
W_ERROR_HAVE_NO_MEMORY(r->server_name);
6835
r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6836
W_ERROR_HAVE_NO_MEMORY(r->user_name);
6837
r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6838
W_ERROR_HAVE_NO_MEMORY(r->document_name);
6839
r->data_type = talloc_strdup(mem_ctx, "RAW");
6840
W_ERROR_HAVE_NO_MEMORY(r->data_type);
6841
r->text_status = talloc_strdup(mem_ctx, "");
6842
W_ERROR_HAVE_NO_MEMORY(r->text_status);
6844
r->status = nt_printj_status(queue->status);
6845
r->priority = queue->priority;
6846
r->position = position;
6847
r->total_pages = queue->page_count;
6848
r->pages_printed = 0; /* ??? */
6850
init_systemtime(&r->submitted, t);
6855
/****************************************************************************
6857
****************************************************************************/
6859
static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6860
struct spoolss_JobInfo2 *r,
6861
const print_queue_struct *queue,
6862
int position, int snum,
6863
struct spoolss_PrinterInfo2 *pinfo2,
6864
struct spoolss_DeviceMode *devmode)
6868
t = gmtime(&queue->time);
6870
r->job_id = queue->job;
6872
r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6873
W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6874
r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6875
W_ERROR_HAVE_NO_MEMORY(r->server_name);
6876
r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6877
W_ERROR_HAVE_NO_MEMORY(r->user_name);
6878
r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6879
W_ERROR_HAVE_NO_MEMORY(r->document_name);
6880
r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6881
W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6882
r->data_type = talloc_strdup(mem_ctx, "RAW");
6883
W_ERROR_HAVE_NO_MEMORY(r->data_type);
6884
r->print_processor = talloc_strdup(mem_ctx, "winprint");
6885
W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6886
r->parameters = talloc_strdup(mem_ctx, "");
6887
W_ERROR_HAVE_NO_MEMORY(r->parameters);
6888
r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6889
W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6891
r->devmode = devmode;
6893
r->text_status = talloc_strdup(mem_ctx, "");
6894
W_ERROR_HAVE_NO_MEMORY(r->text_status);
6898
r->status = nt_printj_status(queue->status);
6899
r->priority = queue->priority;
6900
r->position = position;
6903
r->total_pages = queue->page_count;
6904
r->size = queue->size;
6905
init_systemtime(&r->submitted, t);
6907
r->pages_printed = 0; /* ??? */
6912
/****************************************************************************
6914
****************************************************************************/
6916
static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6917
struct spoolss_JobInfo3 *r,
6918
const print_queue_struct *queue,
6919
const print_queue_struct *next_queue,
6920
int position, int snum,
6921
struct spoolss_PrinterInfo2 *pinfo2)
6923
r->job_id = queue->job;
6926
r->next_job_id = next_queue->job;
6933
/****************************************************************************
6934
Enumjobs at level 1.
6935
****************************************************************************/
6937
static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6938
const print_queue_struct *queue,
6939
uint32_t num_queues, int snum,
6940
struct spoolss_PrinterInfo2 *pinfo2,
6941
union spoolss_JobInfo **info_p,
6944
union spoolss_JobInfo *info;
6946
WERROR result = WERR_OK;
6948
info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6949
W_ERROR_HAVE_NO_MEMORY(info);
6951
*count = num_queues;
6953
for (i=0; i<*count; i++) {
6954
result = fill_job_info1(info,
6960
if (!W_ERROR_IS_OK(result)) {
6966
if (!W_ERROR_IS_OK(result)) {
6977
/****************************************************************************
6978
Enumjobs at level 2.
6979
****************************************************************************/
6981
static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6982
const print_queue_struct *queue,
6983
uint32_t num_queues, int snum,
6984
struct spoolss_PrinterInfo2 *pinfo2,
6985
union spoolss_JobInfo **info_p,
6988
union spoolss_JobInfo *info;
6990
WERROR result = WERR_OK;
6992
info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6993
W_ERROR_HAVE_NO_MEMORY(info);
6995
*count = num_queues;
6997
for (i=0; i<*count; i++) {
6998
struct spoolss_DeviceMode *devmode;
7000
result = spoolss_create_default_devmode(info,
7001
pinfo2->printername,
7003
if (!W_ERROR_IS_OK(result)) {
7004
DEBUG(3, ("Can't proceed w/o a devmode!"));
7008
result = fill_job_info2(info,
7015
if (!W_ERROR_IS_OK(result)) {
7021
if (!W_ERROR_IS_OK(result)) {
7032
/****************************************************************************
7033
Enumjobs at level 3.
7034
****************************************************************************/
7036
static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7037
const print_queue_struct *queue,
7038
uint32_t num_queues, int snum,
7039
struct spoolss_PrinterInfo2 *pinfo2,
7040
union spoolss_JobInfo **info_p,
7043
union spoolss_JobInfo *info;
7045
WERROR result = WERR_OK;
7047
info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7048
W_ERROR_HAVE_NO_MEMORY(info);
7050
*count = num_queues;
7052
for (i=0; i<*count; i++) {
7053
const print_queue_struct *next_queue = NULL;
7056
next_queue = &queue[i+1];
7059
result = fill_job_info3(info,
7066
if (!W_ERROR_IS_OK(result)) {
7072
if (!W_ERROR_IS_OK(result)) {
7083
/****************************************************************
7085
****************************************************************/
7087
WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7088
struct spoolss_EnumJobs *r)
7091
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7093
print_status_struct prt_status;
7094
print_queue_struct *queue = NULL;
7097
/* that's an [in out] buffer */
7099
if (!r->in.buffer && (r->in.offered != 0)) {
7100
return WERR_INVALID_PARAM;
7103
DEBUG(4,("_spoolss_EnumJobs\n"));
7107
*r->out.info = NULL;
7109
/* lookup the printer snum and tdb entry */
7111
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7115
result = winreg_get_printer_internal(p->mem_ctx,
7116
get_session_info_system(),
7118
lp_const_servicename(snum),
7120
if (!W_ERROR_IS_OK(result)) {
7124
count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7125
DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7126
count, prt_status.status, prt_status.message));
7130
TALLOC_FREE(pinfo2);
7134
switch (r->in.level) {
7136
result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7137
pinfo2, r->out.info, r->out.count);
7140
result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7141
pinfo2, r->out.info, r->out.count);
7144
result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7145
pinfo2, r->out.info, r->out.count);
7148
result = WERR_UNKNOWN_LEVEL;
7153
TALLOC_FREE(pinfo2);
7155
if (!W_ERROR_IS_OK(result)) {
7159
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7161
*r->out.info, r->in.level,
7163
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7164
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7166
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7169
/****************************************************************
7170
_spoolss_ScheduleJob
7171
****************************************************************/
7173
WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7174
struct spoolss_ScheduleJob *r)
7179
/****************************************************************
7180
****************************************************************/
7182
static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7183
struct messaging_context *msg_ctx,
7184
const char *printer_name,
7186
struct spoolss_SetJobInfo1 *r)
7190
if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7194
if (strequal(old_doc_name, r->document_name)) {
7198
if (!print_job_set_name(server_event_context(), msg_ctx,
7199
printer_name, job_id, r->document_name)) {
7206
/****************************************************************
7208
****************************************************************/
7210
WERROR _spoolss_SetJob(struct pipes_struct *p,
7211
struct spoolss_SetJob *r)
7213
const struct auth_serversupplied_info *session_info = p->session_info;
7215
WERROR errcode = WERR_BADFUNC;
7217
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7221
if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7222
return WERR_INVALID_PRINTER_NAME;
7225
switch (r->in.command) {
7226
case SPOOLSS_JOB_CONTROL_CANCEL:
7227
case SPOOLSS_JOB_CONTROL_DELETE:
7228
errcode = print_job_delete(session_info, p->msg_ctx,
7229
snum, r->in.job_id);
7230
if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7234
case SPOOLSS_JOB_CONTROL_PAUSE:
7235
if (print_job_pause(session_info, p->msg_ctx,
7236
snum, r->in.job_id, &errcode)) {
7240
case SPOOLSS_JOB_CONTROL_RESTART:
7241
case SPOOLSS_JOB_CONTROL_RESUME:
7242
if (print_job_resume(session_info, p->msg_ctx,
7243
snum, r->in.job_id, &errcode)) {
7251
return WERR_UNKNOWN_LEVEL;
7254
if (!W_ERROR_IS_OK(errcode)) {
7258
if (r->in.ctr == NULL) {
7262
switch (r->in.ctr->level) {
7264
errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7265
lp_const_servicename(snum),
7267
r->in.ctr->info.info1);
7273
return WERR_UNKNOWN_LEVEL;
7279
/****************************************************************************
7280
Enumerates all printer drivers by level and architecture.
7281
****************************************************************************/
7283
static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7284
const struct auth_serversupplied_info *session_info,
7285
struct messaging_context *msg_ctx,
7286
const char *servername,
7287
const char *architecture,
7289
union spoolss_DriverInfo **info_p,
7294
struct spoolss_DriverInfo8 *driver;
7295
union spoolss_DriverInfo *info = NULL;
7297
WERROR result = WERR_OK;
7298
uint32_t num_drivers;
7299
const char **drivers;
7300
struct dcerpc_binding_handle *b;
7305
result = winreg_printer_binding_handle(mem_ctx,
7309
if (!W_ERROR_IS_OK(result)) {
7313
for (version=0; version<DRIVER_MAX_VERSION; version++) {
7314
result = winreg_get_driver_list(mem_ctx, b,
7315
architecture, version,
7316
&num_drivers, &drivers);
7317
if (!W_ERROR_IS_OK(result)) {
7320
DEBUG(4, ("we have:[%d] drivers in environment"
7321
" [%s] and version [%d]\n",
7322
num_drivers, architecture, version));
7324
if (num_drivers != 0) {
7325
info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7326
union spoolss_DriverInfo,
7327
count + num_drivers);
7329
DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7330
"failed to enlarge driver info buffer!\n"));
7331
result = WERR_NOMEM;
7336
for (i = 0; i < num_drivers; i++) {
7337
DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7339
result = winreg_get_driver(mem_ctx, b,
7340
architecture, drivers[i],
7342
if (!W_ERROR_IS_OK(result)) {
7348
result = fill_printer_driver_info1(info, &info[count+i].info1,
7349
driver, servername);
7352
result = fill_printer_driver_info2(info, &info[count+i].info2,
7353
driver, servername);
7356
result = fill_printer_driver_info3(info, &info[count+i].info3,
7357
driver, servername);
7360
result = fill_printer_driver_info4(info, &info[count+i].info4,
7361
driver, servername);
7364
result = fill_printer_driver_info5(info, &info[count+i].info5,
7365
driver, servername);
7368
result = fill_printer_driver_info6(info, &info[count+i].info6,
7369
driver, servername);
7372
result = fill_printer_driver_info8(info, &info[count+i].info8,
7373
driver, servername);
7376
result = WERR_UNKNOWN_LEVEL;
7380
TALLOC_FREE(driver);
7382
if (!W_ERROR_IS_OK(result)) {
7387
count += num_drivers;
7388
TALLOC_FREE(drivers);
7392
TALLOC_FREE(drivers);
7394
if (!W_ERROR_IS_OK(result)) {
7405
/****************************************************************************
7406
Enumerates all printer drivers by level.
7407
****************************************************************************/
7409
static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7410
const struct auth_serversupplied_info *session_info,
7411
struct messaging_context *msg_ctx,
7412
const char *servername,
7413
const char *architecture,
7415
union spoolss_DriverInfo **info_p,
7419
WERROR result = WERR_OK;
7421
if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7423
for (a=0; archi_table[a].long_archi != NULL; a++) {
7425
union spoolss_DriverInfo *info = NULL;
7428
result = enumprinterdrivers_level_by_architecture(mem_ctx,
7432
archi_table[a].long_archi,
7436
if (!W_ERROR_IS_OK(result)) {
7440
for (i=0; i < count; i++) {
7441
ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7442
info[i], info_p, count_p);
7449
return enumprinterdrivers_level_by_architecture(mem_ctx,
7459
/****************************************************************
7460
_spoolss_EnumPrinterDrivers
7461
****************************************************************/
7463
WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7464
struct spoolss_EnumPrinterDrivers *r)
7466
const char *cservername;
7469
/* that's an [in out] buffer */
7471
if (!r->in.buffer && (r->in.offered != 0)) {
7472
return WERR_INVALID_PARAM;
7475
DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7479
*r->out.info = NULL;
7481
cservername = canon_servername(r->in.server);
7483
if (!is_myname_or_ipaddr(cservername)) {
7484
return WERR_UNKNOWN_PRINTER_DRIVER;
7487
result = enumprinterdrivers_level(p->mem_ctx,
7488
get_session_info_system(),
7495
if (!W_ERROR_IS_OK(result)) {
7499
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7500
spoolss_EnumPrinterDrivers,
7501
*r->out.info, r->in.level,
7503
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7504
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7506
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7509
/****************************************************************
7511
****************************************************************/
7513
WERROR _spoolss_EnumForms(struct pipes_struct *p,
7514
struct spoolss_EnumForms *r)
7520
*r->out.info = NULL;
7522
/* that's an [in out] buffer */
7524
if (!r->in.buffer && (r->in.offered != 0) ) {
7525
return WERR_INVALID_PARAM;
7528
DEBUG(4,("_spoolss_EnumForms\n"));
7529
DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7530
DEBUGADD(5,("Info level [%d]\n", r->in.level));
7532
switch (r->in.level) {
7534
result = winreg_printer_enumforms1_internal(p->mem_ctx,
7535
get_session_info_system(),
7541
result = WERR_UNKNOWN_LEVEL;
7545
if (!W_ERROR_IS_OK(result)) {
7549
if (*r->out.count == 0) {
7550
return WERR_NO_MORE_ITEMS;
7553
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7555
*r->out.info, r->in.level,
7557
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7558
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7560
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7563
/****************************************************************
7565
****************************************************************/
7567
WERROR _spoolss_GetForm(struct pipes_struct *p,
7568
struct spoolss_GetForm *r)
7572
/* that's an [in out] buffer */
7574
if (!r->in.buffer && (r->in.offered != 0)) {
7575
return WERR_INVALID_PARAM;
7578
DEBUG(4,("_spoolss_GetForm\n"));
7579
DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7580
DEBUGADD(5,("Info level [%d]\n", r->in.level));
7582
switch (r->in.level) {
7584
result = winreg_printer_getform1_internal(p->mem_ctx,
7585
get_session_info_system(),
7588
&r->out.info->info1);
7591
result = WERR_UNKNOWN_LEVEL;
7595
if (!W_ERROR_IS_OK(result)) {
7596
TALLOC_FREE(r->out.info);
7600
*r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7601
r->out.info, r->in.level);
7602
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7604
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7607
/****************************************************************************
7608
****************************************************************************/
7610
static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7611
struct spoolss_PortInfo1 *r,
7614
r->port_name = talloc_strdup(mem_ctx, name);
7615
W_ERROR_HAVE_NO_MEMORY(r->port_name);
7620
/****************************************************************************
7621
TODO: This probably needs distinguish between TCP/IP and Local ports
7623
****************************************************************************/
7625
static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7626
struct spoolss_PortInfo2 *r,
7629
r->port_name = talloc_strdup(mem_ctx, name);
7630
W_ERROR_HAVE_NO_MEMORY(r->port_name);
7632
r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7633
W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7635
r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7636
W_ERROR_HAVE_NO_MEMORY(r->description);
7638
r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7645
/****************************************************************************
7646
wrapper around the enumer ports command
7647
****************************************************************************/
7649
static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7651
char *cmd = lp_enumports_cmd();
7652
char **qlines = NULL;
7653
char *command = NULL;
7661
/* if no hook then just fill in the default port */
7664
if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7667
if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7668
TALLOC_FREE(qlines);
7675
/* we have a valid enumport command */
7677
command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7682
DEBUG(10,("Running [%s]\n", command));
7683
ret = smbrun(command, &fd);
7684
DEBUG(10,("Returned [%d]\n", ret));
7685
TALLOC_FREE(command);
7690
return WERR_ACCESS_DENIED;
7694
qlines = fd_lines_load(fd, &numlines, 0, NULL);
7695
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7705
/****************************************************************************
7707
****************************************************************************/
7709
static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7710
union spoolss_PortInfo **info_p,
7713
union spoolss_PortInfo *info = NULL;
7715
WERROR result = WERR_OK;
7716
char **qlines = NULL;
7719
result = enumports_hook(talloc_tos(), &numlines, &qlines );
7720
if (!W_ERROR_IS_OK(result)) {
7725
info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7727
DEBUG(10,("Returning WERR_NOMEM\n"));
7728
result = WERR_NOMEM;
7732
for (i=0; i<numlines; i++) {
7733
DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7734
result = fill_port_1(info, &info[i].info1, qlines[i]);
7735
if (!W_ERROR_IS_OK(result)) {
7740
TALLOC_FREE(qlines);
7743
if (!W_ERROR_IS_OK(result)) {
7745
TALLOC_FREE(qlines);
7757
/****************************************************************************
7759
****************************************************************************/
7761
static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7762
union spoolss_PortInfo **info_p,
7765
union spoolss_PortInfo *info = NULL;
7767
WERROR result = WERR_OK;
7768
char **qlines = NULL;
7771
result = enumports_hook(talloc_tos(), &numlines, &qlines );
7772
if (!W_ERROR_IS_OK(result)) {
7777
info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7779
DEBUG(10,("Returning WERR_NOMEM\n"));
7780
result = WERR_NOMEM;
7784
for (i=0; i<numlines; i++) {
7785
DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7786
result = fill_port_2(info, &info[i].info2, qlines[i]);
7787
if (!W_ERROR_IS_OK(result)) {
7792
TALLOC_FREE(qlines);
7795
if (!W_ERROR_IS_OK(result)) {
7797
TALLOC_FREE(qlines);
7809
/****************************************************************
7811
****************************************************************/
7813
WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7814
struct spoolss_EnumPorts *r)
7818
/* that's an [in out] buffer */
7820
if (!r->in.buffer && (r->in.offered != 0)) {
7821
return WERR_INVALID_PARAM;
7824
DEBUG(4,("_spoolss_EnumPorts\n"));
7828
*r->out.info = NULL;
7830
switch (r->in.level) {
7832
result = enumports_level_1(p->mem_ctx, r->out.info,
7836
result = enumports_level_2(p->mem_ctx, r->out.info,
7840
return WERR_UNKNOWN_LEVEL;
7843
if (!W_ERROR_IS_OK(result)) {
7847
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7849
*r->out.info, r->in.level,
7851
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7852
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7854
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7857
/****************************************************************************
7858
****************************************************************************/
7860
static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7862
struct spoolss_SetPrinterInfoCtr *info_ctr,
7863
struct spoolss_DeviceMode *devmode,
7864
struct security_descriptor *secdesc,
7865
struct spoolss_UserLevelCtr *user_ctr,
7866
struct policy_handle *handle)
7868
struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7869
uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7871
WERROR err = WERR_OK;
7873
/* samba does not have a concept of local, non-shared printers yet, so
7874
* make sure we always setup sharename - gd */
7875
if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7876
(info2->printername != NULL && info2->printername[0] != '\0')) {
7877
DEBUG(5, ("spoolss_addprinterex_level_2: "
7878
"no sharename has been set, setting printername %s as sharename\n",
7879
info2->printername));
7880
info2->sharename = info2->printername;
7883
/* check to see if the printer already exists */
7884
if ((snum = print_queue_snum(info2->sharename)) != -1) {
7885
DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7887
return WERR_PRINTER_ALREADY_EXISTS;
7890
if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7891
if ((snum = print_queue_snum(info2->printername)) != -1) {
7892
DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7893
info2->printername));
7894
return WERR_PRINTER_ALREADY_EXISTS;
7898
/* validate printer info struct */
7899
if (!info2->printername || strlen(info2->printername) == 0) {
7900
return WERR_INVALID_PRINTER_NAME;
7902
if (!info2->portname || strlen(info2->portname) == 0) {
7903
return WERR_UNKNOWN_PORT;
7905
if (!info2->drivername || strlen(info2->drivername) == 0) {
7906
return WERR_UNKNOWN_PRINTER_DRIVER;
7908
if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7909
return WERR_UNKNOWN_PRINTPROCESSOR;
7912
/* FIXME!!! smbd should check to see if the driver is installed before
7913
trying to add a printer like this --jerry */
7915
if (*lp_addprinter_cmd() ) {
7916
if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7917
info2, p->client_id->addr,
7919
return WERR_ACCESS_DENIED;
7922
DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7923
"smb.conf parameter \"addprinter command\" is defined. This "
7924
"parameter must exist for this call to succeed\n",
7925
info2->sharename ));
7928
if ((snum = print_queue_snum(info2->sharename)) == -1) {
7929
return WERR_ACCESS_DENIED;
7932
/* you must be a printer admin to add a new printer */
7933
if (!print_access_check(p->session_info,
7936
PRINTER_ACCESS_ADMINISTER)) {
7937
return WERR_ACCESS_DENIED;
7941
* Do sanity check on the requested changes for Samba.
7944
if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7945
return WERR_INVALID_PARAM;
7948
if (devmode == NULL) {
7949
info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7952
update_dsspooler(p->mem_ctx,
7953
get_session_info_system(),
7959
err = winreg_update_printer_internal(p->mem_ctx,
7960
get_session_info_system(),
7967
if (!W_ERROR_IS_OK(err)) {
7971
err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7972
if (!W_ERROR_IS_OK(err)) {
7973
/* Handle open failed - remove addition. */
7974
ZERO_STRUCTP(handle);
7981
/****************************************************************
7982
_spoolss_AddPrinterEx
7983
****************************************************************/
7985
WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7986
struct spoolss_AddPrinterEx *r)
7988
switch (r->in.info_ctr->level) {
7990
/* we don't handle yet */
7991
/* but I know what to do ... */
7992
return WERR_UNKNOWN_LEVEL;
7994
return spoolss_addprinterex_level_2(p, r->in.server,
7996
r->in.devmode_ctr->devmode,
7997
r->in.secdesc_ctr->sd,
7998
r->in.userlevel_ctr,
8001
return WERR_UNKNOWN_LEVEL;
8005
/****************************************************************
8007
****************************************************************/
8009
WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8010
struct spoolss_AddPrinter *r)
8012
struct spoolss_AddPrinterEx a;
8013
struct spoolss_UserLevelCtr userlevel_ctr;
8015
ZERO_STRUCT(userlevel_ctr);
8017
userlevel_ctr.level = 1;
8019
a.in.server = r->in.server;
8020
a.in.info_ctr = r->in.info_ctr;
8021
a.in.devmode_ctr = r->in.devmode_ctr;
8022
a.in.secdesc_ctr = r->in.secdesc_ctr;
8023
a.in.userlevel_ctr = &userlevel_ctr;
8024
a.out.handle = r->out.handle;
8026
return _spoolss_AddPrinterEx(p, &a);
8029
/****************************************************************
8030
_spoolss_AddPrinterDriverEx
8031
****************************************************************/
8033
WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8034
struct spoolss_AddPrinterDriverEx *r)
8036
WERROR err = WERR_OK;
8037
const char *driver_name = NULL;
8042
case NDR_SPOOLSS_ADDPRINTERDRIVER:
8043
fn = "_spoolss_AddPrinterDriver";
8045
case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8046
fn = "_spoolss_AddPrinterDriverEx";
8049
return WERR_INVALID_PARAM;
8053
* we only support the semantics of AddPrinterDriver()
8054
* i.e. only copy files that are newer than existing ones
8057
if (r->in.flags == 0) {
8058
return WERR_INVALID_PARAM;
8061
if (r->in.flags != APD_COPY_NEW_FILES) {
8062
return WERR_ACCESS_DENIED;
8066
if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8067
/* Clever hack from Martin Zielinski <mz@seh.de>
8068
* to allow downgrade from level 8 (Vista).
8070
DEBUG(0,("%s: level %d not yet implemented\n", fn,
8071
r->in.info_ctr->level));
8072
return WERR_UNKNOWN_LEVEL;
8075
DEBUG(5,("Cleaning driver's information\n"));
8076
err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8077
if (!W_ERROR_IS_OK(err))
8080
DEBUG(5,("Moving driver to final destination\n"));
8081
err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8082
if (!W_ERROR_IS_OK(err)) {
8086
err = winreg_add_driver_internal(p->mem_ctx,
8087
get_session_info_system(),
8092
if (!W_ERROR_IS_OK(err)) {
8097
* I think this is where he DrvUpgradePrinter() hook would be
8098
* be called in a driver's interface DLL on a Windows NT 4.0/2k
8099
* server. Right now, we just need to send ourselves a message
8100
* to update each printer bound to this driver. --jerry
8103
if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8104
DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8112
/****************************************************************
8113
_spoolss_AddPrinterDriver
8114
****************************************************************/
8116
WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8117
struct spoolss_AddPrinterDriver *r)
8119
struct spoolss_AddPrinterDriverEx a;
8121
switch (r->in.info_ctr->level) {
8128
return WERR_UNKNOWN_LEVEL;
8131
a.in.servername = r->in.servername;
8132
a.in.info_ctr = r->in.info_ctr;
8133
a.in.flags = APD_COPY_NEW_FILES;
8135
return _spoolss_AddPrinterDriverEx(p, &a);
8138
/****************************************************************************
8139
****************************************************************************/
8141
struct _spoolss_paths {
8147
enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8149
static const struct _spoolss_paths spoolss_paths[]= {
8150
{ SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8151
{ SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8154
static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8155
const char *servername,
8156
const char *environment,
8160
const char *pservername = NULL;
8161
const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8162
const char *short_archi;
8166
/* environment may be empty */
8167
if (environment && strlen(environment)) {
8168
long_archi = environment;
8171
/* servername may be empty */
8172
if (servername && strlen(servername)) {
8173
pservername = canon_servername(servername);
8175
if (!is_myname_or_ipaddr(pservername)) {
8176
return WERR_INVALID_PARAM;
8180
if (!(short_archi = get_short_archi(long_archi))) {
8181
return WERR_INVALID_ENVIRONMENT;
8184
switch (component) {
8185
case SPOOLSS_PRTPROCS_PATH:
8186
case SPOOLSS_DRIVER_PATH:
8188
*path = talloc_asprintf(mem_ctx,
8191
spoolss_paths[component].share,
8194
*path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8195
SPOOLSS_DEFAULT_SERVER_PATH,
8196
spoolss_paths[component].dir,
8201
return WERR_INVALID_PARAM;
8211
/****************************************************************************
8212
****************************************************************************/
8214
static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8215
const char *servername,
8216
const char *environment,
8217
struct spoolss_DriverDirectoryInfo1 *r)
8222
werr = compose_spoolss_server_path(mem_ctx,
8225
SPOOLSS_DRIVER_PATH,
8227
if (!W_ERROR_IS_OK(werr)) {
8231
DEBUG(4,("printer driver directory: [%s]\n", path));
8233
r->directory_name = path;
8238
/****************************************************************
8239
_spoolss_GetPrinterDriverDirectory
8240
****************************************************************/
8242
WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8243
struct spoolss_GetPrinterDriverDirectory *r)
8247
/* that's an [in out] buffer */
8249
if (!r->in.buffer && (r->in.offered != 0)) {
8250
return WERR_INVALID_PARAM;
8253
DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8258
/* r->in.level is ignored */
8260
werror = getprinterdriverdir_level_1(p->mem_ctx,
8263
&r->out.info->info1);
8264
if (!W_ERROR_IS_OK(werror)) {
8265
TALLOC_FREE(r->out.info);
8269
*r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8270
r->out.info, r->in.level);
8271
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8273
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8276
/****************************************************************
8277
_spoolss_EnumPrinterData
8278
****************************************************************/
8280
WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8281
struct spoolss_EnumPrinterData *r)
8284
struct spoolss_EnumPrinterDataEx r2;
8286
struct spoolss_PrinterEnumValues *info, *val = NULL;
8289
r2.in.handle = r->in.handle;
8290
r2.in.key_name = "PrinterDriverData";
8292
r2.out.count = &count;
8293
r2.out.info = &info;
8294
r2.out.needed = &needed;
8296
result = _spoolss_EnumPrinterDataEx(p, &r2);
8297
if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8298
r2.in.offered = needed;
8299
result = _spoolss_EnumPrinterDataEx(p, &r2);
8301
if (!W_ERROR_IS_OK(result)) {
8306
* The NT machine wants to know the biggest size of value and data
8308
* cf: MSDN EnumPrinterData remark section
8311
if (!r->in.value_offered && !r->in.data_offered) {
8312
uint32_t biggest_valuesize = 0;
8313
uint32_t biggest_datasize = 0;
8316
DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8318
for (i=0; i<count; i++) {
8320
name_length = strlen(info[i].value_name);
8321
if (strlen(info[i].value_name) > biggest_valuesize) {
8322
biggest_valuesize = name_length;
8325
if (info[i].data_length > biggest_datasize) {
8326
biggest_datasize = info[i].data_length;
8329
DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8333
/* the value is an UNICODE string but real_value_size is the length
8334
in bytes including the trailing 0 */
8336
*r->out.value_needed = 2 * (1 + biggest_valuesize);
8337
*r->out.data_needed = biggest_datasize;
8339
DEBUG(6,("final values: [%d], [%d]\n",
8340
*r->out.value_needed, *r->out.data_needed));
8345
if (r->in.enum_index < count) {
8346
val = &info[r->in.enum_index];
8350
/* out_value should default to "" or else NT4 has
8351
problems unmarshalling the response */
8353
if (r->in.value_offered) {
8354
*r->out.value_needed = 1;
8355
r->out.value_name = talloc_strdup(r, "");
8356
if (!r->out.value_name) {
8360
r->out.value_name = NULL;
8361
*r->out.value_needed = 0;
8364
/* the data is counted in bytes */
8366
*r->out.data_needed = r->in.data_offered;
8368
result = WERR_NO_MORE_ITEMS;
8372
* - counted in bytes in the request
8373
* - counted in UNICODE chars in the max reply
8374
* - counted in bytes in the real size
8376
* take a pause *before* coding not *during* coding
8380
if (r->in.value_offered) {
8381
r->out.value_name = talloc_strdup(r, val->value_name);
8382
if (!r->out.value_name) {
8385
*r->out.value_needed = val->value_name_len;
8387
r->out.value_name = NULL;
8388
*r->out.value_needed = 0;
8393
*r->out.type = val->type;
8395
/* data - counted in bytes */
8398
* See the section "Dynamically Typed Query Parameters"
8402
if (r->out.data && val->data && val->data->data &&
8403
val->data_length && r->in.data_offered) {
8404
memcpy(r->out.data, val->data->data,
8405
MIN(val->data_length,r->in.data_offered));
8408
*r->out.data_needed = val->data_length;
8416
/****************************************************************
8417
_spoolss_SetPrinterData
8418
****************************************************************/
8420
WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8421
struct spoolss_SetPrinterData *r)
8423
struct spoolss_SetPrinterDataEx r2;
8425
r2.in.handle = r->in.handle;
8426
r2.in.key_name = "PrinterDriverData";
8427
r2.in.value_name = r->in.value_name;
8428
r2.in.type = r->in.type;
8429
r2.in.data = r->in.data;
8430
r2.in.offered = r->in.offered;
8432
return _spoolss_SetPrinterDataEx(p, &r2);
8435
/****************************************************************
8436
_spoolss_ResetPrinter
8437
****************************************************************/
8439
WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8440
struct spoolss_ResetPrinter *r)
8442
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8445
DEBUG(5,("_spoolss_ResetPrinter\n"));
8448
* All we do is to check to see if the handle and queue is valid.
8449
* This call really doesn't mean anything to us because we only
8450
* support RAW printing. --jerry
8454
DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8455
OUR_HANDLE(r->in.handle)));
8459
if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8463
/* blindly return success */
8467
/****************************************************************
8468
_spoolss_DeletePrinterData
8469
****************************************************************/
8471
WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8472
struct spoolss_DeletePrinterData *r)
8474
struct spoolss_DeletePrinterDataEx r2;
8476
r2.in.handle = r->in.handle;
8477
r2.in.key_name = "PrinterDriverData";
8478
r2.in.value_name = r->in.value_name;
8480
return _spoolss_DeletePrinterDataEx(p, &r2);
8483
/****************************************************************
8485
****************************************************************/
8487
WERROR _spoolss_AddForm(struct pipes_struct *p,
8488
struct spoolss_AddForm *r)
8490
struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8492
WERROR status = WERR_OK;
8493
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8494
struct dcerpc_binding_handle *b;
8496
DEBUG(5,("_spoolss_AddForm\n"));
8499
DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8500
OUR_HANDLE(r->in.handle)));
8504
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8505
and not a printer admin, then fail */
8507
if ((p->session_info->utok.uid != sec_initial_uid()) &&
8508
!security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8509
!token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8510
p->session_info->info3->base.domain.string,
8512
p->session_info->security_token,
8513
lp_printer_admin(snum))) {
8514
DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8515
return WERR_ACCESS_DENIED;
8518
switch (form->flags) {
8519
case SPOOLSS_FORM_USER:
8520
case SPOOLSS_FORM_BUILTIN:
8521
case SPOOLSS_FORM_PRINTER:
8524
return WERR_INVALID_PARAM;
8527
status = winreg_printer_binding_handle(p->mem_ctx,
8528
get_session_info_system(),
8531
if (!W_ERROR_IS_OK(status)) {
8535
status = winreg_printer_addform1(p->mem_ctx, b,
8537
if (!W_ERROR_IS_OK(status)) {
8542
* ChangeID must always be set if this is a printer
8544
if (Printer->printer_type == SPLHND_PRINTER) {
8545
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8549
status = winreg_printer_update_changeid(p->mem_ctx, b,
8550
lp_const_servicename(snum));
8551
if (!W_ERROR_IS_OK(status)) {
8559
/****************************************************************
8561
****************************************************************/
8563
WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8564
struct spoolss_DeleteForm *r)
8566
const char *form_name = r->in.form_name;
8567
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8569
WERROR status = WERR_OK;
8570
struct dcerpc_binding_handle *b;
8572
DEBUG(5,("_spoolss_DeleteForm\n"));
8575
DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8576
OUR_HANDLE(r->in.handle)));
8580
if ((p->session_info->utok.uid != sec_initial_uid()) &&
8581
!security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8582
!token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8583
p->session_info->info3->base.domain.string,
8585
p->session_info->security_token,
8586
lp_printer_admin(snum))) {
8587
DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8588
return WERR_ACCESS_DENIED;
8591
status = winreg_printer_binding_handle(p->mem_ctx,
8592
get_session_info_system(),
8595
if (!W_ERROR_IS_OK(status)) {
8599
status = winreg_printer_deleteform1(p->mem_ctx, b,
8601
if (!W_ERROR_IS_OK(status)) {
8606
* ChangeID must always be set if this is a printer
8608
if (Printer->printer_type == SPLHND_PRINTER) {
8609
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8613
status = winreg_printer_update_changeid(p->mem_ctx, b,
8614
lp_const_servicename(snum));
8615
if (!W_ERROR_IS_OK(status)) {
8623
/****************************************************************
8625
****************************************************************/
8627
WERROR _spoolss_SetForm(struct pipes_struct *p,
8628
struct spoolss_SetForm *r)
8630
struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8631
const char *form_name = r->in.form_name;
8633
WERROR status = WERR_OK;
8634
struct dcerpc_binding_handle *b;
8636
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8638
DEBUG(5,("_spoolss_SetForm\n"));
8641
DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8642
OUR_HANDLE(r->in.handle)));
8646
/* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8647
and not a printer admin, then fail */
8649
if ((p->session_info->utok.uid != sec_initial_uid()) &&
8650
!security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8651
!token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8652
p->session_info->info3->base.domain.string,
8654
p->session_info->security_token,
8655
lp_printer_admin(snum))) {
8656
DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8657
return WERR_ACCESS_DENIED;
8660
status = winreg_printer_binding_handle(p->mem_ctx,
8661
get_session_info_system(),
8664
if (!W_ERROR_IS_OK(status)) {
8668
status = winreg_printer_setform1(p->mem_ctx, b,
8671
if (!W_ERROR_IS_OK(status)) {
8676
* ChangeID must always be set if this is a printer
8678
if (Printer->printer_type == SPLHND_PRINTER) {
8679
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8683
status = winreg_printer_update_changeid(p->mem_ctx, b,
8684
lp_const_servicename(snum));
8685
if (!W_ERROR_IS_OK(status)) {
8693
/****************************************************************************
8694
fill_print_processor1
8695
****************************************************************************/
8697
static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8698
struct spoolss_PrintProcessorInfo1 *r,
8699
const char *print_processor_name)
8701
r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8702
W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8707
/****************************************************************************
8708
enumprintprocessors level 1.
8709
****************************************************************************/
8711
static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8712
union spoolss_PrintProcessorInfo **info_p,
8715
union spoolss_PrintProcessorInfo *info;
8718
info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8719
W_ERROR_HAVE_NO_MEMORY(info);
8723
result = fill_print_processor1(info, &info[0].info1, "winprint");
8724
if (!W_ERROR_IS_OK(result)) {
8729
if (!W_ERROR_IS_OK(result)) {
8740
/****************************************************************
8741
_spoolss_EnumPrintProcessors
8742
****************************************************************/
8744
WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8745
struct spoolss_EnumPrintProcessors *r)
8749
/* that's an [in out] buffer */
8751
if (!r->in.buffer && (r->in.offered != 0)) {
8752
return WERR_INVALID_PARAM;
8755
DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8758
* Enumerate the print processors ...
8760
* Just reply with "winprint", to keep NT happy
8761
* and I can use my nice printer checker.
8766
*r->out.info = NULL;
8768
if (!get_short_archi(r->in.environment)) {
8769
return WERR_INVALID_ENVIRONMENT;
8772
switch (r->in.level) {
8774
result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8778
return WERR_UNKNOWN_LEVEL;
8781
if (!W_ERROR_IS_OK(result)) {
8785
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8786
spoolss_EnumPrintProcessors,
8787
*r->out.info, r->in.level,
8789
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8790
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8792
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8795
/****************************************************************************
8796
fill_printprocdatatype1
8797
****************************************************************************/
8799
static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8800
struct spoolss_PrintProcDataTypesInfo1 *r,
8801
const char *name_array)
8803
r->name_array = talloc_strdup(mem_ctx, name_array);
8804
W_ERROR_HAVE_NO_MEMORY(r->name_array);
8809
/****************************************************************************
8810
enumprintprocdatatypes level 1.
8811
****************************************************************************/
8813
static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8814
union spoolss_PrintProcDataTypesInfo **info_p,
8818
union spoolss_PrintProcDataTypesInfo *info;
8820
info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8821
W_ERROR_HAVE_NO_MEMORY(info);
8825
result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8826
if (!W_ERROR_IS_OK(result)) {
8831
if (!W_ERROR_IS_OK(result)) {
8842
/****************************************************************
8843
_spoolss_EnumPrintProcDataTypes
8844
****************************************************************/
8846
WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8847
struct spoolss_EnumPrintProcDataTypes *r)
8851
/* that's an [in out] buffer */
8853
if (!r->in.buffer && (r->in.offered != 0)) {
8854
return WERR_INVALID_PARAM;
8857
DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8861
*r->out.info = NULL;
8863
if (r->in.print_processor_name == NULL ||
8864
!strequal(r->in.print_processor_name, "winprint")) {
8865
return WERR_UNKNOWN_PRINTPROCESSOR;
8868
switch (r->in.level) {
8870
result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8874
return WERR_UNKNOWN_LEVEL;
8877
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8878
spoolss_EnumPrintProcDataTypes,
8879
*r->out.info, r->in.level,
8881
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8882
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8884
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8887
/****************************************************************************
8889
****************************************************************************/
8891
static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8892
struct spoolss_MonitorInfo1 *r,
8893
const char *monitor_name)
8895
r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8896
W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8901
/****************************************************************************
8903
****************************************************************************/
8905
static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8906
struct spoolss_MonitorInfo2 *r,
8907
const char *monitor_name,
8908
const char *environment,
8909
const char *dll_name)
8911
r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8912
W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8913
r->environment = talloc_strdup(mem_ctx, environment);
8914
W_ERROR_HAVE_NO_MEMORY(r->environment);
8915
r->dll_name = talloc_strdup(mem_ctx, dll_name);
8916
W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8921
/****************************************************************************
8922
enumprintmonitors level 1.
8923
****************************************************************************/
8925
static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8926
union spoolss_MonitorInfo **info_p,
8929
union spoolss_MonitorInfo *info;
8930
WERROR result = WERR_OK;
8932
info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8933
W_ERROR_HAVE_NO_MEMORY(info);
8937
result = fill_monitor_1(info, &info[0].info1,
8939
if (!W_ERROR_IS_OK(result)) {
8943
result = fill_monitor_1(info, &info[1].info1,
8945
if (!W_ERROR_IS_OK(result)) {
8950
if (!W_ERROR_IS_OK(result)) {
8961
/****************************************************************************
8962
enumprintmonitors level 2.
8963
****************************************************************************/
8965
static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8966
union spoolss_MonitorInfo **info_p,
8969
union spoolss_MonitorInfo *info;
8970
WERROR result = WERR_OK;
8972
info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8973
W_ERROR_HAVE_NO_MEMORY(info);
8977
result = fill_monitor_2(info, &info[0].info2,
8979
"Windows NT X86", /* FIXME */
8981
if (!W_ERROR_IS_OK(result)) {
8985
result = fill_monitor_2(info, &info[1].info2,
8987
"Windows NT X86", /* FIXME */
8989
if (!W_ERROR_IS_OK(result)) {
8994
if (!W_ERROR_IS_OK(result)) {
9005
/****************************************************************
9006
_spoolss_EnumMonitors
9007
****************************************************************/
9009
WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9010
struct spoolss_EnumMonitors *r)
9014
/* that's an [in out] buffer */
9016
if (!r->in.buffer && (r->in.offered != 0)) {
9017
return WERR_INVALID_PARAM;
9020
DEBUG(5,("_spoolss_EnumMonitors\n"));
9023
* Enumerate the print monitors ...
9025
* Just reply with "Local Port", to keep NT happy
9026
* and I can use my nice printer checker.
9031
*r->out.info = NULL;
9033
switch (r->in.level) {
9035
result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9039
result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9043
return WERR_UNKNOWN_LEVEL;
9046
if (!W_ERROR_IS_OK(result)) {
9050
*r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9051
spoolss_EnumMonitors,
9052
*r->out.info, r->in.level,
9054
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9055
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9057
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9060
/****************************************************************************
9061
****************************************************************************/
9063
static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9064
const print_queue_struct *queue,
9065
int count, int snum,
9066
struct spoolss_PrinterInfo2 *pinfo2,
9068
struct spoolss_JobInfo1 *r)
9073
for (i=0; i<count; i++) {
9074
if (queue[i].job == (int)jobid) {
9080
if (found == false) {
9081
/* NT treats not found as bad param... yet another bad choice */
9082
return WERR_INVALID_PARAM;
9085
return fill_job_info1(mem_ctx,
9093
/****************************************************************************
9094
****************************************************************************/
9096
static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9097
const print_queue_struct *queue,
9098
int count, int snum,
9099
struct spoolss_PrinterInfo2 *pinfo2,
9101
struct spoolss_JobInfo2 *r)
9105
struct spoolss_DeviceMode *devmode;
9108
for (i=0; i<count; i++) {
9109
if (queue[i].job == (int)jobid) {
9115
if (found == false) {
9116
/* NT treats not found as bad param... yet another bad
9118
return WERR_INVALID_PARAM;
9122
* if the print job does not have a DEVMODE associated with it,
9123
* just use the one for the printer. A NULL devicemode is not
9124
* a failure condition
9127
devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9129
result = spoolss_create_default_devmode(mem_ctx,
9130
pinfo2->printername,
9132
if (!W_ERROR_IS_OK(result)) {
9133
DEBUG(3, ("Can't proceed w/o a devmode!"));
9138
return fill_job_info2(mem_ctx,
9147
/****************************************************************
9149
****************************************************************/
9151
WERROR _spoolss_GetJob(struct pipes_struct *p,
9152
struct spoolss_GetJob *r)
9154
WERROR result = WERR_OK;
9155
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9158
print_queue_struct *queue = NULL;
9159
print_status_struct prt_status;
9161
/* that's an [in out] buffer */
9163
if (!r->in.buffer && (r->in.offered != 0)) {
9164
return WERR_INVALID_PARAM;
9167
DEBUG(5,("_spoolss_GetJob\n"));
9171
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9175
result = winreg_get_printer_internal(p->mem_ctx,
9176
get_session_info_system(),
9178
lp_const_servicename(snum),
9180
if (!W_ERROR_IS_OK(result)) {
9184
count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9186
DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9187
count, prt_status.status, prt_status.message));
9189
switch (r->in.level) {
9191
result = getjob_level_1(p->mem_ctx,
9192
queue, count, snum, pinfo2,
9193
r->in.job_id, &r->out.info->info1);
9196
result = getjob_level_2(p->mem_ctx,
9197
queue, count, snum, pinfo2,
9198
r->in.job_id, &r->out.info->info2);
9201
result = WERR_UNKNOWN_LEVEL;
9206
TALLOC_FREE(pinfo2);
9208
if (!W_ERROR_IS_OK(result)) {
9209
TALLOC_FREE(r->out.info);
9213
*r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9215
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9217
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9220
/****************************************************************
9221
_spoolss_GetPrinterDataEx
9222
****************************************************************/
9224
WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9225
struct spoolss_GetPrinterDataEx *r)
9228
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9229
const char *printer;
9231
WERROR result = WERR_OK;
9233
enum winreg_Type val_type = REG_NONE;
9234
uint8_t *val_data = NULL;
9235
uint32_t val_size = 0;
9236
struct dcerpc_binding_handle *b;
9238
DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9240
DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9241
r->in.key_name, r->in.value_name));
9243
/* in case of problem, return some default values */
9246
*r->out.type = REG_NONE;
9249
DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9250
OUR_HANDLE(r->in.handle)));
9251
result = WERR_BADFID;
9255
/* Is the handle to a printer or to the server? */
9257
if (Printer->printer_type == SPLHND_SERVER) {
9259
union spoolss_PrinterData data;
9261
result = getprinterdata_printer_server(p->mem_ctx,
9265
if (!W_ERROR_IS_OK(result)) {
9269
result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9270
*r->out.type, &data);
9271
if (!W_ERROR_IS_OK(result)) {
9275
*r->out.needed = blob.length;
9277
if (r->in.offered >= *r->out.needed) {
9278
memcpy(r->out.data, blob.data, blob.length);
9281
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9284
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9287
printer = lp_const_servicename(snum);
9289
/* check to see if the keyname is valid */
9290
if (!strlen(r->in.key_name)) {
9291
return WERR_INVALID_PARAM;
9294
result = winreg_printer_binding_handle(p->mem_ctx,
9295
get_session_info_system(),
9298
if (!W_ERROR_IS_OK(result)) {
9302
/* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9303
if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9304
strequal(r->in.value_name, "ChangeId")) {
9305
*r->out.type = REG_DWORD;
9307
if (r->in.offered >= *r->out.needed) {
9308
uint32_t changeid = 0;
9310
result = winreg_printer_get_changeid(p->mem_ctx, b,
9313
if (!W_ERROR_IS_OK(result)) {
9317
SIVAL(r->out.data, 0, changeid);
9323
result = winreg_get_printer_dataex(p->mem_ctx, b,
9330
if (!W_ERROR_IS_OK(result)) {
9334
*r->out.needed = val_size;
9335
*r->out.type = val_type;
9337
if (r->in.offered >= *r->out.needed) {
9338
memcpy(r->out.data, val_data, val_size);
9342
/* retain type when returning WERR_MORE_DATA */
9343
r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9345
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9348
/****************************************************************
9349
_spoolss_SetPrinterDataEx
9350
****************************************************************/
9352
WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9353
struct spoolss_SetPrinterDataEx *r)
9355
struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9357
WERROR result = WERR_OK;
9358
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9360
struct dcerpc_binding_handle *b;
9362
DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9364
/* From MSDN documentation of SetPrinterDataEx: pass request to
9365
SetPrinterData if key is "PrinterDriverData" */
9368
DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9369
OUR_HANDLE(r->in.handle)));
9373
if (Printer->printer_type == SPLHND_SERVER) {
9374
DEBUG(10,("_spoolss_SetPrinterDataEx: "
9375
"Not implemented for server handles yet\n"));
9376
return WERR_INVALID_PARAM;
9379
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9384
* Access check : NT returns "access denied" if you make a
9385
* SetPrinterData call without the necessary privildge.
9386
* we were originally returning OK if nothing changed
9387
* which made Win2k issue **a lot** of SetPrinterData
9388
* when connecting to a printer --jerry
9391
if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9392
DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9393
"change denied by handle access permissions\n"));
9394
return WERR_ACCESS_DENIED;
9397
result = winreg_printer_binding_handle(p->mem_ctx,
9398
get_session_info_system(),
9401
if (!W_ERROR_IS_OK(result)) {
9405
result = winreg_get_printer(Printer, b,
9406
lp_servicename(snum),
9408
if (!W_ERROR_IS_OK(result)) {
9412
/* check for OID in valuename */
9414
oid_string = strchr(r->in.value_name, ',');
9420
/* save the registry data */
9422
result = winreg_set_printer_dataex(p->mem_ctx, b,
9430
if (W_ERROR_IS_OK(result)) {
9431
/* save the OID if one was specified */
9433
char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9434
r->in.key_name, SPOOL_OID_KEY);
9436
result = WERR_NOMEM;
9441
* I'm not checking the status here on purpose. Don't know
9442
* if this is right, but I'm returning the status from the
9443
* previous set_printer_dataex() call. I have no idea if
9444
* this is right. --jerry
9446
winreg_set_printer_dataex(p->mem_ctx, b,
9451
(uint8_t *) oid_string,
9452
strlen(oid_string) + 1);
9455
result = winreg_printer_update_changeid(p->mem_ctx, b,
9456
lp_const_servicename(snum));
9461
talloc_free(pinfo2);
9465
/****************************************************************
9466
_spoolss_DeletePrinterDataEx
9467
****************************************************************/
9469
WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9470
struct spoolss_DeletePrinterDataEx *r)
9472
const char *printer;
9474
WERROR status = WERR_OK;
9475
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9477
DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9480
DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9481
"Invalid handle (%s:%u:%u).\n",
9482
OUR_HANDLE(r->in.handle)));
9486
if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9487
DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9488
"printer properties change denied by handle\n"));
9489
return WERR_ACCESS_DENIED;
9492
if (!r->in.value_name || !r->in.key_name) {
9496
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9499
printer = lp_const_servicename(snum);
9501
status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9502
get_session_info_system(),
9507
if (W_ERROR_IS_OK(status)) {
9508
status = winreg_printer_update_changeid_internal(p->mem_ctx,
9509
get_session_info_system(),
9517
/****************************************************************
9518
_spoolss_EnumPrinterKey
9519
****************************************************************/
9521
WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9522
struct spoolss_EnumPrinterKey *r)
9525
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9527
WERROR result = WERR_BADFILE;
9528
const char **array = NULL;
9531
DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9534
DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9535
OUR_HANDLE(r->in.handle)));
9539
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9543
result = winreg_enum_printer_key_internal(p->mem_ctx,
9544
get_session_info_system(),
9546
lp_const_servicename(snum),
9550
if (!W_ERROR_IS_OK(result)) {
9554
if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9555
result = WERR_NOMEM;
9559
*r->out._ndr_size = r->in.offered / 2;
9560
*r->out.needed = blob.length;
9562
if (r->in.offered < *r->out.needed) {
9563
result = WERR_MORE_DATA;
9566
r->out.key_buffer->string_array = array;
9570
if (!W_ERROR_IS_OK(result)) {
9572
if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9580
/****************************************************************
9581
_spoolss_DeletePrinterKey
9582
****************************************************************/
9584
WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9585
struct spoolss_DeletePrinterKey *r)
9587
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9590
const char *printer;
9591
struct dcerpc_binding_handle *b;
9593
DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9596
DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9597
OUR_HANDLE(r->in.handle)));
9601
/* if keyname == NULL, return error */
9602
if ( !r->in.key_name )
9603
return WERR_INVALID_PARAM;
9605
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9609
if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9610
DEBUG(3, ("_spoolss_DeletePrinterKey: "
9611
"printer properties change denied by handle\n"));
9612
return WERR_ACCESS_DENIED;
9615
printer = lp_const_servicename(snum);
9617
status = winreg_printer_binding_handle(p->mem_ctx,
9618
get_session_info_system(),
9621
if (!W_ERROR_IS_OK(status)) {
9625
/* delete the key and all subkeys */
9626
status = winreg_delete_printer_key(p->mem_ctx, b,
9629
if (W_ERROR_IS_OK(status)) {
9630
status = winreg_printer_update_changeid(p->mem_ctx, b,
9637
/****************************************************************
9638
_spoolss_EnumPrinterDataEx
9639
****************************************************************/
9641
WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9642
struct spoolss_EnumPrinterDataEx *r)
9645
struct spoolss_PrinterEnumValues *info = NULL;
9646
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9650
DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9654
*r->out.info = NULL;
9657
DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9658
OUR_HANDLE(r->in.handle)));
9663
* first check for a keyname of NULL or "". Win2k seems to send
9664
* this a lot and we should send back WERR_INVALID_PARAM
9665
* no need to spend time looking up the printer in this case.
9669
if (!strlen(r->in.key_name)) {
9670
result = WERR_INVALID_PARAM;
9674
if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9678
/* now look for a match on the key name */
9679
result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9680
get_session_info_system(),
9682
lp_const_servicename(snum),
9686
if (!W_ERROR_IS_OK(result)) {
9690
#if 0 /* FIXME - gd */
9691
/* housekeeping information in the reply */
9693
/* Fix from Martin Zielinski <mz@seh.de> - ensure
9694
* the hand marshalled container size is a multiple
9695
* of 4 bytes for RPC alignment.
9699
needed += 4-(needed % 4);
9702
*r->out.count = count;
9703
*r->out.info = info;
9706
if (!W_ERROR_IS_OK(result)) {
9710
*r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9711
spoolss_EnumPrinterDataEx,
9714
*r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9715
*r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9717
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9720
/****************************************************************************
9721
****************************************************************************/
9723
static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9724
const char *servername,
9725
const char *environment,
9726
struct spoolss_PrintProcessorDirectoryInfo1 *r)
9731
werr = compose_spoolss_server_path(mem_ctx,
9734
SPOOLSS_PRTPROCS_PATH,
9736
if (!W_ERROR_IS_OK(werr)) {
9740
DEBUG(4,("print processor directory: [%s]\n", path));
9742
r->directory_name = path;
9747
/****************************************************************
9748
_spoolss_GetPrintProcessorDirectory
9749
****************************************************************/
9751
WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9752
struct spoolss_GetPrintProcessorDirectory *r)
9755
char *prnproc_share = NULL;
9756
bool prnproc_share_exists = false;
9759
/* that's an [in out] buffer */
9761
if (!r->in.buffer && (r->in.offered != 0)) {
9762
return WERR_INVALID_PARAM;
9765
DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9770
/* r->in.level is ignored */
9772
/* We always should reply with a local print processor directory so that
9773
* users are not forced to have a [prnproc$] share on the Samba spoolss
9774
* server, if users decide to do so, lets announce it though - Guenther */
9776
snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9777
if (!prnproc_share) {
9781
prnproc_share_exists = true;
9784
result = getprintprocessordirectory_level_1(p->mem_ctx,
9785
prnproc_share_exists ? r->in.server : NULL,
9787
&r->out.info->info1);
9788
if (!W_ERROR_IS_OK(result)) {
9789
TALLOC_FREE(r->out.info);
9793
*r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9794
r->out.info, r->in.level);
9795
r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9797
return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9800
/*******************************************************************
9801
********************************************************************/
9803
static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9804
const char *dllname)
9806
enum ndr_err_code ndr_err;
9807
struct spoolss_MonitorUi ui;
9809
ui.dll_name = dllname;
9811
ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9812
(ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9813
if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9814
NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9816
return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9819
/*******************************************************************
9820
Streams the monitor UI DLL name in UNICODE
9821
*******************************************************************/
9823
static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9824
struct security_token *token, DATA_BLOB *in,
9825
DATA_BLOB *out, uint32_t *needed)
9827
const char *dllname = "tcpmonui.dll";
9829
*needed = (strlen(dllname)+1) * 2;
9831
if (out->length < *needed) {
9832
return WERR_INSUFFICIENT_BUFFER;
9835
if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9842
/*******************************************************************
9843
********************************************************************/
9845
static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9846
struct spoolss_PortData1 *port1,
9847
const DATA_BLOB *buf)
9849
enum ndr_err_code ndr_err;
9850
ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9851
(ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9852
if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9853
NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9855
return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9858
/*******************************************************************
9859
********************************************************************/
9861
static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9862
struct spoolss_PortData2 *port2,
9863
const DATA_BLOB *buf)
9865
enum ndr_err_code ndr_err;
9866
ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9867
(ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9868
if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9869
NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9871
return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9874
/*******************************************************************
9875
Create a new TCP/IP port
9876
*******************************************************************/
9878
static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9879
struct security_token *token, DATA_BLOB *in,
9880
DATA_BLOB *out, uint32_t *needed)
9882
struct spoolss_PortData1 port1;
9883
struct spoolss_PortData2 port2;
9884
char *device_uri = NULL;
9887
const char *portname;
9888
const char *hostaddress;
9890
uint32_t port_number;
9893
/* peek for spoolss_PortData version */
9895
if (!in || (in->length < (128 + 4))) {
9896
return WERR_GENERAL_FAILURE;
9899
version = IVAL(in->data, 128);
9905
if (!pull_port_data_1(mem_ctx, &port1, in)) {
9909
portname = port1.portname;
9910
hostaddress = port1.hostaddress;
9911
queue = port1.queue;
9912
protocol = port1.protocol;
9913
port_number = port1.port_number;
9919
if (!pull_port_data_2(mem_ctx, &port2, in)) {
9923
portname = port2.portname;
9924
hostaddress = port2.hostaddress;
9925
queue = port2.queue;
9926
protocol = port2.protocol;
9927
port_number = port2.port_number;
9931
DEBUG(1,("xcvtcp_addport: "
9932
"unknown version of port_data: %d\n", version));
9933
return WERR_UNKNOWN_PORT;
9936
/* create the device URI and call the add_port_hook() */
9939
case PROTOCOL_RAWTCP_TYPE:
9940
device_uri = talloc_asprintf(mem_ctx,
9941
"socket://%s:%d/", hostaddress,
9945
case PROTOCOL_LPR_TYPE:
9946
device_uri = talloc_asprintf(mem_ctx,
9947
"lpr://%s/%s", hostaddress, queue );
9951
return WERR_UNKNOWN_PORT;
9958
return add_port_hook(mem_ctx, token, portname, device_uri);
9961
/*******************************************************************
9962
*******************************************************************/
9964
struct xcv_api_table xcvtcp_cmds[] = {
9965
{ "MonitorUI", xcvtcp_monitorui },
9966
{ "AddPort", xcvtcp_addport},
9970
static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9971
struct security_token *token, const char *command,
9978
DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9980
for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9981
if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9982
return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9985
return WERR_BADFUNC;
9988
/*******************************************************************
9989
*******************************************************************/
9990
#if 0 /* don't support management using the "Local Port" monitor */
9992
static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9993
struct security_token *token, DATA_BLOB *in,
9994
DATA_BLOB *out, uint32_t *needed)
9996
const char *dllname = "localui.dll";
9998
*needed = (strlen(dllname)+1) * 2;
10000
if (out->length < *needed) {
10001
return WERR_INSUFFICIENT_BUFFER;
10004
if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10011
/*******************************************************************
10012
*******************************************************************/
10014
struct xcv_api_table xcvlocal_cmds[] = {
10015
{ "MonitorUI", xcvlocal_monitorui },
10019
struct xcv_api_table xcvlocal_cmds[] = {
10026
/*******************************************************************
10027
*******************************************************************/
10029
static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10030
struct security_token *token, const char *command,
10031
DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10036
DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10038
for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10039
if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10040
return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10042
return WERR_BADFUNC;
10045
/****************************************************************
10047
****************************************************************/
10049
WERROR _spoolss_XcvData(struct pipes_struct *p,
10050
struct spoolss_XcvData *r)
10052
struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10053
DATA_BLOB out_data = data_blob_null;
10057
DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10058
OUR_HANDLE(r->in.handle)));
10059
return WERR_BADFID;
10062
/* Has to be a handle to the TCP/IP port monitor */
10064
if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10065
DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10066
return WERR_BADFID;
10069
/* requires administrative access to the server */
10071
if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10072
DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10073
return WERR_ACCESS_DENIED;
10076
/* Allocate the outgoing buffer */
10078
if (r->in.out_data_size) {
10079
out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10080
if (out_data.data == NULL) {
10085
switch ( Printer->printer_type ) {
10086
case SPLHND_PORTMON_TCP:
10087
werror = process_xcvtcp_command(p->mem_ctx,
10088
p->session_info->security_token,
10089
r->in.function_name,
10090
&r->in.in_data, &out_data,
10093
case SPLHND_PORTMON_LOCAL:
10094
werror = process_xcvlocal_command(p->mem_ctx,
10095
p->session_info->security_token,
10096
r->in.function_name,
10097
&r->in.in_data, &out_data,
10101
werror = WERR_INVALID_PRINT_MONITOR;
10104
if (!W_ERROR_IS_OK(werror)) {
10108
*r->out.status_code = 0;
10110
if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10111
memcpy(r->out.out_data, out_data.data,
10112
MIN(r->in.out_data_size, out_data.length));
10118
/****************************************************************
10119
_spoolss_AddPrintProcessor
10120
****************************************************************/
10122
WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10123
struct spoolss_AddPrintProcessor *r)
10125
/* for now, just indicate success and ignore the add. We'll
10126
automatically set the winprint processor for printer
10127
entries later. Used to debug the LexMark Optra S 1855 PCL
10133
/****************************************************************
10135
****************************************************************/
10137
WERROR _spoolss_AddPort(struct pipes_struct *p,
10138
struct spoolss_AddPort *r)
10140
/* do what w2k3 does */
10142
return WERR_NOT_SUPPORTED;
10145
/****************************************************************
10146
_spoolss_GetPrinterDriver
10147
****************************************************************/
10149
WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10150
struct spoolss_GetPrinterDriver *r)
10152
p->rng_fault_state = true;
10153
return WERR_NOT_SUPPORTED;
10156
/****************************************************************
10157
_spoolss_ReadPrinter
10158
****************************************************************/
10160
WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10161
struct spoolss_ReadPrinter *r)
10163
p->rng_fault_state = true;
10164
return WERR_NOT_SUPPORTED;
10167
/****************************************************************
10168
_spoolss_WaitForPrinterChange
10169
****************************************************************/
10171
WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10172
struct spoolss_WaitForPrinterChange *r)
10174
p->rng_fault_state = true;
10175
return WERR_NOT_SUPPORTED;
10178
/****************************************************************
10179
_spoolss_ConfigurePort
10180
****************************************************************/
10182
WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10183
struct spoolss_ConfigurePort *r)
10185
p->rng_fault_state = true;
10186
return WERR_NOT_SUPPORTED;
10189
/****************************************************************
10190
_spoolss_DeletePort
10191
****************************************************************/
10193
WERROR _spoolss_DeletePort(struct pipes_struct *p,
10194
struct spoolss_DeletePort *r)
10196
p->rng_fault_state = true;
10197
return WERR_NOT_SUPPORTED;
10200
/****************************************************************
10201
_spoolss_CreatePrinterIC
10202
****************************************************************/
10204
WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10205
struct spoolss_CreatePrinterIC *r)
10207
p->rng_fault_state = true;
10208
return WERR_NOT_SUPPORTED;
10211
/****************************************************************
10212
_spoolss_PlayGDIScriptOnPrinterIC
10213
****************************************************************/
10215
WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10216
struct spoolss_PlayGDIScriptOnPrinterIC *r)
10218
p->rng_fault_state = true;
10219
return WERR_NOT_SUPPORTED;
10222
/****************************************************************
10223
_spoolss_DeletePrinterIC
10224
****************************************************************/
10226
WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10227
struct spoolss_DeletePrinterIC *r)
10229
p->rng_fault_state = true;
10230
return WERR_NOT_SUPPORTED;
10233
/****************************************************************
10234
_spoolss_AddPrinterConnection
10235
****************************************************************/
10237
WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10238
struct spoolss_AddPrinterConnection *r)
10240
p->rng_fault_state = true;
10241
return WERR_NOT_SUPPORTED;
10244
/****************************************************************
10245
_spoolss_DeletePrinterConnection
10246
****************************************************************/
10248
WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10249
struct spoolss_DeletePrinterConnection *r)
10251
p->rng_fault_state = true;
10252
return WERR_NOT_SUPPORTED;
10255
/****************************************************************
10256
_spoolss_PrinterMessageBox
10257
****************************************************************/
10259
WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10260
struct spoolss_PrinterMessageBox *r)
10262
p->rng_fault_state = true;
10263
return WERR_NOT_SUPPORTED;
10266
/****************************************************************
10267
_spoolss_AddMonitor
10268
****************************************************************/
10270
WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10271
struct spoolss_AddMonitor *r)
10273
p->rng_fault_state = true;
10274
return WERR_NOT_SUPPORTED;
10277
/****************************************************************
10278
_spoolss_DeleteMonitor
10279
****************************************************************/
10281
WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10282
struct spoolss_DeleteMonitor *r)
10284
p->rng_fault_state = true;
10285
return WERR_NOT_SUPPORTED;
10288
/****************************************************************
10289
_spoolss_DeletePrintProcessor
10290
****************************************************************/
10292
WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10293
struct spoolss_DeletePrintProcessor *r)
10295
p->rng_fault_state = true;
10296
return WERR_NOT_SUPPORTED;
10299
/****************************************************************
10300
_spoolss_AddPrintProvidor
10301
****************************************************************/
10303
WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10304
struct spoolss_AddPrintProvidor *r)
10306
p->rng_fault_state = true;
10307
return WERR_NOT_SUPPORTED;
10310
/****************************************************************
10311
_spoolss_DeletePrintProvidor
10312
****************************************************************/
10314
WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10315
struct spoolss_DeletePrintProvidor *r)
10317
p->rng_fault_state = true;
10318
return WERR_NOT_SUPPORTED;
10321
/****************************************************************
10322
_spoolss_FindFirstPrinterChangeNotification
10323
****************************************************************/
10325
WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10326
struct spoolss_FindFirstPrinterChangeNotification *r)
10328
p->rng_fault_state = true;
10329
return WERR_NOT_SUPPORTED;
10332
/****************************************************************
10333
_spoolss_FindNextPrinterChangeNotification
10334
****************************************************************/
10336
WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10337
struct spoolss_FindNextPrinterChangeNotification *r)
10339
p->rng_fault_state = true;
10340
return WERR_NOT_SUPPORTED;
10343
/****************************************************************
10344
_spoolss_RouterFindFirstPrinterChangeNotificationOld
10345
****************************************************************/
10347
WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10348
struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10350
p->rng_fault_state = true;
10351
return WERR_NOT_SUPPORTED;
10354
/****************************************************************
10355
_spoolss_ReplyOpenPrinter
10356
****************************************************************/
10358
WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10359
struct spoolss_ReplyOpenPrinter *r)
10361
p->rng_fault_state = true;
10362
return WERR_NOT_SUPPORTED;
10365
/****************************************************************
10366
_spoolss_RouterReplyPrinter
10367
****************************************************************/
10369
WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10370
struct spoolss_RouterReplyPrinter *r)
10372
p->rng_fault_state = true;
10373
return WERR_NOT_SUPPORTED;
10376
/****************************************************************
10377
_spoolss_ReplyClosePrinter
10378
****************************************************************/
10380
WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10381
struct spoolss_ReplyClosePrinter *r)
10383
p->rng_fault_state = true;
10384
return WERR_NOT_SUPPORTED;
10387
/****************************************************************
10389
****************************************************************/
10391
WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10392
struct spoolss_AddPortEx *r)
10394
p->rng_fault_state = true;
10395
return WERR_NOT_SUPPORTED;
10398
/****************************************************************
10399
_spoolss_RouterFindFirstPrinterChangeNotification
10400
****************************************************************/
10402
WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10403
struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10405
p->rng_fault_state = true;
10406
return WERR_NOT_SUPPORTED;
10409
/****************************************************************
10410
_spoolss_SpoolerInit
10411
****************************************************************/
10413
WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10414
struct spoolss_SpoolerInit *r)
10416
p->rng_fault_state = true;
10417
return WERR_NOT_SUPPORTED;
10420
/****************************************************************
10421
_spoolss_ResetPrinterEx
10422
****************************************************************/
10424
WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10425
struct spoolss_ResetPrinterEx *r)
10427
p->rng_fault_state = true;
10428
return WERR_NOT_SUPPORTED;
10431
/****************************************************************
10432
_spoolss_RouterReplyPrinterEx
10433
****************************************************************/
10435
WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10436
struct spoolss_RouterReplyPrinterEx *r)
10438
p->rng_fault_state = true;
10439
return WERR_NOT_SUPPORTED;
10442
/****************************************************************
10444
****************************************************************/
10446
WERROR _spoolss_44(struct pipes_struct *p,
10447
struct spoolss_44 *r)
10449
p->rng_fault_state = true;
10450
return WERR_NOT_SUPPORTED;
10453
/****************************************************************
10455
****************************************************************/
10457
WERROR _spoolss_SetPort(struct pipes_struct *p,
10458
struct spoolss_SetPort *r)
10460
p->rng_fault_state = true;
10461
return WERR_NOT_SUPPORTED;
10464
/****************************************************************
10466
****************************************************************/
10468
WERROR _spoolss_4a(struct pipes_struct *p,
10469
struct spoolss_4a *r)
10471
p->rng_fault_state = true;
10472
return WERR_NOT_SUPPORTED;
10475
/****************************************************************
10477
****************************************************************/
10479
WERROR _spoolss_4b(struct pipes_struct *p,
10480
struct spoolss_4b *r)
10482
p->rng_fault_state = true;
10483
return WERR_NOT_SUPPORTED;
10486
/****************************************************************
10488
****************************************************************/
10490
WERROR _spoolss_4c(struct pipes_struct *p,
10491
struct spoolss_4c *r)
10493
p->rng_fault_state = true;
10494
return WERR_NOT_SUPPORTED;
10497
/****************************************************************
10499
****************************************************************/
10501
WERROR _spoolss_53(struct pipes_struct *p,
10502
struct spoolss_53 *r)
10504
p->rng_fault_state = true;
10505
return WERR_NOT_SUPPORTED;
10508
/****************************************************************
10509
_spoolss_AddPerMachineConnection
10510
****************************************************************/
10512
WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10513
struct spoolss_AddPerMachineConnection *r)
10515
p->rng_fault_state = true;
10516
return WERR_NOT_SUPPORTED;
10519
/****************************************************************
10520
_spoolss_DeletePerMachineConnection
10521
****************************************************************/
10523
WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10524
struct spoolss_DeletePerMachineConnection *r)
10526
p->rng_fault_state = true;
10527
return WERR_NOT_SUPPORTED;
10530
/****************************************************************
10531
_spoolss_EnumPerMachineConnections
10532
****************************************************************/
10534
WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10535
struct spoolss_EnumPerMachineConnections *r)
10537
p->rng_fault_state = true;
10538
return WERR_NOT_SUPPORTED;
10541
/****************************************************************
10543
****************************************************************/
10545
WERROR _spoolss_5a(struct pipes_struct *p,
10546
struct spoolss_5a *r)
10548
p->rng_fault_state = true;
10549
return WERR_NOT_SUPPORTED;
10552
/****************************************************************
10554
****************************************************************/
10556
WERROR _spoolss_5b(struct pipes_struct *p,
10557
struct spoolss_5b *r)
10559
p->rng_fault_state = true;
10560
return WERR_NOT_SUPPORTED;
10563
/****************************************************************
10565
****************************************************************/
10567
WERROR _spoolss_5c(struct pipes_struct *p,
10568
struct spoolss_5c *r)
10570
p->rng_fault_state = true;
10571
return WERR_NOT_SUPPORTED;
10574
/****************************************************************
10576
****************************************************************/
10578
WERROR _spoolss_5d(struct pipes_struct *p,
10579
struct spoolss_5d *r)
10581
p->rng_fault_state = true;
10582
return WERR_NOT_SUPPORTED;
10585
/****************************************************************
10587
****************************************************************/
10589
WERROR _spoolss_5e(struct pipes_struct *p,
10590
struct spoolss_5e *r)
10592
p->rng_fault_state = true;
10593
return WERR_NOT_SUPPORTED;
10596
/****************************************************************
10598
****************************************************************/
10600
WERROR _spoolss_5f(struct pipes_struct *p,
10601
struct spoolss_5f *r)
10603
p->rng_fault_state = true;
10604
return WERR_NOT_SUPPORTED;
10607
/****************************************************************
10609
****************************************************************/
10611
WERROR _spoolss_60(struct pipes_struct *p,
10612
struct spoolss_60 *r)
10614
p->rng_fault_state = true;
10615
return WERR_NOT_SUPPORTED;
10618
/****************************************************************
10620
****************************************************************/
10622
WERROR _spoolss_61(struct pipes_struct *p,
10623
struct spoolss_61 *r)
10625
p->rng_fault_state = true;
10626
return WERR_NOT_SUPPORTED;
10629
/****************************************************************
10631
****************************************************************/
10633
WERROR _spoolss_62(struct pipes_struct *p,
10634
struct spoolss_62 *r)
10636
p->rng_fault_state = true;
10637
return WERR_NOT_SUPPORTED;
10640
/****************************************************************
10642
****************************************************************/
10644
WERROR _spoolss_63(struct pipes_struct *p,
10645
struct spoolss_63 *r)
10647
p->rng_fault_state = true;
10648
return WERR_NOT_SUPPORTED;
10651
/****************************************************************
10653
****************************************************************/
10655
WERROR _spoolss_64(struct pipes_struct *p,
10656
struct spoolss_64 *r)
10658
p->rng_fault_state = true;
10659
return WERR_NOT_SUPPORTED;
10662
/****************************************************************
10664
****************************************************************/
10666
WERROR _spoolss_65(struct pipes_struct *p,
10667
struct spoolss_65 *r)
10669
p->rng_fault_state = true;
10670
return WERR_NOT_SUPPORTED;
10673
/****************************************************************
10674
_spoolss_GetCorePrinterDrivers
10675
****************************************************************/
10677
WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10678
struct spoolss_GetCorePrinterDrivers *r)
10680
p->rng_fault_state = true;
10681
return WERR_NOT_SUPPORTED;
10684
/****************************************************************
10686
****************************************************************/
10688
WERROR _spoolss_67(struct pipes_struct *p,
10689
struct spoolss_67 *r)
10691
p->rng_fault_state = true;
10692
return WERR_NOT_SUPPORTED;
10695
/****************************************************************
10696
_spoolss_GetPrinterDriverPackagePath
10697
****************************************************************/
10699
WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10700
struct spoolss_GetPrinterDriverPackagePath *r)
10702
p->rng_fault_state = true;
10703
return WERR_NOT_SUPPORTED;
10706
/****************************************************************
10708
****************************************************************/
10710
WERROR _spoolss_69(struct pipes_struct *p,
10711
struct spoolss_69 *r)
10713
p->rng_fault_state = true;
10714
return WERR_NOT_SUPPORTED;
10717
/****************************************************************
10719
****************************************************************/
10721
WERROR _spoolss_6a(struct pipes_struct *p,
10722
struct spoolss_6a *r)
10724
p->rng_fault_state = true;
10725
return WERR_NOT_SUPPORTED;
10728
/****************************************************************
10730
****************************************************************/
10732
WERROR _spoolss_6b(struct pipes_struct *p,
10733
struct spoolss_6b *r)
10735
p->rng_fault_state = true;
10736
return WERR_NOT_SUPPORTED;
10739
/****************************************************************
10741
****************************************************************/
10743
WERROR _spoolss_6c(struct pipes_struct *p,
10744
struct spoolss_6c *r)
10746
p->rng_fault_state = true;
10747
return WERR_NOT_SUPPORTED;
10750
/****************************************************************
10752
****************************************************************/
10754
WERROR _spoolss_6d(struct pipes_struct *p,
10755
struct spoolss_6d *r)
10757
p->rng_fault_state = true;
10758
return WERR_NOT_SUPPORTED;