spoolss: accept XPS_PASS datatype used by Windows 8
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob8372c43fbaf24c5eeea15f4ce5174cb915370a2f
1 /*
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. */
30 #include "includes.h"
31 #include "ntdomain.h"
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"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.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)
70 #undef DBGC_CLASS
71 #define DBGC_CLASS DBGC_RPC_SRV
73 #ifndef MAX_OPEN_PRINTER_EXS
74 #define MAX_OPEN_PRINTER_EXS 50
75 #endif
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;
86 bool page_started;
87 uint32 jobid; /* jobid in printing backend */
88 int printer_type;
89 const char *servername;
90 fstring sharename;
91 uint32 type;
92 uint32 access_granted;
93 struct {
94 uint32 flags;
95 uint32 options;
96 fstring localmachine;
97 uint32 printerlocal;
98 struct spoolss_NotifyOption *option;
99 struct policy_handle cli_hnd;
100 struct notify_back_channel *cli_chan;
101 uint32 change;
102 /* are we in a FindNextPrinterChangeNotify() call? */
103 bool fnpcn;
104 struct messaging_context *msg_ctx;
105 } notify;
106 struct {
107 fstring machine;
108 fstring user;
109 } client;
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;
125 int snum;
126 uint32_t counter;
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 = {
148 PRINTER_READ,
149 PRINTER_WRITE,
150 PRINTER_EXECUTE,
151 PRINTER_ALL_ACCESS
154 /* Map generic permissions to print server object specific permissions */
156 const struct standard_mapping printserver_std_mapping = {
157 SERVER_READ,
158 SERVER_WRITE,
159 SERVER_EXECUTE,
160 SERVER_ALL_ACCESS
163 /* API table for Xcv Monitor functions */
165 struct xcv_api_table {
166 const char *name;
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 == '\\') {
180 pservername++;
182 return pservername;
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
188 switch (v) {
189 case LPQ_QUEUED:
190 return 0;
191 case LPQ_PAUSED:
192 return JOB_STATUS_PAUSED;
193 case LPQ_SPOOLING:
194 return JOB_STATUS_SPOOLING;
195 case LPQ_PRINTING:
196 return JOB_STATUS_PRINTING;
197 case LPQ_ERROR:
198 return JOB_STATUS_ERROR;
199 case LPQ_DELETING:
200 return JOB_STATUS_DELETING;
201 case LPQ_OFFLINE:
202 return JOB_STATUS_OFFLINE;
203 case LPQ_PAPEROUT:
204 return JOB_STATUS_PAPEROUT;
205 case LPQ_PRINTED:
206 return JOB_STATUS_PRINTED;
207 case LPQ_DELETED:
208 return JOB_STATUS_DELETED;
209 case LPQ_BLOCKED:
210 return JOB_STATUS_BLOCKED_DEVQ;
211 case LPQ_USER_INTERVENTION:
212 return JOB_STATUS_USER_INTERVENTION;
214 return 0;
217 static int nt_printq_status(int v)
219 switch (v) {
220 case LPQ_PAUSED:
221 return PRINTER_STATUS_PAUSED;
222 case LPQ_QUEUED:
223 case LPQ_SPOOLING:
224 case LPQ_PRINTING:
225 return 0;
227 return 0;
230 /***************************************************************************
231 Disconnect from the client
232 ****************************************************************************/
234 static void srv_spoolss_replycloseprinter(int snum,
235 struct printer_handle *prn_hnd)
237 WERROR result;
238 NTSTATUS status;
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);
256 return;
259 status = dcerpc_spoolss_ReplyClosePrinter(
260 prn_hnd->notify.cli_chan->binding_handle,
261 talloc_tos(),
262 &prn_hnd->notify.cli_hnd,
263 &result);
264 if (!NT_STATUS_IS_OK(status)) {
265 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
266 nt_errstr(status)));
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--;
298 prn_hnd->notify.cli_chan = NULL;
302 /****************************************************************************
303 Functions to free a printer entry datastruct.
304 ****************************************************************************/
306 static int printer_entry_destructor(struct printer_handle *Printer)
308 if (Printer->notify.cli_chan != NULL &&
309 Printer->notify.cli_chan->active_connections > 0) {
310 int snum = -1;
312 switch(Printer->printer_type) {
313 case SPLHND_SERVER:
314 srv_spoolss_replycloseprinter(snum, Printer);
315 break;
317 case SPLHND_PRINTER:
318 snum = print_queue_snum(Printer->sharename);
319 if (snum != -1) {
320 srv_spoolss_replycloseprinter(snum, Printer);
322 break;
323 default:
324 break;
328 Printer->notify.flags=0;
329 Printer->notify.options=0;
330 Printer->notify.localmachine[0]='\0';
331 Printer->notify.printerlocal=0;
332 TALLOC_FREE(Printer->notify.option);
333 TALLOC_FREE(Printer->devmode);
335 /* Remove from the internal list. */
336 DLIST_REMOVE(printers_list, Printer);
337 return 0;
340 /****************************************************************************
341 find printer index by handle
342 ****************************************************************************/
344 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
345 struct policy_handle *hnd)
347 struct printer_handle *find_printer = NULL;
349 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
350 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
351 return NULL;
354 return find_printer;
357 /****************************************************************************
358 Close printer index by handle.
359 ****************************************************************************/
361 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
363 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
365 if (!Printer) {
366 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
367 OUR_HANDLE(hnd)));
368 return false;
371 close_policy_hnd(p, hnd);
373 return true;
376 /****************************************************************************
377 Delete a printer given a handle.
378 ****************************************************************************/
380 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
381 const char *sharename,
382 struct messaging_context *msg_ctx)
384 char *cmd = lp_deleteprinter_cmd();
385 char *command = NULL;
386 int ret;
387 bool is_print_op = false;
389 /* can't fail if we don't try */
391 if ( !*cmd )
392 return WERR_OK;
394 command = talloc_asprintf(ctx,
395 "%s \"%s\"",
396 cmd, sharename);
397 if (!command) {
398 return WERR_NOMEM;
400 if ( token )
401 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
403 DEBUG(10,("Running [%s]\n", command));
405 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
407 if ( is_print_op )
408 become_root();
410 if ( (ret = smbrun(command, NULL)) == 0 ) {
411 /* Tell everyone we updated smb.conf. */
412 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
415 if ( is_print_op )
416 unbecome_root();
418 /********** END SePrintOperatorPrivlege BLOCK **********/
420 DEBUGADD(10,("returned [%d]\n", ret));
422 TALLOC_FREE(command);
424 if (ret != 0)
425 return WERR_BADFID; /* What to return here? */
427 /* go ahead and re-read the services immediately */
428 become_root();
429 reload_services(msg_ctx, -1, false);
430 unbecome_root();
432 if ( lp_servicenumber( sharename ) >= 0 )
433 return WERR_ACCESS_DENIED;
435 return WERR_OK;
438 /****************************************************************************
439 Delete a printer given a handle.
440 ****************************************************************************/
442 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
444 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
445 WERROR result;
447 if (!Printer) {
448 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
449 OUR_HANDLE(hnd)));
450 return WERR_BADFID;
454 * It turns out that Windows allows delete printer on a handle
455 * opened by an admin user, then used on a pipe handle created
456 * by an anonymous user..... but they're working on security.... riiight !
457 * JRA.
460 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
461 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
462 return WERR_ACCESS_DENIED;
465 /* this does not need a become root since the access check has been
466 done on the handle already */
468 result = winreg_delete_printer_key_internal(p->mem_ctx,
469 get_session_info_system(),
470 p->msg_ctx,
471 Printer->sharename,
472 "");
473 if (!W_ERROR_IS_OK(result)) {
474 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
475 return WERR_BADFID;
478 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
479 Printer->sharename, p->msg_ctx);
480 if (!W_ERROR_IS_OK(result)) {
481 return result;
483 prune_printername_cache();
484 return WERR_OK;
487 /****************************************************************************
488 Return the snum of a printer corresponding to an handle.
489 ****************************************************************************/
491 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
492 int *number, struct share_params **params)
494 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
496 if (!Printer) {
497 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
498 OUR_HANDLE(hnd)));
499 return false;
502 switch (Printer->printer_type) {
503 case SPLHND_PRINTER:
504 DEBUG(4,("short name:%s\n", Printer->sharename));
505 *number = print_queue_snum(Printer->sharename);
506 return (*number != -1);
507 case SPLHND_SERVER:
508 return false;
509 default:
510 return false;
514 /****************************************************************************
515 Set printer handle type.
516 Check if it's \\server or \\server\printer
517 ****************************************************************************/
519 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
521 DEBUG(3,("Setting printer type=%s\n", handlename));
523 /* it's a print server */
524 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
525 DEBUGADD(4,("Printer is a print server\n"));
526 Printer->printer_type = SPLHND_SERVER;
528 /* it's a printer (set_printer_hnd_name() will handle port monitors */
529 else {
530 DEBUGADD(4,("Printer is a printer\n"));
531 Printer->printer_type = SPLHND_PRINTER;
534 return true;
537 static void prune_printername_cache_fn(const char *key, const char *value,
538 time_t timeout, void *private_data)
540 gencache_del(key);
543 static void prune_printername_cache(void)
545 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
548 /****************************************************************************
549 Set printer handle name.. Accept names like \\server, \\server\printer,
550 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
551 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
552 XcvDataPort() interface.
553 ****************************************************************************/
555 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
556 const struct auth_serversupplied_info *session_info,
557 struct messaging_context *msg_ctx,
558 struct printer_handle *Printer,
559 const char *handlename)
561 int snum;
562 int n_services=lp_numservices();
563 char *aprinter;
564 const char *printername;
565 const char *servername = NULL;
566 fstring sname;
567 bool found = false;
568 struct spoolss_PrinterInfo2 *info2 = NULL;
569 WERROR result;
570 char *p;
573 * Hopefully nobody names his printers like this. Maybe \ or ,
574 * are illegal in printer names even?
576 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
577 char *cache_key;
578 char *tmp;
580 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
581 (unsigned long)strlen(handlename)));
583 aprinter = CONST_DISCARD(char *, handlename);
584 if ( *handlename == '\\' ) {
585 servername = canon_servername(handlename);
586 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
587 *aprinter = '\0';
588 aprinter++;
590 if (!is_myname_or_ipaddr(servername)) {
591 return WERR_INVALID_PRINTER_NAME;
593 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
594 if (Printer->servername == NULL) {
595 return WERR_NOMEM;
599 if (Printer->printer_type == SPLHND_SERVER) {
600 return WERR_OK;
603 if (Printer->printer_type != SPLHND_PRINTER) {
604 return WERR_INVALID_HANDLE;
607 DEBUGADD(5, ("searching for [%s]\n", aprinter));
609 p = strchr(aprinter, ',');
610 if (p != NULL) {
611 char *p2 = p;
612 p++;
613 if (*p == ' ') {
614 p++;
616 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
617 *p2 = '\0';
618 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
619 *p2 = '\0';
623 if (p) {
624 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
627 /* check for the Port Monitor Interface */
628 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
629 Printer->printer_type = SPLHND_PORTMON_TCP;
630 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
631 found = true;
633 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
634 Printer->printer_type = SPLHND_PORTMON_LOCAL;
635 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
636 found = true;
640 * With hundreds of printers, the "for" loop iterating all
641 * shares can be quite expensive, as it is done on every
642 * OpenPrinter. The loop maps "aprinter" to "sname", the
643 * result of which we cache in gencache.
646 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
647 aprinter);
648 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
650 found = (strcmp(tmp, printer_not_found) != 0);
651 if (!found) {
652 DEBUG(4, ("Printer %s not found\n", aprinter));
653 SAFE_FREE(tmp);
654 return WERR_INVALID_PRINTER_NAME;
656 fstrcpy(sname, tmp);
657 SAFE_FREE(tmp);
660 /* Search all sharenames first as this is easier than pulling
661 the printer_info_2 off of disk. Don't use find_service() since
662 that calls out to map_username() */
664 /* do another loop to look for printernames */
665 for (snum = 0; !found && snum < n_services; snum++) {
666 const char *printer = lp_const_servicename(snum);
668 /* no point going on if this is not a printer */
669 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
670 continue;
673 /* ignore [printers] share */
674 if (strequal(printer, "printers")) {
675 continue;
678 fstrcpy(sname, printer);
679 if (strequal(aprinter, printer)) {
680 found = true;
681 break;
684 /* no point looking up the printer object if
685 we aren't allowing printername != sharename */
686 if (lp_force_printername(snum)) {
687 continue;
690 result = winreg_get_printer_internal(mem_ctx,
691 session_info,
692 msg_ctx,
693 sname,
694 &info2);
695 if ( !W_ERROR_IS_OK(result) ) {
696 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
697 sname, win_errstr(result)));
698 continue;
701 printername = strrchr(info2->printername, '\\');
702 if (printername == NULL) {
703 printername = info2->printername;
704 } else {
705 printername++;
708 if (strequal(printername, aprinter)) {
709 found = true;
710 break;
713 DEBUGADD(10, ("printername: %s\n", printername));
715 TALLOC_FREE(info2);
718 if ( !found ) {
719 if (cache_key != NULL) {
720 gencache_set(cache_key, printer_not_found,
721 time(NULL)+300);
722 TALLOC_FREE(cache_key);
724 DEBUGADD(4,("Printer not found\n"));
725 return WERR_INVALID_PRINTER_NAME;
728 if (cache_key != NULL) {
729 gencache_set(cache_key, sname, time(NULL)+300);
730 TALLOC_FREE(cache_key);
733 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
735 fstrcpy(Printer->sharename, sname);
737 return WERR_OK;
740 /****************************************************************************
741 Find first available printer slot. creates a printer handle for you.
742 ****************************************************************************/
744 static WERROR open_printer_hnd(struct pipes_struct *p,
745 struct policy_handle *hnd,
746 const char *name,
747 uint32_t access_granted)
749 struct printer_handle *new_printer;
750 WERROR result;
752 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
754 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
755 if (new_printer == NULL) {
756 return WERR_NOMEM;
758 talloc_set_destructor(new_printer, printer_entry_destructor);
760 /* This also steals the printer_handle on the policy_handle */
761 if (!create_policy_hnd(p, hnd, new_printer)) {
762 TALLOC_FREE(new_printer);
763 return WERR_INVALID_HANDLE;
766 /* Add to the internal list. */
767 DLIST_ADD(printers_list, new_printer);
769 new_printer->notify.option=NULL;
771 if (!set_printer_hnd_printertype(new_printer, name)) {
772 close_printer_handle(p, hnd);
773 return WERR_INVALID_HANDLE;
776 result = set_printer_hnd_name(p->mem_ctx,
777 get_session_info_system(),
778 p->msg_ctx,
779 new_printer, name);
780 if (!W_ERROR_IS_OK(result)) {
781 close_printer_handle(p, hnd);
782 return result;
785 new_printer->access_granted = access_granted;
787 DEBUG(5, ("%d printer handles active\n",
788 (int)num_pipe_handles(p)));
790 return WERR_OK;
793 /***************************************************************************
794 check to see if the client motify handle is monitoring the notification
795 given by (notify_type, notify_field).
796 **************************************************************************/
798 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
799 uint16_t notify_field)
801 return true;
804 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
805 uint16_t notify_field)
807 struct spoolss_NotifyOption *option = p->notify.option;
808 uint32_t i, j;
811 * Flags should always be zero when the change notify
812 * is registered by the client's spooler. A user Win32 app
813 * might use the flags though instead of the NOTIFY_OPTION_INFO
814 * --jerry
817 if (!option) {
818 return false;
821 if (p->notify.flags)
822 return is_monitoring_event_flags(
823 p->notify.flags, notify_type, notify_field);
825 for (i = 0; i < option->count; i++) {
827 /* Check match for notify_type */
829 if (option->types[i].type != notify_type)
830 continue;
832 /* Check match for field */
834 for (j = 0; j < option->types[i].count; j++) {
835 if (option->types[i].fields[j].field == notify_field) {
836 return true;
841 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
842 p->servername, p->sharename, notify_type, notify_field));
844 return false;
847 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
848 _data->data.integer[0] = _integer; \
849 _data->data.integer[1] = 0;
852 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
853 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
854 if (!_data->data.string.string) {\
855 _data->data.string.size = 0; \
857 _data->data.string.size = strlen_m_term(_p) * 2;
859 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
860 _data->data.devmode.devmode = _devmode;
862 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
863 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
864 if (!_data->data.sd.sd) { \
865 _data->data.sd.sd_size = 0; \
867 _data->data.sd.sd_size = \
868 ndr_size_security_descriptor(_data->data.sd.sd, 0);
870 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
871 struct tm *t,
872 const char **pp,
873 uint32_t *plen)
875 struct spoolss_Time st;
876 uint32_t len = 16;
877 char *p;
879 if (!init_systemtime(&st, t)) {
880 return;
883 p = talloc_array(mem_ctx, char, len);
884 if (!p) {
885 return;
889 * Systemtime must be linearized as a set of UINT16's.
890 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
893 SSVAL(p, 0, st.year);
894 SSVAL(p, 2, st.month);
895 SSVAL(p, 4, st.day_of_week);
896 SSVAL(p, 6, st.day);
897 SSVAL(p, 8, st.hour);
898 SSVAL(p, 10, st.minute);
899 SSVAL(p, 12, st.second);
900 SSVAL(p, 14, st.millisecond);
902 *pp = p;
903 *plen = len;
906 /* Convert a notification message to a struct spoolss_Notify */
908 static void notify_one_value(struct spoolss_notify_msg *msg,
909 struct spoolss_Notify *data,
910 TALLOC_CTX *mem_ctx)
912 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
915 static void notify_string(struct spoolss_notify_msg *msg,
916 struct spoolss_Notify *data,
917 TALLOC_CTX *mem_ctx)
919 /* The length of the message includes the trailing \0 */
921 data->data.string.size = msg->len * 2;
922 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
923 if (!data->data.string.string) {
924 data->data.string.size = 0;
925 return;
929 static void notify_system_time(struct spoolss_notify_msg *msg,
930 struct spoolss_Notify *data,
931 TALLOC_CTX *mem_ctx)
933 data->data.string.string = NULL;
934 data->data.string.size = 0;
936 if (msg->len != sizeof(time_t)) {
937 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
938 msg->len));
939 return;
942 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
943 &data->data.string.string,
944 &data->data.string.size);
947 struct notify2_message_table {
948 const char *name;
949 void (*fn)(struct spoolss_notify_msg *msg,
950 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
953 static struct notify2_message_table printer_notify_table[] = {
954 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
955 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
956 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
957 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
958 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
959 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
960 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
961 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
962 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
963 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
964 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
965 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
966 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
967 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
968 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
969 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
970 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
971 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
972 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
975 static struct notify2_message_table job_notify_table[] = {
976 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
977 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
978 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
979 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
980 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
981 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
982 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
983 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
984 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
985 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
986 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
987 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
988 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
989 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
990 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
991 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
992 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
993 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
994 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
995 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
996 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
997 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
998 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
999 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1003 /***********************************************************************
1004 Allocate talloc context for container object
1005 **********************************************************************/
1007 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 if ( !ctr )
1010 return;
1012 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1014 return;
1017 /***********************************************************************
1018 release all allocated memory and zero out structure
1019 **********************************************************************/
1021 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 if ( !ctr )
1024 return;
1026 if ( ctr->ctx )
1027 talloc_destroy(ctr->ctx);
1029 ZERO_STRUCTP(ctr);
1031 return;
1034 /***********************************************************************
1035 **********************************************************************/
1037 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1039 if ( !ctr )
1040 return NULL;
1042 return ctr->ctx;
1045 /***********************************************************************
1046 **********************************************************************/
1048 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1050 if ( !ctr || !ctr->msg_groups )
1051 return NULL;
1053 if ( idx >= ctr->num_groups )
1054 return NULL;
1056 return &ctr->msg_groups[idx];
1060 /***********************************************************************
1061 How many groups of change messages do we have ?
1062 **********************************************************************/
1064 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1066 if ( !ctr )
1067 return 0;
1069 return ctr->num_groups;
1072 /***********************************************************************
1073 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1074 **********************************************************************/
1076 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1078 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1079 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1080 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1081 int i, new_slot;
1083 if ( !ctr || !msg )
1084 return 0;
1086 /* loop over all groups looking for a matching printer name */
1088 for ( i=0; i<ctr->num_groups; i++ ) {
1089 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1090 break;
1093 /* add a new group? */
1095 if ( i == ctr->num_groups ) {
1096 ctr->num_groups++;
1098 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1099 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1100 return 0;
1102 ctr->msg_groups = groups;
1104 /* clear the new entry and set the printer name */
1106 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1107 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1110 /* add the change messages; 'i' is the correct index now regardless */
1112 msg_grp = &ctr->msg_groups[i];
1114 msg_grp->num_msgs++;
1116 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1117 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1118 return 0;
1120 msg_grp->msgs = msg_list;
1122 new_slot = msg_grp->num_msgs-1;
1123 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1125 /* need to allocate own copy of data */
1127 if ( msg->len != 0 )
1128 msg_grp->msgs[new_slot].notify.data = (char *)
1129 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1131 return ctr->num_groups;
1134 static void construct_info_data(struct spoolss_Notify *info_data,
1135 enum spoolss_NotifyType type,
1136 uint16_t field, int id);
1138 /***********************************************************************
1139 Send a change notication message on all handles which have a call
1140 back registered
1141 **********************************************************************/
1143 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1144 struct printer_handle *prn_hnd,
1145 SPOOLSS_NOTIFY_MSG *messages,
1146 uint32_t num_msgs,
1147 struct spoolss_Notify **_notifies,
1148 int *_count)
1150 struct spoolss_Notify *notifies;
1151 SPOOLSS_NOTIFY_MSG *msg;
1152 int count = 0;
1153 uint32_t id;
1154 int i;
1156 notifies = talloc_zero_array(mem_ctx,
1157 struct spoolss_Notify, num_msgs);
1158 if (!notifies) {
1159 return ENOMEM;
1162 for (i = 0; i < num_msgs; i++) {
1164 msg = &messages[i];
1166 /* Are we monitoring this event? */
1168 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1169 continue;
1172 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1173 "for printer [%s]\n",
1174 msg->type, msg->field, prn_hnd->sharename));
1177 * if the is a printer notification handle and not a job
1178 * notification type, then set the id to 0.
1179 * Otherwise just use what was specified in the message.
1181 * When registering change notification on a print server
1182 * handle we always need to send back the id (snum) matching
1183 * the printer for which the change took place.
1184 * For change notify registered on a printer handle,
1185 * this does not matter and the id should be 0.
1187 * --jerry
1190 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1191 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1192 id = 0;
1193 } else {
1194 id = msg->id;
1197 /* Convert unix jobid to smb jobid */
1199 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1200 id = sysjob_to_jobid(msg->id);
1202 if (id == -1) {
1203 DEBUG(3, ("no such unix jobid %d\n",
1204 msg->id));
1205 continue;
1209 construct_info_data(&notifies[count],
1210 msg->type, msg->field, id);
1212 switch(msg->type) {
1213 case PRINTER_NOTIFY_TYPE:
1214 if (printer_notify_table[msg->field].fn) {
1215 printer_notify_table[msg->field].fn(msg,
1216 &notifies[count], mem_ctx);
1218 break;
1220 case JOB_NOTIFY_TYPE:
1221 if (job_notify_table[msg->field].fn) {
1222 job_notify_table[msg->field].fn(msg,
1223 &notifies[count], mem_ctx);
1225 break;
1227 default:
1228 DEBUG(5, ("Unknown notification type %d\n",
1229 msg->type));
1230 continue;
1233 count++;
1236 *_notifies = notifies;
1237 *_count = count;
1239 return 0;
1242 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1243 struct printer_handle *prn_hnd,
1244 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1246 struct spoolss_Notify *notifies;
1247 int count = 0;
1248 union spoolss_ReplyPrinterInfo info;
1249 struct spoolss_NotifyInfo info0;
1250 uint32_t reply_result;
1251 NTSTATUS status;
1252 WERROR werr;
1253 int ret;
1255 /* Is there notification on this handle? */
1256 if (prn_hnd->notify.cli_chan == NULL ||
1257 prn_hnd->notify.cli_chan->active_connections == 0) {
1258 return 0;
1261 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1262 prn_hnd->servername, prn_hnd->sharename));
1264 /* For this printer? Print servers always receive notifications. */
1265 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1266 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1267 return 0;
1270 DEBUG(10,("Our printer\n"));
1272 /* build the array of change notifications */
1273 ret = build_notify2_messages(mem_ctx, prn_hnd,
1274 msg_group->msgs,
1275 msg_group->num_msgs,
1276 &notifies, &count);
1277 if (ret) {
1278 return ret;
1281 info0.version = 0x2;
1282 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1283 info0.count = count;
1284 info0.notifies = notifies;
1286 info.info0 = &info0;
1288 status = dcerpc_spoolss_RouterReplyPrinterEx(
1289 prn_hnd->notify.cli_chan->binding_handle,
1290 mem_ctx,
1291 &prn_hnd->notify.cli_hnd,
1292 prn_hnd->notify.change, /* color */
1293 prn_hnd->notify.flags,
1294 &reply_result,
1295 0, /* reply_type, must be 0 */
1296 info, &werr);
1297 if (!NT_STATUS_IS_OK(status)) {
1298 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1299 "failed: %s\n",
1300 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301 nt_errstr(status)));
1302 werr = ntstatus_to_werror(status);
1303 } else if (!W_ERROR_IS_OK(werr)) {
1304 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1305 "failed: %s\n",
1306 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1307 win_errstr(werr)));
1309 switch (reply_result) {
1310 case 0:
1311 break;
1312 case PRINTER_NOTIFY_INFO_DISCARDED:
1313 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1314 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1315 break;
1316 default:
1317 break;
1320 return 0;
1323 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1325 struct printer_handle *p;
1326 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1327 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1328 int ret;
1330 if ( !msg_group ) {
1331 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1332 return;
1335 if (!msg_group->msgs) {
1336 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1337 return;
1340 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1342 /* loop over all printers */
1344 for (p = printers_list; p; p = p->next) {
1345 ret = send_notify2_printer(mem_ctx, p, msg_group);
1346 if (ret) {
1347 goto done;
1351 done:
1352 DEBUG(8,("send_notify2_changes: Exit...\n"));
1353 return;
1356 /***********************************************************************
1357 **********************************************************************/
1359 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1362 uint32_t tv_sec, tv_usec;
1363 size_t offset = 0;
1365 /* Unpack message */
1367 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1368 msg->printer);
1370 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1371 &tv_sec, &tv_usec,
1372 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1374 if (msg->len == 0)
1375 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1376 &msg->notify.value[0], &msg->notify.value[1]);
1377 else
1378 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1379 &msg->len, &msg->notify.data);
1381 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1382 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1384 tv->tv_sec = tv_sec;
1385 tv->tv_usec = tv_usec;
1387 if (msg->len == 0)
1388 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1389 msg->notify.value[1]));
1390 else
1391 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1393 return true;
1396 /********************************************************************
1397 Receive a notify2 message list
1398 ********************************************************************/
1400 static void receive_notify2_message_list(struct messaging_context *msg,
1401 void *private_data,
1402 uint32_t msg_type,
1403 struct server_id server_id,
1404 DATA_BLOB *data)
1406 size_t msg_count, i;
1407 char *buf = (char *)data->data;
1408 char *msg_ptr;
1409 size_t msg_len;
1410 SPOOLSS_NOTIFY_MSG notify;
1411 SPOOLSS_NOTIFY_MSG_CTR messages;
1412 int num_groups;
1414 if (data->length < 4) {
1415 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1416 return;
1419 msg_count = IVAL(buf, 0);
1420 msg_ptr = buf + 4;
1422 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1424 if (msg_count == 0) {
1425 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1426 return;
1429 /* initialize the container */
1431 ZERO_STRUCT( messages );
1432 notify_msg_ctr_init( &messages );
1435 * build message groups for each printer identified
1436 * in a change_notify msg. Remember that a PCN message
1437 * includes the handle returned for the srv_spoolss_replyopenprinter()
1438 * call. Therefore messages are grouped according to printer handle.
1441 for ( i=0; i<msg_count; i++ ) {
1442 struct timeval msg_tv;
1444 if (msg_ptr + 4 - buf > data->length) {
1445 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1446 return;
1449 msg_len = IVAL(msg_ptr,0);
1450 msg_ptr += 4;
1452 if (msg_ptr + msg_len - buf > data->length) {
1453 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1454 return;
1457 /* unpack messages */
1459 ZERO_STRUCT( notify );
1460 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1461 msg_ptr += msg_len;
1463 /* add to correct list in container */
1465 notify_msg_ctr_addmsg( &messages, &notify );
1467 /* free memory that might have been allocated by notify2_unpack_msg() */
1469 if ( notify.len != 0 )
1470 SAFE_FREE( notify.notify.data );
1473 /* process each group of messages */
1475 num_groups = notify_msg_ctr_numgroups( &messages );
1476 for ( i=0; i<num_groups; i++ )
1477 send_notify2_changes( &messages, i );
1480 /* cleanup */
1482 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1483 (uint32_t)msg_count ));
1485 notify_msg_ctr_destroy( &messages );
1487 return;
1490 /********************************************************************
1491 Send a message to ourself about new driver being installed
1492 so we can upgrade the information for each printer bound to this
1493 driver
1494 ********************************************************************/
1496 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1497 struct messaging_context *msg_ctx)
1499 int len = strlen(drivername);
1501 if (!len)
1502 return false;
1504 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1505 drivername));
1507 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1508 MSG_PRINTER_DRVUPGRADE,
1509 (uint8_t *)drivername, len+1);
1511 return true;
1514 void srv_spoolss_cleanup(void)
1516 struct printer_session_counter *session_counter;
1518 for (session_counter = counter_list;
1519 session_counter != NULL;
1520 session_counter = counter_list) {
1521 DLIST_REMOVE(counter_list, session_counter);
1522 TALLOC_FREE(session_counter);
1526 /**********************************************************************
1527 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1528 over all printers, upgrading ones as necessary
1529 **********************************************************************/
1531 void do_drv_upgrade_printer(struct messaging_context *msg,
1532 void *private_data,
1533 uint32_t msg_type,
1534 struct server_id server_id,
1535 DATA_BLOB *data)
1537 TALLOC_CTX *tmp_ctx;
1538 struct auth_serversupplied_info *session_info = NULL;
1539 struct spoolss_PrinterInfo2 *pinfo2;
1540 NTSTATUS status;
1541 WERROR result;
1542 const char *drivername;
1543 int snum;
1544 int n_services = lp_numservices();
1545 struct dcerpc_binding_handle *b = NULL;
1547 tmp_ctx = talloc_new(NULL);
1548 if (!tmp_ctx) return;
1550 status = make_session_info_system(tmp_ctx, &session_info);
1551 if (!NT_STATUS_IS_OK(status)) {
1552 DEBUG(0, ("do_drv_upgrade_printer: "
1553 "Could not create system session_info\n"));
1554 goto done;
1557 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1558 if (!drivername) {
1559 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1560 goto done;
1563 DEBUG(10, ("do_drv_upgrade_printer: "
1564 "Got message for new driver [%s]\n", drivername));
1566 /* Iterate the printer list */
1568 for (snum = 0; snum < n_services; snum++) {
1569 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1570 continue;
1573 /* ignore [printers] share */
1574 if (strequal(lp_const_servicename(snum), "printers")) {
1575 continue;
1578 if (b == NULL) {
1579 result = winreg_printer_binding_handle(tmp_ctx,
1580 session_info,
1581 msg,
1582 &b);
1583 if (!W_ERROR_IS_OK(result)) {
1584 break;
1588 result = winreg_get_printer(tmp_ctx, b,
1589 lp_const_servicename(snum),
1590 &pinfo2);
1592 if (!W_ERROR_IS_OK(result)) {
1593 continue;
1596 if (!pinfo2->drivername) {
1597 continue;
1600 if (strcmp(drivername, pinfo2->drivername) != 0) {
1601 continue;
1604 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1606 /* all we care about currently is the change_id */
1607 result = winreg_printer_update_changeid(tmp_ctx, b,
1608 pinfo2->printername);
1610 if (!W_ERROR_IS_OK(result)) {
1611 DEBUG(3, ("do_drv_upgrade_printer: "
1612 "Failed to update changeid [%s]\n",
1613 win_errstr(result)));
1617 /* all done */
1618 done:
1619 talloc_free(tmp_ctx);
1622 /********************************************************************
1623 Update the cache for all printq's with a registered client
1624 connection
1625 ********************************************************************/
1627 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1629 struct printer_handle *printer = printers_list;
1630 int snum;
1632 /* loop through all printers and update the cache where
1633 a client is connected */
1634 while (printer) {
1635 if ((printer->printer_type == SPLHND_PRINTER) &&
1636 ((printer->notify.cli_chan != NULL) &&
1637 (printer->notify.cli_chan->active_connections > 0))) {
1638 snum = print_queue_snum(printer->sharename);
1639 print_queue_status(msg_ctx, snum, NULL, NULL);
1642 printer = printer->next;
1645 return;
1648 /****************************************************************
1649 _spoolss_OpenPrinter
1650 ****************************************************************/
1652 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1653 struct spoolss_OpenPrinter *r)
1655 struct spoolss_OpenPrinterEx e;
1656 WERROR werr;
1658 ZERO_STRUCT(e.in.userlevel);
1660 e.in.printername = r->in.printername;
1661 e.in.datatype = r->in.datatype;
1662 e.in.devmode_ctr = r->in.devmode_ctr;
1663 e.in.access_mask = r->in.access_mask;
1664 e.in.level = 0;
1666 e.out.handle = r->out.handle;
1668 werr = _spoolss_OpenPrinterEx(p, &e);
1670 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1671 /* OpenPrinterEx returns this for a bad
1672 * printer name. We must return WERR_INVALID_PRINTER_NAME
1673 * instead.
1675 werr = WERR_INVALID_PRINTER_NAME;
1678 return werr;
1681 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1682 struct spoolss_DeviceMode *orig,
1683 struct spoolss_DeviceMode **dest)
1685 struct spoolss_DeviceMode *dm;
1687 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1688 if (!dm) {
1689 return WERR_NOMEM;
1692 /* copy all values, then duplicate strings and structs */
1693 *dm = *orig;
1695 dm->devicename = talloc_strdup(dm, orig->devicename);
1696 if (!dm->devicename) {
1697 return WERR_NOMEM;
1699 dm->formname = talloc_strdup(dm, orig->formname);
1700 if (!dm->formname) {
1701 return WERR_NOMEM;
1703 if (orig->driverextra_data.data) {
1704 dm->driverextra_data.data =
1705 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1706 orig->driverextra_data.length);
1707 if (!dm->driverextra_data.data) {
1708 return WERR_NOMEM;
1712 *dest = dm;
1713 return WERR_OK;
1716 /****************************************************************
1717 _spoolss_OpenPrinterEx
1718 ****************************************************************/
1720 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1721 struct spoolss_OpenPrinterEx *r)
1723 int snum;
1724 struct printer_handle *Printer=NULL;
1725 WERROR result;
1727 if (!r->in.printername) {
1728 return WERR_INVALID_PARAM;
1731 if (r->in.level > 3) {
1732 return WERR_INVALID_PARAM;
1734 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1735 (r->in.level == 2 && !r->in.userlevel.level2) ||
1736 (r->in.level == 3 && !r->in.userlevel.level3)) {
1737 return WERR_INVALID_PARAM;
1740 /* some sanity check because you can open a printer or a print server */
1741 /* aka: \\server\printer or \\server */
1743 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1745 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1746 if (!W_ERROR_IS_OK(result)) {
1747 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1748 "for printer %s\n", r->in.printername));
1749 ZERO_STRUCTP(r->out.handle);
1750 return result;
1753 Printer = find_printer_index_by_hnd(p, r->out.handle);
1754 if ( !Printer ) {
1755 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1756 "handle we created for printer %s\n", r->in.printername));
1757 close_printer_handle(p, r->out.handle);
1758 ZERO_STRUCTP(r->out.handle);
1759 return WERR_INVALID_PARAM;
1763 * First case: the user is opening the print server:
1765 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1766 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1768 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1769 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1770 * or if the user is listed in the smb.conf printer admin parameter.
1772 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1773 * client view printer folder, but does not show the MSAPW.
1775 * Note: this test needs code to check access rights here too. Jeremy
1776 * could you look at this?
1778 * Second case: the user is opening a printer:
1779 * NT doesn't let us connect to a printer if the connecting user
1780 * doesn't have print permission.
1782 * Third case: user is opening a Port Monitor
1783 * access checks same as opening a handle to the print server.
1786 switch (Printer->printer_type )
1788 case SPLHND_SERVER:
1789 case SPLHND_PORTMON_TCP:
1790 case SPLHND_PORTMON_LOCAL:
1791 /* Printserver handles use global struct... */
1793 snum = -1;
1795 /* Map standard access rights to object specific access rights */
1797 se_map_standard(&r->in.access_mask,
1798 &printserver_std_mapping);
1800 /* Deny any object specific bits that don't apply to print
1801 servers (i.e printer and job specific bits) */
1803 r->in.access_mask &= SEC_MASK_SPECIFIC;
1805 if (r->in.access_mask &
1806 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1807 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1808 close_printer_handle(p, r->out.handle);
1809 ZERO_STRUCTP(r->out.handle);
1810 return WERR_ACCESS_DENIED;
1813 /* Allow admin access */
1815 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1817 if (!lp_ms_add_printer_wizard()) {
1818 close_printer_handle(p, r->out.handle);
1819 ZERO_STRUCTP(r->out.handle);
1820 return WERR_ACCESS_DENIED;
1823 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1824 and not a printer admin, then fail */
1826 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1827 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1828 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1829 !token_contains_name_in_list(
1830 uidtoname(p->session_info->utok.uid),
1831 p->session_info->info3->base.domain.string,
1832 NULL,
1833 p->session_info->security_token,
1834 lp_printer_admin(snum))) {
1835 close_printer_handle(p, r->out.handle);
1836 ZERO_STRUCTP(r->out.handle);
1837 DEBUG(3,("access DENIED as user is not root, "
1838 "has no printoperator privilege, "
1839 "not a member of the printoperator builtin group and "
1840 "is not in printer admin list"));
1841 return WERR_ACCESS_DENIED;
1844 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1846 else
1848 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1851 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1852 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1854 /* We fall through to return WERR_OK */
1855 break;
1857 case SPLHND_PRINTER:
1858 /* NT doesn't let us connect to a printer if the connecting user
1859 doesn't have print permission. */
1861 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1862 close_printer_handle(p, r->out.handle);
1863 ZERO_STRUCTP(r->out.handle);
1864 return WERR_BADFID;
1867 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1868 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1871 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1873 /* map an empty access mask to the minimum access mask */
1874 if (r->in.access_mask == 0x0)
1875 r->in.access_mask = PRINTER_ACCESS_USE;
1878 * If we are not serving the printer driver for this printer,
1879 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1880 * will keep NT clients happy --jerry
1883 if (lp_use_client_driver(snum)
1884 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1886 r->in.access_mask = PRINTER_ACCESS_USE;
1889 /* check smb.conf parameters and the the sec_desc */
1891 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1892 p->client_id->name, p->client_id->addr)) {
1893 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894 ZERO_STRUCTP(r->out.handle);
1895 return WERR_ACCESS_DENIED;
1898 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1899 p->session_info->security_token, snum) ||
1900 !print_access_check(p->session_info,
1901 p->msg_ctx,
1902 snum,
1903 r->in.access_mask)) {
1904 DEBUG(3, ("access DENIED for printer open\n"));
1905 close_printer_handle(p, r->out.handle);
1906 ZERO_STRUCTP(r->out.handle);
1907 return WERR_ACCESS_DENIED;
1910 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 close_printer_handle(p, r->out.handle);
1913 ZERO_STRUCTP(r->out.handle);
1914 return WERR_ACCESS_DENIED;
1917 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919 else
1920 r->in.access_mask = PRINTER_ACCESS_USE;
1922 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1925 winreg_create_printer_internal(p->mem_ctx,
1926 get_session_info_system(),
1927 p->msg_ctx,
1928 lp_const_servicename(snum));
1930 break;
1932 default:
1933 /* sanity check to prevent programmer error */
1934 ZERO_STRUCTP(r->out.handle);
1935 return WERR_BADFID;
1938 Printer->access_granted = r->in.access_mask;
1941 * If the client sent a devmode in the OpenPrinter() call, then
1942 * save it here in case we get a job submission on this handle
1945 if ((Printer->printer_type != SPLHND_SERVER)
1946 && (r->in.devmode_ctr.devmode != NULL)) {
1947 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948 &Printer->devmode);
1951 return WERR_OK;
1954 /****************************************************************
1955 _spoolss_ClosePrinter
1956 ****************************************************************/
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959 struct spoolss_ClosePrinter *r)
1961 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1963 if (Printer && Printer->document_started) {
1964 struct spoolss_EndDocPrinter e;
1966 e.in.handle = r->in.handle;
1968 _spoolss_EndDocPrinter(p, &e);
1971 if (!close_printer_handle(p, r->in.handle))
1972 return WERR_BADFID;
1974 /* clear the returned printer handle. Observed behavior
1975 from Win2k server. Don't think this really matters.
1976 Previous code just copied the value of the closed
1977 handle. --jerry */
1979 ZERO_STRUCTP(r->out.handle);
1981 return WERR_OK;
1984 /****************************************************************
1985 _spoolss_DeletePrinter
1986 ****************************************************************/
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989 struct spoolss_DeletePrinter *r)
1991 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992 WERROR result;
1993 int snum;
1995 if (Printer && Printer->document_started) {
1996 struct spoolss_EndDocPrinter e;
1998 e.in.handle = r->in.handle;
2000 _spoolss_EndDocPrinter(p, &e);
2003 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004 winreg_delete_printer_key_internal(p->mem_ctx,
2005 get_session_info_system(),
2006 p->msg_ctx,
2007 lp_const_servicename(snum),
2008 "");
2011 result = delete_printer_handle(p, r->in.handle);
2013 return result;
2016 /*******************************************************************
2017 * static function to lookup the version id corresponding to an
2018 * long architecture string
2019 ******************************************************************/
2021 static const struct print_architecture_table_node archi_table[]= {
2023 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2024 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2025 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2026 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2027 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2028 {"Windows IA64", SPL_ARCH_IA64, 3 },
2029 {"Windows x64", SPL_ARCH_X64, 3 },
2030 {NULL, "", -1 }
2033 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2034 SPOOLSS_DRIVER_VERSION_NT35,
2035 SPOOLSS_DRIVER_VERSION_NT4,
2036 SPOOLSS_DRIVER_VERSION_200X,
2037 -1};
2039 static int get_version_id(const char *arch)
2041 int i;
2043 for (i=0; archi_table[i].long_archi != NULL; i++)
2045 if (strcmp(arch, archi_table[i].long_archi) == 0)
2046 return (archi_table[i].version);
2049 return -1;
2052 /****************************************************************
2053 _spoolss_DeletePrinterDriver
2054 ****************************************************************/
2056 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2057 struct spoolss_DeletePrinterDriver *r)
2060 struct spoolss_DriverInfo8 *info = NULL;
2061 int version;
2062 WERROR status;
2063 struct dcerpc_binding_handle *b;
2064 TALLOC_CTX *tmp_ctx = NULL;
2065 int i;
2066 bool found;
2068 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2069 and not a printer admin, then fail */
2071 if ( (p->session_info->utok.uid != sec_initial_uid())
2072 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2073 && !token_contains_name_in_list(
2074 uidtoname(p->session_info->utok.uid),
2075 p->session_info->info3->base.domain.string,
2076 NULL,
2077 p->session_info->security_token,
2078 lp_printer_admin(-1)) )
2080 return WERR_ACCESS_DENIED;
2083 /* check that we have a valid driver name first */
2085 if ((version = get_version_id(r->in.architecture)) == -1)
2086 return WERR_INVALID_ENVIRONMENT;
2088 tmp_ctx = talloc_new(p->mem_ctx);
2089 if (!tmp_ctx) {
2090 return WERR_NOMEM;
2093 status = winreg_printer_binding_handle(tmp_ctx,
2094 get_session_info_system(),
2095 p->msg_ctx,
2096 &b);
2097 if (!W_ERROR_IS_OK(status)) {
2098 goto done;
2101 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2102 status = winreg_get_driver(tmp_ctx, b,
2103 r->in.architecture, r->in.driver,
2104 drv_cversion[i], &info);
2105 if (!W_ERROR_IS_OK(status)) {
2106 DEBUG(5, ("skipping del of driver with version %d\n",
2107 drv_cversion[i]));
2108 continue;
2110 found = true;
2112 if (printer_driver_in_use(tmp_ctx, get_session_info_system(),
2113 p->msg_ctx, info)) {
2114 status = WERR_PRINTER_DRIVER_IN_USE;
2115 goto done;
2118 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2119 if (!W_ERROR_IS_OK(status)) {
2120 DEBUG(0, ("failed del of driver with version %d\n",
2121 drv_cversion[i]));
2122 goto done;
2125 if (found == false) {
2126 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2127 status = WERR_UNKNOWN_PRINTER_DRIVER;
2128 } else {
2129 status = WERR_OK;
2132 done:
2133 talloc_free(tmp_ctx);
2134 return status;
2137 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2138 struct pipes_struct *p,
2139 struct spoolss_DeletePrinterDriverEx *r,
2140 struct dcerpc_binding_handle *b,
2141 struct spoolss_DriverInfo8 *info)
2143 WERROR status;
2144 bool delete_files;
2146 if (printer_driver_in_use(mem_ctx, get_session_info_system(),
2147 p->msg_ctx, info)) {
2148 status = WERR_PRINTER_DRIVER_IN_USE;
2149 goto done;
2153 * we have a couple of cases to consider.
2154 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2155 * then the delete should fail if **any** files overlap with
2156 * other drivers
2157 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2158 * non-overlapping files
2159 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2160 * is set, then do not delete any files
2161 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2164 delete_files = r->in.delete_flags
2165 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2167 if (delete_files) {
2168 bool in_use = printer_driver_files_in_use(mem_ctx,
2169 get_session_info_system(),
2170 p->msg_ctx,
2171 info);
2172 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2173 status = WERR_PRINTER_DRIVER_IN_USE;
2174 goto done;
2177 * printer_driver_files_in_use() has trimmed overlapping files
2178 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2182 status = winreg_del_driver(mem_ctx, b, info, info->version);
2183 if (!W_ERROR_IS_OK(status)) {
2184 goto done;
2188 * now delete any associated files if delete_files is
2189 * true. Even if this part failes, we return succes
2190 * because the driver doesn not exist any more
2192 if (delete_files) {
2193 delete_driver_files(get_session_info_system(), info);
2196 done:
2197 return status;
2200 /****************************************************************
2201 _spoolss_DeletePrinterDriverEx
2202 ****************************************************************/
2204 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2205 struct spoolss_DeletePrinterDriverEx *r)
2207 struct spoolss_DriverInfo8 *info = NULL;
2208 WERROR status;
2209 struct dcerpc_binding_handle *b;
2210 TALLOC_CTX *tmp_ctx = NULL;
2211 int i;
2212 bool found;
2214 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2215 and not a printer admin, then fail */
2217 if ( (p->session_info->utok.uid != sec_initial_uid())
2218 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2219 && !token_contains_name_in_list(
2220 uidtoname(p->session_info->utok.uid),
2221 p->session_info->info3->base.domain.string,
2222 NULL,
2223 p->session_info->security_token, lp_printer_admin(-1)) )
2225 return WERR_ACCESS_DENIED;
2228 /* check that we have a valid driver name first */
2229 if (get_version_id(r->in.architecture) == -1) {
2230 /* this is what NT returns */
2231 return WERR_INVALID_ENVIRONMENT;
2234 tmp_ctx = talloc_new(p->mem_ctx);
2235 if (!tmp_ctx) {
2236 return WERR_NOMEM;
2239 status = winreg_printer_binding_handle(tmp_ctx,
2240 get_session_info_system(),
2241 p->msg_ctx,
2242 &b);
2243 if (!W_ERROR_IS_OK(status)) {
2244 goto done;
2247 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2248 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2249 && (drv_cversion[i] != r->in.version)) {
2250 continue;
2253 /* check if a driver with this version exists before delete */
2254 status = winreg_get_driver(tmp_ctx, b,
2255 r->in.architecture, r->in.driver,
2256 drv_cversion[i], &info);
2257 if (!W_ERROR_IS_OK(status)) {
2258 DEBUG(5, ("skipping del of driver with version %d\n",
2259 drv_cversion[i]));
2260 continue;
2262 found = true;
2264 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2265 if (!W_ERROR_IS_OK(status)) {
2266 DEBUG(0, ("failed to delete driver with version %d\n",
2267 drv_cversion[i]));
2268 goto done;
2271 if (found == false) {
2272 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2273 status = WERR_UNKNOWN_PRINTER_DRIVER;
2274 } else {
2275 status = WERR_OK;
2278 done:
2279 talloc_free(tmp_ctx);
2280 return status;
2284 /********************************************************************
2285 GetPrinterData on a printer server Handle.
2286 ********************************************************************/
2288 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2289 const char *value,
2290 enum winreg_Type *type,
2291 union spoolss_PrinterData *data)
2293 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2295 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2296 *type = REG_DWORD;
2297 data->value = 0x00;
2298 return WERR_OK;
2301 if (!StrCaseCmp(value, "BeepEnabled")) {
2302 *type = REG_DWORD;
2303 data->value = 0x00;
2304 return WERR_OK;
2307 if (!StrCaseCmp(value, "EventLog")) {
2308 *type = REG_DWORD;
2309 /* formally was 0x1b */
2310 data->value = 0x00;
2311 return WERR_OK;
2314 if (!StrCaseCmp(value, "NetPopup")) {
2315 *type = REG_DWORD;
2316 data->value = 0x00;
2317 return WERR_OK;
2320 if (!StrCaseCmp(value, "MajorVersion")) {
2321 *type = REG_DWORD;
2323 /* Windows NT 4.0 seems to not allow uploading of drivers
2324 to a server that reports 0x3 as the MajorVersion.
2325 need to investigate more how Win2k gets around this .
2326 -- jerry */
2328 if (RA_WINNT == get_remote_arch()) {
2329 data->value = 0x02;
2330 } else {
2331 data->value = 0x03;
2334 return WERR_OK;
2337 if (!StrCaseCmp(value, "MinorVersion")) {
2338 *type = REG_DWORD;
2339 data->value = 0x00;
2340 return WERR_OK;
2343 /* REG_BINARY
2344 * uint32_t size = 0x114
2345 * uint32_t major = 5
2346 * uint32_t minor = [0|1]
2347 * uint32_t build = [2195|2600]
2348 * extra unicode string = e.g. "Service Pack 3"
2350 if (!StrCaseCmp(value, "OSVersion")) {
2351 DATA_BLOB blob;
2352 enum ndr_err_code ndr_err;
2353 struct spoolss_OSVersion os;
2355 os.major = 5; /* Windows 2000 == 5.0 */
2356 os.minor = 0;
2357 os.build = 2195; /* build */
2358 os.extra_string = ""; /* leave extra string empty */
2360 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2361 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2362 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2363 return WERR_GENERAL_FAILURE;
2366 *type = REG_BINARY;
2367 data->binary = blob;
2369 return WERR_OK;
2373 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2374 *type = REG_SZ;
2376 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2377 W_ERROR_HAVE_NO_MEMORY(data->string);
2379 return WERR_OK;
2382 if (!StrCaseCmp(value, "Architecture")) {
2383 *type = REG_SZ;
2384 data->string = talloc_strdup(mem_ctx,
2385 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2386 W_ERROR_HAVE_NO_MEMORY(data->string);
2388 return WERR_OK;
2391 if (!StrCaseCmp(value, "DsPresent")) {
2392 *type = REG_DWORD;
2394 /* only show the publish check box if we are a
2395 member of a AD domain */
2397 if (lp_security() == SEC_ADS) {
2398 data->value = 0x01;
2399 } else {
2400 data->value = 0x00;
2402 return WERR_OK;
2405 if (!StrCaseCmp(value, "DNSMachineName")) {
2406 const char *hostname = get_mydnsfullname();
2408 if (!hostname) {
2409 return WERR_BADFILE;
2412 *type = REG_SZ;
2413 data->string = talloc_strdup(mem_ctx, hostname);
2414 W_ERROR_HAVE_NO_MEMORY(data->string);
2416 return WERR_OK;
2419 *type = REG_NONE;
2421 return WERR_INVALID_PARAM;
2424 /****************************************************************
2425 _spoolss_GetPrinterData
2426 ****************************************************************/
2428 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2429 struct spoolss_GetPrinterData *r)
2431 struct spoolss_GetPrinterDataEx r2;
2433 r2.in.handle = r->in.handle;
2434 r2.in.key_name = "PrinterDriverData";
2435 r2.in.value_name = r->in.value_name;
2436 r2.in.offered = r->in.offered;
2437 r2.out.type = r->out.type;
2438 r2.out.data = r->out.data;
2439 r2.out.needed = r->out.needed;
2441 return _spoolss_GetPrinterDataEx(p, &r2);
2444 /*********************************************************
2445 Connect to the client machine.
2446 **********************************************************/
2448 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2449 struct sockaddr_storage *client_ss, const char *remote_machine)
2451 NTSTATUS ret;
2452 struct cli_state *the_cli;
2453 struct sockaddr_storage rm_addr;
2454 char addr[INET6_ADDRSTRLEN];
2456 if ( is_zero_addr(client_ss) ) {
2457 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2458 remote_machine));
2459 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2460 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2461 return false;
2463 print_sockaddr(addr, sizeof(addr), &rm_addr);
2464 } else {
2465 rm_addr = *client_ss;
2466 print_sockaddr(addr, sizeof(addr), &rm_addr);
2467 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2468 addr));
2471 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2472 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2473 addr));
2474 return false;
2477 /* setup the connection */
2478 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2479 &rm_addr, 0, "IPC$", "IPC",
2480 "", /* username */
2481 "", /* domain */
2482 "", /* password */
2483 0, lp_client_signing());
2485 if ( !NT_STATUS_IS_OK( ret ) ) {
2486 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2487 remote_machine ));
2488 return false;
2491 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2492 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2493 cli_shutdown(the_cli);
2494 return false;
2498 * Ok - we have an anonymous connection to the IPC$ share.
2499 * Now start the NT Domain stuff :-).
2502 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2503 if (!NT_STATUS_IS_OK(ret)) {
2504 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2505 remote_machine, nt_errstr(ret)));
2506 cli_shutdown(the_cli);
2507 return false;
2510 return true;
2513 /***************************************************************************
2514 Connect to the client.
2515 ****************************************************************************/
2517 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2518 uint32_t localprinter,
2519 enum winreg_Type type,
2520 struct policy_handle *handle,
2521 struct notify_back_channel **_chan,
2522 struct sockaddr_storage *client_ss,
2523 struct messaging_context *msg_ctx)
2525 WERROR result;
2526 NTSTATUS status;
2527 struct notify_back_channel *chan;
2529 for (chan = back_channels; chan; chan = chan->next) {
2530 if (memcmp(&chan->client_address, client_ss,
2531 sizeof(struct sockaddr_storage)) == 0) {
2532 break;
2537 * If it's the first connection, contact the client
2538 * and connect to the IPC$ share anonymously
2540 if (!chan) {
2541 fstring unix_printer;
2543 /* the +2 is to strip the leading 2 backslashs */
2544 fstrcpy(unix_printer, printer + 2);
2546 chan = talloc_zero(back_channels, struct notify_back_channel);
2547 if (!chan) {
2548 return false;
2550 chan->client_address = *client_ss;
2552 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2553 TALLOC_FREE(chan);
2554 return false;
2556 chan->binding_handle = chan->cli_pipe->binding_handle;
2558 DLIST_ADD(back_channels, chan);
2560 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2561 receive_notify2_message_list);
2562 /* Tell the connections db we're now interested in printer
2563 * notify messages. */
2564 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2565 true, FLAG_MSG_PRINT_NOTIFY);
2569 * Tell the specific printing tdb we want messages for this printer
2570 * by registering our PID.
2573 if (!print_notify_register_pid(snum)) {
2574 DEBUG(0, ("Failed to register our pid for printer %s\n",
2575 printer));
2578 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2579 talloc_tos(),
2580 printer,
2581 localprinter,
2582 type,
2584 NULL,
2585 handle,
2586 &result);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2589 result = ntstatus_to_werror(status);
2590 } else if (!W_ERROR_IS_OK(result)) {
2591 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2594 chan->active_connections++;
2595 *_chan = chan;
2597 return (W_ERROR_IS_OK(result));
2600 /****************************************************************
2601 ****************************************************************/
2603 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2604 const struct spoolss_NotifyOption *r)
2606 struct spoolss_NotifyOption *option;
2607 uint32_t i,k;
2609 if (!r) {
2610 return NULL;
2613 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2614 if (!option) {
2615 return NULL;
2618 *option = *r;
2620 if (!option->count) {
2621 return option;
2624 option->types = talloc_zero_array(option,
2625 struct spoolss_NotifyOptionType, option->count);
2626 if (!option->types) {
2627 talloc_free(option);
2628 return NULL;
2631 for (i=0; i < option->count; i++) {
2632 option->types[i] = r->types[i];
2634 if (option->types[i].count) {
2635 option->types[i].fields = talloc_zero_array(option,
2636 union spoolss_Field, option->types[i].count);
2637 if (!option->types[i].fields) {
2638 talloc_free(option);
2639 return NULL;
2641 for (k=0; k<option->types[i].count; k++) {
2642 option->types[i].fields[k] =
2643 r->types[i].fields[k];
2648 return option;
2651 /****************************************************************
2652 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2654 * before replying OK: status=0 a rpc call is made to the workstation
2655 * asking ReplyOpenPrinter
2657 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2658 * called from api_spoolss_rffpcnex
2659 ****************************************************************/
2661 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2662 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2664 int snum = -1;
2665 struct spoolss_NotifyOption *option = r->in.notify_options;
2666 struct sockaddr_storage client_ss;
2668 /* store the notify value in the printer struct */
2670 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2672 if (!Printer) {
2673 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2674 "Invalid handle (%s:%u:%u).\n",
2675 OUR_HANDLE(r->in.handle)));
2676 return WERR_BADFID;
2679 Printer->notify.flags = r->in.flags;
2680 Printer->notify.options = r->in.options;
2681 Printer->notify.printerlocal = r->in.printer_local;
2682 Printer->notify.msg_ctx = p->msg_ctx;
2684 TALLOC_FREE(Printer->notify.option);
2685 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2687 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2689 /* Connect to the client machine and send a ReplyOpenPrinter */
2691 if ( Printer->printer_type == SPLHND_SERVER)
2692 snum = -1;
2693 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2694 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2695 return WERR_BADFID;
2697 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698 "client_address is %s\n", p->client_id->addr));
2700 if (!lp_print_notify_backchannel(snum)) {
2701 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2702 "backchannel disabled\n"));
2703 return WERR_SERVER_UNAVAILABLE;
2706 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2707 AI_NUMERICHOST)) {
2708 return WERR_SERVER_UNAVAILABLE;
2711 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2712 Printer->notify.printerlocal, REG_SZ,
2713 &Printer->notify.cli_hnd,
2714 &Printer->notify.cli_chan,
2715 &client_ss, p->msg_ctx)) {
2716 return WERR_SERVER_UNAVAILABLE;
2719 return WERR_OK;
2722 /*******************************************************************
2723 * fill a notify_info_data with the servername
2724 ********************************************************************/
2726 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2727 int snum,
2728 struct spoolss_Notify *data,
2729 print_queue_struct *queue,
2730 struct spoolss_PrinterInfo2 *pinfo2,
2731 TALLOC_CTX *mem_ctx)
2733 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2736 /*******************************************************************
2737 * fill a notify_info_data with the printername (not including the servername).
2738 ********************************************************************/
2740 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2741 int snum,
2742 struct spoolss_Notify *data,
2743 print_queue_struct *queue,
2744 struct spoolss_PrinterInfo2 *pinfo2,
2745 TALLOC_CTX *mem_ctx)
2747 /* the notify name should not contain the \\server\ part */
2748 const char *p = strrchr(pinfo2->printername, '\\');
2750 if (!p) {
2751 p = pinfo2->printername;
2752 } else {
2753 p++;
2756 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2759 /*******************************************************************
2760 * fill a notify_info_data with the servicename
2761 ********************************************************************/
2763 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2764 int snum,
2765 struct spoolss_Notify *data,
2766 print_queue_struct *queue,
2767 struct spoolss_PrinterInfo2 *pinfo2,
2768 TALLOC_CTX *mem_ctx)
2770 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2773 /*******************************************************************
2774 * fill a notify_info_data with the port name
2775 ********************************************************************/
2777 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2778 int snum,
2779 struct spoolss_Notify *data,
2780 print_queue_struct *queue,
2781 struct spoolss_PrinterInfo2 *pinfo2,
2782 TALLOC_CTX *mem_ctx)
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2787 /*******************************************************************
2788 * fill a notify_info_data with the printername
2789 * but it doesn't exist, have to see what to do
2790 ********************************************************************/
2792 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2793 int snum,
2794 struct spoolss_Notify *data,
2795 print_queue_struct *queue,
2796 struct spoolss_PrinterInfo2 *pinfo2,
2797 TALLOC_CTX *mem_ctx)
2799 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2802 /*******************************************************************
2803 * fill a notify_info_data with the comment
2804 ********************************************************************/
2806 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2807 int snum,
2808 struct spoolss_Notify *data,
2809 print_queue_struct *queue,
2810 struct spoolss_PrinterInfo2 *pinfo2,
2811 TALLOC_CTX *mem_ctx)
2813 const char *p;
2815 if (*pinfo2->comment == '\0') {
2816 p = lp_comment(snum);
2817 } else {
2818 p = pinfo2->comment;
2821 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2824 /*******************************************************************
2825 * fill a notify_info_data with the comment
2826 * location = "Room 1, floor 2, building 3"
2827 ********************************************************************/
2829 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2830 int snum,
2831 struct spoolss_Notify *data,
2832 print_queue_struct *queue,
2833 struct spoolss_PrinterInfo2 *pinfo2,
2834 TALLOC_CTX *mem_ctx)
2836 const char *loc = pinfo2->location;
2837 NTSTATUS status;
2839 status = printer_list_get_printer(mem_ctx,
2840 pinfo2->sharename,
2841 NULL,
2842 &loc,
2843 NULL);
2844 if (NT_STATUS_IS_OK(status)) {
2845 if (loc == NULL) {
2846 loc = pinfo2->location;
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2853 /*******************************************************************
2854 * fill a notify_info_data with the device mode
2855 * jfm:xxxx don't to it for know but that's a real problem !!!
2856 ********************************************************************/
2858 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2859 int snum,
2860 struct spoolss_Notify *data,
2861 print_queue_struct *queue,
2862 struct spoolss_PrinterInfo2 *pinfo2,
2863 TALLOC_CTX *mem_ctx)
2865 /* for a dummy implementation we have to zero the fields */
2866 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2869 /*******************************************************************
2870 * fill a notify_info_data with the separator file name
2871 ********************************************************************/
2873 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2874 int snum,
2875 struct spoolss_Notify *data,
2876 print_queue_struct *queue,
2877 struct spoolss_PrinterInfo2 *pinfo2,
2878 TALLOC_CTX *mem_ctx)
2880 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2883 /*******************************************************************
2884 * fill a notify_info_data with the print processor
2885 * jfm:xxxx return always winprint to indicate we don't do anything to it
2886 ********************************************************************/
2888 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2889 int snum,
2890 struct spoolss_Notify *data,
2891 print_queue_struct *queue,
2892 struct spoolss_PrinterInfo2 *pinfo2,
2893 TALLOC_CTX *mem_ctx)
2895 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2898 /*******************************************************************
2899 * fill a notify_info_data with the print processor options
2900 * jfm:xxxx send an empty string
2901 ********************************************************************/
2903 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2904 int snum,
2905 struct spoolss_Notify *data,
2906 print_queue_struct *queue,
2907 struct spoolss_PrinterInfo2 *pinfo2,
2908 TALLOC_CTX *mem_ctx)
2910 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2913 /*******************************************************************
2914 * fill a notify_info_data with the data type
2915 * jfm:xxxx always send RAW as data type
2916 ********************************************************************/
2918 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2919 int snum,
2920 struct spoolss_Notify *data,
2921 print_queue_struct *queue,
2922 struct spoolss_PrinterInfo2 *pinfo2,
2923 TALLOC_CTX *mem_ctx)
2925 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2928 /*******************************************************************
2929 * fill a notify_info_data with the security descriptor
2930 * jfm:xxxx send an null pointer to say no security desc
2931 * have to implement security before !
2932 ********************************************************************/
2934 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2935 int snum,
2936 struct spoolss_Notify *data,
2937 print_queue_struct *queue,
2938 struct spoolss_PrinterInfo2 *pinfo2,
2939 TALLOC_CTX *mem_ctx)
2941 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2944 /*******************************************************************
2945 * fill a notify_info_data with the attributes
2946 * jfm:xxxx a samba printer is always shared
2947 ********************************************************************/
2949 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2950 int snum,
2951 struct spoolss_Notify *data,
2952 print_queue_struct *queue,
2953 struct spoolss_PrinterInfo2 *pinfo2,
2954 TALLOC_CTX *mem_ctx)
2956 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2959 /*******************************************************************
2960 * fill a notify_info_data with the priority
2961 ********************************************************************/
2963 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2964 int snum,
2965 struct spoolss_Notify *data,
2966 print_queue_struct *queue,
2967 struct spoolss_PrinterInfo2 *pinfo2,
2968 TALLOC_CTX *mem_ctx)
2970 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2973 /*******************************************************************
2974 * fill a notify_info_data with the default priority
2975 ********************************************************************/
2977 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2978 int snum,
2979 struct spoolss_Notify *data,
2980 print_queue_struct *queue,
2981 struct spoolss_PrinterInfo2 *pinfo2,
2982 TALLOC_CTX *mem_ctx)
2984 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2987 /*******************************************************************
2988 * fill a notify_info_data with the start time
2989 ********************************************************************/
2991 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2992 int snum,
2993 struct spoolss_Notify *data,
2994 print_queue_struct *queue,
2995 struct spoolss_PrinterInfo2 *pinfo2,
2996 TALLOC_CTX *mem_ctx)
2998 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3001 /*******************************************************************
3002 * fill a notify_info_data with the until time
3003 ********************************************************************/
3005 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3006 int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 struct spoolss_PrinterInfo2 *pinfo2,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3015 /*******************************************************************
3016 * fill a notify_info_data with the status
3017 ********************************************************************/
3019 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3020 int snum,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 struct spoolss_PrinterInfo2 *pinfo2,
3024 TALLOC_CTX *mem_ctx)
3026 print_status_struct status;
3028 print_queue_length(msg_ctx, snum, &status);
3029 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3032 /*******************************************************************
3033 * fill a notify_info_data with the number of jobs queued
3034 ********************************************************************/
3036 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3037 int snum,
3038 struct spoolss_Notify *data,
3039 print_queue_struct *queue,
3040 struct spoolss_PrinterInfo2 *pinfo2,
3041 TALLOC_CTX *mem_ctx)
3043 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3044 data, print_queue_length(msg_ctx, snum, NULL));
3047 /*******************************************************************
3048 * fill a notify_info_data with the average ppm
3049 ********************************************************************/
3051 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3052 int snum,
3053 struct spoolss_Notify *data,
3054 print_queue_struct *queue,
3055 struct spoolss_PrinterInfo2 *pinfo2,
3056 TALLOC_CTX *mem_ctx)
3058 /* always respond 8 pages per minutes */
3059 /* a little hard ! */
3060 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3063 /*******************************************************************
3064 * fill a notify_info_data with username
3065 ********************************************************************/
3067 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3068 int snum,
3069 struct spoolss_Notify *data,
3070 print_queue_struct *queue,
3071 struct spoolss_PrinterInfo2 *pinfo2,
3072 TALLOC_CTX *mem_ctx)
3074 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3082 int snum,
3083 struct spoolss_Notify *data,
3084 print_queue_struct *queue,
3085 struct spoolss_PrinterInfo2 *pinfo2,
3086 TALLOC_CTX *mem_ctx)
3088 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3091 /*******************************************************************
3092 * fill a notify_info_data with job name
3093 ********************************************************************/
3095 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3096 int snum,
3097 struct spoolss_Notify *data,
3098 print_queue_struct *queue,
3099 struct spoolss_PrinterInfo2 *pinfo2,
3100 TALLOC_CTX *mem_ctx)
3102 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3105 /*******************************************************************
3106 * fill a notify_info_data with job status
3107 ********************************************************************/
3109 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3110 int snum,
3111 struct spoolss_Notify *data,
3112 print_queue_struct *queue,
3113 struct spoolss_PrinterInfo2 *pinfo2,
3114 TALLOC_CTX *mem_ctx)
3117 * Now we're returning job status codes we just return a "" here. JRA.
3120 const char *p = "";
3122 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3123 p = "unknown";
3125 switch (queue->status) {
3126 case LPQ_QUEUED:
3127 p = "Queued";
3128 break;
3129 case LPQ_PAUSED:
3130 p = ""; /* NT provides the paused string */
3131 break;
3132 case LPQ_SPOOLING:
3133 p = "Spooling";
3134 break;
3135 case LPQ_PRINTING:
3136 p = "Printing";
3137 break;
3139 #endif /* NO LONGER NEEDED. */
3141 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3144 /*******************************************************************
3145 * fill a notify_info_data with job time
3146 ********************************************************************/
3148 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3149 int snum,
3150 struct spoolss_Notify *data,
3151 print_queue_struct *queue,
3152 struct spoolss_PrinterInfo2 *pinfo2,
3153 TALLOC_CTX *mem_ctx)
3155 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3158 /*******************************************************************
3159 * fill a notify_info_data with job size
3160 ********************************************************************/
3162 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3163 int snum,
3164 struct spoolss_Notify *data,
3165 print_queue_struct *queue,
3166 struct spoolss_PrinterInfo2 *pinfo2,
3167 TALLOC_CTX *mem_ctx)
3169 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3172 /*******************************************************************
3173 * fill a notify_info_data with page info
3174 ********************************************************************/
3175 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3176 int snum,
3177 struct spoolss_Notify *data,
3178 print_queue_struct *queue,
3179 struct spoolss_PrinterInfo2 *pinfo2,
3180 TALLOC_CTX *mem_ctx)
3182 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3185 /*******************************************************************
3186 * fill a notify_info_data with pages printed info.
3187 ********************************************************************/
3188 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3189 int snum,
3190 struct spoolss_Notify *data,
3191 print_queue_struct *queue,
3192 struct spoolss_PrinterInfo2 *pinfo2,
3193 TALLOC_CTX *mem_ctx)
3195 /* Add code when back-end tracks this */
3196 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3199 /*******************************************************************
3200 Fill a notify_info_data with job position.
3201 ********************************************************************/
3203 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3204 int snum,
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, queue->sysjob);
3213 /*******************************************************************
3214 Fill a notify_info_data with submitted time.
3215 ********************************************************************/
3217 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3218 int snum,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 struct spoolss_PrinterInfo2 *pinfo2,
3222 TALLOC_CTX *mem_ctx)
3224 data->data.string.string = NULL;
3225 data->data.string.size = 0;
3227 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3228 &data->data.string.string,
3229 &data->data.string.size);
3233 struct s_notify_info_data_table
3235 enum spoolss_NotifyType type;
3236 uint16_t field;
3237 const char *name;
3238 enum spoolss_NotifyTable variable_type;
3239 void (*fn) (struct messaging_context *msg_ctx,
3240 int snum, struct spoolss_Notify *data,
3241 print_queue_struct *queue,
3242 struct spoolss_PrinterInfo2 *pinfo2,
3243 TALLOC_CTX *mem_ctx);
3246 /* A table describing the various print notification constants and
3247 whether the notification data is a pointer to a variable sized
3248 buffer, a one value uint32_t or a two value uint32_t. */
3250 static const struct s_notify_info_data_table notify_info_data_table[] =
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3303 /*******************************************************************
3304 Return the variable_type of info_data structure.
3305 ********************************************************************/
3307 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3308 uint16_t field)
3310 int i=0;
3312 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3313 if ( (notify_info_data_table[i].type == type) &&
3314 (notify_info_data_table[i].field == field) ) {
3315 return notify_info_data_table[i].variable_type;
3319 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3321 return (enum spoolss_NotifyTable) 0;
3324 /****************************************************************************
3325 ****************************************************************************/
3327 static bool search_notify(enum spoolss_NotifyType type,
3328 uint16_t field,
3329 int *value)
3331 int i;
3333 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3334 if (notify_info_data_table[i].type == type &&
3335 notify_info_data_table[i].field == field &&
3336 notify_info_data_table[i].fn != NULL) {
3337 *value = i;
3338 return true;
3342 return false;
3345 /****************************************************************************
3346 ****************************************************************************/
3348 static void construct_info_data(struct spoolss_Notify *info_data,
3349 enum spoolss_NotifyType type,
3350 uint16_t field, int id)
3352 info_data->type = type;
3353 info_data->field.field = field;
3354 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3355 info_data->job_id = id;
3358 /*******************************************************************
3360 * fill a notify_info struct with info asked
3362 ********************************************************************/
3364 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3365 struct printer_handle *print_hnd,
3366 struct spoolss_NotifyInfo *info,
3367 struct spoolss_PrinterInfo2 *pinfo2,
3368 int snum,
3369 const struct spoolss_NotifyOptionType *option_type,
3370 uint32_t id,
3371 TALLOC_CTX *mem_ctx)
3373 int field_num,j;
3374 enum spoolss_NotifyType type;
3375 uint16_t field;
3377 struct spoolss_Notify *current_data;
3379 type = option_type->type;
3381 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3382 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3383 option_type->count, lp_servicename(snum)));
3385 for(field_num=0; field_num < option_type->count; field_num++) {
3386 field = option_type->fields[field_num].field;
3388 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3390 if (!search_notify(type, field, &j) )
3391 continue;
3393 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3394 struct spoolss_Notify,
3395 info->count + 1);
3396 if (info->notifies == NULL) {
3397 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3398 return false;
3401 current_data = &info->notifies[info->count];
3403 construct_info_data(current_data, type, field, id);
3405 DEBUG(10, ("construct_notify_printer_info: "
3406 "calling [%s] snum=%d printername=[%s])\n",
3407 notify_info_data_table[j].name, snum,
3408 pinfo2->printername));
3410 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3411 NULL, pinfo2, mem_ctx);
3413 info->count++;
3416 return true;
3419 /*******************************************************************
3421 * fill a notify_info struct with info asked
3423 ********************************************************************/
3425 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3426 print_queue_struct *queue,
3427 struct spoolss_NotifyInfo *info,
3428 struct spoolss_PrinterInfo2 *pinfo2,
3429 int snum,
3430 const struct spoolss_NotifyOptionType *option_type,
3431 uint32_t id,
3432 TALLOC_CTX *mem_ctx)
3434 int field_num,j;
3435 enum spoolss_NotifyType type;
3436 uint16_t field;
3437 struct spoolss_Notify *current_data;
3439 DEBUG(4,("construct_notify_jobs_info\n"));
3441 type = option_type->type;
3443 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3444 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3445 option_type->count));
3447 for(field_num=0; field_num<option_type->count; field_num++) {
3448 field = option_type->fields[field_num].field;
3450 if (!search_notify(type, field, &j) )
3451 continue;
3453 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3454 struct spoolss_Notify,
3455 info->count + 1);
3456 if (info->notifies == NULL) {
3457 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3458 return false;
3461 current_data=&(info->notifies[info->count]);
3463 construct_info_data(current_data, type, field, id);
3464 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3465 queue, pinfo2, mem_ctx);
3466 info->count++;
3469 return true;
3473 * JFM: The enumeration is not that simple, it's even non obvious.
3475 * let's take an example: I want to monitor the PRINTER SERVER for
3476 * the printer's name and the number of jobs currently queued.
3477 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3478 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3480 * I have 3 printers on the back of my server.
3482 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3483 * structures.
3484 * Number Data Id
3485 * 1 printer 1 name 1
3486 * 2 printer 1 cjob 1
3487 * 3 printer 2 name 2
3488 * 4 printer 2 cjob 2
3489 * 5 printer 3 name 3
3490 * 6 printer 3 name 3
3492 * that's the print server case, the printer case is even worse.
3495 /*******************************************************************
3497 * enumerate all printers on the printserver
3498 * fill a notify_info struct with info asked
3500 ********************************************************************/
3502 static WERROR printserver_notify_info(struct pipes_struct *p,
3503 struct policy_handle *hnd,
3504 struct spoolss_NotifyInfo *info,
3505 TALLOC_CTX *mem_ctx)
3507 int snum;
3508 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3509 int n_services=lp_numservices();
3510 int i;
3511 struct spoolss_NotifyOption *option;
3512 struct spoolss_NotifyOptionType option_type;
3513 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3514 WERROR result;
3516 DEBUG(4,("printserver_notify_info\n"));
3518 if (!Printer)
3519 return WERR_BADFID;
3521 option = Printer->notify.option;
3523 info->version = 2;
3524 info->notifies = NULL;
3525 info->count = 0;
3527 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3528 sending a ffpcn() request first */
3530 if ( !option )
3531 return WERR_BADFID;
3533 for (i=0; i<option->count; i++) {
3534 option_type = option->types[i];
3536 if (option_type.type != PRINTER_NOTIFY_TYPE)
3537 continue;
3539 for (snum = 0; snum < n_services; snum++) {
3540 if (!lp_browseable(snum) ||
3541 !lp_snum_ok(snum) ||
3542 !lp_print_ok(snum)) {
3543 continue; /* skip */
3546 /* Maybe we should use the SYSTEM session_info here... */
3547 result = winreg_get_printer_internal(mem_ctx,
3548 get_session_info_system(),
3549 p->msg_ctx,
3550 lp_servicename(snum),
3551 &pinfo2);
3552 if (!W_ERROR_IS_OK(result)) {
3553 DEBUG(4, ("printserver_notify_info: "
3554 "Failed to get printer [%s]\n",
3555 lp_servicename(snum)));
3556 continue;
3560 construct_notify_printer_info(p->msg_ctx,
3561 Printer, info,
3562 pinfo2, snum,
3563 &option_type, snum,
3564 mem_ctx);
3566 TALLOC_FREE(pinfo2);
3570 #if 0
3572 * Debugging information, don't delete.
3575 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3576 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3577 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3579 for (i=0; i<info->count; i++) {
3580 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3581 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3582 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3584 #endif
3586 return WERR_OK;
3589 /*******************************************************************
3591 * fill a notify_info struct with info asked
3593 ********************************************************************/
3595 static WERROR printer_notify_info(struct pipes_struct *p,
3596 struct policy_handle *hnd,
3597 struct spoolss_NotifyInfo *info,
3598 TALLOC_CTX *mem_ctx)
3600 int snum;
3601 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3602 int i;
3603 uint32_t id;
3604 struct spoolss_NotifyOption *option;
3605 struct spoolss_NotifyOptionType option_type;
3606 int count,j;
3607 print_queue_struct *queue=NULL;
3608 print_status_struct status;
3609 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3610 WERROR result;
3612 DEBUG(4,("printer_notify_info\n"));
3614 if (!Printer)
3615 return WERR_BADFID;
3617 option = Printer->notify.option;
3618 id = 0x0;
3620 info->version = 2;
3621 info->notifies = NULL;
3622 info->count = 0;
3624 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3625 sending a ffpcn() request first */
3627 if ( !option )
3628 return WERR_BADFID;
3630 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3631 return WERR_BADFID;
3634 /* Maybe we should use the SYSTEM session_info here... */
3635 result = winreg_get_printer_internal(mem_ctx,
3636 get_session_info_system(),
3637 p->msg_ctx,
3638 lp_servicename(snum), &pinfo2);
3639 if (!W_ERROR_IS_OK(result)) {
3640 return WERR_BADFID;
3644 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3645 * correct servername.
3647 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3648 if (pinfo2->servername == NULL) {
3649 return WERR_NOMEM;
3652 for (i=0; i<option->count; i++) {
3653 option_type = option->types[i];
3655 switch (option_type.type) {
3656 case PRINTER_NOTIFY_TYPE:
3657 if (construct_notify_printer_info(p->msg_ctx,
3658 Printer, info,
3659 pinfo2, snum,
3660 &option_type, id,
3661 mem_ctx)) {
3662 id--;
3664 break;
3666 case JOB_NOTIFY_TYPE:
3668 count = print_queue_status(p->msg_ctx, snum, &queue,
3669 &status);
3671 for (j=0; j<count; j++) {
3672 construct_notify_jobs_info(p->msg_ctx,
3673 &queue[j], info,
3674 pinfo2, snum,
3675 &option_type,
3676 queue[j].sysjob,
3677 mem_ctx);
3680 SAFE_FREE(queue);
3681 break;
3686 * Debugging information, don't delete.
3689 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3690 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3691 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3693 for (i=0; i<info->count; i++) {
3694 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3695 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3696 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3700 talloc_free(pinfo2);
3701 return WERR_OK;
3704 /****************************************************************
3705 _spoolss_RouterRefreshPrinterChangeNotify
3706 ****************************************************************/
3708 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3709 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3711 struct spoolss_NotifyInfo *info;
3713 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3714 WERROR result = WERR_BADFID;
3716 /* we always have a spoolss_NotifyInfo struct */
3717 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3718 if (!info) {
3719 result = WERR_NOMEM;
3720 goto done;
3723 *r->out.info = info;
3725 if (!Printer) {
3726 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3727 "Invalid handle (%s:%u:%u).\n",
3728 OUR_HANDLE(r->in.handle)));
3729 goto done;
3732 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3735 * We are now using the change value, and
3736 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3737 * I don't have a global notification system, I'm sending back all the
3738 * information even when _NOTHING_ has changed.
3741 /* We need to keep track of the change value to send back in
3742 RRPCN replies otherwise our updates are ignored. */
3744 Printer->notify.fnpcn = true;
3746 if (Printer->notify.cli_chan != NULL &&
3747 Printer->notify.cli_chan->active_connections > 0) {
3748 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3749 "Saving change value in request [%x]\n",
3750 r->in.change_low));
3751 Printer->notify.change = r->in.change_low;
3754 /* just ignore the spoolss_NotifyOption */
3756 switch (Printer->printer_type) {
3757 case SPLHND_SERVER:
3758 result = printserver_notify_info(p, r->in.handle,
3759 info, p->mem_ctx);
3760 break;
3762 case SPLHND_PRINTER:
3763 result = printer_notify_info(p, r->in.handle,
3764 info, p->mem_ctx);
3765 break;
3768 Printer->notify.fnpcn = false;
3770 done:
3771 return result;
3774 /********************************************************************
3775 ********************************************************************/
3777 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3778 const char *servername,
3779 const char *printername,
3780 const char **printername_p)
3782 /* FIXME: add lp_force_printername() */
3784 if (servername == NULL) {
3785 *printername_p = talloc_strdup(mem_ctx, printername);
3786 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3787 return WERR_OK;
3790 if (servername[0] == '\\' && servername[1] == '\\') {
3791 servername += 2;
3794 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3795 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3797 return WERR_OK;
3800 /********************************************************************
3801 ********************************************************************/
3803 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3804 const char *printername)
3806 if (dm == NULL) {
3807 return;
3810 dm->devicename = talloc_strndup(dm, printername,
3811 MIN(strlen(printername), 31));
3814 /********************************************************************
3815 * construct_printer_info_0
3816 * fill a printer_info_0 struct
3817 ********************************************************************/
3819 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3820 const struct auth_serversupplied_info *session_info,
3821 struct messaging_context *msg_ctx,
3822 struct spoolss_PrinterInfo2 *info2,
3823 const char *servername,
3824 struct spoolss_PrinterInfo0 *r,
3825 int snum)
3827 int count;
3828 struct printer_session_counter *session_counter;
3829 struct timeval setuptime;
3830 print_status_struct status;
3831 WERROR result;
3833 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3834 if (!W_ERROR_IS_OK(result)) {
3835 return result;
3838 if (servername) {
3839 r->servername = talloc_strdup(mem_ctx, servername);
3840 W_ERROR_HAVE_NO_MEMORY(r->servername);
3841 } else {
3842 r->servername = NULL;
3845 count = print_queue_length(msg_ctx, snum, &status);
3847 /* check if we already have a counter for this printer */
3848 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3849 if (session_counter->snum == snum)
3850 break;
3853 /* it's the first time, add it to the list */
3854 if (session_counter == NULL) {
3855 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3856 W_ERROR_HAVE_NO_MEMORY(session_counter);
3857 session_counter->snum = snum;
3858 session_counter->counter = 0;
3859 DLIST_ADD(counter_list, session_counter);
3862 /* increment it */
3863 session_counter->counter++;
3865 r->cjobs = count;
3866 r->total_jobs = 0;
3867 r->total_bytes = 0;
3869 get_startup_time(&setuptime);
3870 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3872 /* JFM:
3873 * the global_counter should be stored in a TDB as it's common to all the clients
3874 * and should be zeroed on samba startup
3876 r->global_counter = session_counter->counter;
3877 r->total_pages = 0;
3878 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3879 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3880 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3881 r->free_build = SPOOLSS_RELEASE_BUILD;
3882 r->spooling = 0;
3883 r->max_spooling = 0;
3884 r->session_counter = session_counter->counter;
3885 r->num_error_out_of_paper = 0x0;
3886 r->num_error_not_ready = 0x0; /* number of print failure */
3887 r->job_error = 0x0;
3888 r->number_of_processors = 0x1;
3889 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3890 r->high_part_total_bytes = 0x0;
3892 /* ChangeID in milliseconds*/
3893 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3894 info2->sharename, &r->change_id);
3896 r->last_error = WERR_OK;
3897 r->status = nt_printq_status(status.status);
3898 r->enumerate_network_printers = 0x0;
3899 r->c_setprinter = 0x0;
3900 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3901 r->processor_level = 0x6; /* 6 ???*/
3902 r->ref_ic = 0;
3903 r->reserved2 = 0;
3904 r->reserved3 = 0;
3906 return WERR_OK;
3910 /********************************************************************
3911 * construct_printer_info1
3912 * fill a spoolss_PrinterInfo1 struct
3913 ********************************************************************/
3915 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3916 const struct spoolss_PrinterInfo2 *info2,
3917 uint32_t flags,
3918 const char *servername,
3919 struct spoolss_PrinterInfo1 *r,
3920 int snum)
3922 WERROR result;
3924 r->flags = flags;
3926 if (info2->comment == NULL || info2->comment[0] == '\0') {
3927 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3928 } else {
3929 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3931 W_ERROR_HAVE_NO_MEMORY(r->comment);
3933 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3934 if (!W_ERROR_IS_OK(result)) {
3935 return result;
3938 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3939 r->name,
3940 info2->drivername,
3941 r->comment);
3942 W_ERROR_HAVE_NO_MEMORY(r->description);
3944 return WERR_OK;
3947 /********************************************************************
3948 * construct_printer_info2
3949 * fill a spoolss_PrinterInfo2 struct
3950 ********************************************************************/
3952 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3953 struct messaging_context *msg_ctx,
3954 const struct spoolss_PrinterInfo2 *info2,
3955 const char *servername,
3956 struct spoolss_PrinterInfo2 *r,
3957 int snum)
3959 int count;
3960 print_status_struct status;
3961 WERROR result;
3963 count = print_queue_length(msg_ctx, snum, &status);
3965 if (servername) {
3966 r->servername = talloc_strdup(mem_ctx, servername);
3967 W_ERROR_HAVE_NO_MEMORY(r->servername);
3968 } else {
3969 r->servername = NULL;
3972 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3973 if (!W_ERROR_IS_OK(result)) {
3974 return result;
3977 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3978 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3979 r->portname = talloc_strdup(mem_ctx, info2->portname);
3980 W_ERROR_HAVE_NO_MEMORY(r->portname);
3981 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3982 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3984 if (info2->comment[0] == '\0') {
3985 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3986 } else {
3987 r->comment = talloc_strdup(mem_ctx, info2->comment);
3989 W_ERROR_HAVE_NO_MEMORY(r->comment);
3991 r->location = talloc_strdup(mem_ctx, info2->location);
3992 if (info2->location[0] == '\0') {
3993 const char *loc = NULL;
3994 NTSTATUS nt_status;
3996 nt_status = printer_list_get_printer(mem_ctx,
3997 info2->sharename,
3998 NULL,
3999 &loc,
4000 NULL);
4001 if (NT_STATUS_IS_OK(nt_status)) {
4002 if (loc != NULL) {
4003 r->location = talloc_strdup(mem_ctx, loc);
4007 W_ERROR_HAVE_NO_MEMORY(r->location);
4009 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4010 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4011 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4012 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4013 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4014 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4015 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4016 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4018 r->attributes = info2->attributes;
4020 r->priority = info2->priority;
4021 r->defaultpriority = info2->defaultpriority;
4022 r->starttime = info2->starttime;
4023 r->untiltime = info2->untiltime;
4024 r->status = nt_printq_status(status.status);
4025 r->cjobs = count;
4026 r->averageppm = info2->averageppm;
4028 if (info2->devmode != NULL) {
4029 result = copy_devicemode(mem_ctx,
4030 info2->devmode,
4031 &r->devmode);
4032 if (!W_ERROR_IS_OK(result)) {
4033 return result;
4035 } else if (lp_default_devmode(snum)) {
4036 result = spoolss_create_default_devmode(mem_ctx,
4037 info2->printername,
4038 &r->devmode);
4039 if (!W_ERROR_IS_OK(result)) {
4040 return result;
4042 } else {
4043 r->devmode = NULL;
4044 DEBUG(8,("Returning NULL Devicemode!\n"));
4047 compose_devicemode_devicename(r->devmode, r->printername);
4049 r->secdesc = NULL;
4051 if (info2->secdesc != NULL) {
4052 /* don't use talloc_steal() here unless you do a deep steal of all
4053 the SEC_DESC members */
4055 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4058 return WERR_OK;
4061 /********************************************************************
4062 * construct_printer_info3
4063 * fill a spoolss_PrinterInfo3 struct
4064 ********************************************************************/
4066 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4067 const struct spoolss_PrinterInfo2 *info2,
4068 const char *servername,
4069 struct spoolss_PrinterInfo3 *r,
4070 int snum)
4072 /* These are the components of the SD we are returning. */
4074 if (info2->secdesc != NULL) {
4075 /* don't use talloc_steal() here unless you do a deep steal of all
4076 the SEC_DESC members */
4078 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4079 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4082 return WERR_OK;
4085 /********************************************************************
4086 * construct_printer_info4
4087 * fill a spoolss_PrinterInfo4 struct
4088 ********************************************************************/
4090 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4091 const struct spoolss_PrinterInfo2 *info2,
4092 const char *servername,
4093 struct spoolss_PrinterInfo4 *r,
4094 int snum)
4096 WERROR result;
4098 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4099 if (!W_ERROR_IS_OK(result)) {
4100 return result;
4103 if (servername) {
4104 r->servername = talloc_strdup(mem_ctx, servername);
4105 W_ERROR_HAVE_NO_MEMORY(r->servername);
4106 } else {
4107 r->servername = NULL;
4110 r->attributes = info2->attributes;
4112 return WERR_OK;
4115 /********************************************************************
4116 * construct_printer_info5
4117 * fill a spoolss_PrinterInfo5 struct
4118 ********************************************************************/
4120 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4121 const struct spoolss_PrinterInfo2 *info2,
4122 const char *servername,
4123 struct spoolss_PrinterInfo5 *r,
4124 int snum)
4126 WERROR result;
4128 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4129 if (!W_ERROR_IS_OK(result)) {
4130 return result;
4133 r->portname = talloc_strdup(mem_ctx, info2->portname);
4134 W_ERROR_HAVE_NO_MEMORY(r->portname);
4136 r->attributes = info2->attributes;
4138 /* these two are not used by NT+ according to MSDN */
4139 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4140 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4142 return WERR_OK;
4145 /********************************************************************
4146 * construct_printer_info_6
4147 * fill a spoolss_PrinterInfo6 struct
4148 ********************************************************************/
4150 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4151 struct messaging_context *msg_ctx,
4152 const struct spoolss_PrinterInfo2 *info2,
4153 const char *servername,
4154 struct spoolss_PrinterInfo6 *r,
4155 int snum)
4157 int count;
4158 print_status_struct status;
4160 count = print_queue_length(msg_ctx, snum, &status);
4162 r->status = nt_printq_status(status.status);
4164 return WERR_OK;
4167 /********************************************************************
4168 * construct_printer_info7
4169 * fill a spoolss_PrinterInfo7 struct
4170 ********************************************************************/
4172 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4173 struct messaging_context *msg_ctx,
4174 const char *servername,
4175 struct spoolss_PrinterInfo7 *r,
4176 int snum)
4178 struct auth_serversupplied_info *session_info;
4179 char *printer;
4180 NTSTATUS status;
4181 WERROR werr;
4182 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4183 if (tmp_ctx == NULL) {
4184 return WERR_NOMEM;
4187 status = make_session_info_system(tmp_ctx, &session_info);
4188 if (!NT_STATUS_IS_OK(status)) {
4189 DEBUG(0, ("construct_printer_info7: "
4190 "Could not create system session_info\n"));
4191 werr = WERR_NOMEM;
4192 goto out_tmp_free;
4195 printer = lp_servicename(snum);
4196 if (printer == NULL) {
4197 DEBUG(0, ("invalid printer snum %d\n", snum));
4198 werr = WERR_INVALID_PARAM;
4199 goto out_tmp_free;
4202 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4203 servername, printer, NULL)) {
4204 struct GUID guid;
4205 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4206 printer, &guid);
4207 if (!W_ERROR_IS_OK(werr)) {
4208 goto out_tmp_free;
4210 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4211 r->action = DSPRINT_PUBLISH;
4212 } else {
4213 r->guid = talloc_strdup(mem_ctx, "");
4214 r->action = DSPRINT_UNPUBLISH;
4216 if (r->guid == NULL) {
4217 werr = WERR_NOMEM;
4218 goto out_tmp_free;
4221 werr = WERR_OK;
4222 out_tmp_free:
4223 talloc_free(tmp_ctx);
4224 return werr;
4227 /********************************************************************
4228 * construct_printer_info8
4229 * fill a spoolss_PrinterInfo8 struct
4230 ********************************************************************/
4232 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4233 const struct spoolss_PrinterInfo2 *info2,
4234 const char *servername,
4235 struct spoolss_DeviceModeInfo *r,
4236 int snum)
4238 WERROR result;
4239 const char *printername;
4241 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4242 if (!W_ERROR_IS_OK(result)) {
4243 return result;
4246 if (info2->devmode != NULL) {
4247 result = copy_devicemode(mem_ctx,
4248 info2->devmode,
4249 &r->devmode);
4250 if (!W_ERROR_IS_OK(result)) {
4251 return result;
4253 } else if (lp_default_devmode(snum)) {
4254 result = spoolss_create_default_devmode(mem_ctx,
4255 info2->printername,
4256 &r->devmode);
4257 if (!W_ERROR_IS_OK(result)) {
4258 return result;
4260 } else {
4261 r->devmode = NULL;
4262 DEBUG(8,("Returning NULL Devicemode!\n"));
4265 compose_devicemode_devicename(r->devmode, printername);
4267 return WERR_OK;
4271 /********************************************************************
4272 ********************************************************************/
4274 static bool snum_is_shared_printer(int snum)
4276 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4279 /********************************************************************
4280 Spoolss_enumprinters.
4281 ********************************************************************/
4283 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4284 const struct auth_serversupplied_info *session_info,
4285 struct messaging_context *msg_ctx,
4286 const char *servername,
4287 uint32_t level,
4288 uint32_t flags,
4289 union spoolss_PrinterInfo **info_p,
4290 uint32_t *count_p)
4292 int snum;
4293 int n_services = lp_numservices();
4294 union spoolss_PrinterInfo *info = NULL;
4295 uint32_t count = 0;
4296 WERROR result = WERR_OK;
4297 struct dcerpc_binding_handle *b = NULL;
4299 *count_p = 0;
4300 *info_p = NULL;
4302 for (snum = 0; snum < n_services; snum++) {
4304 const char *printer;
4305 struct spoolss_PrinterInfo2 *info2;
4307 if (!snum_is_shared_printer(snum)) {
4308 continue;
4311 printer = lp_const_servicename(snum);
4313 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4314 printer, snum));
4316 if (b == NULL) {
4317 result = winreg_printer_binding_handle(mem_ctx,
4318 session_info,
4319 msg_ctx,
4320 &b);
4321 if (!W_ERROR_IS_OK(result)) {
4322 goto out;
4326 result = winreg_create_printer(mem_ctx, b,
4327 printer);
4328 if (!W_ERROR_IS_OK(result)) {
4329 goto out;
4332 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4333 union spoolss_PrinterInfo,
4334 count + 1);
4335 if (!info) {
4336 result = WERR_NOMEM;
4337 goto out;
4340 result = winreg_get_printer(mem_ctx, b,
4341 printer, &info2);
4342 if (!W_ERROR_IS_OK(result)) {
4343 goto out;
4346 switch (level) {
4347 case 0:
4348 result = construct_printer_info0(info, session_info,
4349 msg_ctx, info2,
4350 servername,
4351 &info[count].info0, snum);
4352 break;
4353 case 1:
4354 result = construct_printer_info1(info, info2, flags,
4355 servername,
4356 &info[count].info1, snum);
4357 break;
4358 case 2:
4359 result = construct_printer_info2(info, msg_ctx, info2,
4360 servername,
4361 &info[count].info2, snum);
4362 break;
4363 case 4:
4364 result = construct_printer_info4(info, info2,
4365 servername,
4366 &info[count].info4, snum);
4367 break;
4368 case 5:
4369 result = construct_printer_info5(info, info2,
4370 servername,
4371 &info[count].info5, snum);
4372 break;
4374 default:
4375 result = WERR_UNKNOWN_LEVEL;
4376 goto out;
4379 if (!W_ERROR_IS_OK(result)) {
4380 goto out;
4383 count++;
4386 *count_p = count;
4387 *info_p = info;
4389 out:
4390 if (!W_ERROR_IS_OK(result)) {
4391 TALLOC_FREE(info);
4392 return result;
4395 *info_p = info;
4397 return WERR_OK;
4400 /********************************************************************
4401 * handle enumeration of printers at level 0
4402 ********************************************************************/
4404 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4405 const struct auth_serversupplied_info *session_info,
4406 struct messaging_context *msg_ctx,
4407 uint32_t flags,
4408 const char *servername,
4409 union spoolss_PrinterInfo **info,
4410 uint32_t *count)
4412 DEBUG(4,("enum_all_printers_info_0\n"));
4414 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4415 servername, 0, flags, info, count);
4419 /********************************************************************
4420 ********************************************************************/
4422 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4423 const struct auth_serversupplied_info *session_info,
4424 struct messaging_context *msg_ctx,
4425 const char *servername,
4426 uint32_t flags,
4427 union spoolss_PrinterInfo **info,
4428 uint32_t *count)
4430 DEBUG(4,("enum_all_printers_info_1\n"));
4432 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4433 servername, 1, flags, info, count);
4436 /********************************************************************
4437 enum_all_printers_info_1_local.
4438 *********************************************************************/
4440 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4441 const struct auth_serversupplied_info *session_info,
4442 struct messaging_context *msg_ctx,
4443 const char *servername,
4444 union spoolss_PrinterInfo **info,
4445 uint32_t *count)
4447 DEBUG(4,("enum_all_printers_info_1_local\n"));
4449 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4450 servername, PRINTER_ENUM_ICON8, info, count);
4453 /********************************************************************
4454 enum_all_printers_info_1_name.
4455 *********************************************************************/
4457 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4458 const struct auth_serversupplied_info *session_info,
4459 struct messaging_context *msg_ctx,
4460 const char *servername,
4461 union spoolss_PrinterInfo **info,
4462 uint32_t *count)
4464 const char *s = servername;
4466 DEBUG(4,("enum_all_printers_info_1_name\n"));
4468 if (servername != NULL &&
4469 (servername[0] == '\\') && (servername[1] == '\\')) {
4470 s = servername + 2;
4473 if (!is_myname_or_ipaddr(s)) {
4474 return WERR_INVALID_NAME;
4477 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4478 servername, PRINTER_ENUM_ICON8, info, count);
4481 /********************************************************************
4482 enum_all_printers_info_1_network.
4483 *********************************************************************/
4485 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4486 const struct auth_serversupplied_info *session_info,
4487 struct messaging_context *msg_ctx,
4488 const char *servername,
4489 union spoolss_PrinterInfo **info,
4490 uint32_t *count)
4492 const char *s = servername;
4494 DEBUG(4,("enum_all_printers_info_1_network\n"));
4496 /* If we respond to a enum_printers level 1 on our name with flags
4497 set to PRINTER_ENUM_REMOTE with a list of printers then these
4498 printers incorrectly appear in the APW browse list.
4499 Specifically the printers for the server appear at the workgroup
4500 level where all the other servers in the domain are
4501 listed. Windows responds to this call with a
4502 WERR_CAN_NOT_COMPLETE so we should do the same. */
4504 if (servername != NULL &&
4505 (servername[0] == '\\') && (servername[1] == '\\')) {
4506 s = servername + 2;
4509 if (is_myname_or_ipaddr(s)) {
4510 return WERR_CAN_NOT_COMPLETE;
4513 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4514 servername, PRINTER_ENUM_NAME, info, count);
4517 /********************************************************************
4518 * api_spoolss_enumprinters
4520 * called from api_spoolss_enumprinters (see this to understand)
4521 ********************************************************************/
4523 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4524 const struct auth_serversupplied_info *session_info,
4525 struct messaging_context *msg_ctx,
4526 const char *servername,
4527 union spoolss_PrinterInfo **info,
4528 uint32_t *count)
4530 DEBUG(4,("enum_all_printers_info_2\n"));
4532 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4533 servername, 2, 0, info, count);
4536 /********************************************************************
4537 * handle enumeration of printers at level 1
4538 ********************************************************************/
4540 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4541 const struct auth_serversupplied_info *session_info,
4542 struct messaging_context *msg_ctx,
4543 uint32_t flags,
4544 const char *servername,
4545 union spoolss_PrinterInfo **info,
4546 uint32_t *count)
4548 /* Not all the flags are equals */
4550 if (flags & PRINTER_ENUM_LOCAL) {
4551 return enum_all_printers_info_1_local(mem_ctx, session_info,
4552 msg_ctx, servername, info, count);
4555 if (flags & PRINTER_ENUM_NAME) {
4556 return enum_all_printers_info_1_name(mem_ctx, session_info,
4557 msg_ctx, servername, info,
4558 count);
4561 if (flags & PRINTER_ENUM_NETWORK) {
4562 return enum_all_printers_info_1_network(mem_ctx, session_info,
4563 msg_ctx, servername, info,
4564 count);
4567 return WERR_OK; /* NT4sp5 does that */
4570 /********************************************************************
4571 * handle enumeration of printers at level 2
4572 ********************************************************************/
4574 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4575 const struct auth_serversupplied_info *session_info,
4576 struct messaging_context *msg_ctx,
4577 uint32_t flags,
4578 const char *servername,
4579 union spoolss_PrinterInfo **info,
4580 uint32_t *count)
4582 if (flags & PRINTER_ENUM_LOCAL) {
4584 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4585 servername,
4586 info, count);
4589 if (flags & PRINTER_ENUM_NAME) {
4590 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4591 return WERR_INVALID_NAME;
4594 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4595 servername,
4596 info, count);
4599 if (flags & PRINTER_ENUM_REMOTE) {
4600 return WERR_UNKNOWN_LEVEL;
4603 return WERR_OK;
4606 /********************************************************************
4607 * handle enumeration of printers at level 4
4608 ********************************************************************/
4610 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4611 const struct auth_serversupplied_info *session_info,
4612 struct messaging_context *msg_ctx,
4613 uint32_t flags,
4614 const char *servername,
4615 union spoolss_PrinterInfo **info,
4616 uint32_t *count)
4618 DEBUG(4,("enum_all_printers_info_4\n"));
4620 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4621 servername, 4, flags, info, count);
4625 /********************************************************************
4626 * handle enumeration of printers at level 5
4627 ********************************************************************/
4629 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4630 const struct auth_serversupplied_info *session_info,
4631 struct messaging_context *msg_ctx,
4632 uint32_t flags,
4633 const char *servername,
4634 union spoolss_PrinterInfo **info,
4635 uint32_t *count)
4637 DEBUG(4,("enum_all_printers_info_5\n"));
4639 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4640 servername, 5, flags, info, count);
4643 /****************************************************************
4644 _spoolss_EnumPrinters
4645 ****************************************************************/
4647 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4648 struct spoolss_EnumPrinters *r)
4650 const struct auth_serversupplied_info *session_info = get_session_info_system();
4651 WERROR result;
4653 /* that's an [in out] buffer */
4655 if (!r->in.buffer && (r->in.offered != 0)) {
4656 return WERR_INVALID_PARAM;
4659 DEBUG(4,("_spoolss_EnumPrinters\n"));
4661 *r->out.needed = 0;
4662 *r->out.count = 0;
4663 *r->out.info = NULL;
4666 * Level 1:
4667 * flags==PRINTER_ENUM_NAME
4668 * if name=="" then enumerates all printers
4669 * if name!="" then enumerate the printer
4670 * flags==PRINTER_ENUM_REMOTE
4671 * name is NULL, enumerate printers
4672 * Level 2: name!="" enumerates printers, name can't be NULL
4673 * Level 3: doesn't exist
4674 * Level 4: does a local registry lookup
4675 * Level 5: same as Level 2
4678 if (r->in.server && r->in.server[0] == '\0') {
4679 r->in.server = NULL;
4682 switch (r->in.level) {
4683 case 0:
4684 result = enumprinters_level0(p->mem_ctx, session_info,
4685 p->msg_ctx, r->in.flags,
4686 r->in.server,
4687 r->out.info, r->out.count);
4688 break;
4689 case 1:
4690 result = enumprinters_level1(p->mem_ctx, session_info,
4691 p->msg_ctx, r->in.flags,
4692 r->in.server,
4693 r->out.info, r->out.count);
4694 break;
4695 case 2:
4696 result = enumprinters_level2(p->mem_ctx, session_info,
4697 p->msg_ctx, r->in.flags,
4698 r->in.server,
4699 r->out.info, r->out.count);
4700 break;
4701 case 4:
4702 result = enumprinters_level4(p->mem_ctx, session_info,
4703 p->msg_ctx, r->in.flags,
4704 r->in.server,
4705 r->out.info, r->out.count);
4706 break;
4707 case 5:
4708 result = enumprinters_level5(p->mem_ctx, session_info,
4709 p->msg_ctx, r->in.flags,
4710 r->in.server,
4711 r->out.info, r->out.count);
4712 break;
4713 default:
4714 return WERR_UNKNOWN_LEVEL;
4717 if (!W_ERROR_IS_OK(result)) {
4718 return result;
4721 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4722 spoolss_EnumPrinters,
4723 *r->out.info, r->in.level,
4724 *r->out.count);
4725 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4726 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4728 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4731 /****************************************************************
4732 _spoolss_GetPrinter
4733 ****************************************************************/
4735 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4736 struct spoolss_GetPrinter *r)
4738 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4739 struct spoolss_PrinterInfo2 *info2 = NULL;
4740 WERROR result = WERR_OK;
4741 int snum;
4743 /* that's an [in out] buffer */
4745 if (!r->in.buffer && (r->in.offered != 0)) {
4746 return WERR_INVALID_PARAM;
4749 *r->out.needed = 0;
4751 if (Printer == NULL) {
4752 return WERR_BADFID;
4755 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4756 return WERR_BADFID;
4759 result = winreg_get_printer_internal(p->mem_ctx,
4760 get_session_info_system(),
4761 p->msg_ctx,
4762 lp_const_servicename(snum),
4763 &info2);
4764 if (!W_ERROR_IS_OK(result)) {
4765 goto out;
4768 switch (r->in.level) {
4769 case 0:
4770 result = construct_printer_info0(p->mem_ctx,
4771 get_session_info_system(),
4772 p->msg_ctx,
4773 info2,
4774 Printer->servername,
4775 &r->out.info->info0,
4776 snum);
4777 break;
4778 case 1:
4779 result = construct_printer_info1(p->mem_ctx, info2,
4780 PRINTER_ENUM_ICON8,
4781 Printer->servername,
4782 &r->out.info->info1, snum);
4783 break;
4784 case 2:
4785 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4786 Printer->servername,
4787 &r->out.info->info2, snum);
4788 break;
4789 case 3:
4790 result = construct_printer_info3(p->mem_ctx, info2,
4791 Printer->servername,
4792 &r->out.info->info3, snum);
4793 break;
4794 case 4:
4795 result = construct_printer_info4(p->mem_ctx, info2,
4796 Printer->servername,
4797 &r->out.info->info4, snum);
4798 break;
4799 case 5:
4800 result = construct_printer_info5(p->mem_ctx, info2,
4801 Printer->servername,
4802 &r->out.info->info5, snum);
4803 break;
4804 case 6:
4805 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4806 Printer->servername,
4807 &r->out.info->info6, snum);
4808 break;
4809 case 7:
4810 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4811 Printer->servername,
4812 &r->out.info->info7, snum);
4813 break;
4814 case 8:
4815 result = construct_printer_info8(p->mem_ctx, info2,
4816 Printer->servername,
4817 &r->out.info->info8, snum);
4818 break;
4819 default:
4820 result = WERR_UNKNOWN_LEVEL;
4821 break;
4824 out:
4825 if (!W_ERROR_IS_OK(result)) {
4826 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4827 r->in.level, win_errstr(result)));
4828 TALLOC_FREE(r->out.info);
4829 return result;
4832 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4833 r->out.info, r->in.level);
4834 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4836 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4839 /********************************************************************
4840 ********************************************************************/
4842 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4843 do { \
4844 if (in && strlen(in)) { \
4845 out = talloc_strdup(mem_ctx, in); \
4846 } else { \
4847 out = talloc_strdup(mem_ctx, ""); \
4849 W_ERROR_HAVE_NO_MEMORY(out); \
4850 } while (0);
4852 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4853 do { \
4854 if (in && strlen(in)) { \
4855 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4856 } else { \
4857 out = talloc_strdup(mem_ctx, ""); \
4859 W_ERROR_HAVE_NO_MEMORY(out); \
4860 } while (0);
4862 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4863 const char **string_array,
4864 const char ***presult,
4865 const char *cservername,
4866 const char *arch,
4867 int version)
4869 int i, num_strings = 0;
4870 const char **array = NULL;
4872 if (string_array == NULL) {
4873 return WERR_INVALID_PARAMETER;
4876 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4877 const char *str = NULL;
4879 if (cservername == NULL || arch == NULL) {
4880 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4881 } else {
4882 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4885 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4886 TALLOC_FREE(array);
4887 return WERR_NOMEM;
4891 if (i > 0) {
4892 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4893 &array, &num_strings);
4896 if (presult) {
4897 *presult = array;
4900 return WERR_OK;
4903 /********************************************************************
4904 * fill a spoolss_DriverInfo1 struct
4905 ********************************************************************/
4907 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4908 struct spoolss_DriverInfo1 *r,
4909 const struct spoolss_DriverInfo8 *driver,
4910 const char *servername)
4912 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4913 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4915 return WERR_OK;
4918 /********************************************************************
4919 * fill a spoolss_DriverInfo2 struct
4920 ********************************************************************/
4922 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4923 struct spoolss_DriverInfo2 *r,
4924 const struct spoolss_DriverInfo8 *driver,
4925 const char *servername)
4928 const char *cservername = canon_servername(servername);
4930 r->version = driver->version;
4932 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4933 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4934 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4935 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4937 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938 driver->architecture,
4939 driver->version,
4940 driver->driver_path,
4941 r->driver_path);
4943 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4944 driver->architecture,
4945 driver->version,
4946 driver->data_file,
4947 r->data_file);
4949 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4950 driver->architecture,
4951 driver->version,
4952 driver->config_file,
4953 r->config_file);
4955 return WERR_OK;
4958 /********************************************************************
4959 * fill a spoolss_DriverInfo3 struct
4960 ********************************************************************/
4962 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4963 struct spoolss_DriverInfo3 *r,
4964 const struct spoolss_DriverInfo8 *driver,
4965 const char *servername)
4967 const char *cservername = canon_servername(servername);
4969 r->version = driver->version;
4971 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4972 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4973 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4974 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4976 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4977 driver->architecture,
4978 driver->version,
4979 driver->driver_path,
4980 r->driver_path);
4982 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4983 driver->architecture,
4984 driver->version,
4985 driver->data_file,
4986 r->data_file);
4988 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4989 driver->architecture,
4990 driver->version,
4991 driver->config_file,
4992 r->config_file);
4994 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995 driver->architecture,
4996 driver->version,
4997 driver->help_file,
4998 r->help_file);
5000 FILL_DRIVER_STRING(mem_ctx,
5001 driver->monitor_name,
5002 r->monitor_name);
5004 FILL_DRIVER_STRING(mem_ctx,
5005 driver->default_datatype,
5006 r->default_datatype);
5008 return string_array_from_driver_info(mem_ctx,
5009 driver->dependent_files,
5010 &r->dependent_files,
5011 cservername,
5012 driver->architecture,
5013 driver->version);
5016 /********************************************************************
5017 * fill a spoolss_DriverInfo4 struct
5018 ********************************************************************/
5020 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5021 struct spoolss_DriverInfo4 *r,
5022 const struct spoolss_DriverInfo8 *driver,
5023 const char *servername)
5025 const char *cservername = canon_servername(servername);
5026 WERROR result;
5028 r->version = driver->version;
5030 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5031 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5032 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5033 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5035 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5036 driver->architecture,
5037 driver->version,
5038 driver->driver_path,
5039 r->driver_path);
5041 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5042 driver->architecture,
5043 driver->version,
5044 driver->data_file,
5045 r->data_file);
5047 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5048 driver->architecture,
5049 driver->version,
5050 driver->config_file,
5051 r->config_file);
5053 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5054 driver->architecture,
5055 driver->version,
5056 driver->help_file,
5057 r->help_file);
5059 result = string_array_from_driver_info(mem_ctx,
5060 driver->dependent_files,
5061 &r->dependent_files,
5062 cservername,
5063 driver->architecture,
5064 driver->version);
5065 if (!W_ERROR_IS_OK(result)) {
5066 return result;
5069 FILL_DRIVER_STRING(mem_ctx,
5070 driver->monitor_name,
5071 r->monitor_name);
5073 FILL_DRIVER_STRING(mem_ctx,
5074 driver->default_datatype,
5075 r->default_datatype);
5078 result = string_array_from_driver_info(mem_ctx,
5079 driver->previous_names,
5080 &r->previous_names,
5081 NULL, NULL, 0);
5083 return result;
5086 /********************************************************************
5087 * fill a spoolss_DriverInfo5 struct
5088 ********************************************************************/
5090 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5091 struct spoolss_DriverInfo5 *r,
5092 const struct spoolss_DriverInfo8 *driver,
5093 const char *servername)
5095 const char *cservername = canon_servername(servername);
5097 r->version = driver->version;
5099 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5100 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5101 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5102 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5104 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105 driver->architecture,
5106 driver->version,
5107 driver->driver_path,
5108 r->driver_path);
5110 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5111 driver->architecture,
5112 driver->version,
5113 driver->data_file,
5114 r->data_file);
5116 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5117 driver->architecture,
5118 driver->version,
5119 driver->config_file,
5120 r->config_file);
5122 r->driver_attributes = 0;
5123 r->config_version = 0;
5124 r->driver_version = 0;
5126 return WERR_OK;
5128 /********************************************************************
5129 * fill a spoolss_DriverInfo6 struct
5130 ********************************************************************/
5132 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5133 struct spoolss_DriverInfo6 *r,
5134 const struct spoolss_DriverInfo8 *driver,
5135 const char *servername)
5137 const char *cservername = canon_servername(servername);
5138 WERROR result;
5140 r->version = driver->version;
5142 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5143 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5144 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5145 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5147 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5148 driver->architecture,
5149 driver->version,
5150 driver->driver_path,
5151 r->driver_path);
5153 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5154 driver->architecture,
5155 driver->version,
5156 driver->data_file,
5157 r->data_file);
5159 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5160 driver->architecture,
5161 driver->version,
5162 driver->config_file,
5163 r->config_file);
5165 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5166 driver->architecture,
5167 driver->version,
5168 driver->help_file,
5169 r->help_file);
5171 FILL_DRIVER_STRING(mem_ctx,
5172 driver->monitor_name,
5173 r->monitor_name);
5175 FILL_DRIVER_STRING(mem_ctx,
5176 driver->default_datatype,
5177 r->default_datatype);
5179 result = string_array_from_driver_info(mem_ctx,
5180 driver->dependent_files,
5181 &r->dependent_files,
5182 cservername,
5183 driver->architecture,
5184 driver->version);
5185 if (!W_ERROR_IS_OK(result)) {
5186 return result;
5189 result = string_array_from_driver_info(mem_ctx,
5190 driver->previous_names,
5191 &r->previous_names,
5192 NULL, NULL, 0);
5193 if (!W_ERROR_IS_OK(result)) {
5194 return result;
5197 r->driver_date = driver->driver_date;
5198 r->driver_version = driver->driver_version;
5200 FILL_DRIVER_STRING(mem_ctx,
5201 driver->manufacturer_name,
5202 r->manufacturer_name);
5203 FILL_DRIVER_STRING(mem_ctx,
5204 driver->manufacturer_url,
5205 r->manufacturer_url);
5206 FILL_DRIVER_STRING(mem_ctx,
5207 driver->hardware_id,
5208 r->hardware_id);
5209 FILL_DRIVER_STRING(mem_ctx,
5210 driver->provider,
5211 r->provider);
5213 return WERR_OK;
5216 /********************************************************************
5217 * fill a spoolss_DriverInfo8 struct
5218 ********************************************************************/
5220 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5221 struct spoolss_DriverInfo8 *r,
5222 const struct spoolss_DriverInfo8 *driver,
5223 const char *servername)
5225 const char *cservername = canon_servername(servername);
5226 WERROR result;
5228 r->version = driver->version;
5230 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5231 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5232 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5233 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5235 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5236 driver->architecture,
5237 driver->version,
5238 driver->driver_path,
5239 r->driver_path);
5241 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5242 driver->architecture,
5243 driver->version,
5244 driver->data_file,
5245 r->data_file);
5247 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5248 driver->architecture,
5249 driver->version,
5250 driver->config_file,
5251 r->config_file);
5253 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5254 driver->architecture,
5255 driver->version,
5256 driver->help_file,
5257 r->help_file);
5259 FILL_DRIVER_STRING(mem_ctx,
5260 driver->monitor_name,
5261 r->monitor_name);
5263 FILL_DRIVER_STRING(mem_ctx,
5264 driver->default_datatype,
5265 r->default_datatype);
5267 result = string_array_from_driver_info(mem_ctx,
5268 driver->dependent_files,
5269 &r->dependent_files,
5270 cservername,
5271 driver->architecture,
5272 driver->version);
5273 if (!W_ERROR_IS_OK(result)) {
5274 return result;
5277 result = string_array_from_driver_info(mem_ctx,
5278 driver->previous_names,
5279 &r->previous_names,
5280 NULL, NULL, 0);
5281 if (!W_ERROR_IS_OK(result)) {
5282 return result;
5285 r->driver_date = driver->driver_date;
5286 r->driver_version = driver->driver_version;
5288 FILL_DRIVER_STRING(mem_ctx,
5289 driver->manufacturer_name,
5290 r->manufacturer_name);
5291 FILL_DRIVER_STRING(mem_ctx,
5292 driver->manufacturer_url,
5293 r->manufacturer_url);
5294 FILL_DRIVER_STRING(mem_ctx,
5295 driver->hardware_id,
5296 r->hardware_id);
5297 FILL_DRIVER_STRING(mem_ctx,
5298 driver->provider,
5299 r->provider);
5301 FILL_DRIVER_STRING(mem_ctx,
5302 driver->print_processor,
5303 r->print_processor);
5304 FILL_DRIVER_STRING(mem_ctx,
5305 driver->vendor_setup,
5306 r->vendor_setup);
5308 result = string_array_from_driver_info(mem_ctx,
5309 driver->color_profiles,
5310 &r->color_profiles,
5311 NULL, NULL, 0);
5312 if (!W_ERROR_IS_OK(result)) {
5313 return result;
5316 FILL_DRIVER_STRING(mem_ctx,
5317 driver->inf_path,
5318 r->inf_path);
5320 r->printer_driver_attributes = driver->printer_driver_attributes;
5322 result = string_array_from_driver_info(mem_ctx,
5323 driver->core_driver_dependencies,
5324 &r->core_driver_dependencies,
5325 NULL, NULL, 0);
5326 if (!W_ERROR_IS_OK(result)) {
5327 return result;
5330 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5331 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5333 return WERR_OK;
5336 #if 0 /* disabled until marshalling issues are resolved - gd */
5337 /********************************************************************
5338 ********************************************************************/
5340 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5341 struct spoolss_DriverFileInfo *r,
5342 const char *cservername,
5343 const char *file_name,
5344 enum spoolss_DriverFileType file_type,
5345 uint32_t file_version)
5347 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5348 cservername, file_name);
5349 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5350 r->file_type = file_type;
5351 r->file_version = file_version;
5353 return WERR_OK;
5356 /********************************************************************
5357 ********************************************************************/
5359 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5360 const struct spoolss_DriverInfo8 *driver,
5361 const char *cservername,
5362 struct spoolss_DriverFileInfo **info_p,
5363 uint32_t *count_p)
5365 struct spoolss_DriverFileInfo *info = NULL;
5366 uint32_t count = 0;
5367 WERROR result;
5368 uint32_t i;
5370 *info_p = NULL;
5371 *count_p = 0;
5373 if (strlen(driver->driver_path)) {
5374 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5375 struct spoolss_DriverFileInfo,
5376 count + 1);
5377 W_ERROR_HAVE_NO_MEMORY(info);
5378 result = fill_spoolss_DriverFileInfo(info,
5379 &info[count],
5380 cservername,
5381 driver->driver_path,
5382 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5384 W_ERROR_NOT_OK_RETURN(result);
5385 count++;
5388 if (strlen(driver->config_file)) {
5389 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5390 struct spoolss_DriverFileInfo,
5391 count + 1);
5392 W_ERROR_HAVE_NO_MEMORY(info);
5393 result = fill_spoolss_DriverFileInfo(info,
5394 &info[count],
5395 cservername,
5396 driver->config_file,
5397 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5399 W_ERROR_NOT_OK_RETURN(result);
5400 count++;
5403 if (strlen(driver->data_file)) {
5404 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5405 struct spoolss_DriverFileInfo,
5406 count + 1);
5407 W_ERROR_HAVE_NO_MEMORY(info);
5408 result = fill_spoolss_DriverFileInfo(info,
5409 &info[count],
5410 cservername,
5411 driver->data_file,
5412 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5414 W_ERROR_NOT_OK_RETURN(result);
5415 count++;
5418 if (strlen(driver->help_file)) {
5419 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5420 struct spoolss_DriverFileInfo,
5421 count + 1);
5422 W_ERROR_HAVE_NO_MEMORY(info);
5423 result = fill_spoolss_DriverFileInfo(info,
5424 &info[count],
5425 cservername,
5426 driver->help_file,
5427 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5429 W_ERROR_NOT_OK_RETURN(result);
5430 count++;
5433 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5434 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5435 struct spoolss_DriverFileInfo,
5436 count + 1);
5437 W_ERROR_HAVE_NO_MEMORY(info);
5438 result = fill_spoolss_DriverFileInfo(info,
5439 &info[count],
5440 cservername,
5441 driver->dependent_files[i],
5442 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5444 W_ERROR_NOT_OK_RETURN(result);
5445 count++;
5448 *info_p = info;
5449 *count_p = count;
5451 return WERR_OK;
5454 /********************************************************************
5455 * fill a spoolss_DriverInfo101 struct
5456 ********************************************************************/
5458 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5459 struct spoolss_DriverInfo101 *r,
5460 const struct spoolss_DriverInfo8 *driver,
5461 const char *servername)
5463 const char *cservername = canon_servername(servername);
5464 WERROR result;
5466 r->version = driver->version;
5468 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5469 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5470 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5471 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5473 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5474 cservername,
5475 &r->file_info,
5476 &r->file_count);
5477 if (!W_ERROR_IS_OK(result)) {
5478 return result;
5481 FILL_DRIVER_STRING(mem_ctx,
5482 driver->monitor_name,
5483 r->monitor_name);
5485 FILL_DRIVER_STRING(mem_ctx,
5486 driver->default_datatype,
5487 r->default_datatype);
5489 result = string_array_from_driver_info(mem_ctx,
5490 driver->previous_names,
5491 &r->previous_names,
5492 NULL, NULL, 0);
5493 if (!W_ERROR_IS_OK(result)) {
5494 return result;
5497 r->driver_date = driver->driver_date;
5498 r->driver_version = driver->driver_version;
5500 FILL_DRIVER_STRING(mem_ctx,
5501 driver->manufacturer_name,
5502 r->manufacturer_name);
5503 FILL_DRIVER_STRING(mem_ctx,
5504 driver->manufacturer_url,
5505 r->manufacturer_url);
5506 FILL_DRIVER_STRING(mem_ctx,
5507 driver->hardware_id,
5508 r->hardware_id);
5509 FILL_DRIVER_STRING(mem_ctx,
5510 driver->provider,
5511 r->provider);
5513 return WERR_OK;
5515 #endif
5516 /********************************************************************
5517 ********************************************************************/
5519 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5520 const struct auth_serversupplied_info *session_info,
5521 struct messaging_context *msg_ctx,
5522 uint32_t level,
5523 union spoolss_DriverInfo *r,
5524 int snum,
5525 const char *servername,
5526 const char *architecture,
5527 uint32_t version)
5529 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5530 struct spoolss_DriverInfo8 *driver;
5531 WERROR result;
5532 struct dcerpc_binding_handle *b;
5534 if (level == 101) {
5535 return WERR_UNKNOWN_LEVEL;
5538 result = winreg_printer_binding_handle(mem_ctx,
5539 session_info,
5540 msg_ctx,
5541 &b);
5542 if (!W_ERROR_IS_OK(result)) {
5543 return result;
5546 result = winreg_get_printer(mem_ctx, b,
5547 lp_const_servicename(snum),
5548 &pinfo2);
5550 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5551 win_errstr(result)));
5553 if (!W_ERROR_IS_OK(result)) {
5554 return WERR_INVALID_PRINTER_NAME;
5557 result = winreg_get_driver(mem_ctx, b,
5558 architecture,
5559 pinfo2->drivername, version, &driver);
5561 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5562 win_errstr(result)));
5564 if (!W_ERROR_IS_OK(result)) {
5566 * Is this a W2k client ?
5569 if (version < 3) {
5570 talloc_free(pinfo2);
5571 return WERR_UNKNOWN_PRINTER_DRIVER;
5574 /* Yes - try again with a WinNT driver. */
5575 version = 2;
5576 result = winreg_get_driver(mem_ctx, b,
5577 architecture,
5578 pinfo2->drivername,
5579 version, &driver);
5580 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5581 win_errstr(result)));
5582 if (!W_ERROR_IS_OK(result)) {
5583 talloc_free(pinfo2);
5584 return WERR_UNKNOWN_PRINTER_DRIVER;
5588 switch (level) {
5589 case 1:
5590 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5591 break;
5592 case 2:
5593 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5594 break;
5595 case 3:
5596 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5597 break;
5598 case 4:
5599 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5600 break;
5601 case 5:
5602 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5603 break;
5604 case 6:
5605 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5606 break;
5607 case 8:
5608 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5609 break;
5610 #if 0 /* disabled until marshalling issues are resolved - gd */
5611 case 101:
5612 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5613 break;
5614 #endif
5615 default:
5616 result = WERR_UNKNOWN_LEVEL;
5617 break;
5620 talloc_free(pinfo2);
5621 talloc_free(driver);
5623 return result;
5626 /****************************************************************
5627 _spoolss_GetPrinterDriver2
5628 ****************************************************************/
5630 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5631 struct spoolss_GetPrinterDriver2 *r)
5633 struct printer_handle *printer;
5634 WERROR result;
5635 uint32_t version = r->in.client_major_version;
5637 int snum;
5639 /* that's an [in out] buffer */
5641 if (!r->in.buffer && (r->in.offered != 0)) {
5642 return WERR_INVALID_PARAM;
5645 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5647 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5648 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5649 return WERR_INVALID_PRINTER_NAME;
5652 *r->out.needed = 0;
5653 *r->out.server_major_version = 0;
5654 *r->out.server_minor_version = 0;
5656 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5657 return WERR_BADFID;
5660 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5661 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5662 "downgrading to v3\n"));
5663 version = SPOOLSS_DRIVER_VERSION_200X;
5666 result = construct_printer_driver_info_level(p->mem_ctx,
5667 get_session_info_system(),
5668 p->msg_ctx,
5669 r->in.level, r->out.info,
5670 snum, printer->servername,
5671 r->in.architecture,
5672 version);
5673 if (!W_ERROR_IS_OK(result)) {
5674 TALLOC_FREE(r->out.info);
5675 return result;
5678 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5679 r->out.info, r->in.level);
5680 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5682 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5686 /****************************************************************
5687 _spoolss_StartPagePrinter
5688 ****************************************************************/
5690 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5691 struct spoolss_StartPagePrinter *r)
5693 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5695 if (!Printer) {
5696 DEBUG(3,("_spoolss_StartPagePrinter: "
5697 "Error in startpageprinter printer handle\n"));
5698 return WERR_BADFID;
5701 Printer->page_started = true;
5702 return WERR_OK;
5705 /****************************************************************
5706 _spoolss_EndPagePrinter
5707 ****************************************************************/
5709 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5710 struct spoolss_EndPagePrinter *r)
5712 int snum;
5714 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5716 if (!Printer) {
5717 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5718 OUR_HANDLE(r->in.handle)));
5719 return WERR_BADFID;
5722 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5723 return WERR_BADFID;
5725 Printer->page_started = false;
5726 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5728 return WERR_OK;
5731 /****************************************************************
5732 _spoolss_StartDocPrinter
5733 ****************************************************************/
5735 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5736 struct spoolss_StartDocPrinter *r)
5738 struct spoolss_DocumentInfo1 *info_1;
5739 int snum;
5740 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5741 WERROR werr;
5743 if (!Printer) {
5744 DEBUG(2,("_spoolss_StartDocPrinter: "
5745 "Invalid handle (%s:%u:%u)\n",
5746 OUR_HANDLE(r->in.handle)));
5747 return WERR_BADFID;
5750 if (Printer->jobid) {
5751 DEBUG(2, ("_spoolss_StartDocPrinter: "
5752 "StartDocPrinter called twice! "
5753 "(existing jobid = %d)\n", Printer->jobid));
5754 return WERR_INVALID_HANDLE;
5757 if (r->in.level != 1) {
5758 return WERR_UNKNOWN_LEVEL;
5761 info_1 = r->in.info.info1;
5764 * a nice thing with NT is it doesn't listen to what you tell it.
5765 * when asked to send _only_ RAW datas, it tries to send datas
5766 * in EMF format.
5768 * So I add checks like in NT Server ...
5771 if (info_1->datatype) {
5773 * The v4 driver model used in Windows 8 declares print jobs
5774 * intended to bypass the XPS processing layer by setting
5775 * datatype to "XPS_PASS" instead of "RAW".
5777 if ((strcmp(info_1->datatype, "RAW") != 0)
5778 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5779 *r->out.job_id = 0;
5780 return WERR_INVALID_DATATYPE;
5784 /* get the share number of the printer */
5785 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5786 return WERR_BADFID;
5789 werr = print_job_start(p->session_info,
5790 p->msg_ctx,
5791 p->client_id->name,
5792 snum,
5793 info_1->document_name,
5794 info_1->output_file,
5795 Printer->devmode,
5796 &Printer->jobid);
5798 /* An error occured in print_job_start() so return an appropriate
5799 NT error code. */
5801 if (!W_ERROR_IS_OK(werr)) {
5802 return werr;
5805 Printer->document_started = true;
5806 *r->out.job_id = Printer->jobid;
5808 return WERR_OK;
5811 /****************************************************************
5812 _spoolss_EndDocPrinter
5813 ****************************************************************/
5815 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5816 struct spoolss_EndDocPrinter *r)
5818 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5819 NTSTATUS status;
5820 int snum;
5822 if (!Printer) {
5823 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5824 OUR_HANDLE(r->in.handle)));
5825 return WERR_BADFID;
5828 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5829 return WERR_BADFID;
5832 Printer->document_started = false;
5833 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5834 if (!NT_STATUS_IS_OK(status)) {
5835 DEBUG(2, ("_spoolss_EndDocPrinter: "
5836 "print_job_end failed [%s]\n",
5837 nt_errstr(status)));
5840 Printer->jobid = 0;
5841 return ntstatus_to_werror(status);
5844 /****************************************************************
5845 _spoolss_WritePrinter
5846 ****************************************************************/
5848 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5849 struct spoolss_WritePrinter *r)
5851 ssize_t buffer_written;
5852 int snum;
5853 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5855 if (!Printer) {
5856 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5857 OUR_HANDLE(r->in.handle)));
5858 *r->out.num_written = r->in._data_size;
5859 return WERR_BADFID;
5862 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5863 return WERR_BADFID;
5865 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5866 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5867 snum, Printer->jobid,
5868 (const char *)r->in.data.data,
5869 (size_t)r->in._data_size);
5870 if (buffer_written == (ssize_t)-1) {
5871 *r->out.num_written = 0;
5872 if (errno == ENOSPC)
5873 return WERR_NO_SPOOL_SPACE;
5874 else
5875 return WERR_ACCESS_DENIED;
5878 *r->out.num_written = r->in._data_size;
5880 return WERR_OK;
5883 /********************************************************************
5884 * api_spoolss_getprinter
5885 * called from the spoolss dispatcher
5887 ********************************************************************/
5889 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5890 struct pipes_struct *p)
5892 const struct auth_serversupplied_info *session_info = p->session_info;
5893 int snum;
5894 WERROR errcode = WERR_BADFUNC;
5895 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5897 if (!Printer) {
5898 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5899 OUR_HANDLE(handle)));
5900 return WERR_BADFID;
5903 if (!get_printer_snum(p, handle, &snum, NULL))
5904 return WERR_BADFID;
5906 switch (command) {
5907 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5908 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5909 break;
5910 case SPOOLSS_PRINTER_CONTROL_RESUME:
5911 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5912 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5913 break;
5914 case SPOOLSS_PRINTER_CONTROL_PURGE:
5915 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5916 break;
5917 default:
5918 return WERR_UNKNOWN_LEVEL;
5921 return errcode;
5925 /****************************************************************
5926 _spoolss_AbortPrinter
5927 * From MSDN: "Deletes printer's spool file if printer is configured
5928 * for spooling"
5929 ****************************************************************/
5931 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5932 struct spoolss_AbortPrinter *r)
5934 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5935 int snum;
5936 WERROR errcode = WERR_OK;
5938 if (!Printer) {
5939 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5940 OUR_HANDLE(r->in.handle)));
5941 return WERR_BADFID;
5944 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5945 return WERR_BADFID;
5947 if (!Printer->document_started) {
5948 return WERR_SPL_NO_STARTDOC;
5951 errcode = print_job_delete(p->session_info,
5952 p->msg_ctx,
5953 snum,
5954 Printer->jobid);
5956 return errcode;
5959 /********************************************************************
5960 * called by spoolss_api_setprinter
5961 * when updating a printer description
5962 ********************************************************************/
5964 static WERROR update_printer_sec(struct policy_handle *handle,
5965 struct pipes_struct *p,
5966 struct sec_desc_buf *secdesc_ctr)
5968 struct spoolss_security_descriptor *new_secdesc = NULL;
5969 struct spoolss_security_descriptor *old_secdesc = NULL;
5970 const char *printer;
5971 WERROR result;
5972 int snum;
5973 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5974 struct dcerpc_binding_handle *b;
5976 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5977 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5978 OUR_HANDLE(handle)));
5980 result = WERR_BADFID;
5981 goto done;
5984 if (secdesc_ctr == NULL) {
5985 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5986 result = WERR_INVALID_PARAM;
5987 goto done;
5989 printer = lp_const_servicename(snum);
5991 /* Check the user has permissions to change the security
5992 descriptor. By experimentation with two NT machines, the user
5993 requires Full Access to the printer to change security
5994 information. */
5996 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5997 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5998 result = WERR_ACCESS_DENIED;
5999 goto done;
6002 result = winreg_printer_binding_handle(p->mem_ctx,
6003 get_session_info_system(),
6004 p->msg_ctx,
6005 &b);
6006 if (!W_ERROR_IS_OK(result)) {
6007 goto done;
6010 /* NT seems to like setting the security descriptor even though
6011 nothing may have actually changed. */
6012 result = winreg_get_printer_secdesc(p->mem_ctx, b,
6013 printer,
6014 &old_secdesc);
6015 if (!W_ERROR_IS_OK(result)) {
6016 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6017 result = WERR_BADFID;
6018 goto done;
6021 if (DEBUGLEVEL >= 10) {
6022 struct security_acl *the_acl;
6023 int i;
6025 the_acl = old_secdesc->dacl;
6026 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6027 printer, the_acl->num_aces));
6029 for (i = 0; i < the_acl->num_aces; i++) {
6030 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6031 &the_acl->aces[i].trustee),
6032 the_acl->aces[i].access_mask));
6035 the_acl = secdesc_ctr->sd->dacl;
6037 if (the_acl) {
6038 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6039 printer, the_acl->num_aces));
6041 for (i = 0; i < the_acl->num_aces; i++) {
6042 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6043 &the_acl->aces[i].trustee),
6044 the_acl->aces[i].access_mask));
6046 } else {
6047 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6051 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
6052 if (new_secdesc == NULL) {
6053 result = WERR_NOMEM;
6054 goto done;
6057 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6058 result = WERR_OK;
6059 goto done;
6062 result = winreg_set_printer_secdesc(p->mem_ctx, b,
6063 printer,
6064 new_secdesc);
6066 done:
6067 return result;
6070 /********************************************************************
6071 Canonicalize printer info from a client
6072 ********************************************************************/
6074 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6075 struct spoolss_SetPrinterInfo2 *info2,
6076 int snum)
6078 fstring printername;
6079 const char *p;
6081 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6082 "portname=%s drivername=%s comment=%s location=%s\n",
6083 info2->servername, info2->printername, info2->sharename,
6084 info2->portname, info2->drivername, info2->comment,
6085 info2->location));
6087 /* we force some elements to "correct" values */
6088 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6089 if (info2->servername == NULL) {
6090 return false;
6092 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6093 if (info2->sharename == NULL) {
6094 return false;
6097 /* check to see if we allow printername != sharename */
6098 if (lp_force_printername(snum)) {
6099 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6100 global_myname(), info2->sharename);
6101 } else {
6102 /* make sure printername is in \\server\printername format */
6103 fstrcpy(printername, info2->printername);
6104 p = printername;
6105 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6106 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6107 p++;
6110 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6111 global_myname(), p);
6113 if (info2->printername == NULL) {
6114 return false;
6117 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6118 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6120 return true;
6123 /****************************************************************************
6124 ****************************************************************************/
6126 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6128 char *cmd = lp_addport_cmd();
6129 char *command = NULL;
6130 int ret;
6131 bool is_print_op = false;
6133 if ( !*cmd ) {
6134 return WERR_ACCESS_DENIED;
6137 command = talloc_asprintf(ctx,
6138 "%s \"%s\" \"%s\"", cmd, portname, uri );
6139 if (!command) {
6140 return WERR_NOMEM;
6143 if ( token )
6144 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6146 DEBUG(10,("Running [%s]\n", command));
6148 /********* BEGIN SePrintOperatorPrivilege **********/
6150 if ( is_print_op )
6151 become_root();
6153 ret = smbrun(command, NULL);
6155 if ( is_print_op )
6156 unbecome_root();
6158 /********* END SePrintOperatorPrivilege **********/
6160 DEBUGADD(10,("returned [%d]\n", ret));
6162 TALLOC_FREE(command);
6164 if ( ret != 0 ) {
6165 return WERR_ACCESS_DENIED;
6168 return WERR_OK;
6171 /****************************************************************************
6172 ****************************************************************************/
6174 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6175 struct spoolss_SetPrinterInfo2 *info2,
6176 const char *remote_machine,
6177 struct messaging_context *msg_ctx)
6179 char *cmd = lp_addprinter_cmd();
6180 char **qlines;
6181 char *command = NULL;
6182 int numlines;
6183 int ret;
6184 int fd;
6185 bool is_print_op = false;
6187 if (!remote_machine) {
6188 return false;
6191 command = talloc_asprintf(ctx,
6192 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6193 cmd, info2->printername, info2->sharename,
6194 info2->portname, info2->drivername,
6195 info2->location, info2->comment, remote_machine);
6196 if (!command) {
6197 return false;
6200 if ( token )
6201 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6203 DEBUG(10,("Running [%s]\n", command));
6205 /********* BEGIN SePrintOperatorPrivilege **********/
6207 if ( is_print_op )
6208 become_root();
6210 if ( (ret = smbrun(command, &fd)) == 0 ) {
6211 /* Tell everyone we updated smb.conf. */
6212 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6215 if ( is_print_op )
6216 unbecome_root();
6218 /********* END SePrintOperatorPrivilege **********/
6220 DEBUGADD(10,("returned [%d]\n", ret));
6222 TALLOC_FREE(command);
6224 if ( ret != 0 ) {
6225 if (fd != -1)
6226 close(fd);
6227 return false;
6230 /* reload our services immediately */
6231 become_root();
6232 reload_services(msg_ctx, -1, false);
6233 unbecome_root();
6235 numlines = 0;
6236 /* Get lines and convert them back to dos-codepage */
6237 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6238 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6239 close(fd);
6241 /* Set the portname to what the script says the portname should be. */
6242 /* but don't require anything to be return from the script exit a good error code */
6244 if (numlines) {
6245 /* Set the portname to what the script says the portname should be. */
6246 info2->portname = talloc_strdup(ctx, qlines[0]);
6247 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6250 TALLOC_FREE(qlines);
6251 return true;
6254 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6255 const struct auth_serversupplied_info *session_info,
6256 struct messaging_context *msg_ctx,
6257 int snum,
6258 struct spoolss_SetPrinterInfo2 *printer,
6259 struct spoolss_PrinterInfo2 *old_printer)
6261 bool force_update = (old_printer == NULL);
6262 const char *dnsdomname;
6263 const char *longname;
6264 const char *uncname;
6265 const char *spooling;
6266 DATA_BLOB buffer;
6267 WERROR result = WERR_OK;
6268 struct dcerpc_binding_handle *b;
6270 result = winreg_printer_binding_handle(mem_ctx,
6271 session_info,
6272 msg_ctx,
6273 &b);
6274 if (!W_ERROR_IS_OK(result)) {
6275 return result;
6278 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6279 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6280 winreg_set_printer_dataex(mem_ctx, b,
6281 printer->sharename,
6282 SPOOL_DSSPOOLER_KEY,
6283 SPOOL_REG_DRIVERNAME,
6284 REG_SZ,
6285 buffer.data,
6286 buffer.length);
6288 if (!force_update) {
6289 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6290 printer->drivername));
6292 notify_printer_driver(server_event_context(), msg_ctx,
6293 snum, printer->drivername ?
6294 printer->drivername : "");
6298 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6299 push_reg_sz(mem_ctx, &buffer, printer->comment);
6300 winreg_set_printer_dataex(mem_ctx, b,
6301 printer->sharename,
6302 SPOOL_DSSPOOLER_KEY,
6303 SPOOL_REG_DESCRIPTION,
6304 REG_SZ,
6305 buffer.data,
6306 buffer.length);
6308 if (!force_update) {
6309 notify_printer_comment(server_event_context(), msg_ctx,
6310 snum, printer->comment ?
6311 printer->comment : "");
6315 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6316 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6317 winreg_set_printer_dataex(mem_ctx, b,
6318 printer->sharename,
6319 SPOOL_DSSPOOLER_KEY,
6320 SPOOL_REG_PRINTSHARENAME,
6321 REG_SZ,
6322 buffer.data,
6323 buffer.length);
6325 if (!force_update) {
6326 notify_printer_sharename(server_event_context(),
6327 msg_ctx,
6328 snum, printer->sharename ?
6329 printer->sharename : "");
6333 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6334 const char *p;
6336 p = strrchr(printer->printername, '\\' );
6337 if (p != NULL) {
6338 p++;
6339 } else {
6340 p = printer->printername;
6343 push_reg_sz(mem_ctx, &buffer, p);
6344 winreg_set_printer_dataex(mem_ctx, b,
6345 printer->sharename,
6346 SPOOL_DSSPOOLER_KEY,
6347 SPOOL_REG_PRINTERNAME,
6348 REG_SZ,
6349 buffer.data,
6350 buffer.length);
6352 if (!force_update) {
6353 notify_printer_printername(server_event_context(),
6354 msg_ctx, snum, p ? p : "");
6358 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6359 push_reg_sz(mem_ctx, &buffer, printer->portname);
6360 winreg_set_printer_dataex(mem_ctx, b,
6361 printer->sharename,
6362 SPOOL_DSSPOOLER_KEY,
6363 SPOOL_REG_PORTNAME,
6364 REG_SZ,
6365 buffer.data,
6366 buffer.length);
6368 if (!force_update) {
6369 notify_printer_port(server_event_context(),
6370 msg_ctx, snum, printer->portname ?
6371 printer->portname : "");
6375 if (force_update || !strequal(printer->location, old_printer->location)) {
6376 push_reg_sz(mem_ctx, &buffer, printer->location);
6377 winreg_set_printer_dataex(mem_ctx, b,
6378 printer->sharename,
6379 SPOOL_DSSPOOLER_KEY,
6380 SPOOL_REG_LOCATION,
6381 REG_SZ,
6382 buffer.data,
6383 buffer.length);
6385 if (!force_update) {
6386 notify_printer_location(server_event_context(),
6387 msg_ctx, snum,
6388 printer->location ?
6389 printer->location : "");
6393 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6394 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6395 winreg_set_printer_dataex(mem_ctx, b,
6396 printer->sharename,
6397 SPOOL_DSSPOOLER_KEY,
6398 SPOOL_REG_PRINTSEPARATORFILE,
6399 REG_SZ,
6400 buffer.data,
6401 buffer.length);
6403 if (!force_update) {
6404 notify_printer_sepfile(server_event_context(),
6405 msg_ctx, snum,
6406 printer->sepfile ?
6407 printer->sepfile : "");
6411 if (force_update || printer->starttime != old_printer->starttime) {
6412 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6413 SIVAL(buffer.data, 0, printer->starttime);
6414 winreg_set_printer_dataex(mem_ctx, b,
6415 printer->sharename,
6416 SPOOL_DSSPOOLER_KEY,
6417 SPOOL_REG_PRINTSTARTTIME,
6418 REG_DWORD,
6419 buffer.data,
6420 buffer.length);
6423 if (force_update || printer->untiltime != old_printer->untiltime) {
6424 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6425 SIVAL(buffer.data, 0, printer->untiltime);
6426 winreg_set_printer_dataex(mem_ctx, b,
6427 printer->sharename,
6428 SPOOL_DSSPOOLER_KEY,
6429 SPOOL_REG_PRINTENDTIME,
6430 REG_DWORD,
6431 buffer.data,
6432 buffer.length);
6435 if (force_update || printer->priority != old_printer->priority) {
6436 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6437 SIVAL(buffer.data, 0, printer->priority);
6438 winreg_set_printer_dataex(mem_ctx, b,
6439 printer->sharename,
6440 SPOOL_DSSPOOLER_KEY,
6441 SPOOL_REG_PRIORITY,
6442 REG_DWORD,
6443 buffer.data,
6444 buffer.length);
6447 if (force_update || printer->attributes != old_printer->attributes) {
6448 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6449 SIVAL(buffer.data, 0, (printer->attributes &
6450 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6451 winreg_set_printer_dataex(mem_ctx, b,
6452 printer->sharename,
6453 SPOOL_DSSPOOLER_KEY,
6454 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6455 REG_DWORD,
6456 buffer.data,
6457 buffer.length);
6459 switch (printer->attributes & 0x3) {
6460 case 0:
6461 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6462 break;
6463 case 1:
6464 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6465 break;
6466 case 2:
6467 spooling = SPOOL_REGVAL_PRINTDIRECT;
6468 break;
6469 default:
6470 spooling = "unknown";
6472 push_reg_sz(mem_ctx, &buffer, spooling);
6473 winreg_set_printer_dataex(mem_ctx, b,
6474 printer->sharename,
6475 SPOOL_DSSPOOLER_KEY,
6476 SPOOL_REG_PRINTSPOOLING,
6477 REG_SZ,
6478 buffer.data,
6479 buffer.length);
6482 push_reg_sz(mem_ctx, &buffer, global_myname());
6483 winreg_set_printer_dataex(mem_ctx, b,
6484 printer->sharename,
6485 SPOOL_DSSPOOLER_KEY,
6486 SPOOL_REG_SHORTSERVERNAME,
6487 REG_SZ,
6488 buffer.data,
6489 buffer.length);
6491 dnsdomname = get_mydnsfullname();
6492 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6493 longname = talloc_strdup(mem_ctx, dnsdomname);
6494 } else {
6495 longname = talloc_strdup(mem_ctx, global_myname());
6497 if (longname == NULL) {
6498 result = WERR_NOMEM;
6499 goto done;
6502 push_reg_sz(mem_ctx, &buffer, longname);
6503 winreg_set_printer_dataex(mem_ctx, b,
6504 printer->sharename,
6505 SPOOL_DSSPOOLER_KEY,
6506 SPOOL_REG_SERVERNAME,
6507 REG_SZ,
6508 buffer.data,
6509 buffer.length);
6511 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6512 global_myname(), printer->sharename);
6513 push_reg_sz(mem_ctx, &buffer, uncname);
6514 winreg_set_printer_dataex(mem_ctx, b,
6515 printer->sharename,
6516 SPOOL_DSSPOOLER_KEY,
6517 SPOOL_REG_UNCNAME,
6518 REG_SZ,
6519 buffer.data,
6520 buffer.length);
6522 done:
6523 return result;
6526 /********************************************************************
6527 * Called by spoolss_api_setprinter
6528 * when updating a printer description.
6529 ********************************************************************/
6531 static WERROR update_printer(struct pipes_struct *p,
6532 struct policy_handle *handle,
6533 struct spoolss_SetPrinterInfoCtr *info_ctr,
6534 struct spoolss_DeviceMode *devmode)
6536 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6537 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6538 struct spoolss_PrinterInfo2 *old_printer;
6539 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6540 int snum;
6541 WERROR result = WERR_OK;
6542 TALLOC_CTX *tmp_ctx;
6543 struct dcerpc_binding_handle *b;
6545 DEBUG(8,("update_printer\n"));
6547 tmp_ctx = talloc_new(p->mem_ctx);
6548 if (tmp_ctx == NULL) {
6549 return WERR_NOMEM;
6552 if (!Printer) {
6553 result = WERR_BADFID;
6554 goto done;
6557 if (!get_printer_snum(p, handle, &snum, NULL)) {
6558 result = WERR_BADFID;
6559 goto done;
6562 result = winreg_printer_binding_handle(tmp_ctx,
6563 get_session_info_system(),
6564 p->msg_ctx,
6565 &b);
6566 if (!W_ERROR_IS_OK(result)) {
6567 goto done;
6570 result = winreg_get_printer(tmp_ctx, b,
6571 lp_const_servicename(snum),
6572 &old_printer);
6573 if (!W_ERROR_IS_OK(result)) {
6574 result = WERR_BADFID;
6575 goto done;
6578 /* Do sanity check on the requested changes for Samba */
6579 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6580 result = WERR_INVALID_PARAM;
6581 goto done;
6584 /* FIXME!!! If the driver has changed we really should verify that
6585 it is installed before doing much else --jerry */
6587 /* Check calling user has permission to update printer description */
6588 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6589 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6590 result = WERR_ACCESS_DENIED;
6591 goto done;
6594 /* Call addprinter hook */
6595 /* Check changes to see if this is really needed */
6597 if (*lp_addprinter_cmd() &&
6598 (!strequal(printer->drivername, old_printer->drivername) ||
6599 !strequal(printer->comment, old_printer->comment) ||
6600 !strequal(printer->portname, old_printer->portname) ||
6601 !strequal(printer->location, old_printer->location)) )
6603 /* add_printer_hook() will call reload_services() */
6604 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6605 printer, p->client_id->addr,
6606 p->msg_ctx)) {
6607 result = WERR_ACCESS_DENIED;
6608 goto done;
6612 update_dsspooler(tmp_ctx,
6613 get_session_info_system(),
6614 p->msg_ctx,
6615 snum,
6616 printer,
6617 old_printer);
6619 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6621 if (devmode == NULL) {
6622 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6624 result = winreg_update_printer(tmp_ctx, b,
6625 printer->sharename,
6626 printer_mask,
6627 printer,
6628 devmode,
6629 NULL);
6631 done:
6632 talloc_free(tmp_ctx);
6634 return result;
6637 /****************************************************************************
6638 ****************************************************************************/
6639 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6640 struct policy_handle *handle,
6641 struct spoolss_SetPrinterInfo7 *info7)
6643 #ifdef HAVE_ADS
6644 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6645 WERROR result;
6646 int snum;
6647 struct printer_handle *Printer;
6649 if ( lp_security() != SEC_ADS ) {
6650 return WERR_UNKNOWN_LEVEL;
6653 Printer = find_printer_index_by_hnd(p, handle);
6655 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6657 if (!Printer)
6658 return WERR_BADFID;
6660 if (!get_printer_snum(p, handle, &snum, NULL))
6661 return WERR_BADFID;
6663 result = winreg_get_printer_internal(p->mem_ctx,
6664 get_session_info_system(),
6665 p->msg_ctx,
6666 lp_servicename(snum),
6667 &pinfo2);
6668 if (!W_ERROR_IS_OK(result)) {
6669 return WERR_BADFID;
6672 nt_printer_publish(pinfo2,
6673 get_session_info_system(),
6674 p->msg_ctx,
6675 pinfo2,
6676 info7->action);
6678 TALLOC_FREE(pinfo2);
6679 return WERR_OK;
6680 #else
6681 return WERR_UNKNOWN_LEVEL;
6682 #endif
6685 /********************************************************************
6686 ********************************************************************/
6688 static WERROR update_printer_devmode(struct pipes_struct *p,
6689 struct policy_handle *handle,
6690 struct spoolss_DeviceMode *devmode)
6692 int snum;
6693 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6694 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6696 DEBUG(8,("update_printer_devmode\n"));
6698 if (!Printer) {
6699 return WERR_BADFID;
6702 if (!get_printer_snum(p, handle, &snum, NULL)) {
6703 return WERR_BADFID;
6706 /* Check calling user has permission to update printer description */
6707 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6708 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6709 return WERR_ACCESS_DENIED;
6712 return winreg_update_printer_internal(p->mem_ctx,
6713 get_session_info_system(),
6714 p->msg_ctx,
6715 lp_const_servicename(snum),
6716 info2_mask,
6717 NULL,
6718 devmode,
6719 NULL);
6723 /****************************************************************
6724 _spoolss_SetPrinter
6725 ****************************************************************/
6727 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6728 struct spoolss_SetPrinter *r)
6730 WERROR result;
6732 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6734 if (!Printer) {
6735 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6736 OUR_HANDLE(r->in.handle)));
6737 return WERR_BADFID;
6740 /* check the level */
6741 switch (r->in.info_ctr->level) {
6742 case 0:
6743 return control_printer(r->in.handle, r->in.command, p);
6744 case 2:
6745 result = update_printer(p, r->in.handle,
6746 r->in.info_ctr,
6747 r->in.devmode_ctr->devmode);
6748 if (!W_ERROR_IS_OK(result))
6749 return result;
6750 if (r->in.secdesc_ctr->sd)
6751 result = update_printer_sec(r->in.handle, p,
6752 r->in.secdesc_ctr);
6753 return result;
6754 case 3:
6755 return update_printer_sec(r->in.handle, p,
6756 r->in.secdesc_ctr);
6757 case 7:
6758 return publish_or_unpublish_printer(p, r->in.handle,
6759 r->in.info_ctr->info.info7);
6760 case 8:
6761 return update_printer_devmode(p, r->in.handle,
6762 r->in.devmode_ctr->devmode);
6763 default:
6764 return WERR_UNKNOWN_LEVEL;
6768 /****************************************************************
6769 _spoolss_FindClosePrinterNotify
6770 ****************************************************************/
6772 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6773 struct spoolss_FindClosePrinterNotify *r)
6775 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6777 if (!Printer) {
6778 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6779 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6780 return WERR_BADFID;
6783 if (Printer->notify.cli_chan != NULL &&
6784 Printer->notify.cli_chan->active_connections > 0) {
6785 int snum = -1;
6787 if (Printer->printer_type == SPLHND_PRINTER) {
6788 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6789 return WERR_BADFID;
6793 srv_spoolss_replycloseprinter(snum, Printer);
6796 Printer->notify.flags=0;
6797 Printer->notify.options=0;
6798 Printer->notify.localmachine[0]='\0';
6799 Printer->notify.printerlocal=0;
6800 TALLOC_FREE(Printer->notify.option);
6802 return WERR_OK;
6805 /****************************************************************
6806 _spoolss_AddJob
6807 ****************************************************************/
6809 WERROR _spoolss_AddJob(struct pipes_struct *p,
6810 struct spoolss_AddJob *r)
6812 if (!r->in.buffer && (r->in.offered != 0)) {
6813 return WERR_INVALID_PARAM;
6816 /* this is what a NT server returns for AddJob. AddJob must fail on
6817 * non-local printers */
6819 if (r->in.level != 1) {
6820 return WERR_UNKNOWN_LEVEL;
6823 return WERR_INVALID_PARAM;
6826 /****************************************************************************
6827 fill_job_info1
6828 ****************************************************************************/
6830 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6831 struct spoolss_JobInfo1 *r,
6832 const print_queue_struct *queue,
6833 int position, int snum,
6834 struct spoolss_PrinterInfo2 *pinfo2)
6836 struct tm *t;
6838 t = gmtime(&queue->time);
6840 r->job_id = queue->sysjob;
6842 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6843 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6844 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6845 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6846 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6847 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6848 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6849 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6850 r->data_type = talloc_strdup(mem_ctx, "RAW");
6851 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6852 r->text_status = talloc_strdup(mem_ctx, "");
6853 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6855 r->status = nt_printj_status(queue->status);
6856 r->priority = queue->priority;
6857 r->position = position;
6858 r->total_pages = queue->page_count;
6859 r->pages_printed = 0; /* ??? */
6861 init_systemtime(&r->submitted, t);
6863 return WERR_OK;
6866 /****************************************************************************
6867 fill_job_info2
6868 ****************************************************************************/
6870 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6871 struct spoolss_JobInfo2 *r,
6872 const print_queue_struct *queue,
6873 int position, int snum,
6874 struct spoolss_PrinterInfo2 *pinfo2,
6875 struct spoolss_DeviceMode *devmode)
6877 struct tm *t;
6879 t = gmtime(&queue->time);
6881 r->job_id = queue->sysjob;
6883 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6884 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6885 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6886 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6887 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6888 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6889 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6890 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6891 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6892 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6893 r->data_type = talloc_strdup(mem_ctx, "RAW");
6894 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6895 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6896 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6897 r->parameters = talloc_strdup(mem_ctx, "");
6898 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6899 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6900 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6902 r->devmode = devmode;
6904 r->text_status = talloc_strdup(mem_ctx, "");
6905 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6907 r->secdesc = NULL;
6909 r->status = nt_printj_status(queue->status);
6910 r->priority = queue->priority;
6911 r->position = position;
6912 r->start_time = 0;
6913 r->until_time = 0;
6914 r->total_pages = queue->page_count;
6915 r->size = queue->size;
6916 init_systemtime(&r->submitted, t);
6917 r->time = 0;
6918 r->pages_printed = 0; /* ??? */
6920 return WERR_OK;
6923 /****************************************************************************
6924 fill_job_info3
6925 ****************************************************************************/
6927 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6928 struct spoolss_JobInfo3 *r,
6929 const print_queue_struct *queue,
6930 const print_queue_struct *next_queue,
6931 int position, int snum,
6932 struct spoolss_PrinterInfo2 *pinfo2)
6934 r->job_id = queue->sysjob;
6935 r->next_job_id = 0;
6936 if (next_queue) {
6937 r->next_job_id = next_queue->sysjob;
6939 r->reserved = 0;
6941 return WERR_OK;
6944 /****************************************************************************
6945 Enumjobs at level 1.
6946 ****************************************************************************/
6948 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6949 const print_queue_struct *queue,
6950 uint32_t num_queues, int snum,
6951 struct spoolss_PrinterInfo2 *pinfo2,
6952 union spoolss_JobInfo **info_p,
6953 uint32_t *count)
6955 union spoolss_JobInfo *info;
6956 int i;
6957 WERROR result = WERR_OK;
6959 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6960 W_ERROR_HAVE_NO_MEMORY(info);
6962 *count = num_queues;
6964 for (i=0; i<*count; i++) {
6965 result = fill_job_info1(info,
6966 &info[i].info1,
6967 &queue[i],
6969 snum,
6970 pinfo2);
6971 if (!W_ERROR_IS_OK(result)) {
6972 goto out;
6976 out:
6977 if (!W_ERROR_IS_OK(result)) {
6978 TALLOC_FREE(info);
6979 *count = 0;
6980 return result;
6983 *info_p = info;
6985 return WERR_OK;
6988 /****************************************************************************
6989 Enumjobs at level 2.
6990 ****************************************************************************/
6992 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6993 const print_queue_struct *queue,
6994 uint32_t num_queues, int snum,
6995 struct spoolss_PrinterInfo2 *pinfo2,
6996 union spoolss_JobInfo **info_p,
6997 uint32_t *count)
6999 union spoolss_JobInfo *info;
7000 int i;
7001 WERROR result = WERR_OK;
7003 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7004 W_ERROR_HAVE_NO_MEMORY(info);
7006 *count = num_queues;
7008 for (i=0; i<*count; i++) {
7009 struct spoolss_DeviceMode *devmode;
7011 result = spoolss_create_default_devmode(info,
7012 pinfo2->printername,
7013 &devmode);
7014 if (!W_ERROR_IS_OK(result)) {
7015 DEBUG(3, ("Can't proceed w/o a devmode!"));
7016 goto out;
7019 result = fill_job_info2(info,
7020 &info[i].info2,
7021 &queue[i],
7023 snum,
7024 pinfo2,
7025 devmode);
7026 if (!W_ERROR_IS_OK(result)) {
7027 goto out;
7031 out:
7032 if (!W_ERROR_IS_OK(result)) {
7033 TALLOC_FREE(info);
7034 *count = 0;
7035 return result;
7038 *info_p = info;
7040 return WERR_OK;
7043 /****************************************************************************
7044 Enumjobs at level 3.
7045 ****************************************************************************/
7047 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7048 const print_queue_struct *queue,
7049 uint32_t num_queues, int snum,
7050 struct spoolss_PrinterInfo2 *pinfo2,
7051 union spoolss_JobInfo **info_p,
7052 uint32_t *count)
7054 union spoolss_JobInfo *info;
7055 int i;
7056 WERROR result = WERR_OK;
7058 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7059 W_ERROR_HAVE_NO_MEMORY(info);
7061 *count = num_queues;
7063 for (i=0; i<*count; i++) {
7064 const print_queue_struct *next_queue = NULL;
7066 if (i+1 < *count) {
7067 next_queue = &queue[i+1];
7070 result = fill_job_info3(info,
7071 &info[i].info3,
7072 &queue[i],
7073 next_queue,
7075 snum,
7076 pinfo2);
7077 if (!W_ERROR_IS_OK(result)) {
7078 goto out;
7082 out:
7083 if (!W_ERROR_IS_OK(result)) {
7084 TALLOC_FREE(info);
7085 *count = 0;
7086 return result;
7089 *info_p = info;
7091 return WERR_OK;
7094 /****************************************************************
7095 _spoolss_EnumJobs
7096 ****************************************************************/
7098 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7099 struct spoolss_EnumJobs *r)
7101 WERROR result;
7102 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7103 int snum;
7104 print_status_struct prt_status;
7105 print_queue_struct *queue = NULL;
7106 uint32_t count;
7108 /* that's an [in out] buffer */
7110 if (!r->in.buffer && (r->in.offered != 0)) {
7111 return WERR_INVALID_PARAM;
7114 DEBUG(4,("_spoolss_EnumJobs\n"));
7116 *r->out.needed = 0;
7117 *r->out.count = 0;
7118 *r->out.info = NULL;
7120 /* lookup the printer snum and tdb entry */
7122 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7123 return WERR_BADFID;
7126 result = winreg_get_printer_internal(p->mem_ctx,
7127 get_session_info_system(),
7128 p->msg_ctx,
7129 lp_const_servicename(snum),
7130 &pinfo2);
7131 if (!W_ERROR_IS_OK(result)) {
7132 return result;
7135 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7136 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7137 count, prt_status.status, prt_status.message));
7139 if (count == 0) {
7140 SAFE_FREE(queue);
7141 TALLOC_FREE(pinfo2);
7142 return WERR_OK;
7145 switch (r->in.level) {
7146 case 1:
7147 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7148 pinfo2, r->out.info, r->out.count);
7149 break;
7150 case 2:
7151 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7152 pinfo2, r->out.info, r->out.count);
7153 break;
7154 case 3:
7155 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7156 pinfo2, r->out.info, r->out.count);
7157 break;
7158 default:
7159 result = WERR_UNKNOWN_LEVEL;
7160 break;
7163 SAFE_FREE(queue);
7164 TALLOC_FREE(pinfo2);
7166 if (!W_ERROR_IS_OK(result)) {
7167 return result;
7170 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7171 spoolss_EnumJobs,
7172 *r->out.info, r->in.level,
7173 *r->out.count);
7174 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7175 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7177 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7180 /****************************************************************
7181 _spoolss_ScheduleJob
7182 ****************************************************************/
7184 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7185 struct spoolss_ScheduleJob *r)
7187 return WERR_OK;
7190 /****************************************************************
7191 ****************************************************************/
7193 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7194 struct messaging_context *msg_ctx,
7195 const char *printer_name,
7196 uint32_t job_id,
7197 struct spoolss_SetJobInfo1 *r)
7199 char *old_doc_name;
7201 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7202 return WERR_BADFID;
7205 if (strequal(old_doc_name, r->document_name)) {
7206 return WERR_OK;
7209 if (!print_job_set_name(server_event_context(), msg_ctx,
7210 printer_name, job_id, r->document_name)) {
7211 return WERR_BADFID;
7214 return WERR_OK;
7217 /****************************************************************
7218 _spoolss_SetJob
7219 ****************************************************************/
7221 WERROR _spoolss_SetJob(struct pipes_struct *p,
7222 struct spoolss_SetJob *r)
7224 const struct auth_serversupplied_info *session_info = p->session_info;
7225 int snum;
7226 WERROR errcode = WERR_BADFUNC;
7228 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7229 return WERR_BADFID;
7232 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7233 return WERR_INVALID_PRINTER_NAME;
7236 switch (r->in.command) {
7237 case SPOOLSS_JOB_CONTROL_CANCEL:
7238 case SPOOLSS_JOB_CONTROL_DELETE:
7239 errcode = print_job_delete(session_info, p->msg_ctx,
7240 snum, r->in.job_id);
7241 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7242 errcode = WERR_OK;
7244 break;
7245 case SPOOLSS_JOB_CONTROL_PAUSE:
7246 errcode = print_job_pause(session_info, p->msg_ctx,
7247 snum, r->in.job_id);
7248 break;
7249 case SPOOLSS_JOB_CONTROL_RESTART:
7250 case SPOOLSS_JOB_CONTROL_RESUME:
7251 errcode = print_job_resume(session_info, p->msg_ctx,
7252 snum, r->in.job_id);
7253 break;
7254 case 0:
7255 errcode = WERR_OK;
7256 break;
7257 default:
7258 return WERR_UNKNOWN_LEVEL;
7261 if (!W_ERROR_IS_OK(errcode)) {
7262 return errcode;
7265 if (r->in.ctr == NULL) {
7266 return errcode;
7269 switch (r->in.ctr->level) {
7270 case 1:
7271 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7272 lp_const_servicename(snum),
7273 r->in.job_id,
7274 r->in.ctr->info.info1);
7275 break;
7276 case 2:
7277 case 3:
7278 case 4:
7279 default:
7280 return WERR_UNKNOWN_LEVEL;
7283 return errcode;
7286 /****************************************************************************
7287 Enumerates all printer drivers by level and architecture.
7288 ****************************************************************************/
7290 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7291 const struct auth_serversupplied_info *session_info,
7292 struct messaging_context *msg_ctx,
7293 const char *servername,
7294 const char *architecture,
7295 uint32_t level,
7296 union spoolss_DriverInfo **info_p,
7297 uint32_t *count_p)
7299 int i;
7300 uint32_t version;
7301 struct spoolss_DriverInfo8 *driver;
7302 union spoolss_DriverInfo *info = NULL;
7303 uint32_t count = 0;
7304 WERROR result = WERR_OK;
7305 uint32_t num_drivers;
7306 const char **drivers;
7307 struct dcerpc_binding_handle *b;
7309 *count_p = 0;
7310 *info_p = NULL;
7312 result = winreg_printer_binding_handle(mem_ctx,
7313 session_info,
7314 msg_ctx,
7315 &b);
7316 if (!W_ERROR_IS_OK(result)) {
7317 goto out;
7320 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7321 result = winreg_get_driver_list(mem_ctx, b,
7322 architecture, version,
7323 &num_drivers, &drivers);
7324 if (!W_ERROR_IS_OK(result)) {
7325 goto out;
7327 DEBUG(4, ("we have:[%d] drivers in environment"
7328 " [%s] and version [%d]\n",
7329 num_drivers, architecture, version));
7331 if (num_drivers != 0) {
7332 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7333 union spoolss_DriverInfo,
7334 count + num_drivers);
7335 if (!info) {
7336 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7337 "failed to enlarge driver info buffer!\n"));
7338 result = WERR_NOMEM;
7339 goto out;
7343 for (i = 0; i < num_drivers; i++) {
7344 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7346 result = winreg_get_driver(mem_ctx, b,
7347 architecture, drivers[i],
7348 version, &driver);
7349 if (!W_ERROR_IS_OK(result)) {
7350 goto out;
7353 switch (level) {
7354 case 1:
7355 result = fill_printer_driver_info1(info, &info[count+i].info1,
7356 driver, servername);
7357 break;
7358 case 2:
7359 result = fill_printer_driver_info2(info, &info[count+i].info2,
7360 driver, servername);
7361 break;
7362 case 3:
7363 result = fill_printer_driver_info3(info, &info[count+i].info3,
7364 driver, servername);
7365 break;
7366 case 4:
7367 result = fill_printer_driver_info4(info, &info[count+i].info4,
7368 driver, servername);
7369 break;
7370 case 5:
7371 result = fill_printer_driver_info5(info, &info[count+i].info5,
7372 driver, servername);
7373 break;
7374 case 6:
7375 result = fill_printer_driver_info6(info, &info[count+i].info6,
7376 driver, servername);
7377 break;
7378 case 8:
7379 result = fill_printer_driver_info8(info, &info[count+i].info8,
7380 driver, servername);
7381 break;
7382 default:
7383 result = WERR_UNKNOWN_LEVEL;
7384 break;
7387 TALLOC_FREE(driver);
7389 if (!W_ERROR_IS_OK(result)) {
7390 goto out;
7394 count += num_drivers;
7395 TALLOC_FREE(drivers);
7398 out:
7399 TALLOC_FREE(drivers);
7401 if (!W_ERROR_IS_OK(result)) {
7402 TALLOC_FREE(info);
7403 return result;
7406 *info_p = info;
7407 *count_p = count;
7409 return WERR_OK;
7412 /****************************************************************************
7413 Enumerates all printer drivers by level.
7414 ****************************************************************************/
7416 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7417 const struct auth_serversupplied_info *session_info,
7418 struct messaging_context *msg_ctx,
7419 const char *servername,
7420 const char *architecture,
7421 uint32_t level,
7422 union spoolss_DriverInfo **info_p,
7423 uint32_t *count_p)
7425 uint32_t a,i;
7426 WERROR result = WERR_OK;
7428 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7430 for (a=0; archi_table[a].long_archi != NULL; a++) {
7432 union spoolss_DriverInfo *info = NULL;
7433 uint32_t count = 0;
7435 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7436 session_info,
7437 msg_ctx,
7438 servername,
7439 archi_table[a].long_archi,
7440 level,
7441 &info,
7442 &count);
7443 if (!W_ERROR_IS_OK(result)) {
7444 continue;
7447 for (i=0; i < count; i++) {
7448 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7449 info[i], info_p, count_p);
7453 return result;
7456 return enumprinterdrivers_level_by_architecture(mem_ctx,
7457 session_info,
7458 msg_ctx,
7459 servername,
7460 architecture,
7461 level,
7462 info_p,
7463 count_p);
7466 /****************************************************************
7467 _spoolss_EnumPrinterDrivers
7468 ****************************************************************/
7470 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7471 struct spoolss_EnumPrinterDrivers *r)
7473 const char *cservername;
7474 WERROR result;
7476 /* that's an [in out] buffer */
7478 if (!r->in.buffer && (r->in.offered != 0)) {
7479 return WERR_INVALID_PARAM;
7482 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7484 *r->out.needed = 0;
7485 *r->out.count = 0;
7486 *r->out.info = NULL;
7488 cservername = canon_servername(r->in.server);
7490 if (!is_myname_or_ipaddr(cservername)) {
7491 return WERR_UNKNOWN_PRINTER_DRIVER;
7494 result = enumprinterdrivers_level(p->mem_ctx,
7495 get_session_info_system(),
7496 p->msg_ctx,
7497 cservername,
7498 r->in.environment,
7499 r->in.level,
7500 r->out.info,
7501 r->out.count);
7502 if (!W_ERROR_IS_OK(result)) {
7503 return result;
7506 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7507 spoolss_EnumPrinterDrivers,
7508 *r->out.info, r->in.level,
7509 *r->out.count);
7510 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7511 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7513 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7516 /****************************************************************
7517 _spoolss_EnumForms
7518 ****************************************************************/
7520 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7521 struct spoolss_EnumForms *r)
7523 WERROR result;
7525 *r->out.count = 0;
7526 *r->out.needed = 0;
7527 *r->out.info = NULL;
7529 /* that's an [in out] buffer */
7531 if (!r->in.buffer && (r->in.offered != 0) ) {
7532 return WERR_INVALID_PARAM;
7535 DEBUG(4,("_spoolss_EnumForms\n"));
7536 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7537 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7539 switch (r->in.level) {
7540 case 1:
7541 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7542 get_session_info_system(),
7543 p->msg_ctx,
7544 r->out.count,
7545 r->out.info);
7546 break;
7547 default:
7548 result = WERR_UNKNOWN_LEVEL;
7549 break;
7552 if (!W_ERROR_IS_OK(result)) {
7553 return result;
7556 if (*r->out.count == 0) {
7557 return WERR_NO_MORE_ITEMS;
7560 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7561 spoolss_EnumForms,
7562 *r->out.info, r->in.level,
7563 *r->out.count);
7564 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7565 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7567 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7570 /****************************************************************
7571 _spoolss_GetForm
7572 ****************************************************************/
7574 WERROR _spoolss_GetForm(struct pipes_struct *p,
7575 struct spoolss_GetForm *r)
7577 WERROR result;
7579 /* that's an [in out] buffer */
7581 if (!r->in.buffer && (r->in.offered != 0)) {
7582 return WERR_INVALID_PARAM;
7585 DEBUG(4,("_spoolss_GetForm\n"));
7586 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7587 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7589 switch (r->in.level) {
7590 case 1:
7591 result = winreg_printer_getform1_internal(p->mem_ctx,
7592 get_session_info_system(),
7593 p->msg_ctx,
7594 r->in.form_name,
7595 &r->out.info->info1);
7596 break;
7597 default:
7598 result = WERR_UNKNOWN_LEVEL;
7599 break;
7602 if (!W_ERROR_IS_OK(result)) {
7603 TALLOC_FREE(r->out.info);
7604 return result;
7607 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7608 r->out.info, r->in.level);
7609 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7611 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7614 /****************************************************************************
7615 ****************************************************************************/
7617 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7618 struct spoolss_PortInfo1 *r,
7619 const char *name)
7621 r->port_name = talloc_strdup(mem_ctx, name);
7622 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7624 return WERR_OK;
7627 /****************************************************************************
7628 TODO: This probably needs distinguish between TCP/IP and Local ports
7629 somehow.
7630 ****************************************************************************/
7632 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7633 struct spoolss_PortInfo2 *r,
7634 const char *name)
7636 r->port_name = talloc_strdup(mem_ctx, name);
7637 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7639 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7640 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7642 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7643 W_ERROR_HAVE_NO_MEMORY(r->description);
7645 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7646 r->reserved = 0;
7648 return WERR_OK;
7652 /****************************************************************************
7653 wrapper around the enumer ports command
7654 ****************************************************************************/
7656 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7658 char *cmd = lp_enumports_cmd();
7659 char **qlines = NULL;
7660 char *command = NULL;
7661 int numlines;
7662 int ret;
7663 int fd;
7665 *count = 0;
7666 *lines = NULL;
7668 /* if no hook then just fill in the default port */
7670 if ( !*cmd ) {
7671 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7672 return WERR_NOMEM;
7674 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7675 TALLOC_FREE(qlines);
7676 return WERR_NOMEM;
7678 qlines[1] = NULL;
7679 numlines = 1;
7681 else {
7682 /* we have a valid enumport command */
7684 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7685 if (!command) {
7686 return WERR_NOMEM;
7689 DEBUG(10,("Running [%s]\n", command));
7690 ret = smbrun(command, &fd);
7691 DEBUG(10,("Returned [%d]\n", ret));
7692 TALLOC_FREE(command);
7693 if (ret != 0) {
7694 if (fd != -1) {
7695 close(fd);
7697 return WERR_ACCESS_DENIED;
7700 numlines = 0;
7701 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7702 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7703 close(fd);
7706 *count = numlines;
7707 *lines = qlines;
7709 return WERR_OK;
7712 /****************************************************************************
7713 enumports level 1.
7714 ****************************************************************************/
7716 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7717 union spoolss_PortInfo **info_p,
7718 uint32_t *count)
7720 union spoolss_PortInfo *info = NULL;
7721 int i=0;
7722 WERROR result = WERR_OK;
7723 char **qlines = NULL;
7724 int numlines = 0;
7726 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7727 if (!W_ERROR_IS_OK(result)) {
7728 goto out;
7731 if (numlines) {
7732 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7733 if (!info) {
7734 DEBUG(10,("Returning WERR_NOMEM\n"));
7735 result = WERR_NOMEM;
7736 goto out;
7739 for (i=0; i<numlines; i++) {
7740 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7741 result = fill_port_1(info, &info[i].info1, qlines[i]);
7742 if (!W_ERROR_IS_OK(result)) {
7743 goto out;
7747 TALLOC_FREE(qlines);
7749 out:
7750 if (!W_ERROR_IS_OK(result)) {
7751 TALLOC_FREE(info);
7752 TALLOC_FREE(qlines);
7753 *count = 0;
7754 *info_p = NULL;
7755 return result;
7758 *info_p = info;
7759 *count = numlines;
7761 return WERR_OK;
7764 /****************************************************************************
7765 enumports level 2.
7766 ****************************************************************************/
7768 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7769 union spoolss_PortInfo **info_p,
7770 uint32_t *count)
7772 union spoolss_PortInfo *info = NULL;
7773 int i=0;
7774 WERROR result = WERR_OK;
7775 char **qlines = NULL;
7776 int numlines = 0;
7778 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7779 if (!W_ERROR_IS_OK(result)) {
7780 goto out;
7783 if (numlines) {
7784 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7785 if (!info) {
7786 DEBUG(10,("Returning WERR_NOMEM\n"));
7787 result = WERR_NOMEM;
7788 goto out;
7791 for (i=0; i<numlines; i++) {
7792 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7793 result = fill_port_2(info, &info[i].info2, qlines[i]);
7794 if (!W_ERROR_IS_OK(result)) {
7795 goto out;
7799 TALLOC_FREE(qlines);
7801 out:
7802 if (!W_ERROR_IS_OK(result)) {
7803 TALLOC_FREE(info);
7804 TALLOC_FREE(qlines);
7805 *count = 0;
7806 *info_p = NULL;
7807 return result;
7810 *info_p = info;
7811 *count = numlines;
7813 return WERR_OK;
7816 /****************************************************************
7817 _spoolss_EnumPorts
7818 ****************************************************************/
7820 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7821 struct spoolss_EnumPorts *r)
7823 WERROR result;
7825 /* that's an [in out] buffer */
7827 if (!r->in.buffer && (r->in.offered != 0)) {
7828 return WERR_INVALID_PARAM;
7831 DEBUG(4,("_spoolss_EnumPorts\n"));
7833 *r->out.count = 0;
7834 *r->out.needed = 0;
7835 *r->out.info = NULL;
7837 switch (r->in.level) {
7838 case 1:
7839 result = enumports_level_1(p->mem_ctx, r->out.info,
7840 r->out.count);
7841 break;
7842 case 2:
7843 result = enumports_level_2(p->mem_ctx, r->out.info,
7844 r->out.count);
7845 break;
7846 default:
7847 return WERR_UNKNOWN_LEVEL;
7850 if (!W_ERROR_IS_OK(result)) {
7851 return result;
7854 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7855 spoolss_EnumPorts,
7856 *r->out.info, r->in.level,
7857 *r->out.count);
7858 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7859 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7861 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7864 /****************************************************************************
7865 ****************************************************************************/
7867 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7868 const char *server,
7869 struct spoolss_SetPrinterInfoCtr *info_ctr,
7870 struct spoolss_DeviceMode *devmode,
7871 struct security_descriptor *secdesc,
7872 struct spoolss_UserLevelCtr *user_ctr,
7873 struct policy_handle *handle)
7875 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7876 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7877 int snum;
7878 WERROR err = WERR_OK;
7880 /* samba does not have a concept of local, non-shared printers yet, so
7881 * make sure we always setup sharename - gd */
7882 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7883 (info2->printername != NULL && info2->printername[0] != '\0')) {
7884 DEBUG(5, ("spoolss_addprinterex_level_2: "
7885 "no sharename has been set, setting printername %s as sharename\n",
7886 info2->printername));
7887 info2->sharename = info2->printername;
7890 /* check to see if the printer already exists */
7891 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7892 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7893 info2->sharename));
7894 return WERR_PRINTER_ALREADY_EXISTS;
7897 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7898 if ((snum = print_queue_snum(info2->printername)) != -1) {
7899 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7900 info2->printername));
7901 return WERR_PRINTER_ALREADY_EXISTS;
7905 /* validate printer info struct */
7906 if (!info2->printername || strlen(info2->printername) == 0) {
7907 return WERR_INVALID_PRINTER_NAME;
7909 if (!info2->portname || strlen(info2->portname) == 0) {
7910 return WERR_UNKNOWN_PORT;
7912 if (!info2->drivername || strlen(info2->drivername) == 0) {
7913 return WERR_UNKNOWN_PRINTER_DRIVER;
7915 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7916 return WERR_UNKNOWN_PRINTPROCESSOR;
7919 /* FIXME!!! smbd should check to see if the driver is installed before
7920 trying to add a printer like this --jerry */
7922 if (*lp_addprinter_cmd() ) {
7923 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7924 info2, p->client_id->addr,
7925 p->msg_ctx) ) {
7926 return WERR_ACCESS_DENIED;
7928 } else {
7929 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7930 "smb.conf parameter \"addprinter command\" is defined. This "
7931 "parameter must exist for this call to succeed\n",
7932 info2->sharename ));
7935 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7936 return WERR_ACCESS_DENIED;
7939 /* you must be a printer admin to add a new printer */
7940 if (!print_access_check(p->session_info,
7941 p->msg_ctx,
7942 snum,
7943 PRINTER_ACCESS_ADMINISTER)) {
7944 return WERR_ACCESS_DENIED;
7948 * Do sanity check on the requested changes for Samba.
7951 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7952 return WERR_INVALID_PARAM;
7955 if (devmode == NULL) {
7956 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7959 update_dsspooler(p->mem_ctx,
7960 get_session_info_system(),
7961 p->msg_ctx,
7963 info2,
7964 NULL);
7966 err = winreg_update_printer_internal(p->mem_ctx,
7967 get_session_info_system(),
7968 p->msg_ctx,
7969 info2->sharename,
7970 info2_mask,
7971 info2,
7972 devmode,
7973 secdesc);
7974 if (!W_ERROR_IS_OK(err)) {
7975 return err;
7978 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7979 if (!W_ERROR_IS_OK(err)) {
7980 /* Handle open failed - remove addition. */
7981 ZERO_STRUCTP(handle);
7982 return err;
7985 return WERR_OK;
7988 /****************************************************************
7989 _spoolss_AddPrinterEx
7990 ****************************************************************/
7992 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7993 struct spoolss_AddPrinterEx *r)
7995 switch (r->in.info_ctr->level) {
7996 case 1:
7997 /* we don't handle yet */
7998 /* but I know what to do ... */
7999 return WERR_UNKNOWN_LEVEL;
8000 case 2:
8001 return spoolss_addprinterex_level_2(p, r->in.server,
8002 r->in.info_ctr,
8003 r->in.devmode_ctr->devmode,
8004 r->in.secdesc_ctr->sd,
8005 r->in.userlevel_ctr,
8006 r->out.handle);
8007 default:
8008 return WERR_UNKNOWN_LEVEL;
8012 /****************************************************************
8013 _spoolss_AddPrinter
8014 ****************************************************************/
8016 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8017 struct spoolss_AddPrinter *r)
8019 struct spoolss_AddPrinterEx a;
8020 struct spoolss_UserLevelCtr userlevel_ctr;
8022 ZERO_STRUCT(userlevel_ctr);
8024 userlevel_ctr.level = 1;
8026 a.in.server = r->in.server;
8027 a.in.info_ctr = r->in.info_ctr;
8028 a.in.devmode_ctr = r->in.devmode_ctr;
8029 a.in.secdesc_ctr = r->in.secdesc_ctr;
8030 a.in.userlevel_ctr = &userlevel_ctr;
8031 a.out.handle = r->out.handle;
8033 return _spoolss_AddPrinterEx(p, &a);
8036 /****************************************************************
8037 _spoolss_AddPrinterDriverEx
8038 ****************************************************************/
8040 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8041 struct spoolss_AddPrinterDriverEx *r)
8043 WERROR err = WERR_OK;
8044 const char *driver_name = NULL;
8045 uint32_t version;
8046 const char *fn;
8048 switch (p->opnum) {
8049 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8050 fn = "_spoolss_AddPrinterDriver";
8051 break;
8052 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8053 fn = "_spoolss_AddPrinterDriverEx";
8054 break;
8055 default:
8056 return WERR_INVALID_PARAM;
8060 * we only support the semantics of AddPrinterDriver()
8061 * i.e. only copy files that are newer than existing ones
8064 if (r->in.flags == 0) {
8065 return WERR_INVALID_PARAM;
8068 if (r->in.flags != APD_COPY_NEW_FILES) {
8069 return WERR_ACCESS_DENIED;
8072 /* FIXME */
8073 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8074 /* Clever hack from Martin Zielinski <mz@seh.de>
8075 * to allow downgrade from level 8 (Vista).
8077 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8078 r->in.info_ctr->level));
8079 return WERR_UNKNOWN_LEVEL;
8082 DEBUG(5,("Cleaning driver's information\n"));
8083 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8084 if (!W_ERROR_IS_OK(err))
8085 goto done;
8087 DEBUG(5,("Moving driver to final destination\n"));
8088 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8089 if (!W_ERROR_IS_OK(err)) {
8090 goto done;
8093 err = winreg_add_driver_internal(p->mem_ctx,
8094 get_session_info_system(),
8095 p->msg_ctx,
8096 r->in.info_ctr,
8097 &driver_name,
8098 &version);
8099 if (!W_ERROR_IS_OK(err)) {
8100 goto done;
8104 * I think this is where he DrvUpgradePrinter() hook would be
8105 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8106 * server. Right now, we just need to send ourselves a message
8107 * to update each printer bound to this driver. --jerry
8110 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8111 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8112 fn, driver_name));
8115 done:
8116 return err;
8119 /****************************************************************
8120 _spoolss_AddPrinterDriver
8121 ****************************************************************/
8123 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8124 struct spoolss_AddPrinterDriver *r)
8126 struct spoolss_AddPrinterDriverEx a;
8128 switch (r->in.info_ctr->level) {
8129 case 2:
8130 case 3:
8131 case 4:
8132 case 5:
8133 break;
8134 default:
8135 return WERR_UNKNOWN_LEVEL;
8138 a.in.servername = r->in.servername;
8139 a.in.info_ctr = r->in.info_ctr;
8140 a.in.flags = APD_COPY_NEW_FILES;
8142 return _spoolss_AddPrinterDriverEx(p, &a);
8145 /****************************************************************************
8146 ****************************************************************************/
8148 struct _spoolss_paths {
8149 int type;
8150 const char *share;
8151 const char *dir;
8154 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8156 static const struct _spoolss_paths spoolss_paths[]= {
8157 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8158 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8161 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8162 const char *servername,
8163 const char *environment,
8164 int component,
8165 char **path)
8167 const char *pservername = NULL;
8168 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8169 const char *short_archi;
8171 *path = NULL;
8173 /* environment may be empty */
8174 if (environment && strlen(environment)) {
8175 long_archi = environment;
8178 /* servername may be empty */
8179 if (servername && strlen(servername)) {
8180 pservername = canon_servername(servername);
8182 if (!is_myname_or_ipaddr(pservername)) {
8183 return WERR_INVALID_PARAM;
8187 if (!(short_archi = get_short_archi(long_archi))) {
8188 return WERR_INVALID_ENVIRONMENT;
8191 switch (component) {
8192 case SPOOLSS_PRTPROCS_PATH:
8193 case SPOOLSS_DRIVER_PATH:
8194 if (pservername) {
8195 *path = talloc_asprintf(mem_ctx,
8196 "\\\\%s\\%s\\%s",
8197 pservername,
8198 spoolss_paths[component].share,
8199 short_archi);
8200 } else {
8201 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8202 SPOOLSS_DEFAULT_SERVER_PATH,
8203 spoolss_paths[component].dir,
8204 short_archi);
8206 break;
8207 default:
8208 return WERR_INVALID_PARAM;
8211 if (!*path) {
8212 return WERR_NOMEM;
8215 return WERR_OK;
8218 /****************************************************************************
8219 ****************************************************************************/
8221 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8222 const char *servername,
8223 const char *environment,
8224 struct spoolss_DriverDirectoryInfo1 *r)
8226 WERROR werr;
8227 char *path = NULL;
8229 werr = compose_spoolss_server_path(mem_ctx,
8230 servername,
8231 environment,
8232 SPOOLSS_DRIVER_PATH,
8233 &path);
8234 if (!W_ERROR_IS_OK(werr)) {
8235 return werr;
8238 DEBUG(4,("printer driver directory: [%s]\n", path));
8240 r->directory_name = path;
8242 return WERR_OK;
8245 /****************************************************************
8246 _spoolss_GetPrinterDriverDirectory
8247 ****************************************************************/
8249 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8250 struct spoolss_GetPrinterDriverDirectory *r)
8252 WERROR werror;
8254 /* that's an [in out] buffer */
8256 if (!r->in.buffer && (r->in.offered != 0)) {
8257 return WERR_INVALID_PARAM;
8260 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8261 r->in.level));
8263 *r->out.needed = 0;
8265 /* r->in.level is ignored */
8267 werror = getprinterdriverdir_level_1(p->mem_ctx,
8268 r->in.server,
8269 r->in.environment,
8270 &r->out.info->info1);
8271 if (!W_ERROR_IS_OK(werror)) {
8272 TALLOC_FREE(r->out.info);
8273 return werror;
8276 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8277 r->out.info, r->in.level);
8278 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8280 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8283 /****************************************************************
8284 _spoolss_EnumPrinterData
8285 ****************************************************************/
8287 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8288 struct spoolss_EnumPrinterData *r)
8290 WERROR result;
8291 struct spoolss_EnumPrinterDataEx r2;
8292 uint32_t count;
8293 struct spoolss_PrinterEnumValues *info, *val = NULL;
8294 uint32_t needed;
8296 r2.in.handle = r->in.handle;
8297 r2.in.key_name = "PrinterDriverData";
8298 r2.in.offered = 0;
8299 r2.out.count = &count;
8300 r2.out.info = &info;
8301 r2.out.needed = &needed;
8303 result = _spoolss_EnumPrinterDataEx(p, &r2);
8304 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8305 r2.in.offered = needed;
8306 result = _spoolss_EnumPrinterDataEx(p, &r2);
8308 if (!W_ERROR_IS_OK(result)) {
8309 return result;
8313 * The NT machine wants to know the biggest size of value and data
8315 * cf: MSDN EnumPrinterData remark section
8318 if (!r->in.value_offered && !r->in.data_offered) {
8319 uint32_t biggest_valuesize = 0;
8320 uint32_t biggest_datasize = 0;
8321 int i, name_length;
8323 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8325 for (i=0; i<count; i++) {
8327 name_length = strlen(info[i].value_name);
8328 if (strlen(info[i].value_name) > biggest_valuesize) {
8329 biggest_valuesize = name_length;
8332 if (info[i].data_length > biggest_datasize) {
8333 biggest_datasize = info[i].data_length;
8336 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8337 biggest_datasize));
8340 /* the value is an UNICODE string but real_value_size is the length
8341 in bytes including the trailing 0 */
8343 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8344 *r->out.data_needed = biggest_datasize;
8346 DEBUG(6,("final values: [%d], [%d]\n",
8347 *r->out.value_needed, *r->out.data_needed));
8349 return WERR_OK;
8352 if (r->in.enum_index < count) {
8353 val = &info[r->in.enum_index];
8356 if (val == NULL) {
8357 /* out_value should default to "" or else NT4 has
8358 problems unmarshalling the response */
8360 if (r->in.value_offered) {
8361 *r->out.value_needed = 1;
8362 r->out.value_name = talloc_strdup(r, "");
8363 if (!r->out.value_name) {
8364 return WERR_NOMEM;
8366 } else {
8367 r->out.value_name = NULL;
8368 *r->out.value_needed = 0;
8371 /* the data is counted in bytes */
8373 *r->out.data_needed = r->in.data_offered;
8375 result = WERR_NO_MORE_ITEMS;
8376 } else {
8378 * the value is:
8379 * - counted in bytes in the request
8380 * - counted in UNICODE chars in the max reply
8381 * - counted in bytes in the real size
8383 * take a pause *before* coding not *during* coding
8386 /* name */
8387 if (r->in.value_offered) {
8388 r->out.value_name = talloc_strdup(r, val->value_name);
8389 if (!r->out.value_name) {
8390 return WERR_NOMEM;
8392 *r->out.value_needed = val->value_name_len;
8393 } else {
8394 r->out.value_name = NULL;
8395 *r->out.value_needed = 0;
8398 /* type */
8400 *r->out.type = val->type;
8402 /* data - counted in bytes */
8405 * See the section "Dynamically Typed Query Parameters"
8406 * in MS-RPRN.
8409 if (r->out.data && val->data && val->data->data &&
8410 val->data_length && r->in.data_offered) {
8411 memcpy(r->out.data, val->data->data,
8412 MIN(val->data_length,r->in.data_offered));
8415 *r->out.data_needed = val->data_length;
8417 result = WERR_OK;
8420 return result;
8423 /****************************************************************
8424 _spoolss_SetPrinterData
8425 ****************************************************************/
8427 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8428 struct spoolss_SetPrinterData *r)
8430 struct spoolss_SetPrinterDataEx r2;
8432 r2.in.handle = r->in.handle;
8433 r2.in.key_name = "PrinterDriverData";
8434 r2.in.value_name = r->in.value_name;
8435 r2.in.type = r->in.type;
8436 r2.in.data = r->in.data;
8437 r2.in.offered = r->in.offered;
8439 return _spoolss_SetPrinterDataEx(p, &r2);
8442 /****************************************************************
8443 _spoolss_ResetPrinter
8444 ****************************************************************/
8446 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8447 struct spoolss_ResetPrinter *r)
8449 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8450 int snum;
8452 DEBUG(5,("_spoolss_ResetPrinter\n"));
8455 * All we do is to check to see if the handle and queue is valid.
8456 * This call really doesn't mean anything to us because we only
8457 * support RAW printing. --jerry
8460 if (!Printer) {
8461 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8462 OUR_HANDLE(r->in.handle)));
8463 return WERR_BADFID;
8466 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8467 return WERR_BADFID;
8470 /* blindly return success */
8471 return WERR_OK;
8474 /****************************************************************
8475 _spoolss_DeletePrinterData
8476 ****************************************************************/
8478 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8479 struct spoolss_DeletePrinterData *r)
8481 struct spoolss_DeletePrinterDataEx r2;
8483 r2.in.handle = r->in.handle;
8484 r2.in.key_name = "PrinterDriverData";
8485 r2.in.value_name = r->in.value_name;
8487 return _spoolss_DeletePrinterDataEx(p, &r2);
8490 /****************************************************************
8491 _spoolss_AddForm
8492 ****************************************************************/
8494 WERROR _spoolss_AddForm(struct pipes_struct *p,
8495 struct spoolss_AddForm *r)
8497 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8498 int snum = -1;
8499 WERROR status = WERR_OK;
8500 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8501 struct dcerpc_binding_handle *b;
8503 DEBUG(5,("_spoolss_AddForm\n"));
8505 if (!Printer) {
8506 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8507 OUR_HANDLE(r->in.handle)));
8508 return WERR_BADFID;
8511 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8512 and not a printer admin, then fail */
8514 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8515 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8516 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8517 p->session_info->info3->base.domain.string,
8518 NULL,
8519 p->session_info->security_token,
8520 lp_printer_admin(snum))) {
8521 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8522 return WERR_ACCESS_DENIED;
8525 switch (form->flags) {
8526 case SPOOLSS_FORM_USER:
8527 case SPOOLSS_FORM_BUILTIN:
8528 case SPOOLSS_FORM_PRINTER:
8529 break;
8530 default:
8531 return WERR_INVALID_PARAM;
8534 status = winreg_printer_binding_handle(p->mem_ctx,
8535 get_session_info_system(),
8536 p->msg_ctx,
8537 &b);
8538 if (!W_ERROR_IS_OK(status)) {
8539 return status;
8542 status = winreg_printer_addform1(p->mem_ctx, b,
8543 form);
8544 if (!W_ERROR_IS_OK(status)) {
8545 return status;
8549 * ChangeID must always be set if this is a printer
8551 if (Printer->printer_type == SPLHND_PRINTER) {
8552 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8553 return WERR_BADFID;
8556 status = winreg_printer_update_changeid(p->mem_ctx, b,
8557 lp_const_servicename(snum));
8558 if (!W_ERROR_IS_OK(status)) {
8559 return status;
8563 return status;
8566 /****************************************************************
8567 _spoolss_DeleteForm
8568 ****************************************************************/
8570 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8571 struct spoolss_DeleteForm *r)
8573 const char *form_name = r->in.form_name;
8574 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8575 int snum = -1;
8576 WERROR status = WERR_OK;
8577 struct dcerpc_binding_handle *b;
8579 DEBUG(5,("_spoolss_DeleteForm\n"));
8581 if (!Printer) {
8582 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8583 OUR_HANDLE(r->in.handle)));
8584 return WERR_BADFID;
8587 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8588 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8589 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8590 p->session_info->info3->base.domain.string,
8591 NULL,
8592 p->session_info->security_token,
8593 lp_printer_admin(snum))) {
8594 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8595 return WERR_ACCESS_DENIED;
8598 status = winreg_printer_binding_handle(p->mem_ctx,
8599 get_session_info_system(),
8600 p->msg_ctx,
8601 &b);
8602 if (!W_ERROR_IS_OK(status)) {
8603 return status;
8606 status = winreg_printer_deleteform1(p->mem_ctx, b,
8607 form_name);
8608 if (!W_ERROR_IS_OK(status)) {
8609 return status;
8613 * ChangeID must always be set if this is a printer
8615 if (Printer->printer_type == SPLHND_PRINTER) {
8616 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8617 return WERR_BADFID;
8620 status = winreg_printer_update_changeid(p->mem_ctx, b,
8621 lp_const_servicename(snum));
8622 if (!W_ERROR_IS_OK(status)) {
8623 return status;
8627 return status;
8630 /****************************************************************
8631 _spoolss_SetForm
8632 ****************************************************************/
8634 WERROR _spoolss_SetForm(struct pipes_struct *p,
8635 struct spoolss_SetForm *r)
8637 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8638 const char *form_name = r->in.form_name;
8639 int snum = -1;
8640 WERROR status = WERR_OK;
8641 struct dcerpc_binding_handle *b;
8643 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8645 DEBUG(5,("_spoolss_SetForm\n"));
8647 if (!Printer) {
8648 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8649 OUR_HANDLE(r->in.handle)));
8650 return WERR_BADFID;
8653 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8654 and not a printer admin, then fail */
8656 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8657 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8658 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8659 p->session_info->info3->base.domain.string,
8660 NULL,
8661 p->session_info->security_token,
8662 lp_printer_admin(snum))) {
8663 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8664 return WERR_ACCESS_DENIED;
8667 status = winreg_printer_binding_handle(p->mem_ctx,
8668 get_session_info_system(),
8669 p->msg_ctx,
8670 &b);
8671 if (!W_ERROR_IS_OK(status)) {
8672 return status;
8675 status = winreg_printer_setform1(p->mem_ctx, b,
8676 form_name,
8677 form);
8678 if (!W_ERROR_IS_OK(status)) {
8679 return status;
8683 * ChangeID must always be set if this is a printer
8685 if (Printer->printer_type == SPLHND_PRINTER) {
8686 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8687 return WERR_BADFID;
8690 status = winreg_printer_update_changeid(p->mem_ctx, b,
8691 lp_const_servicename(snum));
8692 if (!W_ERROR_IS_OK(status)) {
8693 return status;
8697 return status;
8700 /****************************************************************************
8701 fill_print_processor1
8702 ****************************************************************************/
8704 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8705 struct spoolss_PrintProcessorInfo1 *r,
8706 const char *print_processor_name)
8708 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8709 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8711 return WERR_OK;
8714 /****************************************************************************
8715 enumprintprocessors level 1.
8716 ****************************************************************************/
8718 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8719 union spoolss_PrintProcessorInfo **info_p,
8720 uint32_t *count)
8722 union spoolss_PrintProcessorInfo *info;
8723 WERROR result;
8725 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8726 W_ERROR_HAVE_NO_MEMORY(info);
8728 *count = 1;
8730 result = fill_print_processor1(info, &info[0].info1, "winprint");
8731 if (!W_ERROR_IS_OK(result)) {
8732 goto out;
8735 out:
8736 if (!W_ERROR_IS_OK(result)) {
8737 TALLOC_FREE(info);
8738 *count = 0;
8739 return result;
8742 *info_p = info;
8744 return WERR_OK;
8747 /****************************************************************
8748 _spoolss_EnumPrintProcessors
8749 ****************************************************************/
8751 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8752 struct spoolss_EnumPrintProcessors *r)
8754 WERROR result;
8756 /* that's an [in out] buffer */
8758 if (!r->in.buffer && (r->in.offered != 0)) {
8759 return WERR_INVALID_PARAM;
8762 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8765 * Enumerate the print processors ...
8767 * Just reply with "winprint", to keep NT happy
8768 * and I can use my nice printer checker.
8771 *r->out.count = 0;
8772 *r->out.needed = 0;
8773 *r->out.info = NULL;
8775 if (!get_short_archi(r->in.environment)) {
8776 return WERR_INVALID_ENVIRONMENT;
8779 switch (r->in.level) {
8780 case 1:
8781 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8782 r->out.count);
8783 break;
8784 default:
8785 return WERR_UNKNOWN_LEVEL;
8788 if (!W_ERROR_IS_OK(result)) {
8789 return result;
8792 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8793 spoolss_EnumPrintProcessors,
8794 *r->out.info, r->in.level,
8795 *r->out.count);
8796 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8797 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8799 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8802 /****************************************************************************
8803 fill_printprocdatatype1
8804 ****************************************************************************/
8806 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8807 struct spoolss_PrintProcDataTypesInfo1 *r,
8808 const char *name_array)
8810 r->name_array = talloc_strdup(mem_ctx, name_array);
8811 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8813 return WERR_OK;
8816 /****************************************************************************
8817 enumprintprocdatatypes level 1.
8818 ****************************************************************************/
8820 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8821 union spoolss_PrintProcDataTypesInfo **info_p,
8822 uint32_t *count)
8824 WERROR result;
8825 union spoolss_PrintProcDataTypesInfo *info;
8827 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8828 W_ERROR_HAVE_NO_MEMORY(info);
8830 *count = 1;
8832 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8833 if (!W_ERROR_IS_OK(result)) {
8834 goto out;
8837 out:
8838 if (!W_ERROR_IS_OK(result)) {
8839 TALLOC_FREE(info);
8840 *count = 0;
8841 return result;
8844 *info_p = info;
8846 return WERR_OK;
8849 /****************************************************************
8850 _spoolss_EnumPrintProcDataTypes
8851 ****************************************************************/
8853 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8854 struct spoolss_EnumPrintProcDataTypes *r)
8856 WERROR result;
8858 /* that's an [in out] buffer */
8860 if (!r->in.buffer && (r->in.offered != 0)) {
8861 return WERR_INVALID_PARAM;
8864 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8866 *r->out.count = 0;
8867 *r->out.needed = 0;
8868 *r->out.info = NULL;
8870 if (r->in.print_processor_name == NULL ||
8871 !strequal(r->in.print_processor_name, "winprint")) {
8872 return WERR_UNKNOWN_PRINTPROCESSOR;
8875 switch (r->in.level) {
8876 case 1:
8877 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8878 r->out.count);
8879 break;
8880 default:
8881 return WERR_UNKNOWN_LEVEL;
8884 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8885 spoolss_EnumPrintProcDataTypes,
8886 *r->out.info, r->in.level,
8887 *r->out.count);
8888 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8889 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8891 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8894 /****************************************************************************
8895 fill_monitor_1
8896 ****************************************************************************/
8898 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8899 struct spoolss_MonitorInfo1 *r,
8900 const char *monitor_name)
8902 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8903 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8905 return WERR_OK;
8908 /****************************************************************************
8909 fill_monitor_2
8910 ****************************************************************************/
8912 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8913 struct spoolss_MonitorInfo2 *r,
8914 const char *monitor_name,
8915 const char *environment,
8916 const char *dll_name)
8918 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8919 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8920 r->environment = talloc_strdup(mem_ctx, environment);
8921 W_ERROR_HAVE_NO_MEMORY(r->environment);
8922 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8923 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8925 return WERR_OK;
8928 /****************************************************************************
8929 enumprintmonitors level 1.
8930 ****************************************************************************/
8932 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8933 union spoolss_MonitorInfo **info_p,
8934 uint32_t *count)
8936 union spoolss_MonitorInfo *info;
8937 WERROR result = WERR_OK;
8939 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8940 W_ERROR_HAVE_NO_MEMORY(info);
8942 *count = 2;
8944 result = fill_monitor_1(info, &info[0].info1,
8945 SPL_LOCAL_PORT);
8946 if (!W_ERROR_IS_OK(result)) {
8947 goto out;
8950 result = fill_monitor_1(info, &info[1].info1,
8951 SPL_TCPIP_PORT);
8952 if (!W_ERROR_IS_OK(result)) {
8953 goto out;
8956 out:
8957 if (!W_ERROR_IS_OK(result)) {
8958 TALLOC_FREE(info);
8959 *count = 0;
8960 return result;
8963 *info_p = info;
8965 return WERR_OK;
8968 /****************************************************************************
8969 enumprintmonitors level 2.
8970 ****************************************************************************/
8972 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8973 union spoolss_MonitorInfo **info_p,
8974 uint32_t *count)
8976 union spoolss_MonitorInfo *info;
8977 WERROR result = WERR_OK;
8979 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8980 W_ERROR_HAVE_NO_MEMORY(info);
8982 *count = 2;
8984 result = fill_monitor_2(info, &info[0].info2,
8985 SPL_LOCAL_PORT,
8986 "Windows NT X86", /* FIXME */
8987 "localmon.dll");
8988 if (!W_ERROR_IS_OK(result)) {
8989 goto out;
8992 result = fill_monitor_2(info, &info[1].info2,
8993 SPL_TCPIP_PORT,
8994 "Windows NT X86", /* FIXME */
8995 "tcpmon.dll");
8996 if (!W_ERROR_IS_OK(result)) {
8997 goto out;
9000 out:
9001 if (!W_ERROR_IS_OK(result)) {
9002 TALLOC_FREE(info);
9003 *count = 0;
9004 return result;
9007 *info_p = info;
9009 return WERR_OK;
9012 /****************************************************************
9013 _spoolss_EnumMonitors
9014 ****************************************************************/
9016 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9017 struct spoolss_EnumMonitors *r)
9019 WERROR result;
9021 /* that's an [in out] buffer */
9023 if (!r->in.buffer && (r->in.offered != 0)) {
9024 return WERR_INVALID_PARAM;
9027 DEBUG(5,("_spoolss_EnumMonitors\n"));
9030 * Enumerate the print monitors ...
9032 * Just reply with "Local Port", to keep NT happy
9033 * and I can use my nice printer checker.
9036 *r->out.count = 0;
9037 *r->out.needed = 0;
9038 *r->out.info = NULL;
9040 switch (r->in.level) {
9041 case 1:
9042 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9043 r->out.count);
9044 break;
9045 case 2:
9046 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9047 r->out.count);
9048 break;
9049 default:
9050 return WERR_UNKNOWN_LEVEL;
9053 if (!W_ERROR_IS_OK(result)) {
9054 return result;
9057 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9058 spoolss_EnumMonitors,
9059 *r->out.info, r->in.level,
9060 *r->out.count);
9061 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9062 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9064 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9067 /****************************************************************************
9068 ****************************************************************************/
9070 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9071 const print_queue_struct *queue,
9072 int count, int snum,
9073 struct spoolss_PrinterInfo2 *pinfo2,
9074 uint32_t jobid,
9075 struct spoolss_JobInfo1 *r)
9077 int i = 0;
9078 bool found = false;
9080 for (i=0; i<count; i++) {
9081 if (queue[i].sysjob == (int)jobid) {
9082 found = true;
9083 break;
9087 if (found == false) {
9088 /* NT treats not found as bad param... yet another bad choice */
9089 return WERR_INVALID_PARAM;
9092 return fill_job_info1(mem_ctx,
9094 &queue[i],
9096 snum,
9097 pinfo2);
9100 /****************************************************************************
9101 ****************************************************************************/
9103 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9104 const print_queue_struct *queue,
9105 int count, int snum,
9106 struct spoolss_PrinterInfo2 *pinfo2,
9107 uint32_t jobid,
9108 struct spoolss_JobInfo2 *r)
9110 int i = 0;
9111 bool found = false;
9112 struct spoolss_DeviceMode *devmode;
9113 WERROR result;
9115 for (i=0; i<count; i++) {
9116 if (queue[i].sysjob == (int)jobid) {
9117 found = true;
9118 break;
9122 if (found == false) {
9123 /* NT treats not found as bad param... yet another bad
9124 choice */
9125 return WERR_INVALID_PARAM;
9129 * if the print job does not have a DEVMODE associated with it,
9130 * just use the one for the printer. A NULL devicemode is not
9131 * a failure condition
9134 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9135 if (!devmode) {
9136 result = spoolss_create_default_devmode(mem_ctx,
9137 pinfo2->printername,
9138 &devmode);
9139 if (!W_ERROR_IS_OK(result)) {
9140 DEBUG(3, ("Can't proceed w/o a devmode!"));
9141 return result;
9145 return fill_job_info2(mem_ctx,
9147 &queue[i],
9149 snum,
9150 pinfo2,
9151 devmode);
9154 /****************************************************************
9155 _spoolss_GetJob
9156 ****************************************************************/
9158 WERROR _spoolss_GetJob(struct pipes_struct *p,
9159 struct spoolss_GetJob *r)
9161 WERROR result = WERR_OK;
9162 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9163 int snum;
9164 int count;
9165 print_queue_struct *queue = NULL;
9166 print_status_struct prt_status;
9168 /* that's an [in out] buffer */
9170 if (!r->in.buffer && (r->in.offered != 0)) {
9171 return WERR_INVALID_PARAM;
9174 DEBUG(5,("_spoolss_GetJob\n"));
9176 *r->out.needed = 0;
9178 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9179 return WERR_BADFID;
9182 result = winreg_get_printer_internal(p->mem_ctx,
9183 get_session_info_system(),
9184 p->msg_ctx,
9185 lp_const_servicename(snum),
9186 &pinfo2);
9187 if (!W_ERROR_IS_OK(result)) {
9188 return result;
9191 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9193 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9194 count, prt_status.status, prt_status.message));
9196 switch (r->in.level) {
9197 case 1:
9198 result = getjob_level_1(p->mem_ctx,
9199 queue, count, snum, pinfo2,
9200 r->in.job_id, &r->out.info->info1);
9201 break;
9202 case 2:
9203 result = getjob_level_2(p->mem_ctx,
9204 queue, count, snum, pinfo2,
9205 r->in.job_id, &r->out.info->info2);
9206 break;
9207 default:
9208 result = WERR_UNKNOWN_LEVEL;
9209 break;
9212 SAFE_FREE(queue);
9213 TALLOC_FREE(pinfo2);
9215 if (!W_ERROR_IS_OK(result)) {
9216 TALLOC_FREE(r->out.info);
9217 return result;
9220 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9221 r->in.level);
9222 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9224 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9227 /****************************************************************
9228 _spoolss_GetPrinterDataEx
9229 ****************************************************************/
9231 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9232 struct spoolss_GetPrinterDataEx *r)
9235 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9236 const char *printer;
9237 int snum = 0;
9238 WERROR result = WERR_OK;
9239 DATA_BLOB blob;
9240 enum winreg_Type val_type = REG_NONE;
9241 uint8_t *val_data = NULL;
9242 uint32_t val_size = 0;
9243 struct dcerpc_binding_handle *b;
9245 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9247 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9248 r->in.key_name, r->in.value_name));
9250 /* in case of problem, return some default values */
9252 *r->out.needed = 0;
9253 *r->out.type = REG_NONE;
9255 if (!Printer) {
9256 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9257 OUR_HANDLE(r->in.handle)));
9258 result = WERR_BADFID;
9259 goto done;
9262 /* Is the handle to a printer or to the server? */
9264 if (Printer->printer_type == SPLHND_SERVER) {
9266 union spoolss_PrinterData data;
9268 result = getprinterdata_printer_server(p->mem_ctx,
9269 r->in.value_name,
9270 r->out.type,
9271 &data);
9272 if (!W_ERROR_IS_OK(result)) {
9273 return result;
9276 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9277 *r->out.type, &data);
9278 if (!W_ERROR_IS_OK(result)) {
9279 return result;
9282 *r->out.needed = blob.length;
9284 if (r->in.offered >= *r->out.needed) {
9285 memcpy(r->out.data, blob.data, blob.length);
9288 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9291 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9292 return WERR_BADFID;
9294 printer = lp_const_servicename(snum);
9296 /* check to see if the keyname is valid */
9297 if (!strlen(r->in.key_name)) {
9298 return WERR_INVALID_PARAM;
9301 result = winreg_printer_binding_handle(p->mem_ctx,
9302 get_session_info_system(),
9303 p->msg_ctx,
9304 &b);
9305 if (!W_ERROR_IS_OK(result)) {
9306 return result;
9309 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9310 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9311 strequal(r->in.value_name, "ChangeId")) {
9312 *r->out.type = REG_DWORD;
9313 *r->out.needed = 4;
9314 if (r->in.offered >= *r->out.needed) {
9315 uint32_t changeid = 0;
9317 result = winreg_printer_get_changeid(p->mem_ctx, b,
9318 printer,
9319 &changeid);
9320 if (!W_ERROR_IS_OK(result)) {
9321 return result;
9324 SIVAL(r->out.data, 0, changeid);
9325 result = WERR_OK;
9327 goto done;
9330 result = winreg_get_printer_dataex(p->mem_ctx, b,
9331 printer,
9332 r->in.key_name,
9333 r->in.value_name,
9334 &val_type,
9335 &val_data,
9336 &val_size);
9337 if (!W_ERROR_IS_OK(result)) {
9338 return result;
9341 *r->out.needed = val_size;
9342 *r->out.type = val_type;
9344 if (r->in.offered >= *r->out.needed) {
9345 memcpy(r->out.data, val_data, val_size);
9348 done:
9349 /* retain type when returning WERR_MORE_DATA */
9350 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9352 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9355 /****************************************************************
9356 _spoolss_SetPrinterDataEx
9357 ****************************************************************/
9359 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9360 struct spoolss_SetPrinterDataEx *r)
9362 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9363 int snum = 0;
9364 WERROR result = WERR_OK;
9365 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9366 char *oid_string;
9367 struct dcerpc_binding_handle *b;
9369 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9371 /* From MSDN documentation of SetPrinterDataEx: pass request to
9372 SetPrinterData if key is "PrinterDriverData" */
9374 if (!Printer) {
9375 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9376 OUR_HANDLE(r->in.handle)));
9377 return WERR_BADFID;
9380 if (Printer->printer_type == SPLHND_SERVER) {
9381 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9382 "Not implemented for server handles yet\n"));
9383 return WERR_INVALID_PARAM;
9386 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9387 return WERR_BADFID;
9391 * Access check : NT returns "access denied" if you make a
9392 * SetPrinterData call without the necessary privildge.
9393 * we were originally returning OK if nothing changed
9394 * which made Win2k issue **a lot** of SetPrinterData
9395 * when connecting to a printer --jerry
9398 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9399 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9400 "change denied by handle access permissions\n"));
9401 return WERR_ACCESS_DENIED;
9404 result = winreg_printer_binding_handle(p->mem_ctx,
9405 get_session_info_system(),
9406 p->msg_ctx,
9407 &b);
9408 if (!W_ERROR_IS_OK(result)) {
9409 return result;
9412 result = winreg_get_printer(Printer, b,
9413 lp_servicename(snum),
9414 &pinfo2);
9415 if (!W_ERROR_IS_OK(result)) {
9416 return result;
9419 /* check for OID in valuename */
9421 oid_string = strchr(r->in.value_name, ',');
9422 if (oid_string) {
9423 *oid_string = '\0';
9424 oid_string++;
9427 /* save the registry data */
9429 result = winreg_set_printer_dataex(p->mem_ctx, b,
9430 pinfo2->sharename,
9431 r->in.key_name,
9432 r->in.value_name,
9433 r->in.type,
9434 r->in.data,
9435 r->in.offered);
9437 if (W_ERROR_IS_OK(result)) {
9438 /* save the OID if one was specified */
9439 if (oid_string) {
9440 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9441 r->in.key_name, SPOOL_OID_KEY);
9442 if (!str) {
9443 result = WERR_NOMEM;
9444 goto done;
9448 * I'm not checking the status here on purpose. Don't know
9449 * if this is right, but I'm returning the status from the
9450 * previous set_printer_dataex() call. I have no idea if
9451 * this is right. --jerry
9453 winreg_set_printer_dataex(p->mem_ctx, b,
9454 pinfo2->sharename,
9455 str,
9456 r->in.value_name,
9457 REG_SZ,
9458 (uint8_t *) oid_string,
9459 strlen(oid_string) + 1);
9462 result = winreg_printer_update_changeid(p->mem_ctx, b,
9463 lp_const_servicename(snum));
9467 done:
9468 talloc_free(pinfo2);
9469 return result;
9472 /****************************************************************
9473 _spoolss_DeletePrinterDataEx
9474 ****************************************************************/
9476 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9477 struct spoolss_DeletePrinterDataEx *r)
9479 const char *printer;
9480 int snum=0;
9481 WERROR status = WERR_OK;
9482 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9484 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9486 if (!Printer) {
9487 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9488 "Invalid handle (%s:%u:%u).\n",
9489 OUR_HANDLE(r->in.handle)));
9490 return WERR_BADFID;
9493 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9494 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9495 "printer properties change denied by handle\n"));
9496 return WERR_ACCESS_DENIED;
9499 if (!r->in.value_name || !r->in.key_name) {
9500 return WERR_NOMEM;
9503 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9504 return WERR_BADFID;
9506 printer = lp_const_servicename(snum);
9508 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9509 get_session_info_system(),
9510 p->msg_ctx,
9511 printer,
9512 r->in.key_name,
9513 r->in.value_name);
9514 if (W_ERROR_IS_OK(status)) {
9515 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9516 get_session_info_system(),
9517 p->msg_ctx,
9518 printer);
9521 return status;
9524 /****************************************************************
9525 _spoolss_EnumPrinterKey
9526 ****************************************************************/
9528 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9529 struct spoolss_EnumPrinterKey *r)
9531 uint32_t num_keys;
9532 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9533 int snum = 0;
9534 WERROR result = WERR_BADFILE;
9535 const char **array = NULL;
9536 DATA_BLOB blob;
9538 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9540 if (!Printer) {
9541 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9542 OUR_HANDLE(r->in.handle)));
9543 return WERR_BADFID;
9546 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9547 return WERR_BADFID;
9550 result = winreg_enum_printer_key_internal(p->mem_ctx,
9551 get_session_info_system(),
9552 p->msg_ctx,
9553 lp_const_servicename(snum),
9554 r->in.key_name,
9555 &num_keys,
9556 &array);
9557 if (!W_ERROR_IS_OK(result)) {
9558 goto done;
9561 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9562 result = WERR_NOMEM;
9563 goto done;
9566 *r->out._ndr_size = r->in.offered / 2;
9567 *r->out.needed = blob.length;
9569 if (r->in.offered < *r->out.needed) {
9570 result = WERR_MORE_DATA;
9571 } else {
9572 result = WERR_OK;
9573 r->out.key_buffer->string_array = array;
9576 done:
9577 if (!W_ERROR_IS_OK(result)) {
9578 TALLOC_FREE(array);
9579 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9580 *r->out.needed = 0;
9584 return result;
9587 /****************************************************************
9588 _spoolss_DeletePrinterKey
9589 ****************************************************************/
9591 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9592 struct spoolss_DeletePrinterKey *r)
9594 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9595 int snum=0;
9596 WERROR status;
9597 const char *printer;
9598 struct dcerpc_binding_handle *b;
9600 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9602 if (!Printer) {
9603 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9604 OUR_HANDLE(r->in.handle)));
9605 return WERR_BADFID;
9608 /* if keyname == NULL, return error */
9609 if ( !r->in.key_name )
9610 return WERR_INVALID_PARAM;
9612 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9613 return WERR_BADFID;
9616 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9617 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9618 "printer properties change denied by handle\n"));
9619 return WERR_ACCESS_DENIED;
9622 printer = lp_const_servicename(snum);
9624 status = winreg_printer_binding_handle(p->mem_ctx,
9625 get_session_info_system(),
9626 p->msg_ctx,
9627 &b);
9628 if (!W_ERROR_IS_OK(status)) {
9629 return status;
9632 /* delete the key and all subkeys */
9633 status = winreg_delete_printer_key(p->mem_ctx, b,
9634 printer,
9635 r->in.key_name);
9636 if (W_ERROR_IS_OK(status)) {
9637 status = winreg_printer_update_changeid(p->mem_ctx, b,
9638 printer);
9641 return status;
9644 /****************************************************************
9645 _spoolss_EnumPrinterDataEx
9646 ****************************************************************/
9648 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9649 struct spoolss_EnumPrinterDataEx *r)
9651 uint32_t count = 0;
9652 struct spoolss_PrinterEnumValues *info = NULL;
9653 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9654 int snum;
9655 WERROR result;
9657 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9659 *r->out.count = 0;
9660 *r->out.needed = 0;
9661 *r->out.info = NULL;
9663 if (!Printer) {
9664 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9665 OUR_HANDLE(r->in.handle)));
9666 return WERR_BADFID;
9670 * first check for a keyname of NULL or "". Win2k seems to send
9671 * this a lot and we should send back WERR_INVALID_PARAM
9672 * no need to spend time looking up the printer in this case.
9673 * --jerry
9676 if (!strlen(r->in.key_name)) {
9677 result = WERR_INVALID_PARAM;
9678 goto done;
9681 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9682 return WERR_BADFID;
9685 /* now look for a match on the key name */
9686 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9687 get_session_info_system(),
9688 p->msg_ctx,
9689 lp_const_servicename(snum),
9690 r->in.key_name,
9691 &count,
9692 &info);
9693 if (!W_ERROR_IS_OK(result)) {
9694 goto done;
9697 #if 0 /* FIXME - gd */
9698 /* housekeeping information in the reply */
9700 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9701 * the hand marshalled container size is a multiple
9702 * of 4 bytes for RPC alignment.
9705 if (needed % 4) {
9706 needed += 4-(needed % 4);
9708 #endif
9709 *r->out.count = count;
9710 *r->out.info = info;
9712 done:
9713 if (!W_ERROR_IS_OK(result)) {
9714 return result;
9717 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9718 spoolss_EnumPrinterDataEx,
9719 *r->out.info,
9720 *r->out.count);
9721 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9722 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9724 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9727 /****************************************************************************
9728 ****************************************************************************/
9730 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9731 const char *servername,
9732 const char *environment,
9733 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9735 WERROR werr;
9736 char *path = NULL;
9738 werr = compose_spoolss_server_path(mem_ctx,
9739 servername,
9740 environment,
9741 SPOOLSS_PRTPROCS_PATH,
9742 &path);
9743 if (!W_ERROR_IS_OK(werr)) {
9744 return werr;
9747 DEBUG(4,("print processor directory: [%s]\n", path));
9749 r->directory_name = path;
9751 return WERR_OK;
9754 /****************************************************************
9755 _spoolss_GetPrintProcessorDirectory
9756 ****************************************************************/
9758 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9759 struct spoolss_GetPrintProcessorDirectory *r)
9761 WERROR result;
9762 char *prnproc_share = NULL;
9763 bool prnproc_share_exists = false;
9764 int snum;
9766 /* that's an [in out] buffer */
9768 if (!r->in.buffer && (r->in.offered != 0)) {
9769 return WERR_INVALID_PARAM;
9772 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9773 r->in.level));
9775 *r->out.needed = 0;
9777 /* r->in.level is ignored */
9779 /* We always should reply with a local print processor directory so that
9780 * users are not forced to have a [prnproc$] share on the Samba spoolss
9781 * server, if users decide to do so, lets announce it though - Guenther */
9783 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9784 if (!prnproc_share) {
9785 return WERR_NOMEM;
9787 if (snum != -1) {
9788 prnproc_share_exists = true;
9791 result = getprintprocessordirectory_level_1(p->mem_ctx,
9792 prnproc_share_exists ? r->in.server : NULL,
9793 r->in.environment,
9794 &r->out.info->info1);
9795 if (!W_ERROR_IS_OK(result)) {
9796 TALLOC_FREE(r->out.info);
9797 return result;
9800 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9801 r->out.info, r->in.level);
9802 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9804 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9807 /*******************************************************************
9808 ********************************************************************/
9810 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9811 const char *dllname)
9813 enum ndr_err_code ndr_err;
9814 struct spoolss_MonitorUi ui;
9816 ui.dll_name = dllname;
9818 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9819 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9820 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9821 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9823 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9826 /*******************************************************************
9827 Streams the monitor UI DLL name in UNICODE
9828 *******************************************************************/
9830 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9831 struct security_token *token, DATA_BLOB *in,
9832 DATA_BLOB *out, uint32_t *needed)
9834 const char *dllname = "tcpmonui.dll";
9836 *needed = (strlen(dllname)+1) * 2;
9838 if (out->length < *needed) {
9839 return WERR_INSUFFICIENT_BUFFER;
9842 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9843 return WERR_NOMEM;
9846 return WERR_OK;
9849 /*******************************************************************
9850 ********************************************************************/
9852 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9853 struct spoolss_PortData1 *port1,
9854 const DATA_BLOB *buf)
9856 enum ndr_err_code ndr_err;
9857 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9858 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9859 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9860 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9862 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9865 /*******************************************************************
9866 ********************************************************************/
9868 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9869 struct spoolss_PortData2 *port2,
9870 const DATA_BLOB *buf)
9872 enum ndr_err_code ndr_err;
9873 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9874 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9875 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9876 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9878 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9881 /*******************************************************************
9882 Create a new TCP/IP port
9883 *******************************************************************/
9885 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9886 struct security_token *token, DATA_BLOB *in,
9887 DATA_BLOB *out, uint32_t *needed)
9889 struct spoolss_PortData1 port1;
9890 struct spoolss_PortData2 port2;
9891 char *device_uri = NULL;
9892 uint32_t version;
9894 const char *portname;
9895 const char *hostaddress;
9896 const char *queue;
9897 uint32_t port_number;
9898 uint32_t protocol;
9900 /* peek for spoolss_PortData version */
9902 if (!in || (in->length < (128 + 4))) {
9903 return WERR_GENERAL_FAILURE;
9906 version = IVAL(in->data, 128);
9908 switch (version) {
9909 case 1:
9910 ZERO_STRUCT(port1);
9912 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9913 return WERR_NOMEM;
9916 portname = port1.portname;
9917 hostaddress = port1.hostaddress;
9918 queue = port1.queue;
9919 protocol = port1.protocol;
9920 port_number = port1.port_number;
9922 break;
9923 case 2:
9924 ZERO_STRUCT(port2);
9926 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9927 return WERR_NOMEM;
9930 portname = port2.portname;
9931 hostaddress = port2.hostaddress;
9932 queue = port2.queue;
9933 protocol = port2.protocol;
9934 port_number = port2.port_number;
9936 break;
9937 default:
9938 DEBUG(1,("xcvtcp_addport: "
9939 "unknown version of port_data: %d\n", version));
9940 return WERR_UNKNOWN_PORT;
9943 /* create the device URI and call the add_port_hook() */
9945 switch (protocol) {
9946 case PROTOCOL_RAWTCP_TYPE:
9947 device_uri = talloc_asprintf(mem_ctx,
9948 "socket://%s:%d/", hostaddress,
9949 port_number);
9950 break;
9952 case PROTOCOL_LPR_TYPE:
9953 device_uri = talloc_asprintf(mem_ctx,
9954 "lpr://%s/%s", hostaddress, queue );
9955 break;
9957 default:
9958 return WERR_UNKNOWN_PORT;
9961 if (!device_uri) {
9962 return WERR_NOMEM;
9965 return add_port_hook(mem_ctx, token, portname, device_uri);
9968 /*******************************************************************
9969 *******************************************************************/
9971 struct xcv_api_table xcvtcp_cmds[] = {
9972 { "MonitorUI", xcvtcp_monitorui },
9973 { "AddPort", xcvtcp_addport},
9974 { NULL, NULL }
9977 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9978 struct security_token *token, const char *command,
9979 DATA_BLOB *inbuf,
9980 DATA_BLOB *outbuf,
9981 uint32_t *needed )
9983 int i;
9985 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9987 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9988 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9989 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9992 return WERR_BADFUNC;
9995 /*******************************************************************
9996 *******************************************************************/
9997 #if 0 /* don't support management using the "Local Port" monitor */
9999 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10000 struct security_token *token, DATA_BLOB *in,
10001 DATA_BLOB *out, uint32_t *needed)
10003 const char *dllname = "localui.dll";
10005 *needed = (strlen(dllname)+1) * 2;
10007 if (out->length < *needed) {
10008 return WERR_INSUFFICIENT_BUFFER;
10011 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10012 return WERR_NOMEM;
10015 return WERR_OK;
10018 /*******************************************************************
10019 *******************************************************************/
10021 struct xcv_api_table xcvlocal_cmds[] = {
10022 { "MonitorUI", xcvlocal_monitorui },
10023 { NULL, NULL }
10025 #else
10026 struct xcv_api_table xcvlocal_cmds[] = {
10027 { NULL, NULL }
10029 #endif
10033 /*******************************************************************
10034 *******************************************************************/
10036 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10037 struct security_token *token, const char *command,
10038 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10039 uint32_t *needed)
10041 int i;
10043 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10045 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10046 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10047 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10049 return WERR_BADFUNC;
10052 /****************************************************************
10053 _spoolss_XcvData
10054 ****************************************************************/
10056 WERROR _spoolss_XcvData(struct pipes_struct *p,
10057 struct spoolss_XcvData *r)
10059 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10060 DATA_BLOB out_data = data_blob_null;
10061 WERROR werror;
10063 if (!Printer) {
10064 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10065 OUR_HANDLE(r->in.handle)));
10066 return WERR_BADFID;
10069 /* Has to be a handle to the TCP/IP port monitor */
10071 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10072 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10073 return WERR_BADFID;
10076 /* requires administrative access to the server */
10078 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10079 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10080 return WERR_ACCESS_DENIED;
10083 /* Allocate the outgoing buffer */
10085 if (r->in.out_data_size) {
10086 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10087 if (out_data.data == NULL) {
10088 return WERR_NOMEM;
10092 switch ( Printer->printer_type ) {
10093 case SPLHND_PORTMON_TCP:
10094 werror = process_xcvtcp_command(p->mem_ctx,
10095 p->session_info->security_token,
10096 r->in.function_name,
10097 &r->in.in_data, &out_data,
10098 r->out.needed);
10099 break;
10100 case SPLHND_PORTMON_LOCAL:
10101 werror = process_xcvlocal_command(p->mem_ctx,
10102 p->session_info->security_token,
10103 r->in.function_name,
10104 &r->in.in_data, &out_data,
10105 r->out.needed);
10106 break;
10107 default:
10108 werror = WERR_INVALID_PRINT_MONITOR;
10111 if (!W_ERROR_IS_OK(werror)) {
10112 return werror;
10115 *r->out.status_code = 0;
10117 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10118 memcpy(r->out.out_data, out_data.data,
10119 MIN(r->in.out_data_size, out_data.length));
10122 return WERR_OK;
10125 /****************************************************************
10126 _spoolss_AddPrintProcessor
10127 ****************************************************************/
10129 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10130 struct spoolss_AddPrintProcessor *r)
10132 /* for now, just indicate success and ignore the add. We'll
10133 automatically set the winprint processor for printer
10134 entries later. Used to debug the LexMark Optra S 1855 PCL
10135 driver --jerry */
10137 return WERR_OK;
10140 /****************************************************************
10141 _spoolss_AddPort
10142 ****************************************************************/
10144 WERROR _spoolss_AddPort(struct pipes_struct *p,
10145 struct spoolss_AddPort *r)
10147 /* do what w2k3 does */
10149 return WERR_NOT_SUPPORTED;
10152 /****************************************************************
10153 _spoolss_GetPrinterDriver
10154 ****************************************************************/
10156 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10157 struct spoolss_GetPrinterDriver *r)
10159 p->rng_fault_state = true;
10160 return WERR_NOT_SUPPORTED;
10163 /****************************************************************
10164 _spoolss_ReadPrinter
10165 ****************************************************************/
10167 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10168 struct spoolss_ReadPrinter *r)
10170 p->rng_fault_state = true;
10171 return WERR_NOT_SUPPORTED;
10174 /****************************************************************
10175 _spoolss_WaitForPrinterChange
10176 ****************************************************************/
10178 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10179 struct spoolss_WaitForPrinterChange *r)
10181 p->rng_fault_state = true;
10182 return WERR_NOT_SUPPORTED;
10185 /****************************************************************
10186 _spoolss_ConfigurePort
10187 ****************************************************************/
10189 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10190 struct spoolss_ConfigurePort *r)
10192 p->rng_fault_state = true;
10193 return WERR_NOT_SUPPORTED;
10196 /****************************************************************
10197 _spoolss_DeletePort
10198 ****************************************************************/
10200 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10201 struct spoolss_DeletePort *r)
10203 p->rng_fault_state = true;
10204 return WERR_NOT_SUPPORTED;
10207 /****************************************************************
10208 _spoolss_CreatePrinterIC
10209 ****************************************************************/
10211 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10212 struct spoolss_CreatePrinterIC *r)
10214 p->rng_fault_state = true;
10215 return WERR_NOT_SUPPORTED;
10218 /****************************************************************
10219 _spoolss_PlayGDIScriptOnPrinterIC
10220 ****************************************************************/
10222 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10223 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10225 p->rng_fault_state = true;
10226 return WERR_NOT_SUPPORTED;
10229 /****************************************************************
10230 _spoolss_DeletePrinterIC
10231 ****************************************************************/
10233 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10234 struct spoolss_DeletePrinterIC *r)
10236 p->rng_fault_state = true;
10237 return WERR_NOT_SUPPORTED;
10240 /****************************************************************
10241 _spoolss_AddPrinterConnection
10242 ****************************************************************/
10244 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10245 struct spoolss_AddPrinterConnection *r)
10247 p->rng_fault_state = true;
10248 return WERR_NOT_SUPPORTED;
10251 /****************************************************************
10252 _spoolss_DeletePrinterConnection
10253 ****************************************************************/
10255 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10256 struct spoolss_DeletePrinterConnection *r)
10258 p->rng_fault_state = true;
10259 return WERR_NOT_SUPPORTED;
10262 /****************************************************************
10263 _spoolss_PrinterMessageBox
10264 ****************************************************************/
10266 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10267 struct spoolss_PrinterMessageBox *r)
10269 p->rng_fault_state = true;
10270 return WERR_NOT_SUPPORTED;
10273 /****************************************************************
10274 _spoolss_AddMonitor
10275 ****************************************************************/
10277 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10278 struct spoolss_AddMonitor *r)
10280 p->rng_fault_state = true;
10281 return WERR_NOT_SUPPORTED;
10284 /****************************************************************
10285 _spoolss_DeleteMonitor
10286 ****************************************************************/
10288 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10289 struct spoolss_DeleteMonitor *r)
10291 p->rng_fault_state = true;
10292 return WERR_NOT_SUPPORTED;
10295 /****************************************************************
10296 _spoolss_DeletePrintProcessor
10297 ****************************************************************/
10299 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10300 struct spoolss_DeletePrintProcessor *r)
10302 p->rng_fault_state = true;
10303 return WERR_NOT_SUPPORTED;
10306 /****************************************************************
10307 _spoolss_AddPrintProvidor
10308 ****************************************************************/
10310 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10311 struct spoolss_AddPrintProvidor *r)
10313 p->rng_fault_state = true;
10314 return WERR_NOT_SUPPORTED;
10317 /****************************************************************
10318 _spoolss_DeletePrintProvidor
10319 ****************************************************************/
10321 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10322 struct spoolss_DeletePrintProvidor *r)
10324 p->rng_fault_state = true;
10325 return WERR_NOT_SUPPORTED;
10328 /****************************************************************
10329 _spoolss_FindFirstPrinterChangeNotification
10330 ****************************************************************/
10332 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10333 struct spoolss_FindFirstPrinterChangeNotification *r)
10335 p->rng_fault_state = true;
10336 return WERR_NOT_SUPPORTED;
10339 /****************************************************************
10340 _spoolss_FindNextPrinterChangeNotification
10341 ****************************************************************/
10343 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10344 struct spoolss_FindNextPrinterChangeNotification *r)
10346 p->rng_fault_state = true;
10347 return WERR_NOT_SUPPORTED;
10350 /****************************************************************
10351 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10352 ****************************************************************/
10354 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10355 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10357 p->rng_fault_state = true;
10358 return WERR_NOT_SUPPORTED;
10361 /****************************************************************
10362 _spoolss_ReplyOpenPrinter
10363 ****************************************************************/
10365 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10366 struct spoolss_ReplyOpenPrinter *r)
10368 p->rng_fault_state = true;
10369 return WERR_NOT_SUPPORTED;
10372 /****************************************************************
10373 _spoolss_RouterReplyPrinter
10374 ****************************************************************/
10376 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10377 struct spoolss_RouterReplyPrinter *r)
10379 p->rng_fault_state = true;
10380 return WERR_NOT_SUPPORTED;
10383 /****************************************************************
10384 _spoolss_ReplyClosePrinter
10385 ****************************************************************/
10387 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10388 struct spoolss_ReplyClosePrinter *r)
10390 p->rng_fault_state = true;
10391 return WERR_NOT_SUPPORTED;
10394 /****************************************************************
10395 _spoolss_AddPortEx
10396 ****************************************************************/
10398 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10399 struct spoolss_AddPortEx *r)
10401 p->rng_fault_state = true;
10402 return WERR_NOT_SUPPORTED;
10405 /****************************************************************
10406 _spoolss_RouterFindFirstPrinterChangeNotification
10407 ****************************************************************/
10409 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10410 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10412 p->rng_fault_state = true;
10413 return WERR_NOT_SUPPORTED;
10416 /****************************************************************
10417 _spoolss_SpoolerInit
10418 ****************************************************************/
10420 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10421 struct spoolss_SpoolerInit *r)
10423 p->rng_fault_state = true;
10424 return WERR_NOT_SUPPORTED;
10427 /****************************************************************
10428 _spoolss_ResetPrinterEx
10429 ****************************************************************/
10431 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10432 struct spoolss_ResetPrinterEx *r)
10434 p->rng_fault_state = true;
10435 return WERR_NOT_SUPPORTED;
10438 /****************************************************************
10439 _spoolss_RouterReplyPrinterEx
10440 ****************************************************************/
10442 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10443 struct spoolss_RouterReplyPrinterEx *r)
10445 p->rng_fault_state = true;
10446 return WERR_NOT_SUPPORTED;
10449 /****************************************************************
10450 _spoolss_44
10451 ****************************************************************/
10453 WERROR _spoolss_44(struct pipes_struct *p,
10454 struct spoolss_44 *r)
10456 p->rng_fault_state = true;
10457 return WERR_NOT_SUPPORTED;
10460 /****************************************************************
10461 _spoolss_SetPort
10462 ****************************************************************/
10464 WERROR _spoolss_SetPort(struct pipes_struct *p,
10465 struct spoolss_SetPort *r)
10467 p->rng_fault_state = true;
10468 return WERR_NOT_SUPPORTED;
10471 /****************************************************************
10472 _spoolss_4a
10473 ****************************************************************/
10475 WERROR _spoolss_4a(struct pipes_struct *p,
10476 struct spoolss_4a *r)
10478 p->rng_fault_state = true;
10479 return WERR_NOT_SUPPORTED;
10482 /****************************************************************
10483 _spoolss_4b
10484 ****************************************************************/
10486 WERROR _spoolss_4b(struct pipes_struct *p,
10487 struct spoolss_4b *r)
10489 p->rng_fault_state = true;
10490 return WERR_NOT_SUPPORTED;
10493 /****************************************************************
10494 _spoolss_4c
10495 ****************************************************************/
10497 WERROR _spoolss_4c(struct pipes_struct *p,
10498 struct spoolss_4c *r)
10500 p->rng_fault_state = true;
10501 return WERR_NOT_SUPPORTED;
10504 /****************************************************************
10505 _spoolss_53
10506 ****************************************************************/
10508 WERROR _spoolss_53(struct pipes_struct *p,
10509 struct spoolss_53 *r)
10511 p->rng_fault_state = true;
10512 return WERR_NOT_SUPPORTED;
10515 /****************************************************************
10516 _spoolss_AddPerMachineConnection
10517 ****************************************************************/
10519 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10520 struct spoolss_AddPerMachineConnection *r)
10522 p->rng_fault_state = true;
10523 return WERR_NOT_SUPPORTED;
10526 /****************************************************************
10527 _spoolss_DeletePerMachineConnection
10528 ****************************************************************/
10530 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10531 struct spoolss_DeletePerMachineConnection *r)
10533 p->rng_fault_state = true;
10534 return WERR_NOT_SUPPORTED;
10537 /****************************************************************
10538 _spoolss_EnumPerMachineConnections
10539 ****************************************************************/
10541 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10542 struct spoolss_EnumPerMachineConnections *r)
10544 p->rng_fault_state = true;
10545 return WERR_NOT_SUPPORTED;
10548 /****************************************************************
10549 _spoolss_5a
10550 ****************************************************************/
10552 WERROR _spoolss_5a(struct pipes_struct *p,
10553 struct spoolss_5a *r)
10555 p->rng_fault_state = true;
10556 return WERR_NOT_SUPPORTED;
10559 /****************************************************************
10560 _spoolss_5b
10561 ****************************************************************/
10563 WERROR _spoolss_5b(struct pipes_struct *p,
10564 struct spoolss_5b *r)
10566 p->rng_fault_state = true;
10567 return WERR_NOT_SUPPORTED;
10570 /****************************************************************
10571 _spoolss_5c
10572 ****************************************************************/
10574 WERROR _spoolss_5c(struct pipes_struct *p,
10575 struct spoolss_5c *r)
10577 p->rng_fault_state = true;
10578 return WERR_NOT_SUPPORTED;
10581 /****************************************************************
10582 _spoolss_5d
10583 ****************************************************************/
10585 WERROR _spoolss_5d(struct pipes_struct *p,
10586 struct spoolss_5d *r)
10588 p->rng_fault_state = true;
10589 return WERR_NOT_SUPPORTED;
10592 /****************************************************************
10593 _spoolss_5e
10594 ****************************************************************/
10596 WERROR _spoolss_5e(struct pipes_struct *p,
10597 struct spoolss_5e *r)
10599 p->rng_fault_state = true;
10600 return WERR_NOT_SUPPORTED;
10603 /****************************************************************
10604 _spoolss_5f
10605 ****************************************************************/
10607 WERROR _spoolss_5f(struct pipes_struct *p,
10608 struct spoolss_5f *r)
10610 p->rng_fault_state = true;
10611 return WERR_NOT_SUPPORTED;
10614 /****************************************************************
10615 _spoolss_60
10616 ****************************************************************/
10618 WERROR _spoolss_60(struct pipes_struct *p,
10619 struct spoolss_60 *r)
10621 p->rng_fault_state = true;
10622 return WERR_NOT_SUPPORTED;
10625 /****************************************************************
10626 _spoolss_61
10627 ****************************************************************/
10629 WERROR _spoolss_61(struct pipes_struct *p,
10630 struct spoolss_61 *r)
10632 p->rng_fault_state = true;
10633 return WERR_NOT_SUPPORTED;
10636 /****************************************************************
10637 _spoolss_62
10638 ****************************************************************/
10640 WERROR _spoolss_62(struct pipes_struct *p,
10641 struct spoolss_62 *r)
10643 p->rng_fault_state = true;
10644 return WERR_NOT_SUPPORTED;
10647 /****************************************************************
10648 _spoolss_63
10649 ****************************************************************/
10651 WERROR _spoolss_63(struct pipes_struct *p,
10652 struct spoolss_63 *r)
10654 p->rng_fault_state = true;
10655 return WERR_NOT_SUPPORTED;
10658 /****************************************************************
10659 _spoolss_64
10660 ****************************************************************/
10662 WERROR _spoolss_64(struct pipes_struct *p,
10663 struct spoolss_64 *r)
10665 p->rng_fault_state = true;
10666 return WERR_NOT_SUPPORTED;
10669 /****************************************************************
10670 _spoolss_65
10671 ****************************************************************/
10673 WERROR _spoolss_65(struct pipes_struct *p,
10674 struct spoolss_65 *r)
10676 p->rng_fault_state = true;
10677 return WERR_NOT_SUPPORTED;
10680 /****************************************************************
10681 _spoolss_GetCorePrinterDrivers
10682 ****************************************************************/
10684 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10685 struct spoolss_GetCorePrinterDrivers *r)
10687 p->rng_fault_state = true;
10688 return WERR_NOT_SUPPORTED;
10691 /****************************************************************
10692 _spoolss_67
10693 ****************************************************************/
10695 WERROR _spoolss_67(struct pipes_struct *p,
10696 struct spoolss_67 *r)
10698 p->rng_fault_state = true;
10699 return WERR_NOT_SUPPORTED;
10702 /****************************************************************
10703 _spoolss_GetPrinterDriverPackagePath
10704 ****************************************************************/
10706 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10707 struct spoolss_GetPrinterDriverPackagePath *r)
10709 p->rng_fault_state = true;
10710 return WERR_NOT_SUPPORTED;
10713 /****************************************************************
10714 _spoolss_69
10715 ****************************************************************/
10717 WERROR _spoolss_69(struct pipes_struct *p,
10718 struct spoolss_69 *r)
10720 p->rng_fault_state = true;
10721 return WERR_NOT_SUPPORTED;
10724 /****************************************************************
10725 _spoolss_6a
10726 ****************************************************************/
10728 WERROR _spoolss_6a(struct pipes_struct *p,
10729 struct spoolss_6a *r)
10731 p->rng_fault_state = true;
10732 return WERR_NOT_SUPPORTED;
10735 /****************************************************************
10736 _spoolss_6b
10737 ****************************************************************/
10739 WERROR _spoolss_6b(struct pipes_struct *p,
10740 struct spoolss_6b *r)
10742 p->rng_fault_state = true;
10743 return WERR_NOT_SUPPORTED;
10746 /****************************************************************
10747 _spoolss_6c
10748 ****************************************************************/
10750 WERROR _spoolss_6c(struct pipes_struct *p,
10751 struct spoolss_6c *r)
10753 p->rng_fault_state = true;
10754 return WERR_NOT_SUPPORTED;
10757 /****************************************************************
10758 _spoolss_6d
10759 ****************************************************************/
10761 WERROR _spoolss_6d(struct pipes_struct *p,
10762 struct spoolss_6d *r)
10764 p->rng_fault_state = true;
10765 return WERR_NOT_SUPPORTED;