s4:libcli/ldap: conversion to tstream
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob0639b87a559bfd91616b5cccbf95826f66122cd1
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 "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.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 "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62 ((info)?ndr_size_##fn(info, level, 0):0)
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
79 struct notify_back_channel;
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86 struct printer_handle *prev, *next;
87 bool document_started;
88 bool page_started;
89 uint32_t jobid; /* jobid in printing backend */
90 int printer_type;
91 const char *servername;
92 fstring sharename;
93 uint32_t type;
94 uint32_t access_granted;
95 struct {
96 uint32_t flags;
97 uint32_t options;
98 fstring localmachine;
99 uint32_t printerlocal;
100 struct spoolss_NotifyOption *option;
101 struct policy_handle cli_hnd;
102 struct notify_back_channel *cli_chan;
103 uint32_t change;
104 /* are we in a FindNextPrinterChangeNotify() call? */
105 bool fnpcn;
106 struct messaging_context *msg_ctx;
107 } notify;
108 struct {
109 fstring machine;
110 fstring user;
111 } client;
113 /* devmode sent in the OpenPrinter() call */
114 struct spoolss_DeviceMode *devmode;
116 /* TODO cache the printer info2 structure */
117 struct spoolss_PrinterInfo2 *info2;
121 static struct printer_handle *printers_list;
123 struct printer_session_counter {
124 struct printer_session_counter *next;
125 struct printer_session_counter *prev;
127 int snum;
128 uint32_t counter;
131 static struct printer_session_counter *counter_list;
133 struct notify_back_channel {
134 struct notify_back_channel *prev, *next;
136 /* associated client */
137 struct sockaddr_storage client_address;
139 /* print notify back-channel pipe handle*/
140 struct rpc_pipe_client *cli_pipe;
141 struct cli_state *cli;
142 uint32_t active_connections;
145 static struct notify_back_channel *back_channels;
147 /* Map generic permissions to printer object specific permissions */
149 const struct standard_mapping printer_std_mapping = {
150 PRINTER_READ,
151 PRINTER_WRITE,
152 PRINTER_EXECUTE,
153 PRINTER_ALL_ACCESS
156 /* Map generic permissions to print server object specific permissions */
158 const struct standard_mapping printserver_std_mapping = {
159 SERVER_READ,
160 SERVER_WRITE,
161 SERVER_EXECUTE,
162 SERVER_ALL_ACCESS
165 /* API table for Xcv Monitor functions */
167 struct xcv_api_table {
168 const char *name;
169 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
172 static void prune_printername_cache(void);
174 /********************************************************************
175 * Canonicalize servername.
176 ********************************************************************/
178 static const char *canon_servername(const char *servername)
180 const char *pservername = servername;
181 while (*pservername == '\\') {
182 pservername++;
184 return pservername;
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
190 switch (v) {
191 case LPQ_QUEUED:
192 return 0;
193 case LPQ_PAUSED:
194 return JOB_STATUS_PAUSED;
195 case LPQ_SPOOLING:
196 return JOB_STATUS_SPOOLING;
197 case LPQ_PRINTING:
198 return JOB_STATUS_PRINTING;
199 case LPQ_ERROR:
200 return JOB_STATUS_ERROR;
201 case LPQ_DELETING:
202 return JOB_STATUS_DELETING;
203 case LPQ_OFFLINE:
204 return JOB_STATUS_OFFLINE;
205 case LPQ_PAPEROUT:
206 return JOB_STATUS_PAPEROUT;
207 case LPQ_PRINTED:
208 return JOB_STATUS_PRINTED;
209 case LPQ_DELETED:
210 return JOB_STATUS_DELETED;
211 case LPQ_BLOCKED:
212 return JOB_STATUS_BLOCKED_DEVQ;
213 case LPQ_USER_INTERVENTION:
214 return JOB_STATUS_USER_INTERVENTION;
216 return 0;
219 static int nt_printq_status(int v)
221 switch (v) {
222 case LPQ_PAUSED:
223 return PRINTER_STATUS_PAUSED;
224 case LPQ_QUEUED:
225 case LPQ_SPOOLING:
226 case LPQ_PRINTING:
227 return 0;
229 return 0;
232 /***************************************************************************
233 Disconnect from the client
234 ****************************************************************************/
236 static void srv_spoolss_replycloseprinter(int snum,
237 struct printer_handle *prn_hnd)
239 WERROR result;
240 NTSTATUS status;
243 * Tell the specific printing tdb we no longer want messages for this printer
244 * by deregistering our PID.
247 if (!print_notify_deregister_pid(snum)) {
248 DEBUG(0, ("Failed to register our pid for printer %s\n",
249 lp_const_servicename(snum)));
252 /* weird if the test succeeds !!! */
253 if (prn_hnd->notify.cli_chan == NULL ||
254 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
255 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
256 prn_hnd->notify.cli_chan->active_connections == 0) {
257 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
258 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
259 TALLOC_FREE(prn_hnd->notify.cli_chan);
260 return;
263 status = dcerpc_spoolss_ReplyClosePrinter(
264 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
265 talloc_tos(),
266 &prn_hnd->notify.cli_hnd,
267 &result);
268 if (!NT_STATUS_IS_OK(status)) {
269 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270 nt_errstr(status)));
271 result = ntstatus_to_werror(status);
272 } else if (!W_ERROR_IS_OK(result)) {
273 DEBUG(0, ("reply_close_printer failed [%s].\n",
274 win_errstr(result)));
277 /* if it's the last connection, deconnect the IPC$ share */
278 if (prn_hnd->notify.cli_chan->active_connections == 1) {
280 cli_shutdown(prn_hnd->notify.cli_chan->cli);
281 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
282 TALLOC_FREE(prn_hnd->notify.cli_chan);
284 if (prn_hnd->notify.msg_ctx != NULL) {
285 messaging_deregister(prn_hnd->notify.msg_ctx,
286 MSG_PRINTER_NOTIFY2, NULL);
290 if (prn_hnd->notify.cli_chan) {
291 prn_hnd->notify.cli_chan->active_connections--;
292 prn_hnd->notify.cli_chan = NULL;
296 /****************************************************************************
297 Functions to free a printer entry datastruct.
298 ****************************************************************************/
300 static int printer_entry_destructor(struct printer_handle *Printer)
302 if (Printer->notify.cli_chan != NULL &&
303 Printer->notify.cli_chan->active_connections > 0) {
304 int snum = -1;
306 switch(Printer->printer_type) {
307 case SPLHND_SERVER:
308 srv_spoolss_replycloseprinter(snum, Printer);
309 break;
311 case SPLHND_PRINTER:
312 snum = print_queue_snum(Printer->sharename);
313 if (snum != -1) {
314 srv_spoolss_replycloseprinter(snum, Printer);
316 break;
317 default:
318 break;
322 Printer->notify.flags=0;
323 Printer->notify.options=0;
324 Printer->notify.localmachine[0]='\0';
325 Printer->notify.printerlocal=0;
326 TALLOC_FREE(Printer->notify.option);
327 TALLOC_FREE(Printer->devmode);
329 /* Remove from the internal list. */
330 DLIST_REMOVE(printers_list, Printer);
331 return 0;
334 /****************************************************************************
335 find printer index by handle
336 ****************************************************************************/
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339 struct policy_handle *hnd)
341 struct printer_handle *find_printer = NULL;
343 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
345 return NULL;
348 return find_printer;
351 /****************************************************************************
352 Close printer index by handle.
353 ****************************************************************************/
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
357 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
359 if (!Printer) {
360 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
361 OUR_HANDLE(hnd)));
362 return false;
365 close_policy_hnd(p, hnd);
367 return true;
370 /****************************************************************************
371 Delete a printer given a handle.
372 ****************************************************************************/
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375 const char *sharename,
376 struct messaging_context *msg_ctx)
378 char *cmd = lp_deleteprinter_command(talloc_tos());
379 char *command = NULL;
380 int ret;
381 bool is_print_op = false;
383 /* can't fail if we don't try */
385 if ( !*cmd )
386 return WERR_OK;
388 command = talloc_asprintf(ctx,
389 "%s \"%s\"",
390 cmd, sharename);
391 if (!command) {
392 return WERR_NOMEM;
394 if ( token )
395 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
397 DEBUG(10,("Running [%s]\n", command));
399 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
401 if ( is_print_op )
402 become_root();
404 if ( (ret = smbrun(command, NULL)) == 0 ) {
405 /* Tell everyone we updated smb.conf. */
406 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
409 if ( is_print_op )
410 unbecome_root();
412 /********** END SePrintOperatorPrivlege BLOCK **********/
414 DEBUGADD(10,("returned [%d]\n", ret));
416 TALLOC_FREE(command);
418 if (ret != 0)
419 return WERR_BADFID; /* What to return here? */
421 return WERR_OK;
424 /****************************************************************************
425 Delete a printer given a handle.
426 ****************************************************************************/
428 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
430 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
431 WERROR result;
433 if (!Printer) {
434 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
435 OUR_HANDLE(hnd)));
436 return WERR_BADFID;
440 * It turns out that Windows allows delete printer on a handle
441 * opened by an admin user, then used on a pipe handle created
442 * by an anonymous user..... but they're working on security.... riiight !
443 * JRA.
446 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
447 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
448 return WERR_ACCESS_DENIED;
451 /* this does not need a become root since the access check has been
452 done on the handle already */
454 result = winreg_delete_printer_key_internal(p->mem_ctx,
455 get_session_info_system(),
456 p->msg_ctx,
457 Printer->sharename,
458 "");
459 if (!W_ERROR_IS_OK(result)) {
460 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
461 return WERR_BADFID;
464 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
465 Printer->sharename, p->msg_ctx);
466 if (!W_ERROR_IS_OK(result)) {
467 return result;
469 prune_printername_cache();
470 return WERR_OK;
473 /****************************************************************************
474 Return the snum of a printer corresponding to an handle.
475 ****************************************************************************/
477 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
478 int *number, struct share_params **params)
480 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
482 if (!Printer) {
483 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
484 OUR_HANDLE(hnd)));
485 return false;
488 switch (Printer->printer_type) {
489 case SPLHND_PRINTER:
490 DEBUG(4,("short name:%s\n", Printer->sharename));
491 *number = print_queue_snum(Printer->sharename);
492 return (*number != -1);
493 case SPLHND_SERVER:
494 return false;
495 default:
496 return false;
500 /****************************************************************************
501 Set printer handle type.
502 Check if it's \\server or \\server\printer
503 ****************************************************************************/
505 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
507 DEBUG(3,("Setting printer type=%s\n", handlename));
509 /* it's a print server */
510 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
511 DEBUGADD(4,("Printer is a print server\n"));
512 Printer->printer_type = SPLHND_SERVER;
514 /* it's a printer (set_printer_hnd_name() will handle port monitors */
515 else {
516 DEBUGADD(4,("Printer is a printer\n"));
517 Printer->printer_type = SPLHND_PRINTER;
520 return true;
523 static void prune_printername_cache_fn(const char *key, const char *value,
524 time_t timeout, void *private_data)
526 gencache_del(key);
529 static void prune_printername_cache(void)
531 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
534 /****************************************************************************
535 Set printer handle name.. Accept names like \\server, \\server\printer,
536 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
537 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
538 XcvDataPort() interface.
539 ****************************************************************************/
541 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
542 const struct auth_session_info *session_info,
543 struct messaging_context *msg_ctx,
544 struct printer_handle *Printer,
545 const char *handlename)
547 int snum;
548 int n_services=lp_numservices();
549 char *aprinter;
550 const char *printername;
551 const char *servername = NULL;
552 fstring sname;
553 bool found = false;
554 struct spoolss_PrinterInfo2 *info2 = NULL;
555 WERROR result;
556 char *p;
559 * Hopefully nobody names his printers like this. Maybe \ or ,
560 * are illegal in printer names even?
562 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
563 char *cache_key;
564 char *tmp;
566 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
567 (unsigned long)strlen(handlename)));
569 aprinter = discard_const_p(char, handlename);
570 if ( *handlename == '\\' ) {
571 servername = canon_servername(handlename);
572 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
573 *aprinter = '\0';
574 aprinter++;
576 if (!is_myname_or_ipaddr(servername)) {
577 return WERR_INVALID_PRINTER_NAME;
579 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
580 if (Printer->servername == NULL) {
581 return WERR_NOMEM;
585 if (Printer->printer_type == SPLHND_SERVER) {
586 return WERR_OK;
589 if (Printer->printer_type != SPLHND_PRINTER) {
590 return WERR_INVALID_HANDLE;
593 DEBUGADD(5, ("searching for [%s]\n", aprinter));
595 p = strchr(aprinter, ',');
596 if (p != NULL) {
597 char *p2 = p;
598 p++;
599 if (*p == ' ') {
600 p++;
602 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
603 *p2 = '\0';
604 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
605 *p2 = '\0';
609 if (p) {
610 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
613 /* check for the Port Monitor Interface */
614 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
615 Printer->printer_type = SPLHND_PORTMON_TCP;
616 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
617 found = true;
619 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
620 Printer->printer_type = SPLHND_PORTMON_LOCAL;
621 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
622 found = true;
625 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
626 if (cache_key == NULL) {
627 return WERR_NOMEM;
631 * With hundreds of printers, the "for" loop iterating all
632 * shares can be quite expensive, as it is done on every
633 * OpenPrinter. The loop maps "aprinter" to "sname", the
634 * result of which we cache in gencache.
636 if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
637 found = (strcmp(tmp, printer_not_found) != 0);
638 if (!found) {
639 DEBUG(4, ("Printer %s not found\n", aprinter));
640 TALLOC_FREE(tmp);
641 return WERR_INVALID_PRINTER_NAME;
643 fstrcpy(sname, tmp);
644 TALLOC_FREE(tmp);
647 /* Search all sharenames first as this is easier than pulling
648 the printer_info_2 off of disk. Don't use find_service() since
649 that calls out to map_username() */
651 /* do another loop to look for printernames */
652 for (snum = 0; !found && snum < n_services; snum++) {
653 const char *printer = lp_const_servicename(snum);
655 /* no point going on if this is not a printer */
656 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
657 continue;
660 /* ignore [printers] share */
661 if (strequal(printer, "printers")) {
662 continue;
665 fstrcpy(sname, printer);
666 if (strequal(aprinter, printer)) {
667 found = true;
668 break;
671 /* no point looking up the printer object if
672 we aren't allowing printername != sharename */
673 if (lp_force_printername(snum)) {
674 continue;
677 result = winreg_get_printer_internal(mem_ctx,
678 session_info,
679 msg_ctx,
680 sname,
681 &info2);
682 if ( !W_ERROR_IS_OK(result) ) {
683 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
684 sname, win_errstr(result)));
685 continue;
688 printername = strrchr(info2->printername, '\\');
689 if (printername == NULL) {
690 printername = info2->printername;
691 } else {
692 printername++;
695 if (strequal(printername, aprinter)) {
696 found = true;
697 break;
700 DEBUGADD(10, ("printername: %s\n", printername));
702 TALLOC_FREE(info2);
705 if (!found) {
706 gencache_set(cache_key, printer_not_found,
707 time_mono(NULL) + 300);
708 TALLOC_FREE(cache_key);
709 DEBUGADD(4,("Printer not found\n"));
710 return WERR_INVALID_PRINTER_NAME;
713 gencache_set(cache_key, sname, time_mono(NULL) + 300);
714 TALLOC_FREE(cache_key);
716 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
718 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
720 return WERR_OK;
723 /****************************************************************************
724 Find first available printer slot. creates a printer handle for you.
725 ****************************************************************************/
727 static WERROR open_printer_hnd(struct pipes_struct *p,
728 struct policy_handle *hnd,
729 const char *name,
730 uint32_t access_granted)
732 struct printer_handle *new_printer;
733 WERROR result;
735 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
737 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
738 if (new_printer == NULL) {
739 return WERR_NOMEM;
741 talloc_set_destructor(new_printer, printer_entry_destructor);
743 /* This also steals the printer_handle on the policy_handle */
744 if (!create_policy_hnd(p, hnd, new_printer)) {
745 TALLOC_FREE(new_printer);
746 return WERR_INVALID_HANDLE;
749 /* Add to the internal list. */
750 DLIST_ADD(printers_list, new_printer);
752 new_printer->notify.option=NULL;
754 if (!set_printer_hnd_printertype(new_printer, name)) {
755 close_printer_handle(p, hnd);
756 return WERR_INVALID_HANDLE;
759 result = set_printer_hnd_name(p->mem_ctx,
760 get_session_info_system(),
761 p->msg_ctx,
762 new_printer, name);
763 if (!W_ERROR_IS_OK(result)) {
764 close_printer_handle(p, hnd);
765 return result;
768 new_printer->access_granted = access_granted;
770 DEBUG(5, ("%d printer handles active\n",
771 (int)num_pipe_handles(p)));
773 return WERR_OK;
776 /***************************************************************************
777 check to see if the client motify handle is monitoring the notification
778 given by (notify_type, notify_field).
779 **************************************************************************/
781 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
782 uint16_t notify_field)
784 return true;
787 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
788 uint16_t notify_field)
790 struct spoolss_NotifyOption *option = p->notify.option;
791 uint32_t i, j;
794 * Flags should always be zero when the change notify
795 * is registered by the client's spooler. A user Win32 app
796 * might use the flags though instead of the NOTIFY_OPTION_INFO
797 * --jerry
800 if (!option) {
801 return false;
804 if (p->notify.flags)
805 return is_monitoring_event_flags(
806 p->notify.flags, notify_type, notify_field);
808 for (i = 0; i < option->count; i++) {
810 /* Check match for notify_type */
812 if (option->types[i].type != notify_type)
813 continue;
815 /* Check match for field */
817 for (j = 0; j < option->types[i].count; j++) {
818 if (option->types[i].fields[j].field == notify_field) {
819 return true;
824 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
825 p->servername, p->sharename, notify_type, notify_field));
827 return false;
830 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
831 _data->data.integer[0] = _integer; \
832 _data->data.integer[1] = 0;
835 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
836 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
837 if (!_data->data.string.string) {\
838 _data->data.string.size = 0; \
840 _data->data.string.size = strlen_m_term(_p) * 2;
842 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
843 _data->data.devmode.devmode = _devmode;
845 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
846 struct tm *t,
847 const char **pp,
848 uint32_t *plen)
850 struct spoolss_Time st;
851 uint32_t len = 16;
852 char *p;
854 if (!init_systemtime(&st, t)) {
855 return;
858 p = talloc_array(mem_ctx, char, len);
859 if (!p) {
860 return;
864 * Systemtime must be linearized as a set of UINT16's.
865 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
868 SSVAL(p, 0, st.year);
869 SSVAL(p, 2, st.month);
870 SSVAL(p, 4, st.day_of_week);
871 SSVAL(p, 6, st.day);
872 SSVAL(p, 8, st.hour);
873 SSVAL(p, 10, st.minute);
874 SSVAL(p, 12, st.second);
875 SSVAL(p, 14, st.millisecond);
877 *pp = p;
878 *plen = len;
881 /* Convert a notification message to a struct spoolss_Notify */
883 static void notify_one_value(struct spoolss_notify_msg *msg,
884 struct spoolss_Notify *data,
885 TALLOC_CTX *mem_ctx)
887 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
890 static void notify_string(struct spoolss_notify_msg *msg,
891 struct spoolss_Notify *data,
892 TALLOC_CTX *mem_ctx)
894 /* The length of the message includes the trailing \0 */
896 data->data.string.size = msg->len * 2;
897 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
898 if (!data->data.string.string) {
899 data->data.string.size = 0;
900 return;
904 static void notify_system_time(struct spoolss_notify_msg *msg,
905 struct spoolss_Notify *data,
906 TALLOC_CTX *mem_ctx)
908 data->data.string.string = NULL;
909 data->data.string.size = 0;
911 if (msg->len != sizeof(time_t)) {
912 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
913 msg->len));
914 return;
917 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
918 &data->data.string.string,
919 &data->data.string.size);
922 struct notify2_message_table {
923 const char *name;
924 void (*fn)(struct spoolss_notify_msg *msg,
925 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
928 static struct notify2_message_table printer_notify_table[] = {
929 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
930 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
931 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
932 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
933 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
934 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
935 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
936 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
937 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
938 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
939 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
940 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
941 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
942 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
943 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
944 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
945 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
946 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
947 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
950 static struct notify2_message_table job_notify_table[] = {
951 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
952 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
953 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
954 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
955 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
956 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
957 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
958 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
959 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
960 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
961 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
962 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
963 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
964 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
965 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
966 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
967 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
968 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
969 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
970 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
971 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
972 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
973 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
974 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
978 /***********************************************************************
979 Allocate talloc context for container object
980 **********************************************************************/
982 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
984 if ( !ctr )
985 return;
987 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
989 return;
992 /***********************************************************************
993 release all allocated memory and zero out structure
994 **********************************************************************/
996 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
998 if ( !ctr )
999 return;
1001 if ( ctr->ctx )
1002 talloc_destroy(ctr->ctx);
1004 ZERO_STRUCTP(ctr);
1006 return;
1009 /***********************************************************************
1010 **********************************************************************/
1012 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1014 if ( !ctr )
1015 return NULL;
1017 return ctr->ctx;
1020 /***********************************************************************
1021 **********************************************************************/
1023 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1025 if ( !ctr || !ctr->msg_groups )
1026 return NULL;
1028 if ( idx >= ctr->num_groups )
1029 return NULL;
1031 return &ctr->msg_groups[idx];
1035 /***********************************************************************
1036 How many groups of change messages do we have ?
1037 **********************************************************************/
1039 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1041 if ( !ctr )
1042 return 0;
1044 return ctr->num_groups;
1047 /***********************************************************************
1048 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1049 **********************************************************************/
1051 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1053 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1054 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1055 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1056 int i, new_slot;
1058 if ( !ctr || !msg )
1059 return 0;
1061 /* loop over all groups looking for a matching printer name */
1063 for ( i=0; i<ctr->num_groups; i++ ) {
1064 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1065 break;
1068 /* add a new group? */
1070 if ( i == ctr->num_groups ) {
1071 ctr->num_groups++;
1073 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1074 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1075 return 0;
1077 ctr->msg_groups = groups;
1079 /* clear the new entry and set the printer name */
1081 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1082 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1085 /* add the change messages; 'i' is the correct index now regardless */
1087 msg_grp = &ctr->msg_groups[i];
1089 msg_grp->num_msgs++;
1091 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1092 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1093 return 0;
1095 msg_grp->msgs = msg_list;
1097 new_slot = msg_grp->num_msgs-1;
1098 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1100 /* need to allocate own copy of data */
1102 if ( msg->len != 0 )
1103 msg_grp->msgs[new_slot].notify.data = (char *)
1104 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1106 return ctr->num_groups;
1109 static void construct_info_data(struct spoolss_Notify *info_data,
1110 enum spoolss_NotifyType type,
1111 uint16_t field, int id);
1113 /***********************************************************************
1114 Send a change notication message on all handles which have a call
1115 back registered
1116 **********************************************************************/
1118 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1119 struct printer_handle *prn_hnd,
1120 SPOOLSS_NOTIFY_MSG *messages,
1121 uint32_t num_msgs,
1122 struct spoolss_Notify **_notifies,
1123 int *_count)
1125 struct spoolss_Notify *notifies;
1126 SPOOLSS_NOTIFY_MSG *msg;
1127 int count = 0;
1128 uint32_t id;
1129 int i;
1131 notifies = talloc_zero_array(mem_ctx,
1132 struct spoolss_Notify, num_msgs);
1133 if (!notifies) {
1134 return ENOMEM;
1137 for (i = 0; i < num_msgs; i++) {
1139 msg = &messages[i];
1141 /* Are we monitoring this event? */
1143 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1144 continue;
1147 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1148 "for printer [%s]\n",
1149 msg->type, msg->field, prn_hnd->sharename));
1152 * if the is a printer notification handle and not a job
1153 * notification type, then set the id to 0.
1154 * Otherwise just use what was specified in the message.
1156 * When registering change notification on a print server
1157 * handle we always need to send back the id (snum) matching
1158 * the printer for which the change took place.
1159 * For change notify registered on a printer handle,
1160 * this does not matter and the id should be 0.
1162 * --jerry
1165 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1166 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1167 id = 0;
1168 } else {
1169 id = msg->id;
1172 /* Convert unix jobid to smb jobid */
1174 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1175 id = sysjob_to_jobid(msg->id);
1177 if (id == -1) {
1178 DEBUG(3, ("no such unix jobid %d\n",
1179 msg->id));
1180 continue;
1184 construct_info_data(&notifies[count],
1185 msg->type, msg->field, id);
1187 switch(msg->type) {
1188 case PRINTER_NOTIFY_TYPE:
1189 if (printer_notify_table[msg->field].fn) {
1190 printer_notify_table[msg->field].fn(msg,
1191 &notifies[count], mem_ctx);
1193 break;
1195 case JOB_NOTIFY_TYPE:
1196 if (job_notify_table[msg->field].fn) {
1197 job_notify_table[msg->field].fn(msg,
1198 &notifies[count], mem_ctx);
1200 break;
1202 default:
1203 DEBUG(5, ("Unknown notification type %d\n",
1204 msg->type));
1205 continue;
1208 count++;
1211 *_notifies = notifies;
1212 *_count = count;
1214 return 0;
1217 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1218 struct printer_handle *prn_hnd,
1219 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1221 struct spoolss_Notify *notifies;
1222 int count = 0;
1223 union spoolss_ReplyPrinterInfo info;
1224 struct spoolss_NotifyInfo info0;
1225 uint32_t reply_result;
1226 NTSTATUS status;
1227 WERROR werr;
1228 int ret;
1230 /* Is there notification on this handle? */
1231 if (prn_hnd->notify.cli_chan == NULL ||
1232 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1233 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1234 prn_hnd->notify.cli_chan->active_connections == 0) {
1235 return 0;
1238 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1239 prn_hnd->servername, prn_hnd->sharename));
1241 /* For this printer? Print servers always receive notifications. */
1242 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1243 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1244 return 0;
1247 DEBUG(10,("Our printer\n"));
1249 /* build the array of change notifications */
1250 ret = build_notify2_messages(mem_ctx, prn_hnd,
1251 msg_group->msgs,
1252 msg_group->num_msgs,
1253 &notifies, &count);
1254 if (ret) {
1255 return ret;
1258 info0.version = 0x2;
1259 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1260 info0.count = count;
1261 info0.notifies = notifies;
1263 info.info0 = &info0;
1265 status = dcerpc_spoolss_RouterReplyPrinterEx(
1266 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1267 mem_ctx,
1268 &prn_hnd->notify.cli_hnd,
1269 prn_hnd->notify.change, /* color */
1270 prn_hnd->notify.flags,
1271 &reply_result,
1272 0, /* reply_type, must be 0 */
1273 info, &werr);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1276 "failed: %s\n",
1277 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1278 nt_errstr(status)));
1279 werr = ntstatus_to_werror(status);
1280 } else if (!W_ERROR_IS_OK(werr)) {
1281 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1282 "failed: %s\n",
1283 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1284 win_errstr(werr)));
1286 switch (reply_result) {
1287 case 0:
1288 break;
1289 case PRINTER_NOTIFY_INFO_DISCARDED:
1290 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1291 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1292 break;
1293 default:
1294 break;
1297 return 0;
1300 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1302 struct printer_handle *p;
1303 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1304 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1305 int ret;
1307 if ( !msg_group ) {
1308 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1309 return;
1312 if (!msg_group->msgs) {
1313 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1314 return;
1317 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1319 /* loop over all printers */
1321 for (p = printers_list; p; p = p->next) {
1322 ret = send_notify2_printer(mem_ctx, p, msg_group);
1323 if (ret) {
1324 goto done;
1328 done:
1329 DEBUG(8,("send_notify2_changes: Exit...\n"));
1330 return;
1333 /***********************************************************************
1334 **********************************************************************/
1336 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1339 uint32_t tv_sec, tv_usec;
1340 size_t offset = 0;
1342 /* Unpack message */
1344 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1345 msg->printer);
1347 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1348 &tv_sec, &tv_usec,
1349 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1351 if (msg->len == 0)
1352 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1353 &msg->notify.value[0], &msg->notify.value[1]);
1354 else
1355 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1356 &msg->len, &msg->notify.data);
1358 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1359 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1361 tv->tv_sec = tv_sec;
1362 tv->tv_usec = tv_usec;
1364 if (msg->len == 0)
1365 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1366 msg->notify.value[1]));
1367 else
1368 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1370 return true;
1373 /********************************************************************
1374 Receive a notify2 message list
1375 ********************************************************************/
1377 static void receive_notify2_message_list(struct messaging_context *msg,
1378 void *private_data,
1379 uint32_t msg_type,
1380 struct server_id server_id,
1381 DATA_BLOB *data)
1383 size_t msg_count, i;
1384 char *buf = (char *)data->data;
1385 char *msg_ptr;
1386 size_t msg_len;
1387 SPOOLSS_NOTIFY_MSG notify;
1388 SPOOLSS_NOTIFY_MSG_CTR messages;
1389 int num_groups;
1391 if (data->length < 4) {
1392 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1393 return;
1396 msg_count = IVAL(buf, 0);
1397 msg_ptr = buf + 4;
1399 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1401 if (msg_count == 0) {
1402 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1403 return;
1406 /* initialize the container */
1408 ZERO_STRUCT( messages );
1409 notify_msg_ctr_init( &messages );
1412 * build message groups for each printer identified
1413 * in a change_notify msg. Remember that a PCN message
1414 * includes the handle returned for the srv_spoolss_replyopenprinter()
1415 * call. Therefore messages are grouped according to printer handle.
1418 for ( i=0; i<msg_count; i++ ) {
1419 struct timeval msg_tv;
1421 if (msg_ptr + 4 - buf > data->length) {
1422 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1423 return;
1426 msg_len = IVAL(msg_ptr,0);
1427 msg_ptr += 4;
1429 if (msg_ptr + msg_len - buf > data->length) {
1430 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1431 return;
1434 /* unpack messages */
1436 ZERO_STRUCT( notify );
1437 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1438 msg_ptr += msg_len;
1440 /* add to correct list in container */
1442 notify_msg_ctr_addmsg( &messages, &notify );
1444 /* free memory that might have been allocated by notify2_unpack_msg() */
1446 if ( notify.len != 0 )
1447 SAFE_FREE( notify.notify.data );
1450 /* process each group of messages */
1452 num_groups = notify_msg_ctr_numgroups( &messages );
1453 for ( i=0; i<num_groups; i++ )
1454 send_notify2_changes( &messages, i );
1457 /* cleanup */
1459 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1460 (uint32_t)msg_count ));
1462 notify_msg_ctr_destroy( &messages );
1464 return;
1467 /********************************************************************
1468 Send a message to ourself about new driver being installed
1469 so we can upgrade the information for each printer bound to this
1470 driver
1471 ********************************************************************/
1473 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1474 struct messaging_context *msg_ctx)
1476 int len = strlen(drivername);
1478 if (!len)
1479 return false;
1481 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1482 drivername));
1484 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1485 MSG_PRINTER_DRVUPGRADE,
1486 (const uint8_t *)drivername, len+1);
1488 return true;
1491 void srv_spoolss_cleanup(void)
1493 struct printer_session_counter *session_counter;
1495 for (session_counter = counter_list;
1496 session_counter != NULL;
1497 session_counter = counter_list) {
1498 DLIST_REMOVE(counter_list, session_counter);
1499 TALLOC_FREE(session_counter);
1503 /**********************************************************************
1504 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1505 over all printers, upgrading ones as necessary
1506 This is now *ONLY* called inside the background lpq updater. JRA.
1507 **********************************************************************/
1509 void do_drv_upgrade_printer(struct messaging_context *msg,
1510 void *private_data,
1511 uint32_t msg_type,
1512 struct server_id server_id,
1513 DATA_BLOB *data)
1515 TALLOC_CTX *tmp_ctx;
1516 const struct auth_session_info *session_info = get_session_info_system();
1517 struct spoolss_PrinterInfo2 *pinfo2;
1518 WERROR result;
1519 const char *drivername;
1520 int snum;
1521 int n_services = lp_numservices();
1522 struct dcerpc_binding_handle *b = NULL;
1524 tmp_ctx = talloc_new(NULL);
1525 if (!tmp_ctx) return;
1527 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1528 if (!drivername) {
1529 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1530 goto done;
1533 DEBUG(10, ("do_drv_upgrade_printer: "
1534 "Got message for new driver [%s]\n", drivername));
1536 /* Iterate the printer list */
1538 for (snum = 0; snum < n_services; snum++) {
1539 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1540 continue;
1543 /* ignore [printers] share */
1544 if (strequal(lp_const_servicename(snum), "printers")) {
1545 continue;
1548 if (b == NULL) {
1549 result = winreg_printer_binding_handle(tmp_ctx,
1550 session_info,
1551 msg,
1552 &b);
1553 if (!W_ERROR_IS_OK(result)) {
1554 break;
1558 result = winreg_get_printer(tmp_ctx, b,
1559 lp_const_servicename(snum),
1560 &pinfo2);
1562 if (!W_ERROR_IS_OK(result)) {
1563 continue;
1566 if (!pinfo2->drivername) {
1567 continue;
1570 if (strcmp(drivername, pinfo2->drivername) != 0) {
1571 continue;
1574 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1576 /* all we care about currently is the change_id */
1577 result = winreg_printer_update_changeid(tmp_ctx, b,
1578 pinfo2->printername);
1580 if (!W_ERROR_IS_OK(result)) {
1581 DEBUG(3, ("do_drv_upgrade_printer: "
1582 "Failed to update changeid [%s]\n",
1583 win_errstr(result)));
1587 /* all done */
1588 done:
1589 talloc_free(tmp_ctx);
1592 /********************************************************************
1593 Update the cache for all printq's with a registered client
1594 connection
1595 ********************************************************************/
1597 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1599 struct printer_handle *printer = printers_list;
1600 int snum;
1602 /* loop through all printers and update the cache where
1603 a client is connected */
1604 while (printer) {
1605 if ((printer->printer_type == SPLHND_PRINTER) &&
1606 ((printer->notify.cli_chan != NULL) &&
1607 (printer->notify.cli_chan->active_connections > 0))) {
1608 snum = print_queue_snum(printer->sharename);
1609 print_queue_status(msg_ctx, snum, NULL, NULL);
1612 printer = printer->next;
1615 return;
1618 /****************************************************************
1619 _spoolss_OpenPrinter
1620 ****************************************************************/
1622 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1623 struct spoolss_OpenPrinter *r)
1625 struct spoolss_OpenPrinterEx e;
1626 struct spoolss_UserLevel1 level1;
1627 WERROR werr;
1629 ZERO_STRUCT(level1);
1631 e.in.printername = r->in.printername;
1632 e.in.datatype = r->in.datatype;
1633 e.in.devmode_ctr = r->in.devmode_ctr;
1634 e.in.access_mask = r->in.access_mask;
1635 e.in.userlevel_ctr.level = 1;
1636 e.in.userlevel_ctr.user_info.level1 = &level1;
1638 e.out.handle = r->out.handle;
1640 werr = _spoolss_OpenPrinterEx(p, &e);
1642 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1643 /* OpenPrinterEx returns this for a bad
1644 * printer name. We must return WERR_INVALID_PRINTER_NAME
1645 * instead.
1647 werr = WERR_INVALID_PRINTER_NAME;
1650 return werr;
1653 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1654 struct spoolss_DeviceMode *orig,
1655 struct spoolss_DeviceMode **dest)
1657 struct spoolss_DeviceMode *dm;
1659 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1660 if (!dm) {
1661 return WERR_NOMEM;
1664 /* copy all values, then duplicate strings and structs */
1665 *dm = *orig;
1667 dm->devicename = talloc_strdup(dm, orig->devicename);
1668 if (!dm->devicename) {
1669 return WERR_NOMEM;
1671 dm->formname = talloc_strdup(dm, orig->formname);
1672 if (!dm->formname) {
1673 return WERR_NOMEM;
1675 if (orig->driverextra_data.data) {
1676 dm->driverextra_data.data =
1677 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1678 orig->driverextra_data.length);
1679 if (!dm->driverextra_data.data) {
1680 return WERR_NOMEM;
1684 *dest = dm;
1685 return WERR_OK;
1688 /****************************************************************
1689 _spoolss_OpenPrinterEx
1690 ****************************************************************/
1692 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1693 struct spoolss_OpenPrinterEx *r)
1695 int snum;
1696 char *raddr;
1697 char *rhost;
1698 struct printer_handle *Printer=NULL;
1699 WERROR result;
1700 int rc;
1702 if (!r->in.printername) {
1703 return WERR_INVALID_PARAM;
1706 if (!*r->in.printername) {
1707 return WERR_INVALID_PARAM;
1710 if (r->in.userlevel_ctr.level > 3) {
1711 return WERR_INVALID_PARAM;
1713 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1714 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1715 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1716 return WERR_INVALID_PARAM;
1720 * The printcap printer share inventory is updated on client
1721 * enumeration. For clients that do not perform enumeration prior to
1722 * access, such as cupssmbadd, we reinitialise the printer share
1723 * inventory on open as well.
1725 become_root();
1726 delete_and_reload_printers(server_event_context(), p->msg_ctx);
1727 unbecome_root();
1729 /* some sanity check because you can open a printer or a print server */
1730 /* aka: \\server\printer or \\server */
1732 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1734 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1735 if (!W_ERROR_IS_OK(result)) {
1736 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1737 "for printer %s\n", r->in.printername));
1738 ZERO_STRUCTP(r->out.handle);
1739 return result;
1742 Printer = find_printer_index_by_hnd(p, r->out.handle);
1743 if ( !Printer ) {
1744 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1745 "handle we created for printer %s\n", r->in.printername));
1746 close_printer_handle(p, r->out.handle);
1747 ZERO_STRUCTP(r->out.handle);
1748 return WERR_INVALID_PARAM;
1752 * First case: the user is opening the print server:
1754 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1755 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1757 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1758 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1759 * or if the user is listed in the smb.conf printer admin parameter.
1761 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1762 * client view printer folder, but does not show the MSAPW.
1764 * Note: this test needs code to check access rights here too. Jeremy
1765 * could you look at this?
1767 * Second case: the user is opening a printer:
1768 * NT doesn't let us connect to a printer if the connecting user
1769 * doesn't have print permission.
1771 * Third case: user is opening a Port Monitor
1772 * access checks same as opening a handle to the print server.
1775 switch (Printer->printer_type )
1777 case SPLHND_SERVER:
1778 case SPLHND_PORTMON_TCP:
1779 case SPLHND_PORTMON_LOCAL:
1780 /* Printserver handles use global struct... */
1782 snum = -1;
1784 /* Map standard access rights to object specific access rights */
1786 se_map_standard(&r->in.access_mask,
1787 &printserver_std_mapping);
1789 /* Deny any object specific bits that don't apply to print
1790 servers (i.e printer and job specific bits) */
1792 r->in.access_mask &= SEC_MASK_SPECIFIC;
1794 if (r->in.access_mask &
1795 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1796 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1797 close_printer_handle(p, r->out.handle);
1798 ZERO_STRUCTP(r->out.handle);
1799 return WERR_ACCESS_DENIED;
1802 /* Allow admin access */
1804 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1806 if (!lp_show_add_printer_wizard()) {
1807 close_printer_handle(p, r->out.handle);
1808 ZERO_STRUCTP(r->out.handle);
1809 return WERR_ACCESS_DENIED;
1812 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1813 and not a printer admin, then fail */
1815 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1816 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1817 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1818 p->session_info->security_token)) {
1819 close_printer_handle(p, r->out.handle);
1820 ZERO_STRUCTP(r->out.handle);
1821 DEBUG(3,("access DENIED as user is not root, "
1822 "has no printoperator privilege, "
1823 "not a member of the printoperator builtin group and "
1824 "is not in printer admin list"));
1825 return WERR_ACCESS_DENIED;
1828 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830 else
1832 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1835 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1836 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838 /* We fall through to return WERR_OK */
1839 break;
1841 case SPLHND_PRINTER:
1842 /* NT doesn't let us connect to a printer if the connecting user
1843 doesn't have print permission. */
1845 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1846 close_printer_handle(p, r->out.handle);
1847 ZERO_STRUCTP(r->out.handle);
1848 return WERR_BADFID;
1851 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1852 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1855 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1857 /* map an empty access mask to the minimum access mask */
1858 if (r->in.access_mask == 0x0)
1859 r->in.access_mask = PRINTER_ACCESS_USE;
1862 * If we are not serving the printer driver for this printer,
1863 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1864 * will keep NT clients happy --jerry
1867 if (lp_use_client_driver(snum)
1868 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1870 r->in.access_mask = PRINTER_ACCESS_USE;
1873 /* check smb.conf parameters and the the sec_desc */
1874 raddr = tsocket_address_inet_addr_string(p->remote_address,
1875 p->mem_ctx);
1876 if (raddr == NULL) {
1877 return WERR_NOMEM;
1880 rc = get_remote_hostname(p->remote_address,
1881 &rhost,
1882 p->mem_ctx);
1883 if (rc < 0) {
1884 return WERR_NOMEM;
1886 if (strequal(rhost, "UNKNOWN")) {
1887 rhost = raddr;
1890 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1891 rhost, raddr)) {
1892 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1893 ZERO_STRUCTP(r->out.handle);
1894 return WERR_ACCESS_DENIED;
1897 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1898 p->session_info->security_token, snum) ||
1899 !W_ERROR_IS_OK(print_access_check(p->session_info,
1900 p->msg_ctx,
1901 snum,
1902 r->in.access_mask))) {
1903 DEBUG(3, ("access DENIED for printer open\n"));
1904 close_printer_handle(p, r->out.handle);
1905 ZERO_STRUCTP(r->out.handle);
1906 return WERR_ACCESS_DENIED;
1909 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1910 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1911 close_printer_handle(p, r->out.handle);
1912 ZERO_STRUCTP(r->out.handle);
1913 return WERR_ACCESS_DENIED;
1916 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1917 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1918 else
1919 r->in.access_mask = PRINTER_ACCESS_USE;
1921 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1922 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924 winreg_create_printer_internal(p->mem_ctx,
1925 get_session_info_system(),
1926 p->msg_ctx,
1927 lp_const_servicename(snum));
1929 break;
1931 default:
1932 /* sanity check to prevent programmer error */
1933 ZERO_STRUCTP(r->out.handle);
1934 return WERR_BADFID;
1937 Printer->access_granted = r->in.access_mask;
1940 * If the client sent a devmode in the OpenPrinter() call, then
1941 * save it here in case we get a job submission on this handle
1944 if ((Printer->printer_type != SPLHND_SERVER)
1945 && (r->in.devmode_ctr.devmode != NULL)) {
1946 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1947 &Printer->devmode);
1950 return WERR_OK;
1953 /****************************************************************
1954 _spoolss_ClosePrinter
1955 ****************************************************************/
1957 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1958 struct spoolss_ClosePrinter *r)
1960 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962 if (Printer && Printer->document_started) {
1963 struct spoolss_EndDocPrinter e;
1965 e.in.handle = r->in.handle;
1967 _spoolss_EndDocPrinter(p, &e);
1970 if (!close_printer_handle(p, r->in.handle))
1971 return WERR_BADFID;
1973 /* clear the returned printer handle. Observed behavior
1974 from Win2k server. Don't think this really matters.
1975 Previous code just copied the value of the closed
1976 handle. --jerry */
1978 ZERO_STRUCTP(r->out.handle);
1980 return WERR_OK;
1983 /****************************************************************
1984 _spoolss_DeletePrinter
1985 ****************************************************************/
1987 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1988 struct spoolss_DeletePrinter *r)
1990 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1991 WERROR result;
1992 int snum;
1994 if (Printer && Printer->document_started) {
1995 struct spoolss_EndDocPrinter e;
1997 e.in.handle = r->in.handle;
1999 _spoolss_EndDocPrinter(p, &e);
2002 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2003 winreg_delete_printer_key_internal(p->mem_ctx,
2004 get_session_info_system(),
2005 p->msg_ctx,
2006 lp_const_servicename(snum),
2007 "");
2010 result = delete_printer_handle(p, r->in.handle);
2012 return result;
2015 /*******************************************************************
2016 * static function to lookup the version id corresponding to an
2017 * long architecture string
2018 ******************************************************************/
2020 static const struct print_architecture_table_node archi_table[]= {
2022 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2023 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2024 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2025 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2026 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2027 {"Windows IA64", SPL_ARCH_IA64, 3 },
2028 {"Windows x64", SPL_ARCH_X64, 3 },
2029 {NULL, "", -1 }
2032 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2033 SPOOLSS_DRIVER_VERSION_NT35,
2034 SPOOLSS_DRIVER_VERSION_NT4,
2035 SPOOLSS_DRIVER_VERSION_200X,
2036 -1};
2038 static int get_version_id(const char *arch)
2040 int i;
2042 for (i=0; archi_table[i].long_archi != NULL; i++)
2044 if (strcmp(arch, archi_table[i].long_archi) == 0)
2045 return (archi_table[i].version);
2048 return -1;
2051 /****************************************************************
2052 _spoolss_DeletePrinterDriver
2053 ****************************************************************/
2055 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2056 struct spoolss_DeletePrinterDriver *r)
2059 struct spoolss_DriverInfo8 *info = NULL;
2060 int version;
2061 WERROR status;
2062 struct dcerpc_binding_handle *b;
2063 TALLOC_CTX *tmp_ctx = NULL;
2064 int i;
2065 bool found;
2067 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2068 and not a printer admin, then fail */
2070 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2071 !security_token_has_privilege(p->session_info->security_token,
2072 SEC_PRIV_PRINT_OPERATOR)) {
2073 return WERR_ACCESS_DENIED;
2076 /* check that we have a valid driver name first */
2078 if ((version = get_version_id(r->in.architecture)) == -1) {
2079 return WERR_INVALID_ENVIRONMENT;
2082 tmp_ctx = talloc_new(p->mem_ctx);
2083 if (!tmp_ctx) {
2084 return WERR_NOMEM;
2087 status = winreg_printer_binding_handle(tmp_ctx,
2088 get_session_info_system(),
2089 p->msg_ctx,
2090 &b);
2091 if (!W_ERROR_IS_OK(status)) {
2092 goto done;
2095 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2096 status = winreg_get_driver(tmp_ctx, b,
2097 r->in.architecture, r->in.driver,
2098 drv_cversion[i], &info);
2099 if (!W_ERROR_IS_OK(status)) {
2100 DEBUG(5, ("skipping del of driver with version %d\n",
2101 drv_cversion[i]));
2102 continue;
2104 found = true;
2106 if (printer_driver_in_use(tmp_ctx, b, info)) {
2107 status = WERR_PRINTER_DRIVER_IN_USE;
2108 goto done;
2111 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2112 if (!W_ERROR_IS_OK(status)) {
2113 DEBUG(0, ("failed del of driver with version %d\n",
2114 drv_cversion[i]));
2115 goto done;
2118 if (found == false) {
2119 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2120 status = WERR_UNKNOWN_PRINTER_DRIVER;
2121 } else {
2122 status = WERR_OK;
2125 done:
2126 talloc_free(tmp_ctx);
2128 return status;
2131 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2132 struct pipes_struct *p,
2133 struct spoolss_DeletePrinterDriverEx *r,
2134 struct dcerpc_binding_handle *b,
2135 struct spoolss_DriverInfo8 *info)
2137 WERROR status;
2138 bool delete_files;
2140 if (printer_driver_in_use(mem_ctx, b, info)) {
2141 status = WERR_PRINTER_DRIVER_IN_USE;
2142 goto done;
2146 * we have a couple of cases to consider.
2147 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2148 * then the delete should fail if **any** files overlap with
2149 * other drivers
2150 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2151 * non-overlapping files
2152 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2153 * are set, then do not delete any files
2154 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2157 delete_files = r->in.delete_flags
2158 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2161 if (delete_files) {
2162 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2163 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2164 status = WERR_PRINTER_DRIVER_IN_USE;
2165 goto done;
2168 * printer_driver_files_in_use() has trimmed overlapping files
2169 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2174 status = winreg_del_driver(mem_ctx, b, info, info->version);
2175 if (!W_ERROR_IS_OK(status)) {
2176 goto done;
2180 * now delete any associated files if delete_files is
2181 * true. Even if this part failes, we return succes
2182 * because the driver doesn not exist any more
2184 if (delete_files) {
2185 delete_driver_files(p->session_info, info);
2188 done:
2189 return status;
2192 /****************************************************************
2193 _spoolss_DeletePrinterDriverEx
2194 ****************************************************************/
2196 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2197 struct spoolss_DeletePrinterDriverEx *r)
2199 struct spoolss_DriverInfo8 *info = NULL;
2200 WERROR status;
2201 struct dcerpc_binding_handle *b;
2202 TALLOC_CTX *tmp_ctx = NULL;
2203 int i;
2204 bool found;
2206 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2207 and not a printer admin, then fail */
2209 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2210 !security_token_has_privilege(p->session_info->security_token,
2211 SEC_PRIV_PRINT_OPERATOR)) {
2212 return WERR_ACCESS_DENIED;
2215 /* check that we have a valid driver name first */
2216 if (get_version_id(r->in.architecture) == -1) {
2217 /* this is what NT returns */
2218 return WERR_INVALID_ENVIRONMENT;
2221 tmp_ctx = talloc_new(p->mem_ctx);
2222 if (!tmp_ctx) {
2223 return WERR_NOMEM;
2226 status = winreg_printer_binding_handle(tmp_ctx,
2227 get_session_info_system(),
2228 p->msg_ctx,
2229 &b);
2230 if (!W_ERROR_IS_OK(status)) {
2231 goto done;
2234 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2235 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2236 && (drv_cversion[i] != r->in.version)) {
2237 continue;
2240 /* check if a driver with this version exists before delete */
2241 status = winreg_get_driver(tmp_ctx, b,
2242 r->in.architecture, r->in.driver,
2243 drv_cversion[i], &info);
2244 if (!W_ERROR_IS_OK(status)) {
2245 DEBUG(5, ("skipping del of driver with version %d\n",
2246 drv_cversion[i]));
2247 continue;
2249 found = true;
2251 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2252 if (!W_ERROR_IS_OK(status)) {
2253 DEBUG(0, ("failed to delete driver with version %d\n",
2254 drv_cversion[i]));
2255 goto done;
2258 if (found == false) {
2259 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2260 status = WERR_UNKNOWN_PRINTER_DRIVER;
2261 } else {
2262 status = WERR_OK;
2265 done:
2266 talloc_free(tmp_ctx);
2267 return status;
2271 /********************************************************************
2272 GetPrinterData on a printer server Handle.
2273 ********************************************************************/
2275 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2276 const char *value,
2277 enum winreg_Type *type,
2278 union spoolss_PrinterData *data)
2280 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2282 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2283 *type = REG_DWORD;
2284 SIVAL(&data->value, 0, 0x00);
2285 return WERR_OK;
2288 if (!strcasecmp_m(value, "BeepEnabled")) {
2289 *type = REG_DWORD;
2290 SIVAL(&data->value, 0, 0x00);
2291 return WERR_OK;
2294 if (!strcasecmp_m(value, "EventLog")) {
2295 *type = REG_DWORD;
2296 /* formally was 0x1b */
2297 SIVAL(&data->value, 0, 0x00);
2298 return WERR_OK;
2301 if (!strcasecmp_m(value, "NetPopup")) {
2302 *type = REG_DWORD;
2303 SIVAL(&data->value, 0, 0x00);
2304 return WERR_OK;
2307 if (!strcasecmp_m(value, "MajorVersion")) {
2308 *type = REG_DWORD;
2310 /* Windows NT 4.0 seems to not allow uploading of drivers
2311 to a server that reports 0x3 as the MajorVersion.
2312 need to investigate more how Win2k gets around this .
2313 -- jerry */
2315 if (RA_WINNT == get_remote_arch()) {
2316 SIVAL(&data->value, 0, 0x02);
2317 } else {
2318 SIVAL(&data->value, 0, 0x03);
2321 return WERR_OK;
2324 if (!strcasecmp_m(value, "MinorVersion")) {
2325 *type = REG_DWORD;
2326 SIVAL(&data->value, 0, 0x00);
2327 return WERR_OK;
2330 /* REG_BINARY
2331 * uint32_t size = 0x114
2332 * uint32_t major = 5
2333 * uint32_t minor = [0|1]
2334 * uint32_t build = [2195|2600]
2335 * extra unicode string = e.g. "Service Pack 3"
2337 if (!strcasecmp_m(value, "OSVersion")) {
2338 DATA_BLOB blob;
2339 enum ndr_err_code ndr_err;
2340 struct spoolss_OSVersion os;
2342 os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2343 "spoolss", "os_major", 5);
2344 /* Windows 2000 == 5.0 */
2345 os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2346 "spoolss", "os_minor", 0);
2347 os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2348 "spoolss", "os_build", 2195);
2349 os.extra_string = ""; /* leave extra string empty */
2351 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2352 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2353 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2354 return WERR_GENERAL_FAILURE;
2357 if (DEBUGLEVEL >= 10) {
2358 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2361 *type = REG_BINARY;
2362 data->binary = blob;
2364 return WERR_OK;
2368 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2369 *type = REG_SZ;
2371 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2372 W_ERROR_HAVE_NO_MEMORY(data->string);
2374 return WERR_OK;
2377 if (!strcasecmp_m(value, "Architecture")) {
2378 *type = REG_SZ;
2379 data->string = talloc_strdup(mem_ctx,
2380 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2381 W_ERROR_HAVE_NO_MEMORY(data->string);
2383 return WERR_OK;
2386 if (!strcasecmp_m(value, "DsPresent")) {
2387 *type = REG_DWORD;
2389 /* only show the publish check box if we are a
2390 member of a AD domain */
2392 if (lp_security() == SEC_ADS) {
2393 SIVAL(&data->value, 0, 0x01);
2394 } else {
2395 SIVAL(&data->value, 0, 0x00);
2397 return WERR_OK;
2400 if (!strcasecmp_m(value, "DNSMachineName")) {
2401 const char *hostname = get_mydnsfullname();
2403 if (!hostname) {
2404 return WERR_BADFILE;
2407 *type = REG_SZ;
2408 data->string = talloc_strdup(mem_ctx, hostname);
2409 W_ERROR_HAVE_NO_MEMORY(data->string);
2411 return WERR_OK;
2414 *type = REG_NONE;
2416 return WERR_INVALID_PARAM;
2419 /****************************************************************
2420 _spoolss_GetPrinterData
2421 ****************************************************************/
2423 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2424 struct spoolss_GetPrinterData *r)
2426 struct spoolss_GetPrinterDataEx r2;
2428 r2.in.handle = r->in.handle;
2429 r2.in.key_name = "PrinterDriverData";
2430 r2.in.value_name = r->in.value_name;
2431 r2.in.offered = r->in.offered;
2432 r2.out.type = r->out.type;
2433 r2.out.data = r->out.data;
2434 r2.out.needed = r->out.needed;
2436 return _spoolss_GetPrinterDataEx(p, &r2);
2439 /*********************************************************
2440 Connect to the client machine.
2441 **********************************************************/
2443 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2444 struct sockaddr_storage *client_ss, const char *remote_machine)
2446 NTSTATUS ret;
2447 struct sockaddr_storage rm_addr;
2448 char addr[INET6_ADDRSTRLEN];
2450 if ( is_zero_addr(client_ss) ) {
2451 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2452 remote_machine));
2453 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2454 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2455 return false;
2457 print_sockaddr(addr, sizeof(addr), &rm_addr);
2458 } else {
2459 rm_addr = *client_ss;
2460 print_sockaddr(addr, sizeof(addr), &rm_addr);
2461 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2462 addr));
2465 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2466 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2467 addr));
2468 return false;
2471 /* setup the connection */
2472 ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2473 &rm_addr, 0, "IPC$", "IPC",
2474 "", /* username */
2475 "", /* domain */
2476 "", /* password */
2477 0, lp_client_signing());
2479 if ( !NT_STATUS_IS_OK( ret ) ) {
2480 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2481 remote_machine ));
2482 return false;
2485 if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2486 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2487 cli_shutdown(*pp_cli);
2488 return false;
2492 * Ok - we have an anonymous connection to the IPC$ share.
2493 * Now start the NT Domain stuff :-).
2496 ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2497 if (!NT_STATUS_IS_OK(ret)) {
2498 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2499 remote_machine, nt_errstr(ret)));
2500 cli_shutdown(*pp_cli);
2501 return false;
2504 return true;
2507 /***************************************************************************
2508 Connect to the client.
2509 ****************************************************************************/
2511 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2512 uint32_t localprinter,
2513 enum winreg_Type type,
2514 struct policy_handle *handle,
2515 struct notify_back_channel **_chan,
2516 struct sockaddr_storage *client_ss,
2517 struct messaging_context *msg_ctx)
2519 WERROR result;
2520 NTSTATUS status;
2521 struct notify_back_channel *chan;
2523 for (chan = back_channels; chan; chan = chan->next) {
2524 if (memcmp(&chan->client_address, client_ss,
2525 sizeof(struct sockaddr_storage)) == 0) {
2526 break;
2531 * If it's the first connection, contact the client
2532 * and connect to the IPC$ share anonymously
2534 if (!chan) {
2535 fstring unix_printer;
2537 /* the +2 is to strip the leading 2 backslashs */
2538 fstrcpy(unix_printer, printer + 2);
2540 chan = talloc_zero(NULL, struct notify_back_channel);
2541 if (!chan) {
2542 return false;
2544 chan->client_address = *client_ss;
2546 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2547 TALLOC_FREE(chan);
2548 return false;
2551 DLIST_ADD(back_channels, chan);
2553 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2554 receive_notify2_message_list);
2557 if (chan->cli_pipe == NULL ||
2558 chan->cli_pipe->binding_handle == NULL) {
2559 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2560 "NULL %s for printer %s\n",
2561 chan->cli_pipe == NULL ?
2562 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2563 printer));
2564 return false;
2568 * Tell the specific printing tdb we want messages for this printer
2569 * by registering our PID.
2572 if (!print_notify_register_pid(snum)) {
2573 DEBUG(0, ("Failed to register our pid for printer %s\n",
2574 printer));
2577 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2578 talloc_tos(),
2579 printer,
2580 localprinter,
2581 type,
2583 NULL,
2584 handle,
2585 &result);
2586 if (!NT_STATUS_IS_OK(status)) {
2587 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2588 result = ntstatus_to_werror(status);
2589 } else if (!W_ERROR_IS_OK(result)) {
2590 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2593 chan->active_connections++;
2594 *_chan = chan;
2596 return (W_ERROR_IS_OK(result));
2599 /****************************************************************
2600 ****************************************************************/
2602 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2603 const struct spoolss_NotifyOption *r)
2605 struct spoolss_NotifyOption *option;
2606 uint32_t i,k;
2608 if (!r) {
2609 return NULL;
2612 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2613 if (!option) {
2614 return NULL;
2617 *option = *r;
2619 if (!option->count) {
2620 return option;
2623 option->types = talloc_zero_array(option,
2624 struct spoolss_NotifyOptionType, option->count);
2625 if (!option->types) {
2626 talloc_free(option);
2627 return NULL;
2630 for (i=0; i < option->count; i++) {
2631 option->types[i] = r->types[i];
2633 if (option->types[i].count) {
2634 option->types[i].fields = talloc_zero_array(option,
2635 union spoolss_Field, option->types[i].count);
2636 if (!option->types[i].fields) {
2637 talloc_free(option);
2638 return NULL;
2640 for (k=0; k<option->types[i].count; k++) {
2641 option->types[i].fields[k] =
2642 r->types[i].fields[k];
2647 return option;
2650 /****************************************************************
2651 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2653 * before replying OK: status=0 a rpc call is made to the workstation
2654 * asking ReplyOpenPrinter
2656 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2657 * called from api_spoolss_rffpcnex
2658 ****************************************************************/
2660 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2661 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2663 int snum = -1;
2664 struct spoolss_NotifyOption *option = r->in.notify_options;
2665 struct sockaddr_storage client_ss;
2666 ssize_t client_len;
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 "remote_address is %s\n",
2699 tsocket_address_string(p->remote_address, p->mem_ctx)));
2701 if (!lp_print_notify_backchannel(snum)) {
2702 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2703 "backchannel disabled\n"));
2704 return WERR_SERVER_UNAVAILABLE;
2707 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2708 (struct sockaddr *) &client_ss,
2709 sizeof(struct sockaddr_storage));
2710 if (client_len < 0) {
2711 return WERR_NOMEM;
2714 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2715 Printer->notify.printerlocal, REG_SZ,
2716 &Printer->notify.cli_hnd,
2717 &Printer->notify.cli_chan,
2718 &client_ss, p->msg_ctx)) {
2719 return WERR_SERVER_UNAVAILABLE;
2722 return WERR_OK;
2725 /*******************************************************************
2726 * fill a notify_info_data with the servername
2727 ********************************************************************/
2729 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2730 int snum,
2731 struct spoolss_Notify *data,
2732 print_queue_struct *queue,
2733 struct spoolss_PrinterInfo2 *pinfo2,
2734 TALLOC_CTX *mem_ctx)
2736 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2739 /*******************************************************************
2740 * fill a notify_info_data with the printername (not including the servername).
2741 ********************************************************************/
2743 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2744 int snum,
2745 struct spoolss_Notify *data,
2746 print_queue_struct *queue,
2747 struct spoolss_PrinterInfo2 *pinfo2,
2748 TALLOC_CTX *mem_ctx)
2750 /* the notify name should not contain the \\server\ part */
2751 const char *p = strrchr(pinfo2->printername, '\\');
2753 if (!p) {
2754 p = pinfo2->printername;
2755 } else {
2756 p++;
2759 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2762 /*******************************************************************
2763 * fill a notify_info_data with the servicename
2764 ********************************************************************/
2766 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2767 int snum,
2768 struct spoolss_Notify *data,
2769 print_queue_struct *queue,
2770 struct spoolss_PrinterInfo2 *pinfo2,
2771 TALLOC_CTX *mem_ctx)
2773 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2776 /*******************************************************************
2777 * fill a notify_info_data with the port name
2778 ********************************************************************/
2780 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2781 int snum,
2782 struct spoolss_Notify *data,
2783 print_queue_struct *queue,
2784 struct spoolss_PrinterInfo2 *pinfo2,
2785 TALLOC_CTX *mem_ctx)
2787 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2790 /*******************************************************************
2791 * fill a notify_info_data with the printername
2792 * but it doesn't exist, have to see what to do
2793 ********************************************************************/
2795 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2796 int snum,
2797 struct spoolss_Notify *data,
2798 print_queue_struct *queue,
2799 struct spoolss_PrinterInfo2 *pinfo2,
2800 TALLOC_CTX *mem_ctx)
2802 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2805 /*******************************************************************
2806 * fill a notify_info_data with the comment
2807 ********************************************************************/
2809 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2810 int snum,
2811 struct spoolss_Notify *data,
2812 print_queue_struct *queue,
2813 struct spoolss_PrinterInfo2 *pinfo2,
2814 TALLOC_CTX *mem_ctx)
2816 const char *p;
2818 if (*pinfo2->comment == '\0') {
2819 p = lp_comment(talloc_tos(), snum);
2820 } else {
2821 p = pinfo2->comment;
2824 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2827 /*******************************************************************
2828 * fill a notify_info_data with the comment
2829 * location = "Room 1, floor 2, building 3"
2830 ********************************************************************/
2832 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2833 int snum,
2834 struct spoolss_Notify *data,
2835 print_queue_struct *queue,
2836 struct spoolss_PrinterInfo2 *pinfo2,
2837 TALLOC_CTX *mem_ctx)
2839 const char *loc = pinfo2->location;
2840 NTSTATUS status;
2842 status = printer_list_get_printer(mem_ctx,
2843 pinfo2->sharename,
2844 NULL,
2845 &loc,
2846 NULL);
2847 if (NT_STATUS_IS_OK(status)) {
2848 if (loc == NULL) {
2849 loc = pinfo2->location;
2853 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2856 /*******************************************************************
2857 * fill a notify_info_data with the device mode
2858 * jfm:xxxx don't to it for know but that's a real problem !!!
2859 ********************************************************************/
2861 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2862 int snum,
2863 struct spoolss_Notify *data,
2864 print_queue_struct *queue,
2865 struct spoolss_PrinterInfo2 *pinfo2,
2866 TALLOC_CTX *mem_ctx)
2868 /* for a dummy implementation we have to zero the fields */
2869 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2872 /*******************************************************************
2873 * fill a notify_info_data with the separator file name
2874 ********************************************************************/
2876 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2877 int snum,
2878 struct spoolss_Notify *data,
2879 print_queue_struct *queue,
2880 struct spoolss_PrinterInfo2 *pinfo2,
2881 TALLOC_CTX *mem_ctx)
2883 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2886 /*******************************************************************
2887 * fill a notify_info_data with the print processor
2888 * jfm:xxxx return always winprint to indicate we don't do anything to it
2889 ********************************************************************/
2891 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2892 int snum,
2893 struct spoolss_Notify *data,
2894 print_queue_struct *queue,
2895 struct spoolss_PrinterInfo2 *pinfo2,
2896 TALLOC_CTX *mem_ctx)
2898 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2901 /*******************************************************************
2902 * fill a notify_info_data with the print processor options
2903 * jfm:xxxx send an empty string
2904 ********************************************************************/
2906 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2907 int snum,
2908 struct spoolss_Notify *data,
2909 print_queue_struct *queue,
2910 struct spoolss_PrinterInfo2 *pinfo2,
2911 TALLOC_CTX *mem_ctx)
2913 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2916 /*******************************************************************
2917 * fill a notify_info_data with the data type
2918 * jfm:xxxx always send RAW as data type
2919 ********************************************************************/
2921 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2922 int snum,
2923 struct spoolss_Notify *data,
2924 print_queue_struct *queue,
2925 struct spoolss_PrinterInfo2 *pinfo2,
2926 TALLOC_CTX *mem_ctx)
2928 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2931 /*******************************************************************
2932 * fill a notify_info_data with the security descriptor
2933 * jfm:xxxx send an null pointer to say no security desc
2934 * have to implement security before !
2935 ********************************************************************/
2937 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2938 int snum,
2939 struct spoolss_Notify *data,
2940 print_queue_struct *queue,
2941 struct spoolss_PrinterInfo2 *pinfo2,
2942 TALLOC_CTX *mem_ctx)
2944 if (pinfo2->secdesc == NULL) {
2945 data->data.sd.sd = NULL;
2946 } else {
2947 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2948 pinfo2->secdesc);
2950 data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2954 /*******************************************************************
2955 * fill a notify_info_data with the attributes
2956 * jfm:xxxx a samba printer is always shared
2957 ********************************************************************/
2959 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2960 int snum,
2961 struct spoolss_Notify *data,
2962 print_queue_struct *queue,
2963 struct spoolss_PrinterInfo2 *pinfo2,
2964 TALLOC_CTX *mem_ctx)
2966 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2969 /*******************************************************************
2970 * fill a notify_info_data with the priority
2971 ********************************************************************/
2973 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2974 int snum,
2975 struct spoolss_Notify *data,
2976 print_queue_struct *queue,
2977 struct spoolss_PrinterInfo2 *pinfo2,
2978 TALLOC_CTX *mem_ctx)
2980 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2983 /*******************************************************************
2984 * fill a notify_info_data with the default priority
2985 ********************************************************************/
2987 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2988 int snum,
2989 struct spoolss_Notify *data,
2990 print_queue_struct *queue,
2991 struct spoolss_PrinterInfo2 *pinfo2,
2992 TALLOC_CTX *mem_ctx)
2994 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2997 /*******************************************************************
2998 * fill a notify_info_data with the start time
2999 ********************************************************************/
3001 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3002 int snum,
3003 struct spoolss_Notify *data,
3004 print_queue_struct *queue,
3005 struct spoolss_PrinterInfo2 *pinfo2,
3006 TALLOC_CTX *mem_ctx)
3008 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3011 /*******************************************************************
3012 * fill a notify_info_data with the until time
3013 ********************************************************************/
3015 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3016 int snum,
3017 struct spoolss_Notify *data,
3018 print_queue_struct *queue,
3019 struct spoolss_PrinterInfo2 *pinfo2,
3020 TALLOC_CTX *mem_ctx)
3022 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3025 /*******************************************************************
3026 * fill a notify_info_data with the status
3027 ********************************************************************/
3029 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3030 int snum,
3031 struct spoolss_Notify *data,
3032 print_queue_struct *queue,
3033 struct spoolss_PrinterInfo2 *pinfo2,
3034 TALLOC_CTX *mem_ctx)
3036 print_status_struct status;
3038 print_queue_length(msg_ctx, snum, &status);
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3042 /*******************************************************************
3043 * fill a notify_info_data with the number of jobs queued
3044 ********************************************************************/
3046 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3047 int snum,
3048 struct spoolss_Notify *data,
3049 print_queue_struct *queue,
3050 struct spoolss_PrinterInfo2 *pinfo2,
3051 TALLOC_CTX *mem_ctx)
3053 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3054 data, print_queue_length(msg_ctx, snum, NULL));
3057 /*******************************************************************
3058 * fill a notify_info_data with the average ppm
3059 ********************************************************************/
3061 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3062 int snum,
3063 struct spoolss_Notify *data,
3064 print_queue_struct *queue,
3065 struct spoolss_PrinterInfo2 *pinfo2,
3066 TALLOC_CTX *mem_ctx)
3068 /* always respond 8 pages per minutes */
3069 /* a little hard ! */
3070 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3073 /*******************************************************************
3074 * fill a notify_info_data with username
3075 ********************************************************************/
3077 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3078 int snum,
3079 struct spoolss_Notify *data,
3080 print_queue_struct *queue,
3081 struct spoolss_PrinterInfo2 *pinfo2,
3082 TALLOC_CTX *mem_ctx)
3084 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3087 /*******************************************************************
3088 * fill a notify_info_data with job status
3089 ********************************************************************/
3091 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3092 int snum,
3093 struct spoolss_Notify *data,
3094 print_queue_struct *queue,
3095 struct spoolss_PrinterInfo2 *pinfo2,
3096 TALLOC_CTX *mem_ctx)
3098 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3101 /*******************************************************************
3102 * fill a notify_info_data with job name
3103 ********************************************************************/
3105 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3106 int snum,
3107 struct spoolss_Notify *data,
3108 print_queue_struct *queue,
3109 struct spoolss_PrinterInfo2 *pinfo2,
3110 TALLOC_CTX *mem_ctx)
3112 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3115 /*******************************************************************
3116 * fill a notify_info_data with job status
3117 ********************************************************************/
3119 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3120 int snum,
3121 struct spoolss_Notify *data,
3122 print_queue_struct *queue,
3123 struct spoolss_PrinterInfo2 *pinfo2,
3124 TALLOC_CTX *mem_ctx)
3127 * Now we're returning job status codes we just return a "" here. JRA.
3130 const char *p = "";
3132 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3133 p = "unknown";
3135 switch (queue->status) {
3136 case LPQ_QUEUED:
3137 p = "Queued";
3138 break;
3139 case LPQ_PAUSED:
3140 p = ""; /* NT provides the paused string */
3141 break;
3142 case LPQ_SPOOLING:
3143 p = "Spooling";
3144 break;
3145 case LPQ_PRINTING:
3146 p = "Printing";
3147 break;
3149 #endif /* NO LONGER NEEDED. */
3151 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3154 /*******************************************************************
3155 * fill a notify_info_data with job time
3156 ********************************************************************/
3158 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3159 int snum,
3160 struct spoolss_Notify *data,
3161 print_queue_struct *queue,
3162 struct spoolss_PrinterInfo2 *pinfo2,
3163 TALLOC_CTX *mem_ctx)
3165 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3168 /*******************************************************************
3169 * fill a notify_info_data with job size
3170 ********************************************************************/
3172 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3173 int snum,
3174 struct spoolss_Notify *data,
3175 print_queue_struct *queue,
3176 struct spoolss_PrinterInfo2 *pinfo2,
3177 TALLOC_CTX *mem_ctx)
3179 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3182 /*******************************************************************
3183 * fill a notify_info_data with page info
3184 ********************************************************************/
3185 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3186 int snum,
3187 struct spoolss_Notify *data,
3188 print_queue_struct *queue,
3189 struct spoolss_PrinterInfo2 *pinfo2,
3190 TALLOC_CTX *mem_ctx)
3192 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3195 /*******************************************************************
3196 * fill a notify_info_data with pages printed info.
3197 ********************************************************************/
3198 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3199 int snum,
3200 struct spoolss_Notify *data,
3201 print_queue_struct *queue,
3202 struct spoolss_PrinterInfo2 *pinfo2,
3203 TALLOC_CTX *mem_ctx)
3205 /* Add code when back-end tracks this */
3206 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3209 /*******************************************************************
3210 Fill a notify_info_data with job position.
3211 ********************************************************************/
3213 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3214 int snum,
3215 struct spoolss_Notify *data,
3216 print_queue_struct *queue,
3217 struct spoolss_PrinterInfo2 *pinfo2,
3218 TALLOC_CTX *mem_ctx)
3220 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3223 /*******************************************************************
3224 Fill a notify_info_data with submitted time.
3225 ********************************************************************/
3227 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3228 int snum,
3229 struct spoolss_Notify *data,
3230 print_queue_struct *queue,
3231 struct spoolss_PrinterInfo2 *pinfo2,
3232 TALLOC_CTX *mem_ctx)
3234 data->data.string.string = NULL;
3235 data->data.string.size = 0;
3237 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3238 &data->data.string.string,
3239 &data->data.string.size);
3243 struct s_notify_info_data_table
3245 enum spoolss_NotifyType type;
3246 uint16_t field;
3247 const char *name;
3248 enum spoolss_NotifyTable variable_type;
3249 void (*fn) (struct messaging_context *msg_ctx,
3250 int snum, struct spoolss_Notify *data,
3251 print_queue_struct *queue,
3252 struct spoolss_PrinterInfo2 *pinfo2,
3253 TALLOC_CTX *mem_ctx);
3256 /* A table describing the various print notification constants and
3257 whether the notification data is a pointer to a variable sized
3258 buffer, a one value uint32_t or a two value uint32_t. */
3260 static const struct s_notify_info_data_table notify_info_data_table[] =
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3313 /*******************************************************************
3314 Return the variable_type of info_data structure.
3315 ********************************************************************/
3317 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3318 uint16_t field)
3320 int i=0;
3322 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3323 if ( (notify_info_data_table[i].type == type) &&
3324 (notify_info_data_table[i].field == field) ) {
3325 return notify_info_data_table[i].variable_type;
3329 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3331 return (enum spoolss_NotifyTable) 0;
3334 /****************************************************************************
3335 ****************************************************************************/
3337 static bool search_notify(enum spoolss_NotifyType type,
3338 uint16_t field,
3339 int *value)
3341 int i;
3343 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3344 if (notify_info_data_table[i].type == type &&
3345 notify_info_data_table[i].field == field &&
3346 notify_info_data_table[i].fn != NULL) {
3347 *value = i;
3348 return true;
3352 return false;
3355 /****************************************************************************
3356 ****************************************************************************/
3358 static void construct_info_data(struct spoolss_Notify *info_data,
3359 enum spoolss_NotifyType type,
3360 uint16_t field, int id)
3362 info_data->type = type;
3363 info_data->field.field = field;
3364 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3365 info_data->job_id = id;
3368 /*******************************************************************
3370 * fill a notify_info struct with info asked
3372 ********************************************************************/
3374 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3375 struct printer_handle *print_hnd,
3376 struct spoolss_NotifyInfo *info,
3377 struct spoolss_PrinterInfo2 *pinfo2,
3378 int snum,
3379 const struct spoolss_NotifyOptionType *option_type,
3380 uint32_t id,
3381 TALLOC_CTX *mem_ctx)
3383 int field_num,j;
3384 enum spoolss_NotifyType type;
3385 uint16_t field;
3387 struct spoolss_Notify *current_data;
3389 type = option_type->type;
3391 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3392 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3393 option_type->count, lp_servicename(talloc_tos(), snum)));
3395 for(field_num=0; field_num < option_type->count; field_num++) {
3396 field = option_type->fields[field_num].field;
3398 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3400 if (!search_notify(type, field, &j) )
3401 continue;
3403 info->notifies = talloc_realloc(info, info->notifies,
3404 struct spoolss_Notify,
3405 info->count + 1);
3406 if (info->notifies == NULL) {
3407 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3408 return false;
3411 current_data = &info->notifies[info->count];
3413 construct_info_data(current_data, type, field, id);
3415 DEBUG(10, ("construct_notify_printer_info: "
3416 "calling [%s] snum=%d printername=[%s])\n",
3417 notify_info_data_table[j].name, snum,
3418 pinfo2->printername));
3420 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3421 NULL, pinfo2, mem_ctx);
3423 info->count++;
3426 return true;
3429 /*******************************************************************
3431 * fill a notify_info struct with info asked
3433 ********************************************************************/
3435 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3436 print_queue_struct *queue,
3437 struct spoolss_NotifyInfo *info,
3438 struct spoolss_PrinterInfo2 *pinfo2,
3439 int snum,
3440 const struct spoolss_NotifyOptionType *option_type,
3441 uint32_t id,
3442 TALLOC_CTX *mem_ctx)
3444 int field_num,j;
3445 enum spoolss_NotifyType type;
3446 uint16_t field;
3447 struct spoolss_Notify *current_data;
3449 DEBUG(4,("construct_notify_jobs_info\n"));
3451 type = option_type->type;
3453 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3454 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3455 option_type->count));
3457 for(field_num=0; field_num<option_type->count; field_num++) {
3458 field = option_type->fields[field_num].field;
3460 if (!search_notify(type, field, &j) )
3461 continue;
3463 info->notifies = talloc_realloc(info, info->notifies,
3464 struct spoolss_Notify,
3465 info->count + 1);
3466 if (info->notifies == NULL) {
3467 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3468 return false;
3471 current_data=&(info->notifies[info->count]);
3473 construct_info_data(current_data, type, field, id);
3474 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3475 queue, pinfo2, mem_ctx);
3476 info->count++;
3479 return true;
3483 * JFM: The enumeration is not that simple, it's even non obvious.
3485 * let's take an example: I want to monitor the PRINTER SERVER for
3486 * the printer's name and the number of jobs currently queued.
3487 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3488 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3490 * I have 3 printers on the back of my server.
3492 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3493 * structures.
3494 * Number Data Id
3495 * 1 printer 1 name 1
3496 * 2 printer 1 cjob 1
3497 * 3 printer 2 name 2
3498 * 4 printer 2 cjob 2
3499 * 5 printer 3 name 3
3500 * 6 printer 3 name 3
3502 * that's the print server case, the printer case is even worse.
3505 /*******************************************************************
3507 * enumerate all printers on the printserver
3508 * fill a notify_info struct with info asked
3510 ********************************************************************/
3512 static WERROR printserver_notify_info(struct pipes_struct *p,
3513 struct policy_handle *hnd,
3514 struct spoolss_NotifyInfo *info,
3515 TALLOC_CTX *mem_ctx)
3517 int snum;
3518 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3519 int n_services=lp_numservices();
3520 int i;
3521 struct spoolss_NotifyOption *option;
3522 struct spoolss_NotifyOptionType option_type;
3523 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3524 WERROR result;
3526 DEBUG(4,("printserver_notify_info\n"));
3528 if (!Printer)
3529 return WERR_BADFID;
3531 option = Printer->notify.option;
3533 info->version = 2;
3534 info->notifies = NULL;
3535 info->count = 0;
3537 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3538 sending a ffpcn() request first */
3540 if ( !option )
3541 return WERR_BADFID;
3543 for (i=0; i<option->count; i++) {
3544 option_type = option->types[i];
3546 if (option_type.type != PRINTER_NOTIFY_TYPE)
3547 continue;
3549 for (snum = 0; snum < n_services; snum++) {
3550 if (!lp_browseable(snum) ||
3551 !lp_snum_ok(snum) ||
3552 !lp_printable(snum)) {
3553 continue; /* skip */
3556 /* Maybe we should use the SYSTEM session_info here... */
3557 result = winreg_get_printer_internal(mem_ctx,
3558 get_session_info_system(),
3559 p->msg_ctx,
3560 lp_servicename(talloc_tos(), snum),
3561 &pinfo2);
3562 if (!W_ERROR_IS_OK(result)) {
3563 DEBUG(4, ("printserver_notify_info: "
3564 "Failed to get printer [%s]\n",
3565 lp_servicename(talloc_tos(), snum)));
3566 continue;
3570 construct_notify_printer_info(p->msg_ctx,
3571 Printer, info,
3572 pinfo2, snum,
3573 &option_type, snum,
3574 mem_ctx);
3576 TALLOC_FREE(pinfo2);
3580 #if 0
3582 * Debugging information, don't delete.
3585 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3586 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3587 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3589 for (i=0; i<info->count; i++) {
3590 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3591 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3592 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3594 #endif
3596 return WERR_OK;
3599 /*******************************************************************
3601 * fill a notify_info struct with info asked
3603 ********************************************************************/
3605 static WERROR printer_notify_info(struct pipes_struct *p,
3606 struct policy_handle *hnd,
3607 struct spoolss_NotifyInfo *info,
3608 TALLOC_CTX *mem_ctx)
3610 int snum;
3611 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3612 int i;
3613 uint32_t id;
3614 struct spoolss_NotifyOption *option;
3615 struct spoolss_NotifyOptionType option_type;
3616 int count,j;
3617 print_queue_struct *queue=NULL;
3618 print_status_struct status;
3619 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3620 WERROR result;
3621 struct tdb_print_db *pdb;
3623 DEBUG(4,("printer_notify_info\n"));
3625 if (!Printer)
3626 return WERR_BADFID;
3628 option = Printer->notify.option;
3629 id = 0x0;
3631 info->version = 2;
3632 info->notifies = NULL;
3633 info->count = 0;
3635 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3636 sending a ffpcn() request first */
3638 if ( !option )
3639 return WERR_BADFID;
3641 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3642 return WERR_BADFID;
3645 pdb = get_print_db_byname(Printer->sharename);
3646 if (pdb == NULL) {
3647 return WERR_BADFID;
3650 /* Maybe we should use the SYSTEM session_info here... */
3651 result = winreg_get_printer_internal(mem_ctx,
3652 get_session_info_system(),
3653 p->msg_ctx,
3654 lp_servicename(talloc_tos(), snum), &pinfo2);
3655 if (!W_ERROR_IS_OK(result)) {
3656 result = WERR_BADFID;
3657 goto err_pdb_drop;
3661 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3662 * correct servername.
3664 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3665 if (pinfo2->servername == NULL) {
3666 result = WERR_NOMEM;
3667 goto err_pdb_drop;
3670 for (i = 0; i < option->count; i++) {
3671 option_type = option->types[i];
3673 switch (option_type.type) {
3674 case PRINTER_NOTIFY_TYPE:
3675 if (construct_notify_printer_info(p->msg_ctx,
3676 Printer, info,
3677 pinfo2, snum,
3678 &option_type, id,
3679 mem_ctx)) {
3680 id--;
3682 break;
3684 case JOB_NOTIFY_TYPE:
3686 count = print_queue_status(p->msg_ctx, snum, &queue,
3687 &status);
3689 for (j = 0; j < count; j++) {
3690 uint32_t jobid;
3691 jobid = sysjob_to_jobid_pdb(pdb,
3692 queue[j].sysjob);
3693 if (jobid == (uint32_t)-1) {
3694 DEBUG(2, ("ignoring untracked job %d\n",
3695 queue[j].sysjob));
3696 continue;
3698 /* FIXME check return value */
3699 construct_notify_jobs_info(p->msg_ctx,
3700 &queue[j], info,
3701 pinfo2, snum,
3702 &option_type,
3703 jobid,
3704 mem_ctx);
3707 SAFE_FREE(queue);
3708 break;
3713 * Debugging information, don't delete.
3716 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3717 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3718 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3720 for (i=0; i<info->count; i++) {
3721 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3722 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3723 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3727 talloc_free(pinfo2);
3728 result = WERR_OK;
3729 err_pdb_drop:
3730 release_print_db(pdb);
3731 return result;
3734 /****************************************************************
3735 _spoolss_RouterRefreshPrinterChangeNotify
3736 ****************************************************************/
3738 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3739 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3741 struct spoolss_NotifyInfo *info;
3743 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3744 WERROR result = WERR_BADFID;
3746 /* we always have a spoolss_NotifyInfo struct */
3747 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3748 if (!info) {
3749 result = WERR_NOMEM;
3750 goto done;
3753 *r->out.info = info;
3755 if (!Printer) {
3756 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3757 "Invalid handle (%s:%u:%u).\n",
3758 OUR_HANDLE(r->in.handle)));
3759 goto done;
3762 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3765 * We are now using the change value, and
3766 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3767 * I don't have a global notification system, I'm sending back all the
3768 * information even when _NOTHING_ has changed.
3771 /* We need to keep track of the change value to send back in
3772 RRPCN replies otherwise our updates are ignored. */
3774 Printer->notify.fnpcn = true;
3776 if (Printer->notify.cli_chan != NULL &&
3777 Printer->notify.cli_chan->active_connections > 0) {
3778 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3779 "Saving change value in request [%x]\n",
3780 r->in.change_low));
3781 Printer->notify.change = r->in.change_low;
3784 /* just ignore the spoolss_NotifyOption */
3786 switch (Printer->printer_type) {
3787 case SPLHND_SERVER:
3788 result = printserver_notify_info(p, r->in.handle,
3789 info, p->mem_ctx);
3790 break;
3792 case SPLHND_PRINTER:
3793 result = printer_notify_info(p, r->in.handle,
3794 info, p->mem_ctx);
3795 break;
3798 Printer->notify.fnpcn = false;
3800 done:
3801 return result;
3804 /********************************************************************
3805 ********************************************************************/
3807 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3808 const char *servername,
3809 const char *printername,
3810 const char **printername_p)
3812 /* FIXME: add lp_force_printername() */
3814 if (servername == NULL) {
3815 *printername_p = talloc_strdup(mem_ctx, printername);
3816 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3817 return WERR_OK;
3820 if (servername[0] == '\\' && servername[1] == '\\') {
3821 servername += 2;
3824 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3825 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3827 return WERR_OK;
3830 /********************************************************************
3831 ********************************************************************/
3833 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3834 const char *printername)
3836 if (dm == NULL) {
3837 return;
3840 dm->devicename = talloc_strndup(dm, printername,
3841 MIN(strlen(printername), 31));
3844 /********************************************************************
3845 * construct_printer_info_0
3846 * fill a printer_info_0 struct
3847 ********************************************************************/
3849 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3850 const struct auth_session_info *session_info,
3851 struct messaging_context *msg_ctx,
3852 struct spoolss_PrinterInfo2 *info2,
3853 const char *servername,
3854 struct spoolss_PrinterInfo0 *r,
3855 int snum)
3857 int count;
3858 struct printer_session_counter *session_counter;
3859 struct timeval setuptime;
3860 print_status_struct status;
3861 WERROR result;
3863 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3864 if (!W_ERROR_IS_OK(result)) {
3865 return result;
3868 if (servername) {
3869 r->servername = talloc_strdup(mem_ctx, servername);
3870 W_ERROR_HAVE_NO_MEMORY(r->servername);
3871 } else {
3872 r->servername = NULL;
3875 count = print_queue_length(msg_ctx, snum, &status);
3877 /* check if we already have a counter for this printer */
3878 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3879 if (session_counter->snum == snum)
3880 break;
3883 /* it's the first time, add it to the list */
3884 if (session_counter == NULL) {
3885 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3886 W_ERROR_HAVE_NO_MEMORY(session_counter);
3887 session_counter->snum = snum;
3888 session_counter->counter = 0;
3889 DLIST_ADD(counter_list, session_counter);
3892 /* increment it */
3893 session_counter->counter++;
3895 r->cjobs = count;
3896 r->total_jobs = 0;
3897 r->total_bytes = 0;
3899 get_startup_time(&setuptime);
3900 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3902 /* JFM:
3903 * the global_counter should be stored in a TDB as it's common to all the clients
3904 * and should be zeroed on samba startup
3906 r->global_counter = session_counter->counter;
3907 r->total_pages = 0;
3908 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3909 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3910 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3911 r->free_build = SPOOLSS_RELEASE_BUILD;
3912 r->spooling = 0;
3913 r->max_spooling = 0;
3914 r->session_counter = session_counter->counter;
3915 r->num_error_out_of_paper = 0x0;
3916 r->num_error_not_ready = 0x0; /* number of print failure */
3917 r->job_error = 0x0;
3918 r->number_of_processors = 0x1;
3919 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3920 r->high_part_total_bytes = 0x0;
3922 /* ChangeID in milliseconds*/
3923 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3924 info2->sharename, &r->change_id);
3926 r->last_error = WERR_OK;
3927 r->status = nt_printq_status(status.status);
3928 r->enumerate_network_printers = 0x0;
3929 r->c_setprinter = 0x0;
3930 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3931 r->processor_level = 0x6; /* 6 ???*/
3932 r->ref_ic = 0;
3933 r->reserved2 = 0;
3934 r->reserved3 = 0;
3936 return WERR_OK;
3940 /********************************************************************
3941 * construct_printer_info1
3942 * fill a spoolss_PrinterInfo1 struct
3943 ********************************************************************/
3945 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3946 const struct spoolss_PrinterInfo2 *info2,
3947 uint32_t flags,
3948 const char *servername,
3949 struct spoolss_PrinterInfo1 *r,
3950 int snum)
3952 WERROR result;
3954 r->flags = flags;
3956 if (info2->comment == NULL || info2->comment[0] == '\0') {
3957 r->comment = lp_comment(mem_ctx, snum);
3958 } else {
3959 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3961 W_ERROR_HAVE_NO_MEMORY(r->comment);
3963 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3964 if (!W_ERROR_IS_OK(result)) {
3965 return result;
3968 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3969 r->name,
3970 info2->drivername,
3971 r->comment);
3972 W_ERROR_HAVE_NO_MEMORY(r->description);
3974 return WERR_OK;
3977 /********************************************************************
3978 * construct_printer_info2
3979 * fill a spoolss_PrinterInfo2 struct
3980 ********************************************************************/
3982 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3983 struct messaging_context *msg_ctx,
3984 const struct spoolss_PrinterInfo2 *info2,
3985 const char *servername,
3986 struct spoolss_PrinterInfo2 *r,
3987 int snum)
3989 int count;
3990 print_status_struct status;
3991 WERROR result;
3993 count = print_queue_length(msg_ctx, snum, &status);
3995 if (servername) {
3996 r->servername = talloc_strdup(mem_ctx, servername);
3997 W_ERROR_HAVE_NO_MEMORY(r->servername);
3998 } else {
3999 r->servername = NULL;
4002 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4003 if (!W_ERROR_IS_OK(result)) {
4004 return result;
4007 r->sharename = lp_servicename(mem_ctx, snum);
4008 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4009 r->portname = talloc_strdup(mem_ctx, info2->portname);
4010 W_ERROR_HAVE_NO_MEMORY(r->portname);
4011 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4012 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4014 if (info2->comment[0] == '\0') {
4015 r->comment = lp_comment(mem_ctx, snum);
4016 } else {
4017 r->comment = talloc_strdup(mem_ctx, info2->comment);
4019 W_ERROR_HAVE_NO_MEMORY(r->comment);
4021 r->location = talloc_strdup(mem_ctx, info2->location);
4022 if (info2->location[0] == '\0') {
4023 const char *loc = NULL;
4024 NTSTATUS nt_status;
4026 nt_status = printer_list_get_printer(mem_ctx,
4027 info2->sharename,
4028 NULL,
4029 &loc,
4030 NULL);
4031 if (NT_STATUS_IS_OK(nt_status)) {
4032 if (loc != NULL) {
4033 r->location = talloc_strdup(mem_ctx, loc);
4037 W_ERROR_HAVE_NO_MEMORY(r->location);
4039 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4040 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4041 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4042 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4043 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4044 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4045 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4046 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4048 r->attributes = info2->attributes;
4050 r->priority = info2->priority;
4051 r->defaultpriority = info2->defaultpriority;
4052 r->starttime = info2->starttime;
4053 r->untiltime = info2->untiltime;
4054 r->status = nt_printq_status(status.status);
4055 r->cjobs = count;
4056 r->averageppm = info2->averageppm;
4058 if (info2->devmode != NULL) {
4059 result = copy_devicemode(mem_ctx,
4060 info2->devmode,
4061 &r->devmode);
4062 if (!W_ERROR_IS_OK(result)) {
4063 return result;
4065 } else if (lp_default_devmode(snum)) {
4066 result = spoolss_create_default_devmode(mem_ctx,
4067 info2->printername,
4068 &r->devmode);
4069 if (!W_ERROR_IS_OK(result)) {
4070 return result;
4072 } else {
4073 r->devmode = NULL;
4074 DEBUG(8,("Returning NULL Devicemode!\n"));
4077 compose_devicemode_devicename(r->devmode, r->printername);
4079 r->secdesc = NULL;
4081 if (info2->secdesc != NULL) {
4082 /* don't use talloc_steal() here unless you do a deep steal of all
4083 the SEC_DESC members */
4085 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4086 if (r->secdesc == NULL) {
4087 return WERR_NOMEM;
4091 return WERR_OK;
4094 /********************************************************************
4095 * construct_printer_info3
4096 * fill a spoolss_PrinterInfo3 struct
4097 ********************************************************************/
4099 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4100 const struct spoolss_PrinterInfo2 *info2,
4101 const char *servername,
4102 struct spoolss_PrinterInfo3 *r,
4103 int snum)
4105 /* These are the components of the SD we are returning. */
4107 if (info2->secdesc != NULL) {
4108 /* don't use talloc_steal() here unless you do a deep steal of all
4109 the SEC_DESC members */
4111 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4112 if (r->secdesc == NULL) {
4113 return WERR_NOMEM;
4117 return WERR_OK;
4120 /********************************************************************
4121 * construct_printer_info4
4122 * fill a spoolss_PrinterInfo4 struct
4123 ********************************************************************/
4125 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4126 const struct spoolss_PrinterInfo2 *info2,
4127 const char *servername,
4128 struct spoolss_PrinterInfo4 *r,
4129 int snum)
4131 WERROR result;
4133 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4134 if (!W_ERROR_IS_OK(result)) {
4135 return result;
4138 if (servername) {
4139 r->servername = talloc_strdup(mem_ctx, servername);
4140 W_ERROR_HAVE_NO_MEMORY(r->servername);
4141 } else {
4142 r->servername = NULL;
4145 r->attributes = info2->attributes;
4147 return WERR_OK;
4150 /********************************************************************
4151 * construct_printer_info5
4152 * fill a spoolss_PrinterInfo5 struct
4153 ********************************************************************/
4155 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4156 const struct spoolss_PrinterInfo2 *info2,
4157 const char *servername,
4158 struct spoolss_PrinterInfo5 *r,
4159 int snum)
4161 WERROR result;
4163 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4164 if (!W_ERROR_IS_OK(result)) {
4165 return result;
4168 r->portname = talloc_strdup(mem_ctx, info2->portname);
4169 W_ERROR_HAVE_NO_MEMORY(r->portname);
4171 r->attributes = info2->attributes;
4173 /* these two are not used by NT+ according to MSDN */
4174 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4175 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4177 return WERR_OK;
4180 /********************************************************************
4181 * construct_printer_info_6
4182 * fill a spoolss_PrinterInfo6 struct
4183 ********************************************************************/
4185 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4186 struct messaging_context *msg_ctx,
4187 const struct spoolss_PrinterInfo2 *info2,
4188 const char *servername,
4189 struct spoolss_PrinterInfo6 *r,
4190 int snum)
4192 print_status_struct status;
4194 print_queue_length(msg_ctx, snum, &status);
4196 r->status = nt_printq_status(status.status);
4198 return WERR_OK;
4201 /********************************************************************
4202 * construct_printer_info7
4203 * fill a spoolss_PrinterInfo7 struct
4204 ********************************************************************/
4206 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4207 struct messaging_context *msg_ctx,
4208 const char *servername,
4209 struct spoolss_PrinterInfo7 *r,
4210 int snum)
4212 const struct auth_session_info *session_info;
4213 char *printer;
4214 WERROR werr;
4215 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4216 if (tmp_ctx == NULL) {
4217 return WERR_NOMEM;
4220 session_info = get_session_info_system();
4221 SMB_ASSERT(session_info != NULL);
4223 printer = lp_servicename(tmp_ctx, snum);
4224 if (printer == NULL) {
4225 DEBUG(0, ("invalid printer snum %d\n", snum));
4226 werr = WERR_INVALID_PARAM;
4227 goto out_tmp_free;
4230 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4231 servername, printer, NULL)) {
4232 struct GUID guid;
4233 struct GUID_txt_buf guid_txt;
4234 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4235 printer, &guid);
4236 if (!W_ERROR_IS_OK(werr)) {
4238 * If we do not have a GUID entry in the registry, then
4239 * try to retrieve it from AD and store it now.
4241 werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4242 &guid);
4243 if (!W_ERROR_IS_OK(werr)) {
4244 DEBUG(1, ("Failed to retrieve GUID for "
4245 "printer [%s] from AD - "
4246 "Is the the printer still "
4247 "published ?\n", printer));
4248 goto out_tmp_free;
4251 werr = nt_printer_guid_store(msg_ctx, printer, guid);
4252 if (!W_ERROR_IS_OK(werr)) {
4253 DEBUG(3, ("failed to store printer %s guid\n",
4254 printer));
4257 r->guid = talloc_strdup_upper(mem_ctx,
4258 GUID_buf_string(&guid, &guid_txt));
4259 r->action = DSPRINT_PUBLISH;
4260 } else {
4261 r->guid = talloc_strdup(mem_ctx, "");
4262 r->action = DSPRINT_UNPUBLISH;
4264 if (r->guid == NULL) {
4265 werr = WERR_NOMEM;
4266 goto out_tmp_free;
4269 werr = WERR_OK;
4270 out_tmp_free:
4271 talloc_free(tmp_ctx);
4272 return werr;
4275 /********************************************************************
4276 * construct_printer_info8
4277 * fill a spoolss_PrinterInfo8 struct
4278 ********************************************************************/
4280 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4281 const struct spoolss_PrinterInfo2 *info2,
4282 const char *servername,
4283 struct spoolss_DeviceModeInfo *r,
4284 int snum)
4286 WERROR result;
4287 const char *printername;
4289 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4290 if (!W_ERROR_IS_OK(result)) {
4291 return result;
4294 if (info2->devmode != NULL) {
4295 result = copy_devicemode(mem_ctx,
4296 info2->devmode,
4297 &r->devmode);
4298 if (!W_ERROR_IS_OK(result)) {
4299 return result;
4301 } else if (lp_default_devmode(snum)) {
4302 result = spoolss_create_default_devmode(mem_ctx,
4303 info2->printername,
4304 &r->devmode);
4305 if (!W_ERROR_IS_OK(result)) {
4306 return result;
4308 } else {
4309 r->devmode = NULL;
4310 DEBUG(8,("Returning NULL Devicemode!\n"));
4313 compose_devicemode_devicename(r->devmode, printername);
4315 return WERR_OK;
4318 /********************************************************************
4319 Spoolss_enumprinters.
4320 ********************************************************************/
4322 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4323 const struct auth_session_info *session_info,
4324 struct messaging_context *msg_ctx,
4325 const char *servername,
4326 uint32_t level,
4327 uint32_t flags,
4328 union spoolss_PrinterInfo **info_p,
4329 uint32_t *count_p)
4331 int snum;
4332 int n_services;
4333 union spoolss_PrinterInfo *info = NULL;
4334 uint32_t count = 0;
4335 WERROR result = WERR_OK;
4336 struct dcerpc_binding_handle *b = NULL;
4337 TALLOC_CTX *tmp_ctx = NULL;
4339 tmp_ctx = talloc_new(mem_ctx);
4340 if (!tmp_ctx) {
4341 return WERR_NOMEM;
4345 * printer shares are updated on client enumeration. The background
4346 * printer process updates printer_list.tdb at regular intervals.
4348 become_root();
4349 delete_and_reload_printers(server_event_context(), msg_ctx);
4350 unbecome_root();
4352 n_services = lp_numservices();
4353 *count_p = 0;
4354 *info_p = NULL;
4356 for (snum = 0; snum < n_services; snum++) {
4358 const char *printer;
4359 struct spoolss_PrinterInfo2 *info2;
4361 if (!snum_is_shared_printer(snum)) {
4362 continue;
4365 printer = lp_const_servicename(snum);
4367 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4368 printer, snum));
4370 if (b == NULL) {
4371 result = winreg_printer_binding_handle(tmp_ctx,
4372 session_info,
4373 msg_ctx,
4374 &b);
4375 if (!W_ERROR_IS_OK(result)) {
4376 goto out;
4380 result = winreg_create_printer(tmp_ctx, b,
4381 printer);
4382 if (!W_ERROR_IS_OK(result)) {
4383 goto out;
4386 info = talloc_realloc(tmp_ctx, info,
4387 union spoolss_PrinterInfo,
4388 count + 1);
4389 if (!info) {
4390 result = WERR_NOMEM;
4391 goto out;
4394 result = winreg_get_printer(tmp_ctx, b,
4395 printer, &info2);
4396 if (!W_ERROR_IS_OK(result)) {
4397 goto out;
4400 switch (level) {
4401 case 0:
4402 result = construct_printer_info0(info, session_info,
4403 msg_ctx, info2,
4404 servername,
4405 &info[count].info0, snum);
4406 break;
4407 case 1:
4408 result = construct_printer_info1(info, info2, flags,
4409 servername,
4410 &info[count].info1, snum);
4411 break;
4412 case 2:
4413 result = construct_printer_info2(info, msg_ctx, info2,
4414 servername,
4415 &info[count].info2, snum);
4416 break;
4417 case 4:
4418 result = construct_printer_info4(info, info2,
4419 servername,
4420 &info[count].info4, snum);
4421 break;
4422 case 5:
4423 result = construct_printer_info5(info, info2,
4424 servername,
4425 &info[count].info5, snum);
4426 break;
4428 default:
4429 result = WERR_UNKNOWN_LEVEL;
4430 goto out;
4433 if (!W_ERROR_IS_OK(result)) {
4434 goto out;
4437 count++;
4440 out:
4441 if (W_ERROR_IS_OK(result)) {
4442 *info_p = talloc_move(mem_ctx, &info);
4443 *count_p = count;
4446 talloc_free(tmp_ctx);
4448 return result;
4451 /********************************************************************
4452 * handle enumeration of printers at level 0
4453 ********************************************************************/
4455 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4456 const struct auth_session_info *session_info,
4457 struct messaging_context *msg_ctx,
4458 uint32_t flags,
4459 const char *servername,
4460 union spoolss_PrinterInfo **info,
4461 uint32_t *count)
4463 DEBUG(4,("enum_all_printers_info_0\n"));
4465 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4466 servername, 0, flags, info, count);
4470 /********************************************************************
4471 ********************************************************************/
4473 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4474 const struct auth_session_info *session_info,
4475 struct messaging_context *msg_ctx,
4476 const char *servername,
4477 uint32_t flags,
4478 union spoolss_PrinterInfo **info,
4479 uint32_t *count)
4481 DEBUG(4,("enum_all_printers_info_1\n"));
4483 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4484 servername, 1, flags, info, count);
4487 /********************************************************************
4488 enum_all_printers_info_1_local.
4489 *********************************************************************/
4491 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4492 const struct auth_session_info *session_info,
4493 struct messaging_context *msg_ctx,
4494 const char *servername,
4495 union spoolss_PrinterInfo **info,
4496 uint32_t *count)
4498 DEBUG(4,("enum_all_printers_info_1_local\n"));
4500 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4501 servername, PRINTER_ENUM_ICON8, info, count);
4504 /********************************************************************
4505 enum_all_printers_info_1_name.
4506 *********************************************************************/
4508 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4509 const struct auth_session_info *session_info,
4510 struct messaging_context *msg_ctx,
4511 const char *servername,
4512 union spoolss_PrinterInfo **info,
4513 uint32_t *count)
4515 const char *s = servername;
4517 DEBUG(4,("enum_all_printers_info_1_name\n"));
4519 if (servername != NULL &&
4520 (servername[0] == '\\') && (servername[1] == '\\')) {
4521 s = servername + 2;
4524 if (!is_myname_or_ipaddr(s)) {
4525 return WERR_INVALID_NAME;
4528 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4529 servername, PRINTER_ENUM_ICON8, info, count);
4532 /********************************************************************
4533 enum_all_printers_info_1_network.
4534 *********************************************************************/
4536 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4537 const struct auth_session_info *session_info,
4538 struct messaging_context *msg_ctx,
4539 const char *servername,
4540 union spoolss_PrinterInfo **info,
4541 uint32_t *count)
4543 const char *s = servername;
4545 DEBUG(4,("enum_all_printers_info_1_network\n"));
4547 /* If we respond to a enum_printers level 1 on our name with flags
4548 set to PRINTER_ENUM_REMOTE with a list of printers then these
4549 printers incorrectly appear in the APW browse list.
4550 Specifically the printers for the server appear at the workgroup
4551 level where all the other servers in the domain are
4552 listed. Windows responds to this call with a
4553 WERR_CAN_NOT_COMPLETE so we should do the same. */
4555 if (servername != NULL &&
4556 (servername[0] == '\\') && (servername[1] == '\\')) {
4557 s = servername + 2;
4560 if (is_myname_or_ipaddr(s)) {
4561 return WERR_CAN_NOT_COMPLETE;
4564 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4565 servername, PRINTER_ENUM_NAME, info, count);
4568 /********************************************************************
4569 * api_spoolss_enumprinters
4571 * called from api_spoolss_enumprinters (see this to understand)
4572 ********************************************************************/
4574 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4575 const struct auth_session_info *session_info,
4576 struct messaging_context *msg_ctx,
4577 const char *servername,
4578 union spoolss_PrinterInfo **info,
4579 uint32_t *count)
4581 DEBUG(4,("enum_all_printers_info_2\n"));
4583 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4584 servername, 2, 0, info, count);
4587 /********************************************************************
4588 * handle enumeration of printers at level 1
4589 ********************************************************************/
4591 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4592 const struct auth_session_info *session_info,
4593 struct messaging_context *msg_ctx,
4594 uint32_t flags,
4595 const char *servername,
4596 union spoolss_PrinterInfo **info,
4597 uint32_t *count)
4599 /* Not all the flags are equals */
4601 if (flags & PRINTER_ENUM_LOCAL) {
4602 return enum_all_printers_info_1_local(mem_ctx, session_info,
4603 msg_ctx, servername, info, count);
4606 if (flags & PRINTER_ENUM_NAME) {
4607 return enum_all_printers_info_1_name(mem_ctx, session_info,
4608 msg_ctx, servername, info,
4609 count);
4612 if (flags & PRINTER_ENUM_NETWORK) {
4613 return enum_all_printers_info_1_network(mem_ctx, session_info,
4614 msg_ctx, servername, info,
4615 count);
4618 return WERR_OK; /* NT4sp5 does that */
4621 /********************************************************************
4622 * handle enumeration of printers at level 2
4623 ********************************************************************/
4625 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4626 const struct auth_session_info *session_info,
4627 struct messaging_context *msg_ctx,
4628 uint32_t flags,
4629 const char *servername,
4630 union spoolss_PrinterInfo **info,
4631 uint32_t *count)
4633 if (flags & PRINTER_ENUM_LOCAL) {
4635 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4636 servername,
4637 info, count);
4640 if (flags & PRINTER_ENUM_NAME) {
4641 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4642 return WERR_INVALID_NAME;
4645 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4646 servername,
4647 info, count);
4650 if (flags & PRINTER_ENUM_REMOTE) {
4651 return WERR_UNKNOWN_LEVEL;
4654 return WERR_OK;
4657 /********************************************************************
4658 * handle enumeration of printers at level 4
4659 ********************************************************************/
4661 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4662 const struct auth_session_info *session_info,
4663 struct messaging_context *msg_ctx,
4664 uint32_t flags,
4665 const char *servername,
4666 union spoolss_PrinterInfo **info,
4667 uint32_t *count)
4669 DEBUG(4,("enum_all_printers_info_4\n"));
4671 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4672 servername, 4, flags, info, count);
4676 /********************************************************************
4677 * handle enumeration of printers at level 5
4678 ********************************************************************/
4680 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4681 const struct auth_session_info *session_info,
4682 struct messaging_context *msg_ctx,
4683 uint32_t flags,
4684 const char *servername,
4685 union spoolss_PrinterInfo **info,
4686 uint32_t *count)
4688 DEBUG(4,("enum_all_printers_info_5\n"));
4690 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4691 servername, 5, flags, info, count);
4694 /****************************************************************
4695 _spoolss_EnumPrinters
4696 ****************************************************************/
4698 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4699 struct spoolss_EnumPrinters *r)
4701 const struct auth_session_info *session_info = get_session_info_system();
4702 WERROR result;
4704 /* that's an [in out] buffer */
4706 if (!r->in.buffer && (r->in.offered != 0)) {
4707 return WERR_INVALID_PARAM;
4710 DEBUG(4,("_spoolss_EnumPrinters\n"));
4712 *r->out.needed = 0;
4713 *r->out.count = 0;
4714 *r->out.info = NULL;
4717 * Level 1:
4718 * flags==PRINTER_ENUM_NAME
4719 * if name=="" then enumerates all printers
4720 * if name!="" then enumerate the printer
4721 * flags==PRINTER_ENUM_REMOTE
4722 * name is NULL, enumerate printers
4723 * Level 2: name!="" enumerates printers, name can't be NULL
4724 * Level 3: doesn't exist
4725 * Level 4: does a local registry lookup
4726 * Level 5: same as Level 2
4729 if (r->in.server && r->in.server[0] == '\0') {
4730 r->in.server = NULL;
4733 switch (r->in.level) {
4734 case 0:
4735 result = enumprinters_level0(p->mem_ctx, session_info,
4736 p->msg_ctx, r->in.flags,
4737 r->in.server,
4738 r->out.info, r->out.count);
4739 break;
4740 case 1:
4741 result = enumprinters_level1(p->mem_ctx, session_info,
4742 p->msg_ctx, r->in.flags,
4743 r->in.server,
4744 r->out.info, r->out.count);
4745 break;
4746 case 2:
4747 result = enumprinters_level2(p->mem_ctx, session_info,
4748 p->msg_ctx, r->in.flags,
4749 r->in.server,
4750 r->out.info, r->out.count);
4751 break;
4752 case 4:
4753 result = enumprinters_level4(p->mem_ctx, session_info,
4754 p->msg_ctx, r->in.flags,
4755 r->in.server,
4756 r->out.info, r->out.count);
4757 break;
4758 case 5:
4759 result = enumprinters_level5(p->mem_ctx, session_info,
4760 p->msg_ctx, r->in.flags,
4761 r->in.server,
4762 r->out.info, r->out.count);
4763 break;
4764 default:
4765 return WERR_UNKNOWN_LEVEL;
4768 if (!W_ERROR_IS_OK(result)) {
4769 return result;
4772 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4773 spoolss_EnumPrinters,
4774 *r->out.info, r->in.level,
4775 *r->out.count);
4776 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4777 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4779 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4782 /****************************************************************
4783 _spoolss_GetPrinter
4784 ****************************************************************/
4786 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4787 struct spoolss_GetPrinter *r)
4789 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4790 struct spoolss_PrinterInfo2 *info2 = NULL;
4791 WERROR result = WERR_OK;
4792 int snum;
4794 /* that's an [in out] buffer */
4796 if (!r->in.buffer && (r->in.offered != 0)) {
4797 result = WERR_INVALID_PARAM;
4798 goto err_info_free;
4801 *r->out.needed = 0;
4803 if (Printer == NULL) {
4804 result = WERR_BADFID;
4805 goto err_info_free;
4808 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4809 result = WERR_BADFID;
4810 goto err_info_free;
4813 result = winreg_get_printer_internal(p->mem_ctx,
4814 get_session_info_system(),
4815 p->msg_ctx,
4816 lp_const_servicename(snum),
4817 &info2);
4818 if (!W_ERROR_IS_OK(result)) {
4819 goto err_info_free;
4822 switch (r->in.level) {
4823 case 0:
4824 result = construct_printer_info0(p->mem_ctx,
4825 get_session_info_system(),
4826 p->msg_ctx,
4827 info2,
4828 Printer->servername,
4829 &r->out.info->info0,
4830 snum);
4831 break;
4832 case 1:
4833 result = construct_printer_info1(p->mem_ctx, info2,
4834 PRINTER_ENUM_ICON8,
4835 Printer->servername,
4836 &r->out.info->info1, snum);
4837 break;
4838 case 2:
4839 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4840 Printer->servername,
4841 &r->out.info->info2, snum);
4842 break;
4843 case 3:
4844 result = construct_printer_info3(p->mem_ctx, info2,
4845 Printer->servername,
4846 &r->out.info->info3, snum);
4847 break;
4848 case 4:
4849 result = construct_printer_info4(p->mem_ctx, info2,
4850 Printer->servername,
4851 &r->out.info->info4, snum);
4852 break;
4853 case 5:
4854 result = construct_printer_info5(p->mem_ctx, info2,
4855 Printer->servername,
4856 &r->out.info->info5, snum);
4857 break;
4858 case 6:
4859 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4860 Printer->servername,
4861 &r->out.info->info6, snum);
4862 break;
4863 case 7:
4864 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4865 Printer->servername,
4866 &r->out.info->info7, snum);
4867 break;
4868 case 8:
4869 result = construct_printer_info8(p->mem_ctx, info2,
4870 Printer->servername,
4871 &r->out.info->info8, snum);
4872 break;
4873 default:
4874 result = WERR_UNKNOWN_LEVEL;
4875 break;
4877 TALLOC_FREE(info2);
4879 if (!W_ERROR_IS_OK(result)) {
4880 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4881 r->in.level, win_errstr(result)));
4882 goto err_info_free;
4885 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4886 r->out.info, r->in.level);
4887 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4889 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4891 err_info_free:
4892 TALLOC_FREE(r->out.info);
4893 return result;
4896 /********************************************************************
4897 ********************************************************************/
4899 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4900 do { \
4901 if (in && strlen(in)) { \
4902 out = talloc_strdup(mem_ctx, in); \
4903 } else { \
4904 out = talloc_strdup(mem_ctx, ""); \
4906 W_ERROR_HAVE_NO_MEMORY(out); \
4907 } while (0);
4909 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4910 do { \
4911 if (in && strlen(in)) { \
4912 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4913 } else { \
4914 out = talloc_strdup(mem_ctx, ""); \
4916 W_ERROR_HAVE_NO_MEMORY(out); \
4917 } while (0);
4919 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4920 const char **string_array,
4921 const char ***presult,
4922 const char *cservername,
4923 const char *arch,
4924 int version)
4926 int i;
4927 size_t num_strings = 0;
4928 const char **array = NULL;
4930 if (string_array == NULL) {
4931 return WERR_INVALID_PARAMETER;
4934 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4935 const char *str = NULL;
4937 if (cservername == NULL || arch == NULL) {
4938 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4939 } else {
4940 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4943 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4944 TALLOC_FREE(array);
4945 return WERR_NOMEM;
4949 if (i > 0) {
4950 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4951 &array, &num_strings);
4954 if (presult != NULL) {
4955 *presult = array;
4956 } else {
4957 talloc_free(array);
4960 return WERR_OK;
4963 /********************************************************************
4964 * fill a spoolss_DriverInfo1 struct
4965 ********************************************************************/
4967 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4968 struct spoolss_DriverInfo1 *r,
4969 const struct spoolss_DriverInfo8 *driver,
4970 const char *servername)
4972 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4973 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4975 return WERR_OK;
4978 /********************************************************************
4979 * fill a spoolss_DriverInfo2 struct
4980 ********************************************************************/
4982 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4983 struct spoolss_DriverInfo2 *r,
4984 const struct spoolss_DriverInfo8 *driver,
4985 const char *servername)
4988 const char *cservername = canon_servername(servername);
4990 r->version = driver->version;
4992 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4993 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4994 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4995 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4997 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998 driver->architecture,
4999 driver->version,
5000 driver->driver_path,
5001 r->driver_path);
5003 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5004 driver->architecture,
5005 driver->version,
5006 driver->data_file,
5007 r->data_file);
5009 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5010 driver->architecture,
5011 driver->version,
5012 driver->config_file,
5013 r->config_file);
5015 return WERR_OK;
5018 /********************************************************************
5019 * fill a spoolss_DriverInfo3 struct
5020 ********************************************************************/
5022 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5023 struct spoolss_DriverInfo3 *r,
5024 const struct spoolss_DriverInfo8 *driver,
5025 const char *servername)
5027 const char *cservername = canon_servername(servername);
5029 r->version = driver->version;
5031 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5032 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5033 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5034 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5036 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5037 driver->architecture,
5038 driver->version,
5039 driver->driver_path,
5040 r->driver_path);
5042 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5043 driver->architecture,
5044 driver->version,
5045 driver->data_file,
5046 r->data_file);
5048 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5049 driver->architecture,
5050 driver->version,
5051 driver->config_file,
5052 r->config_file);
5054 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5055 driver->architecture,
5056 driver->version,
5057 driver->help_file,
5058 r->help_file);
5060 FILL_DRIVER_STRING(mem_ctx,
5061 driver->monitor_name,
5062 r->monitor_name);
5064 FILL_DRIVER_STRING(mem_ctx,
5065 driver->default_datatype,
5066 r->default_datatype);
5068 return string_array_from_driver_info(mem_ctx,
5069 driver->dependent_files,
5070 &r->dependent_files,
5071 cservername,
5072 driver->architecture,
5073 driver->version);
5076 /********************************************************************
5077 * fill a spoolss_DriverInfo4 struct
5078 ********************************************************************/
5080 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5081 struct spoolss_DriverInfo4 *r,
5082 const struct spoolss_DriverInfo8 *driver,
5083 const char *servername)
5085 const char *cservername = canon_servername(servername);
5086 WERROR result;
5088 r->version = driver->version;
5090 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5091 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5092 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5093 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5095 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5096 driver->architecture,
5097 driver->version,
5098 driver->driver_path,
5099 r->driver_path);
5101 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5102 driver->architecture,
5103 driver->version,
5104 driver->data_file,
5105 r->data_file);
5107 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108 driver->architecture,
5109 driver->version,
5110 driver->config_file,
5111 r->config_file);
5113 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5114 driver->architecture,
5115 driver->version,
5116 driver->help_file,
5117 r->help_file);
5119 result = string_array_from_driver_info(mem_ctx,
5120 driver->dependent_files,
5121 &r->dependent_files,
5122 cservername,
5123 driver->architecture,
5124 driver->version);
5125 if (!W_ERROR_IS_OK(result)) {
5126 return result;
5129 FILL_DRIVER_STRING(mem_ctx,
5130 driver->monitor_name,
5131 r->monitor_name);
5133 FILL_DRIVER_STRING(mem_ctx,
5134 driver->default_datatype,
5135 r->default_datatype);
5138 result = string_array_from_driver_info(mem_ctx,
5139 driver->previous_names,
5140 &r->previous_names,
5141 NULL, NULL, 0);
5143 return result;
5146 /********************************************************************
5147 * fill a spoolss_DriverInfo5 struct
5148 ********************************************************************/
5150 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5151 struct spoolss_DriverInfo5 *r,
5152 const struct spoolss_DriverInfo8 *driver,
5153 const char *servername)
5155 const char *cservername = canon_servername(servername);
5157 r->version = driver->version;
5159 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5160 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5161 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5162 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5164 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5165 driver->architecture,
5166 driver->version,
5167 driver->driver_path,
5168 r->driver_path);
5170 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5171 driver->architecture,
5172 driver->version,
5173 driver->data_file,
5174 r->data_file);
5176 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177 driver->architecture,
5178 driver->version,
5179 driver->config_file,
5180 r->config_file);
5182 r->driver_attributes = 0;
5183 r->config_version = 0;
5184 r->driver_version = 0;
5186 return WERR_OK;
5188 /********************************************************************
5189 * fill a spoolss_DriverInfo6 struct
5190 ********************************************************************/
5192 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5193 struct spoolss_DriverInfo6 *r,
5194 const struct spoolss_DriverInfo8 *driver,
5195 const char *servername)
5197 const char *cservername = canon_servername(servername);
5198 WERROR result;
5200 r->version = driver->version;
5202 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5203 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5204 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5205 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5207 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5208 driver->architecture,
5209 driver->version,
5210 driver->driver_path,
5211 r->driver_path);
5213 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5214 driver->architecture,
5215 driver->version,
5216 driver->data_file,
5217 r->data_file);
5219 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5220 driver->architecture,
5221 driver->version,
5222 driver->config_file,
5223 r->config_file);
5225 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5226 driver->architecture,
5227 driver->version,
5228 driver->help_file,
5229 r->help_file);
5231 FILL_DRIVER_STRING(mem_ctx,
5232 driver->monitor_name,
5233 r->monitor_name);
5235 FILL_DRIVER_STRING(mem_ctx,
5236 driver->default_datatype,
5237 r->default_datatype);
5239 result = string_array_from_driver_info(mem_ctx,
5240 driver->dependent_files,
5241 &r->dependent_files,
5242 cservername,
5243 driver->architecture,
5244 driver->version);
5245 if (!W_ERROR_IS_OK(result)) {
5246 return result;
5249 result = string_array_from_driver_info(mem_ctx,
5250 driver->previous_names,
5251 &r->previous_names,
5252 NULL, NULL, 0);
5253 if (!W_ERROR_IS_OK(result)) {
5254 return result;
5257 r->driver_date = driver->driver_date;
5258 r->driver_version = driver->driver_version;
5260 FILL_DRIVER_STRING(mem_ctx,
5261 driver->manufacturer_name,
5262 r->manufacturer_name);
5263 FILL_DRIVER_STRING(mem_ctx,
5264 driver->manufacturer_url,
5265 r->manufacturer_url);
5266 FILL_DRIVER_STRING(mem_ctx,
5267 driver->hardware_id,
5268 r->hardware_id);
5269 FILL_DRIVER_STRING(mem_ctx,
5270 driver->provider,
5271 r->provider);
5273 return WERR_OK;
5276 /********************************************************************
5277 * fill a spoolss_DriverInfo8 struct
5278 ********************************************************************/
5280 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5281 struct spoolss_DriverInfo8 *r,
5282 const struct spoolss_DriverInfo8 *driver,
5283 const char *servername)
5285 const char *cservername = canon_servername(servername);
5286 WERROR result;
5288 r->version = driver->version;
5290 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5291 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5292 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5293 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5295 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5296 driver->architecture,
5297 driver->version,
5298 driver->driver_path,
5299 r->driver_path);
5301 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5302 driver->architecture,
5303 driver->version,
5304 driver->data_file,
5305 r->data_file);
5307 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5308 driver->architecture,
5309 driver->version,
5310 driver->config_file,
5311 r->config_file);
5313 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5314 driver->architecture,
5315 driver->version,
5316 driver->help_file,
5317 r->help_file);
5319 FILL_DRIVER_STRING(mem_ctx,
5320 driver->monitor_name,
5321 r->monitor_name);
5323 FILL_DRIVER_STRING(mem_ctx,
5324 driver->default_datatype,
5325 r->default_datatype);
5327 result = string_array_from_driver_info(mem_ctx,
5328 driver->dependent_files,
5329 &r->dependent_files,
5330 cservername,
5331 driver->architecture,
5332 driver->version);
5333 if (!W_ERROR_IS_OK(result)) {
5334 return result;
5337 result = string_array_from_driver_info(mem_ctx,
5338 driver->previous_names,
5339 &r->previous_names,
5340 NULL, NULL, 0);
5341 if (!W_ERROR_IS_OK(result)) {
5342 return result;
5345 r->driver_date = driver->driver_date;
5346 r->driver_version = driver->driver_version;
5348 FILL_DRIVER_STRING(mem_ctx,
5349 driver->manufacturer_name,
5350 r->manufacturer_name);
5351 FILL_DRIVER_STRING(mem_ctx,
5352 driver->manufacturer_url,
5353 r->manufacturer_url);
5354 FILL_DRIVER_STRING(mem_ctx,
5355 driver->hardware_id,
5356 r->hardware_id);
5357 FILL_DRIVER_STRING(mem_ctx,
5358 driver->provider,
5359 r->provider);
5361 FILL_DRIVER_STRING(mem_ctx,
5362 driver->print_processor,
5363 r->print_processor);
5364 FILL_DRIVER_STRING(mem_ctx,
5365 driver->vendor_setup,
5366 r->vendor_setup);
5368 result = string_array_from_driver_info(mem_ctx,
5369 driver->color_profiles,
5370 &r->color_profiles,
5371 NULL, NULL, 0);
5372 if (!W_ERROR_IS_OK(result)) {
5373 return result;
5376 FILL_DRIVER_STRING(mem_ctx,
5377 driver->inf_path,
5378 r->inf_path);
5380 r->printer_driver_attributes = driver->printer_driver_attributes;
5382 result = string_array_from_driver_info(mem_ctx,
5383 driver->core_driver_dependencies,
5384 &r->core_driver_dependencies,
5385 NULL, NULL, 0);
5386 if (!W_ERROR_IS_OK(result)) {
5387 return result;
5390 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5391 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5393 return WERR_OK;
5396 #if 0 /* disabled until marshalling issues are resolved - gd */
5397 /********************************************************************
5398 ********************************************************************/
5400 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5401 struct spoolss_DriverFileInfo *r,
5402 const char *cservername,
5403 const char *file_name,
5404 enum spoolss_DriverFileType file_type,
5405 uint32_t file_version)
5407 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5408 cservername, file_name);
5409 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5410 r->file_type = file_type;
5411 r->file_version = file_version;
5413 return WERR_OK;
5416 /********************************************************************
5417 ********************************************************************/
5419 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5420 const struct spoolss_DriverInfo8 *driver,
5421 const char *cservername,
5422 struct spoolss_DriverFileInfo **info_p,
5423 uint32_t *count_p)
5425 struct spoolss_DriverFileInfo *info = NULL;
5426 uint32_t count = 0;
5427 WERROR result;
5428 uint32_t i;
5430 *info_p = NULL;
5431 *count_p = 0;
5433 if (strlen(driver->driver_path)) {
5434 info = talloc_realloc(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->driver_path,
5442 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5444 W_ERROR_NOT_OK_RETURN(result);
5445 count++;
5448 if (strlen(driver->config_file)) {
5449 info = talloc_realloc(mem_ctx, info,
5450 struct spoolss_DriverFileInfo,
5451 count + 1);
5452 W_ERROR_HAVE_NO_MEMORY(info);
5453 result = fill_spoolss_DriverFileInfo(info,
5454 &info[count],
5455 cservername,
5456 driver->config_file,
5457 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5459 W_ERROR_NOT_OK_RETURN(result);
5460 count++;
5463 if (strlen(driver->data_file)) {
5464 info = talloc_realloc(mem_ctx, info,
5465 struct spoolss_DriverFileInfo,
5466 count + 1);
5467 W_ERROR_HAVE_NO_MEMORY(info);
5468 result = fill_spoolss_DriverFileInfo(info,
5469 &info[count],
5470 cservername,
5471 driver->data_file,
5472 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5474 W_ERROR_NOT_OK_RETURN(result);
5475 count++;
5478 if (strlen(driver->help_file)) {
5479 info = talloc_realloc(mem_ctx, info,
5480 struct spoolss_DriverFileInfo,
5481 count + 1);
5482 W_ERROR_HAVE_NO_MEMORY(info);
5483 result = fill_spoolss_DriverFileInfo(info,
5484 &info[count],
5485 cservername,
5486 driver->help_file,
5487 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5489 W_ERROR_NOT_OK_RETURN(result);
5490 count++;
5493 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5494 info = talloc_realloc(mem_ctx, info,
5495 struct spoolss_DriverFileInfo,
5496 count + 1);
5497 W_ERROR_HAVE_NO_MEMORY(info);
5498 result = fill_spoolss_DriverFileInfo(info,
5499 &info[count],
5500 cservername,
5501 driver->dependent_files[i],
5502 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5504 W_ERROR_NOT_OK_RETURN(result);
5505 count++;
5508 *info_p = info;
5509 *count_p = count;
5511 return WERR_OK;
5514 /********************************************************************
5515 * fill a spoolss_DriverInfo101 struct
5516 ********************************************************************/
5518 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5519 struct spoolss_DriverInfo101 *r,
5520 const struct spoolss_DriverInfo8 *driver,
5521 const char *servername)
5523 const char *cservername = canon_servername(servername);
5524 WERROR result;
5526 r->version = driver->version;
5528 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5529 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5530 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5531 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5533 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5534 cservername,
5535 &r->file_info,
5536 &r->file_count);
5537 if (!W_ERROR_IS_OK(result)) {
5538 return result;
5541 FILL_DRIVER_STRING(mem_ctx,
5542 driver->monitor_name,
5543 r->monitor_name);
5545 FILL_DRIVER_STRING(mem_ctx,
5546 driver->default_datatype,
5547 r->default_datatype);
5549 result = string_array_from_driver_info(mem_ctx,
5550 driver->previous_names,
5551 &r->previous_names,
5552 NULL, NULL, 0);
5553 if (!W_ERROR_IS_OK(result)) {
5554 return result;
5557 r->driver_date = driver->driver_date;
5558 r->driver_version = driver->driver_version;
5560 FILL_DRIVER_STRING(mem_ctx,
5561 driver->manufacturer_name,
5562 r->manufacturer_name);
5563 FILL_DRIVER_STRING(mem_ctx,
5564 driver->manufacturer_url,
5565 r->manufacturer_url);
5566 FILL_DRIVER_STRING(mem_ctx,
5567 driver->hardware_id,
5568 r->hardware_id);
5569 FILL_DRIVER_STRING(mem_ctx,
5570 driver->provider,
5571 r->provider);
5573 return WERR_OK;
5575 #endif
5576 /********************************************************************
5577 ********************************************************************/
5579 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5580 const struct auth_session_info *session_info,
5581 struct messaging_context *msg_ctx,
5582 uint32_t level,
5583 union spoolss_DriverInfo *r,
5584 int snum,
5585 const char *servername,
5586 const char *architecture,
5587 uint32_t version)
5589 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5590 struct spoolss_DriverInfo8 *driver;
5591 WERROR result;
5592 struct dcerpc_binding_handle *b;
5593 TALLOC_CTX *tmp_ctx = NULL;
5595 if (level == 101) {
5596 return WERR_UNKNOWN_LEVEL;
5599 tmp_ctx = talloc_new(mem_ctx);
5600 if (!tmp_ctx) {
5601 return WERR_NOMEM;
5604 result = winreg_printer_binding_handle(tmp_ctx,
5605 session_info,
5606 msg_ctx,
5607 &b);
5608 if (!W_ERROR_IS_OK(result)) {
5609 goto done;
5612 result = winreg_get_printer(tmp_ctx, b,
5613 lp_const_servicename(snum),
5614 &pinfo2);
5616 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5617 win_errstr(result)));
5619 if (!W_ERROR_IS_OK(result)) {
5620 result = WERR_INVALID_PRINTER_NAME;
5621 goto done;
5624 result = winreg_get_driver(tmp_ctx, b,
5625 architecture,
5626 pinfo2->drivername, version, &driver);
5628 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5629 win_errstr(result)));
5631 if (!W_ERROR_IS_OK(result)) {
5633 * Is this a W2k client ?
5636 if (version < 3) {
5637 result = WERR_UNKNOWN_PRINTER_DRIVER;
5638 goto done;
5641 /* Yes - try again with a WinNT driver. */
5642 version = 2;
5643 result = winreg_get_driver(tmp_ctx, b,
5644 architecture,
5645 pinfo2->drivername,
5646 version, &driver);
5647 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5648 win_errstr(result)));
5649 if (!W_ERROR_IS_OK(result)) {
5650 result = WERR_UNKNOWN_PRINTER_DRIVER;
5651 goto done;
5655 /* these are allocated on mem_ctx and not tmp_ctx because they are
5656 * the 'return value' and need to utlive this call */
5657 switch (level) {
5658 case 1:
5659 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5660 break;
5661 case 2:
5662 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5663 break;
5664 case 3:
5665 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5666 break;
5667 case 4:
5668 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5669 break;
5670 case 5:
5671 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5672 break;
5673 case 6:
5674 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5675 break;
5676 case 8:
5677 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5678 break;
5679 #if 0 /* disabled until marshalling issues are resolved - gd */
5680 case 101:
5681 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5682 break;
5683 #endif
5684 default:
5685 result = WERR_UNKNOWN_LEVEL;
5686 break;
5689 done:
5690 talloc_free(tmp_ctx);
5691 return result;
5694 /****************************************************************
5695 _spoolss_GetPrinterDriver2
5696 ****************************************************************/
5698 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5699 struct spoolss_GetPrinterDriver2 *r)
5701 struct printer_handle *printer;
5702 WERROR result;
5703 uint32_t version = r->in.client_major_version;
5705 int snum;
5707 /* that's an [in out] buffer */
5709 if (!r->in.buffer && (r->in.offered != 0)) {
5710 result = WERR_INVALID_PARAM;
5711 goto err_info_free;
5714 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5716 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5717 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5718 result = WERR_INVALID_PRINTER_NAME;
5719 goto err_info_free;
5722 *r->out.needed = 0;
5723 *r->out.server_major_version = 0;
5724 *r->out.server_minor_version = 0;
5726 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5727 result = WERR_BADFID;
5728 goto err_info_free;
5731 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5732 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5733 "downgrading to v3\n"));
5734 version = SPOOLSS_DRIVER_VERSION_200X;
5737 result = construct_printer_driver_info_level(p->mem_ctx,
5738 get_session_info_system(),
5739 p->msg_ctx,
5740 r->in.level, r->out.info,
5741 snum, printer->servername,
5742 r->in.architecture,
5743 version);
5744 if (!W_ERROR_IS_OK(result)) {
5745 goto err_info_free;
5748 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5749 r->out.info, r->in.level);
5750 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5752 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5754 err_info_free:
5755 TALLOC_FREE(r->out.info);
5756 return result;
5760 /****************************************************************
5761 _spoolss_StartPagePrinter
5762 ****************************************************************/
5764 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5765 struct spoolss_StartPagePrinter *r)
5767 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5769 if (!Printer) {
5770 DEBUG(3,("_spoolss_StartPagePrinter: "
5771 "Error in startpageprinter printer handle\n"));
5772 return WERR_BADFID;
5775 Printer->page_started = true;
5776 return WERR_OK;
5779 /****************************************************************
5780 _spoolss_EndPagePrinter
5781 ****************************************************************/
5783 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5784 struct spoolss_EndPagePrinter *r)
5786 int snum;
5788 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5790 if (!Printer) {
5791 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5792 OUR_HANDLE(r->in.handle)));
5793 return WERR_BADFID;
5796 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5797 return WERR_BADFID;
5799 Printer->page_started = false;
5800 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5802 return WERR_OK;
5805 /****************************************************************
5806 _spoolss_StartDocPrinter
5807 ****************************************************************/
5809 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5810 struct spoolss_StartDocPrinter *r)
5812 struct spoolss_DocumentInfo1 *info_1;
5813 int snum;
5814 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5815 WERROR werr;
5816 char *rhost;
5817 int rc;
5819 if (!Printer) {
5820 DEBUG(2,("_spoolss_StartDocPrinter: "
5821 "Invalid handle (%s:%u:%u)\n",
5822 OUR_HANDLE(r->in.handle)));
5823 return WERR_BADFID;
5826 if (Printer->jobid) {
5827 DEBUG(2, ("_spoolss_StartDocPrinter: "
5828 "StartDocPrinter called twice! "
5829 "(existing jobid = %d)\n", Printer->jobid));
5830 return WERR_INVALID_HANDLE;
5833 if (r->in.info_ctr->level != 1) {
5834 return WERR_UNKNOWN_LEVEL;
5837 info_1 = r->in.info_ctr->info.info1;
5840 * a nice thing with NT is it doesn't listen to what you tell it.
5841 * when asked to send _only_ RAW datas, it tries to send datas
5842 * in EMF format.
5844 * So I add checks like in NT Server ...
5847 if (info_1->datatype) {
5849 * The v4 driver model used in Windows 8 declares print jobs
5850 * intended to bypass the XPS processing layer by setting
5851 * datatype to "XPS_PASS" instead of "RAW".
5853 if ((strcmp(info_1->datatype, "RAW") != 0)
5854 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5855 *r->out.job_id = 0;
5856 return WERR_INVALID_DATATYPE;
5860 /* get the share number of the printer */
5861 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5862 return WERR_BADFID;
5865 rc = get_remote_hostname(p->remote_address,
5866 &rhost,
5867 p->mem_ctx);
5868 if (rc < 0) {
5869 return WERR_NOMEM;
5871 if (strequal(rhost,"UNKNOWN")) {
5872 rhost = tsocket_address_inet_addr_string(p->remote_address,
5873 p->mem_ctx);
5874 if (rhost == NULL) {
5875 return WERR_NOMEM;
5879 werr = print_job_start(p->session_info,
5880 p->msg_ctx,
5881 rhost,
5882 snum,
5883 info_1->document_name,
5884 info_1->output_file,
5885 Printer->devmode,
5886 &Printer->jobid);
5888 /* An error occured in print_job_start() so return an appropriate
5889 NT error code. */
5891 if (!W_ERROR_IS_OK(werr)) {
5892 return werr;
5895 Printer->document_started = true;
5896 *r->out.job_id = Printer->jobid;
5898 return WERR_OK;
5901 /****************************************************************
5902 _spoolss_EndDocPrinter
5903 ****************************************************************/
5905 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5906 struct spoolss_EndDocPrinter *r)
5908 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5909 NTSTATUS status;
5910 int snum;
5912 if (!Printer) {
5913 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5914 OUR_HANDLE(r->in.handle)));
5915 return WERR_BADFID;
5918 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5919 return WERR_BADFID;
5922 Printer->document_started = false;
5923 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5924 if (!NT_STATUS_IS_OK(status)) {
5925 DEBUG(2, ("_spoolss_EndDocPrinter: "
5926 "print_job_end failed [%s]\n",
5927 nt_errstr(status)));
5930 Printer->jobid = 0;
5931 return ntstatus_to_werror(status);
5934 /****************************************************************
5935 _spoolss_WritePrinter
5936 ****************************************************************/
5938 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5939 struct spoolss_WritePrinter *r)
5941 ssize_t buffer_written;
5942 int snum;
5943 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5945 if (!Printer) {
5946 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5947 OUR_HANDLE(r->in.handle)));
5948 *r->out.num_written = r->in._data_size;
5949 return WERR_BADFID;
5952 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5953 return WERR_BADFID;
5955 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5956 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5957 snum, Printer->jobid,
5958 (const char *)r->in.data.data,
5959 (size_t)r->in._data_size);
5960 if (buffer_written == (ssize_t)-1) {
5961 *r->out.num_written = 0;
5962 if (errno == ENOSPC)
5963 return WERR_NO_SPOOL_SPACE;
5964 else
5965 return WERR_ACCESS_DENIED;
5968 *r->out.num_written = r->in._data_size;
5970 return WERR_OK;
5973 /********************************************************************
5974 * api_spoolss_getprinter
5975 * called from the spoolss dispatcher
5977 ********************************************************************/
5979 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5980 struct pipes_struct *p)
5982 const struct auth_session_info *session_info = p->session_info;
5983 int snum;
5984 WERROR errcode = WERR_BADFUNC;
5985 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5987 if (!Printer) {
5988 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5989 OUR_HANDLE(handle)));
5990 return WERR_BADFID;
5993 if (!get_printer_snum(p, handle, &snum, NULL))
5994 return WERR_BADFID;
5996 switch (command) {
5997 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5998 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5999 break;
6000 case SPOOLSS_PRINTER_CONTROL_RESUME:
6001 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6002 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6003 break;
6004 case SPOOLSS_PRINTER_CONTROL_PURGE:
6005 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6006 break;
6007 default:
6008 return WERR_UNKNOWN_LEVEL;
6011 return errcode;
6015 /****************************************************************
6016 _spoolss_AbortPrinter
6017 * From MSDN: "Deletes printer's spool file if printer is configured
6018 * for spooling"
6019 ****************************************************************/
6021 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6022 struct spoolss_AbortPrinter *r)
6024 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6025 int snum;
6026 WERROR errcode = WERR_OK;
6028 if (!Printer) {
6029 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6030 OUR_HANDLE(r->in.handle)));
6031 return WERR_BADFID;
6034 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6035 return WERR_BADFID;
6037 if (!Printer->document_started) {
6038 return WERR_SPL_NO_STARTDOC;
6041 errcode = print_job_delete(p->session_info,
6042 p->msg_ctx,
6043 snum,
6044 Printer->jobid);
6046 return errcode;
6049 /********************************************************************
6050 * called by spoolss_api_setprinter
6051 * when updating a printer description
6052 ********************************************************************/
6054 static WERROR update_printer_sec(struct policy_handle *handle,
6055 struct pipes_struct *p,
6056 struct sec_desc_buf *secdesc_ctr)
6058 struct spoolss_security_descriptor *new_secdesc = NULL;
6059 struct spoolss_security_descriptor *old_secdesc = NULL;
6060 const char *printer;
6061 WERROR result;
6062 int snum;
6063 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6064 struct dcerpc_binding_handle *b;
6065 TALLOC_CTX *tmp_ctx = NULL;
6067 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6068 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6069 OUR_HANDLE(handle)));
6071 result = WERR_BADFID;
6072 goto done;
6075 if (secdesc_ctr == NULL) {
6076 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6077 result = WERR_INVALID_PARAM;
6078 goto done;
6080 printer = lp_const_servicename(snum);
6082 /* Check the user has permissions to change the security
6083 descriptor. By experimentation with two NT machines, the user
6084 requires Full Access to the printer to change security
6085 information. */
6087 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6088 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6089 result = WERR_ACCESS_DENIED;
6090 goto done;
6093 tmp_ctx = talloc_new(p->mem_ctx);
6094 if (!tmp_ctx) {
6095 return WERR_NOMEM;
6098 result = winreg_printer_binding_handle(tmp_ctx,
6099 get_session_info_system(),
6100 p->msg_ctx,
6101 &b);
6102 if (!W_ERROR_IS_OK(result)) {
6103 goto done;
6106 /* NT seems to like setting the security descriptor even though
6107 nothing may have actually changed. */
6108 result = winreg_get_printer_secdesc(tmp_ctx, b,
6109 printer,
6110 &old_secdesc);
6111 if (!W_ERROR_IS_OK(result)) {
6112 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6113 result = WERR_BADFID;
6114 goto done;
6117 if (DEBUGLEVEL >= 10) {
6118 struct security_acl *the_acl;
6119 int i;
6121 the_acl = old_secdesc->dacl;
6122 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6123 printer, the_acl->num_aces));
6125 for (i = 0; i < the_acl->num_aces; i++) {
6126 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6127 &the_acl->aces[i].trustee),
6128 the_acl->aces[i].access_mask));
6131 the_acl = secdesc_ctr->sd->dacl;
6133 if (the_acl) {
6134 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6135 printer, the_acl->num_aces));
6137 for (i = 0; i < the_acl->num_aces; i++) {
6138 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6139 &the_acl->aces[i].trustee),
6140 the_acl->aces[i].access_mask));
6142 } else {
6143 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6147 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6148 if (new_secdesc == NULL) {
6149 result = WERR_NOMEM;
6150 goto done;
6153 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6154 result = WERR_OK;
6155 goto done;
6158 result = winreg_set_printer_secdesc(tmp_ctx, b,
6159 printer,
6160 new_secdesc);
6162 done:
6163 talloc_free(tmp_ctx);
6164 return result;
6167 /********************************************************************
6168 Canonicalize printer info from a client
6169 ********************************************************************/
6171 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6172 struct spoolss_SetPrinterInfo2 *info2,
6173 int snum)
6175 fstring printername;
6176 const char *p;
6178 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6179 "portname=%s drivername=%s comment=%s location=%s\n",
6180 info2->servername, info2->printername, info2->sharename,
6181 info2->portname, info2->drivername, info2->comment,
6182 info2->location));
6184 /* we force some elements to "correct" values */
6185 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6186 if (info2->servername == NULL) {
6187 return false;
6189 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6190 if (info2->sharename == NULL) {
6191 return false;
6194 /* check to see if we allow printername != sharename */
6195 if (lp_force_printername(snum)) {
6196 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6197 lp_netbios_name(), info2->sharename);
6198 } else {
6199 /* make sure printername is in \\server\printername format */
6200 fstrcpy(printername, info2->printername);
6201 p = printername;
6202 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6203 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6204 p++;
6207 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6208 lp_netbios_name(), p);
6210 if (info2->printername == NULL) {
6211 return false;
6214 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6215 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6217 return true;
6220 /****************************************************************************
6221 ****************************************************************************/
6223 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6225 char *cmd = lp_addport_command(talloc_tos());
6226 char *command = NULL;
6227 int ret;
6228 bool is_print_op = false;
6230 if ( !*cmd ) {
6231 return WERR_ACCESS_DENIED;
6234 command = talloc_asprintf(ctx,
6235 "%s \"%s\" \"%s\"", cmd, portname, uri );
6236 if (!command) {
6237 return WERR_NOMEM;
6240 if ( token )
6241 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6243 DEBUG(10,("Running [%s]\n", command));
6245 /********* BEGIN SePrintOperatorPrivilege **********/
6247 if ( is_print_op )
6248 become_root();
6250 ret = smbrun(command, NULL);
6252 if ( is_print_op )
6253 unbecome_root();
6255 /********* END SePrintOperatorPrivilege **********/
6257 DEBUGADD(10,("returned [%d]\n", ret));
6259 TALLOC_FREE(command);
6261 if ( ret != 0 ) {
6262 return WERR_ACCESS_DENIED;
6265 return WERR_OK;
6268 /****************************************************************************
6269 ****************************************************************************/
6271 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6272 int snum)
6275 * As we do not know if we are embedded in the file server process
6276 * or not, we have to pretend that all shares are in use.
6278 return true;
6281 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6282 struct spoolss_SetPrinterInfo2 *info2,
6283 const char *remote_machine,
6284 struct messaging_context *msg_ctx)
6286 char *cmd = lp_addprinter_command(talloc_tos());
6287 char **qlines;
6288 char *command = NULL;
6289 int numlines;
6290 int ret;
6291 int fd;
6292 bool is_print_op = false;
6294 if (!remote_machine) {
6295 return false;
6298 command = talloc_asprintf(ctx,
6299 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6300 cmd, info2->printername, info2->sharename,
6301 info2->portname, info2->drivername,
6302 info2->location, info2->comment, remote_machine);
6303 if (!command) {
6304 return false;
6307 if ( token )
6308 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6310 DEBUG(10,("Running [%s]\n", command));
6312 /********* BEGIN SePrintOperatorPrivilege **********/
6314 if ( is_print_op )
6315 become_root();
6317 if ( (ret = smbrun(command, &fd)) == 0 ) {
6318 /* Tell everyone we updated smb.conf. */
6319 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6322 if ( is_print_op )
6323 unbecome_root();
6325 /********* END SePrintOperatorPrivilege **********/
6327 DEBUGADD(10,("returned [%d]\n", ret));
6329 TALLOC_FREE(command);
6331 if ( ret != 0 ) {
6332 if (fd != -1)
6333 close(fd);
6334 return false;
6337 /* reload our services immediately */
6338 become_root();
6339 reload_services(NULL, spoolss_conn_snum_used, false);
6340 unbecome_root();
6342 numlines = 0;
6343 /* Get lines and convert them back to dos-codepage */
6344 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6345 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6346 close(fd);
6348 /* Set the portname to what the script says the portname should be. */
6349 /* but don't require anything to be return from the script exit a good error code */
6351 if (numlines) {
6352 /* Set the portname to what the script says the portname should be. */
6353 info2->portname = talloc_strdup(ctx, qlines[0]);
6354 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6357 TALLOC_FREE(qlines);
6358 return true;
6361 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6362 const struct auth_session_info *session_info,
6363 struct messaging_context *msg_ctx,
6364 int snum,
6365 struct spoolss_SetPrinterInfo2 *printer,
6366 struct spoolss_PrinterInfo2 *old_printer)
6368 bool force_update = (old_printer == NULL);
6369 const char *dnsdomname;
6370 const char *longname;
6371 const char *uncname;
6372 const char *spooling;
6373 DATA_BLOB buffer;
6374 WERROR result = WERR_OK;
6375 struct dcerpc_binding_handle *b;
6376 TALLOC_CTX *tmp_ctx;
6377 bool ok;
6379 tmp_ctx = talloc_new(mem_ctx);
6380 if (!tmp_ctx) {
6381 return WERR_NOMEM;
6384 result = winreg_printer_binding_handle(tmp_ctx,
6385 session_info,
6386 msg_ctx,
6387 &b);
6388 if (!W_ERROR_IS_OK(result)) {
6389 goto done;
6392 if (printer->drivername != NULL &&
6393 (force_update ||
6394 !strequal(printer->drivername, old_printer->drivername))) {
6395 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6396 if (!ok) {
6397 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6398 result = WERR_INVALID_DATA;
6399 goto done;
6401 result = winreg_set_printer_dataex(tmp_ctx, b,
6402 printer->sharename,
6403 SPOOL_DSSPOOLER_KEY,
6404 SPOOL_REG_DRIVERNAME,
6405 REG_SZ,
6406 buffer.data,
6407 buffer.length);
6408 if (!W_ERROR_IS_OK(result)) {
6409 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6410 goto done;
6413 if (!force_update) {
6414 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6415 printer->drivername));
6417 notify_printer_driver(server_event_context(), msg_ctx,
6418 snum, printer->drivername ?
6419 printer->drivername : "");
6423 if (printer->comment != NULL &&
6424 (force_update ||
6425 !strequal(printer->comment, old_printer->comment))) {
6426 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6427 if (!ok) {
6428 DEBUG(0, ("comment data corrupted\n"));
6429 result = WERR_INVALID_DATA;
6430 goto done;
6432 result = winreg_set_printer_dataex(tmp_ctx, b,
6433 printer->sharename,
6434 SPOOL_DSSPOOLER_KEY,
6435 SPOOL_REG_DESCRIPTION,
6436 REG_SZ,
6437 buffer.data,
6438 buffer.length);
6439 if (!W_ERROR_IS_OK(result)) {
6440 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6441 goto done;
6444 if (!force_update) {
6445 notify_printer_comment(server_event_context(), msg_ctx,
6446 snum, printer->comment ?
6447 printer->comment : "");
6451 if (printer->sharename != NULL &&
6452 (force_update ||
6453 !strequal(printer->sharename, old_printer->sharename))) {
6454 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6455 if (!ok) {
6456 DEBUG(0, ("sharename data corrupted\n"));
6457 result = WERR_INVALID_DATA;
6458 goto done;
6460 result = winreg_set_printer_dataex(tmp_ctx, b,
6461 printer->sharename,
6462 SPOOL_DSSPOOLER_KEY,
6463 SPOOL_REG_PRINTSHARENAME,
6464 REG_SZ,
6465 buffer.data,
6466 buffer.length);
6467 if (!W_ERROR_IS_OK(result)) {
6468 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6469 goto done;
6472 if (!force_update) {
6473 notify_printer_sharename(server_event_context(),
6474 msg_ctx,
6475 snum, printer->sharename ?
6476 printer->sharename : "");
6479 /* name change, purge any cache entries for the old */
6480 prune_printername_cache();
6483 if (printer->printername != NULL &&
6484 (force_update ||
6485 !strequal(printer->printername, old_printer->printername))) {
6486 const char *p;
6488 p = strrchr(printer->printername, '\\' );
6489 if (p != NULL) {
6490 p++;
6491 } else {
6492 p = printer->printername;
6495 ok = push_reg_sz(tmp_ctx, &buffer, p);
6496 if (!ok) {
6497 DEBUG(0, ("printername data corrupted\n"));
6498 result = WERR_INVALID_DATA;
6499 goto done;
6501 result = winreg_set_printer_dataex(tmp_ctx, b,
6502 printer->sharename,
6503 SPOOL_DSSPOOLER_KEY,
6504 SPOOL_REG_PRINTERNAME,
6505 REG_SZ,
6506 buffer.data,
6507 buffer.length);
6508 if (!W_ERROR_IS_OK(result)) {
6509 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6510 goto done;
6513 if (!force_update) {
6514 notify_printer_printername(server_event_context(),
6515 msg_ctx, snum, p ? p : "");
6518 /* name change, purge any cache entries for the old */
6519 prune_printername_cache();
6522 if (printer->portname != NULL &&
6523 (force_update ||
6524 !strequal(printer->portname, old_printer->portname))) {
6525 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6526 if (!ok) {
6527 DEBUG(0, ("portname data corrupted\n"));
6528 result = WERR_INVALID_DATA;
6529 goto done;
6531 result = winreg_set_printer_dataex(tmp_ctx, b,
6532 printer->sharename,
6533 SPOOL_DSSPOOLER_KEY,
6534 SPOOL_REG_PORTNAME,
6535 REG_SZ,
6536 buffer.data,
6537 buffer.length);
6538 if (!W_ERROR_IS_OK(result)) {
6539 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6540 goto done;
6543 if (!force_update) {
6544 notify_printer_port(server_event_context(),
6545 msg_ctx, snum, printer->portname ?
6546 printer->portname : "");
6550 if (printer->location != NULL &&
6551 (force_update ||
6552 !strequal(printer->location, old_printer->location))) {
6553 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6554 if (!ok) {
6555 DEBUG(0, ("location data corrupted\n"));
6556 result = WERR_INVALID_DATA;
6557 goto done;
6559 result = winreg_set_printer_dataex(tmp_ctx, b,
6560 printer->sharename,
6561 SPOOL_DSSPOOLER_KEY,
6562 SPOOL_REG_LOCATION,
6563 REG_SZ,
6564 buffer.data,
6565 buffer.length);
6566 if (!W_ERROR_IS_OK(result)) {
6567 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6568 goto done;
6571 if (!force_update) {
6572 notify_printer_location(server_event_context(),
6573 msg_ctx, snum,
6574 printer->location ?
6575 printer->location : "");
6579 if (printer->sepfile != NULL &&
6580 (force_update ||
6581 !strequal(printer->sepfile, old_printer->sepfile))) {
6582 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6583 if (!ok) {
6584 DEBUG(0, ("sepfile data corrupted\n"));
6585 result = WERR_INVALID_DATA;
6586 goto done;
6588 result = winreg_set_printer_dataex(tmp_ctx, b,
6589 printer->sharename,
6590 SPOOL_DSSPOOLER_KEY,
6591 SPOOL_REG_PRINTSEPARATORFILE,
6592 REG_SZ,
6593 buffer.data,
6594 buffer.length);
6595 if (!W_ERROR_IS_OK(result)) {
6596 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6597 goto done;
6600 if (!force_update) {
6601 notify_printer_sepfile(server_event_context(),
6602 msg_ctx, snum,
6603 printer->sepfile ?
6604 printer->sepfile : "");
6608 if (printer->starttime != 0 &&
6609 (force_update ||
6610 printer->starttime != old_printer->starttime)) {
6611 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6612 SIVAL(buffer.data, 0, printer->starttime);
6613 result = winreg_set_printer_dataex(tmp_ctx, b,
6614 printer->sharename,
6615 SPOOL_DSSPOOLER_KEY,
6616 SPOOL_REG_PRINTSTARTTIME,
6617 REG_DWORD,
6618 buffer.data,
6619 buffer.length);
6620 if (!W_ERROR_IS_OK(result)) {
6621 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6622 goto done;
6626 if (printer->untiltime != 0 &&
6627 (force_update ||
6628 printer->untiltime != old_printer->untiltime)) {
6629 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6630 SIVAL(buffer.data, 0, printer->untiltime);
6631 result = winreg_set_printer_dataex(tmp_ctx, b,
6632 printer->sharename,
6633 SPOOL_DSSPOOLER_KEY,
6634 SPOOL_REG_PRINTENDTIME,
6635 REG_DWORD,
6636 buffer.data,
6637 buffer.length);
6638 if (!W_ERROR_IS_OK(result)) {
6639 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6640 goto done;
6644 if (force_update || printer->priority != old_printer->priority) {
6645 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6646 SIVAL(buffer.data, 0, printer->priority);
6647 result = winreg_set_printer_dataex(tmp_ctx, b,
6648 printer->sharename,
6649 SPOOL_DSSPOOLER_KEY,
6650 SPOOL_REG_PRIORITY,
6651 REG_DWORD,
6652 buffer.data,
6653 buffer.length);
6654 if (!W_ERROR_IS_OK(result)) {
6655 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6656 goto done;
6660 if (force_update || printer->attributes != old_printer->attributes) {
6661 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6662 SIVAL(buffer.data, 0, (printer->attributes &
6663 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6664 result = winreg_set_printer_dataex(tmp_ctx, b,
6665 printer->sharename,
6666 SPOOL_DSSPOOLER_KEY,
6667 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6668 REG_DWORD,
6669 buffer.data,
6670 buffer.length);
6671 if (!W_ERROR_IS_OK(result)) {
6672 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6673 goto done;
6676 switch (printer->attributes & 0x3) {
6677 case 0:
6678 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6679 break;
6680 case 1:
6681 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6682 break;
6683 case 2:
6684 spooling = SPOOL_REGVAL_PRINTDIRECT;
6685 break;
6686 default:
6687 spooling = "unknown";
6689 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6690 if (!ok) {
6691 DEBUG(0, ("printSpooling data corrupted\n"));
6692 result = WERR_INVALID_DATA;
6693 goto done;
6695 winreg_set_printer_dataex(tmp_ctx, b,
6696 printer->sharename,
6697 SPOOL_DSSPOOLER_KEY,
6698 SPOOL_REG_PRINTSPOOLING,
6699 REG_SZ,
6700 buffer.data,
6701 buffer.length);
6704 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6705 if (!ok) {
6706 DEBUG(0, ("shortServerName data corrupted\n"));
6707 result = WERR_INVALID_DATA;
6708 goto done;
6710 result = winreg_set_printer_dataex(tmp_ctx, b,
6711 printer->sharename,
6712 SPOOL_DSSPOOLER_KEY,
6713 SPOOL_REG_SHORTSERVERNAME,
6714 REG_SZ,
6715 buffer.data,
6716 buffer.length);
6717 if (!W_ERROR_IS_OK(result)) {
6718 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6719 goto done;
6722 dnsdomname = get_mydnsfullname();
6723 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6724 longname = talloc_strdup(tmp_ctx, dnsdomname);
6725 } else {
6726 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6728 if (longname == NULL) {
6729 result = WERR_NOMEM;
6730 goto done;
6733 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6734 if (!ok) {
6735 DEBUG(0, ("longname data corrupted\n"));
6736 result = WERR_INVALID_DATA;
6737 goto done;
6739 result = winreg_set_printer_dataex(tmp_ctx, b,
6740 printer->sharename,
6741 SPOOL_DSSPOOLER_KEY,
6742 SPOOL_REG_SERVERNAME,
6743 REG_SZ,
6744 buffer.data,
6745 buffer.length);
6746 if (!W_ERROR_IS_OK(result)) {
6747 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6748 goto done;
6751 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6752 lp_netbios_name(), printer->sharename);
6753 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6754 if (!ok) {
6755 DEBUG(0, ("uncName data corrupted\n"));
6756 result = WERR_INVALID_DATA;
6757 goto done;
6759 result = winreg_set_printer_dataex(tmp_ctx, b,
6760 printer->sharename,
6761 SPOOL_DSSPOOLER_KEY,
6762 SPOOL_REG_UNCNAME,
6763 REG_SZ,
6764 buffer.data,
6765 buffer.length);
6766 if (!W_ERROR_IS_OK(result)) {
6767 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6768 goto done;
6771 done:
6772 talloc_free(tmp_ctx);
6773 return result;
6776 /********************************************************************
6777 * Called by spoolss_api_setprinter
6778 * when updating a printer description.
6779 ********************************************************************/
6781 static WERROR update_printer(struct pipes_struct *p,
6782 struct policy_handle *handle,
6783 struct spoolss_SetPrinterInfoCtr *info_ctr,
6784 struct spoolss_DeviceMode *devmode)
6786 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6787 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6788 struct spoolss_PrinterInfo2 *old_printer;
6789 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6790 int snum;
6791 WERROR result = WERR_OK;
6792 TALLOC_CTX *tmp_ctx;
6793 struct dcerpc_binding_handle *b;
6795 DEBUG(8,("update_printer\n"));
6797 tmp_ctx = talloc_new(p->mem_ctx);
6798 if (tmp_ctx == NULL) {
6799 return WERR_NOMEM;
6802 if (!Printer) {
6803 result = WERR_BADFID;
6804 goto done;
6807 if (!get_printer_snum(p, handle, &snum, NULL)) {
6808 result = WERR_BADFID;
6809 goto done;
6812 result = winreg_printer_binding_handle(tmp_ctx,
6813 get_session_info_system(),
6814 p->msg_ctx,
6815 &b);
6816 if (!W_ERROR_IS_OK(result)) {
6817 goto done;
6820 result = winreg_get_printer(tmp_ctx, b,
6821 lp_const_servicename(snum),
6822 &old_printer);
6823 if (!W_ERROR_IS_OK(result)) {
6824 result = WERR_BADFID;
6825 goto done;
6828 /* Do sanity check on the requested changes for Samba */
6829 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6830 result = WERR_INVALID_PARAM;
6831 goto done;
6834 /* FIXME!!! If the driver has changed we really should verify that
6835 it is installed before doing much else --jerry */
6837 /* Check calling user has permission to update printer description */
6838 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6839 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6840 result = WERR_ACCESS_DENIED;
6841 goto done;
6844 /* Call addprinter hook */
6845 /* Check changes to see if this is really needed */
6847 if (*lp_addprinter_command(talloc_tos()) &&
6848 (!strequal(printer->drivername, old_printer->drivername) ||
6849 !strequal(printer->comment, old_printer->comment) ||
6850 !strequal(printer->portname, old_printer->portname) ||
6851 !strequal(printer->location, old_printer->location)) )
6853 char *raddr;
6855 raddr = tsocket_address_inet_addr_string(p->remote_address,
6856 p->mem_ctx);
6857 if (raddr == NULL) {
6858 return WERR_NOMEM;
6861 /* add_printer_hook() will call reload_services() */
6862 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6863 printer, raddr,
6864 p->msg_ctx)) {
6865 result = WERR_ACCESS_DENIED;
6866 goto done;
6870 result = update_dsspooler(tmp_ctx,
6871 get_session_info_system(),
6872 p->msg_ctx,
6873 snum,
6874 printer,
6875 old_printer);
6876 if (!W_ERROR_IS_OK(result)) {
6877 goto done;
6880 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6882 if (devmode == NULL) {
6883 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6885 result = winreg_update_printer(tmp_ctx, b,
6886 printer->sharename,
6887 printer_mask,
6888 printer,
6889 devmode,
6890 NULL);
6892 done:
6893 talloc_free(tmp_ctx);
6895 return result;
6898 /****************************************************************************
6899 ****************************************************************************/
6900 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6901 struct policy_handle *handle,
6902 struct spoolss_SetPrinterInfo7 *info7)
6904 #ifdef HAVE_ADS
6905 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6906 WERROR result;
6907 int snum;
6908 struct printer_handle *Printer;
6910 if ( lp_security() != SEC_ADS ) {
6911 return WERR_UNKNOWN_LEVEL;
6914 Printer = find_printer_index_by_hnd(p, handle);
6916 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6918 if (!Printer)
6919 return WERR_BADFID;
6921 if (!get_printer_snum(p, handle, &snum, NULL))
6922 return WERR_BADFID;
6924 result = winreg_get_printer_internal(p->mem_ctx,
6925 get_session_info_system(),
6926 p->msg_ctx,
6927 lp_servicename(talloc_tos(), snum),
6928 &pinfo2);
6929 if (!W_ERROR_IS_OK(result)) {
6930 return WERR_BADFID;
6933 nt_printer_publish(pinfo2,
6934 get_session_info_system(),
6935 p->msg_ctx,
6936 pinfo2,
6937 info7->action);
6939 TALLOC_FREE(pinfo2);
6940 return WERR_OK;
6941 #else
6942 return WERR_UNKNOWN_LEVEL;
6943 #endif
6946 /********************************************************************
6947 ********************************************************************/
6949 static WERROR update_printer_devmode(struct pipes_struct *p,
6950 struct policy_handle *handle,
6951 struct spoolss_DeviceMode *devmode)
6953 int snum;
6954 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6955 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6957 DEBUG(8,("update_printer_devmode\n"));
6959 if (!Printer) {
6960 return WERR_BADFID;
6963 if (!get_printer_snum(p, handle, &snum, NULL)) {
6964 return WERR_BADFID;
6967 /* Check calling user has permission to update printer description */
6968 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6969 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6970 return WERR_ACCESS_DENIED;
6973 return winreg_update_printer_internal(p->mem_ctx,
6974 get_session_info_system(),
6975 p->msg_ctx,
6976 lp_const_servicename(snum),
6977 info2_mask,
6978 NULL,
6979 devmode,
6980 NULL);
6984 /****************************************************************
6985 _spoolss_SetPrinter
6986 ****************************************************************/
6988 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6989 struct spoolss_SetPrinter *r)
6991 WERROR result;
6993 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6995 if (!Printer) {
6996 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6997 OUR_HANDLE(r->in.handle)));
6998 return WERR_BADFID;
7001 /* check the level */
7002 switch (r->in.info_ctr->level) {
7003 case 0:
7004 return control_printer(r->in.handle, r->in.command, p);
7005 case 2:
7006 result = update_printer(p, r->in.handle,
7007 r->in.info_ctr,
7008 r->in.devmode_ctr->devmode);
7009 if (!W_ERROR_IS_OK(result))
7010 return result;
7011 if (r->in.secdesc_ctr->sd)
7012 result = update_printer_sec(r->in.handle, p,
7013 r->in.secdesc_ctr);
7014 return result;
7015 case 3:
7016 return update_printer_sec(r->in.handle, p,
7017 r->in.secdesc_ctr);
7018 case 7:
7019 return publish_or_unpublish_printer(p, r->in.handle,
7020 r->in.info_ctr->info.info7);
7021 case 8:
7022 return update_printer_devmode(p, r->in.handle,
7023 r->in.devmode_ctr->devmode);
7024 default:
7025 return WERR_UNKNOWN_LEVEL;
7029 /****************************************************************
7030 _spoolss_FindClosePrinterNotify
7031 ****************************************************************/
7033 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7034 struct spoolss_FindClosePrinterNotify *r)
7036 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7038 if (!Printer) {
7039 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7040 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7041 return WERR_BADFID;
7044 if (Printer->notify.cli_chan != NULL &&
7045 Printer->notify.cli_chan->active_connections > 0) {
7046 int snum = -1;
7048 if (Printer->printer_type == SPLHND_PRINTER) {
7049 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7050 return WERR_BADFID;
7054 srv_spoolss_replycloseprinter(snum, Printer);
7057 Printer->notify.flags=0;
7058 Printer->notify.options=0;
7059 Printer->notify.localmachine[0]='\0';
7060 Printer->notify.printerlocal=0;
7061 TALLOC_FREE(Printer->notify.option);
7063 return WERR_OK;
7066 /****************************************************************
7067 _spoolss_AddJob
7068 ****************************************************************/
7070 WERROR _spoolss_AddJob(struct pipes_struct *p,
7071 struct spoolss_AddJob *r)
7073 if (!r->in.buffer && (r->in.offered != 0)) {
7074 return WERR_INVALID_PARAM;
7077 /* this is what a NT server returns for AddJob. AddJob must fail on
7078 * non-local printers */
7080 if (r->in.level != 1) {
7081 return WERR_UNKNOWN_LEVEL;
7084 return WERR_INVALID_PARAM;
7087 /****************************************************************************
7088 fill_job_info1
7089 ****************************************************************************/
7091 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7092 struct spoolss_JobInfo1 *r,
7093 const print_queue_struct *queue,
7094 uint32_t jobid,
7095 int position, int snum,
7096 struct spoolss_PrinterInfo2 *pinfo2)
7098 struct tm *t;
7100 t = gmtime(&queue->time);
7102 r->job_id = jobid;
7104 r->printer_name = lp_servicename(mem_ctx, snum);
7105 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7106 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7107 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7108 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7109 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7110 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7111 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7112 r->data_type = talloc_strdup(mem_ctx, "RAW");
7113 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7114 r->text_status = talloc_strdup(mem_ctx, "");
7115 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7117 r->status = nt_printj_status(queue->status);
7118 r->priority = queue->priority;
7119 r->position = position;
7120 r->total_pages = queue->page_count;
7121 r->pages_printed = 0; /* ??? */
7123 init_systemtime(&r->submitted, t);
7125 return WERR_OK;
7128 /****************************************************************************
7129 fill_job_info2
7130 ****************************************************************************/
7132 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7133 struct spoolss_JobInfo2 *r,
7134 const print_queue_struct *queue,
7135 uint32_t jobid,
7136 int position, int snum,
7137 struct spoolss_PrinterInfo2 *pinfo2,
7138 struct spoolss_DeviceMode *devmode)
7140 struct tm *t;
7142 t = gmtime(&queue->time);
7144 r->job_id = jobid;
7146 r->printer_name = lp_servicename(mem_ctx, snum);
7147 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7148 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7149 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7150 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7151 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7152 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7153 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7154 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7155 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7156 r->data_type = talloc_strdup(mem_ctx, "RAW");
7157 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7158 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7159 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7160 r->parameters = talloc_strdup(mem_ctx, "");
7161 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7162 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7163 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7165 r->devmode = devmode;
7167 r->text_status = talloc_strdup(mem_ctx, "");
7168 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7170 r->secdesc = NULL;
7172 r->status = nt_printj_status(queue->status);
7173 r->priority = queue->priority;
7174 r->position = position;
7175 r->start_time = 0;
7176 r->until_time = 0;
7177 r->total_pages = queue->page_count;
7178 r->size = queue->size;
7179 init_systemtime(&r->submitted, t);
7180 r->time = 0;
7181 r->pages_printed = 0; /* ??? */
7183 return WERR_OK;
7186 /****************************************************************************
7187 Enumjobs at level 1.
7188 ****************************************************************************/
7190 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7191 const print_queue_struct *queue,
7192 uint32_t num_queues, int snum,
7193 struct spoolss_PrinterInfo2 *pinfo2,
7194 union spoolss_JobInfo **info_p,
7195 uint32_t *count)
7197 union spoolss_JobInfo *info;
7198 int i;
7199 WERROR result = WERR_OK;
7200 uint32_t num_filled;
7201 struct tdb_print_db *pdb;
7203 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7204 if (info == NULL) {
7205 result = WERR_NOMEM;
7206 goto err_out;
7209 pdb = get_print_db_byname(pinfo2->sharename);
7210 if (pdb == NULL) {
7211 result = WERR_INVALID_PARAM;
7212 goto err_info_free;
7215 num_filled = 0;
7216 for (i = 0; i < num_queues; i++) {
7217 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7218 if (jobid == (uint32_t)-1) {
7219 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7220 continue;
7223 result = fill_job_info1(info,
7224 &info[num_filled].info1,
7225 &queue[i],
7226 jobid,
7228 snum,
7229 pinfo2);
7230 if (!W_ERROR_IS_OK(result)) {
7231 goto err_pdb_drop;
7234 num_filled++;
7237 release_print_db(pdb);
7238 *info_p = info;
7239 *count = num_filled;
7241 return WERR_OK;
7243 err_pdb_drop:
7244 release_print_db(pdb);
7245 err_info_free:
7246 TALLOC_FREE(info);
7247 err_out:
7248 *count = 0;
7249 return result;
7252 /****************************************************************************
7253 Enumjobs at level 2.
7254 ****************************************************************************/
7256 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7257 const print_queue_struct *queue,
7258 uint32_t num_queues, int snum,
7259 struct spoolss_PrinterInfo2 *pinfo2,
7260 union spoolss_JobInfo **info_p,
7261 uint32_t *count)
7263 union spoolss_JobInfo *info;
7264 int i;
7265 WERROR result = WERR_OK;
7266 uint32_t num_filled;
7267 struct tdb_print_db *pdb;
7269 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7270 if (info == NULL) {
7271 result = WERR_NOMEM;
7272 goto err_out;
7275 pdb = get_print_db_byname(pinfo2->sharename);
7276 if (pdb == NULL) {
7277 result = WERR_INVALID_PARAM;
7278 goto err_info_free;
7281 num_filled = 0;
7282 for (i = 0; i< num_queues; i++) {
7283 struct spoolss_DeviceMode *devmode;
7284 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7285 if (jobid == (uint32_t)-1) {
7286 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7287 continue;
7290 result = spoolss_create_default_devmode(info,
7291 pinfo2->printername,
7292 &devmode);
7293 if (!W_ERROR_IS_OK(result)) {
7294 DEBUG(3, ("Can't proceed w/o a devmode!"));
7295 goto err_pdb_drop;
7298 result = fill_job_info2(info,
7299 &info[num_filled].info2,
7300 &queue[i],
7301 jobid,
7303 snum,
7304 pinfo2,
7305 devmode);
7306 if (!W_ERROR_IS_OK(result)) {
7307 goto err_pdb_drop;
7309 num_filled++;
7312 release_print_db(pdb);
7313 *info_p = info;
7314 *count = num_filled;
7316 return WERR_OK;
7318 err_pdb_drop:
7319 release_print_db(pdb);
7320 err_info_free:
7321 TALLOC_FREE(info);
7322 err_out:
7323 *count = 0;
7324 return result;
7327 /****************************************************************************
7328 Enumjobs at level 3.
7329 ****************************************************************************/
7331 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7332 const print_queue_struct *queue,
7333 uint32_t num_queues, int snum,
7334 struct spoolss_PrinterInfo2 *pinfo2,
7335 union spoolss_JobInfo **info_p,
7336 uint32_t *count)
7338 union spoolss_JobInfo *info;
7339 int i;
7340 WERROR result = WERR_OK;
7341 uint32_t num_filled;
7342 struct tdb_print_db *pdb;
7344 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7345 if (info == NULL) {
7346 result = WERR_NOMEM;
7347 goto err_out;
7350 pdb = get_print_db_byname(pinfo2->sharename);
7351 if (pdb == NULL) {
7352 result = WERR_INVALID_PARAM;
7353 goto err_info_free;
7356 num_filled = 0;
7357 for (i = 0; i < num_queues; i++) {
7358 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7359 if (jobid == (uint32_t)-1) {
7360 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7361 continue;
7364 info[num_filled].info3.job_id = jobid;
7365 /* next_job_id is overwritten on next iteration */
7366 info[num_filled].info3.next_job_id = 0;
7367 info[num_filled].info3.reserved = 0;
7369 if (num_filled > 0) {
7370 info[num_filled - 1].info3.next_job_id = jobid;
7372 num_filled++;
7375 release_print_db(pdb);
7376 *info_p = info;
7377 *count = num_filled;
7379 return WERR_OK;
7381 err_info_free:
7382 TALLOC_FREE(info);
7383 err_out:
7384 *count = 0;
7385 return result;
7388 /****************************************************************
7389 _spoolss_EnumJobs
7390 ****************************************************************/
7392 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7393 struct spoolss_EnumJobs *r)
7395 WERROR result;
7396 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7397 int snum;
7398 print_status_struct prt_status;
7399 print_queue_struct *queue = NULL;
7400 uint32_t count;
7402 /* that's an [in out] buffer */
7404 if (!r->in.buffer && (r->in.offered != 0)) {
7405 return WERR_INVALID_PARAM;
7408 if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7409 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7410 return WERR_UNKNOWN_LEVEL;
7413 DEBUG(4,("_spoolss_EnumJobs\n"));
7415 *r->out.needed = 0;
7416 *r->out.count = 0;
7417 *r->out.info = NULL;
7419 /* lookup the printer snum and tdb entry */
7421 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7422 return WERR_BADFID;
7425 result = winreg_get_printer_internal(p->mem_ctx,
7426 get_session_info_system(),
7427 p->msg_ctx,
7428 lp_const_servicename(snum),
7429 &pinfo2);
7430 if (!W_ERROR_IS_OK(result)) {
7431 return result;
7434 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7435 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7436 count, prt_status.status, prt_status.message));
7438 if (count == 0) {
7439 SAFE_FREE(queue);
7440 TALLOC_FREE(pinfo2);
7441 return WERR_OK;
7444 switch (r->in.level) {
7445 case 1:
7446 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7447 pinfo2, r->out.info, r->out.count);
7448 break;
7449 case 2:
7450 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7451 pinfo2, r->out.info, r->out.count);
7452 break;
7453 case 3:
7454 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7455 pinfo2, r->out.info, r->out.count);
7456 break;
7457 default:
7458 SMB_ASSERT(false); /* level checked on entry */
7459 break;
7462 SAFE_FREE(queue);
7463 TALLOC_FREE(pinfo2);
7465 if (!W_ERROR_IS_OK(result)) {
7466 return result;
7469 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7470 spoolss_EnumJobs,
7471 *r->out.info, r->in.level,
7472 *r->out.count);
7473 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7474 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7476 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7479 /****************************************************************
7480 _spoolss_ScheduleJob
7481 ****************************************************************/
7483 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7484 struct spoolss_ScheduleJob *r)
7486 return WERR_OK;
7489 /****************************************************************
7490 ****************************************************************/
7492 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7493 struct messaging_context *msg_ctx,
7494 const char *printer_name,
7495 uint32_t job_id,
7496 struct spoolss_SetJobInfo1 *r)
7498 char *old_doc_name;
7500 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7501 return WERR_BADFID;
7504 if (strequal(old_doc_name, r->document_name)) {
7505 return WERR_OK;
7508 if (!print_job_set_name(server_event_context(), msg_ctx,
7509 printer_name, job_id, r->document_name)) {
7510 return WERR_BADFID;
7513 return WERR_OK;
7516 /****************************************************************
7517 _spoolss_SetJob
7518 ****************************************************************/
7520 WERROR _spoolss_SetJob(struct pipes_struct *p,
7521 struct spoolss_SetJob *r)
7523 const struct auth_session_info *session_info = p->session_info;
7524 int snum;
7525 WERROR errcode = WERR_BADFUNC;
7527 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7528 return WERR_BADFID;
7531 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7532 return WERR_INVALID_PRINTER_NAME;
7535 switch (r->in.command) {
7536 case SPOOLSS_JOB_CONTROL_CANCEL:
7537 case SPOOLSS_JOB_CONTROL_DELETE:
7538 errcode = print_job_delete(session_info, p->msg_ctx,
7539 snum, r->in.job_id);
7540 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7541 errcode = WERR_OK;
7543 break;
7544 case SPOOLSS_JOB_CONTROL_PAUSE:
7545 errcode = print_job_pause(session_info, p->msg_ctx,
7546 snum, r->in.job_id);
7547 break;
7548 case SPOOLSS_JOB_CONTROL_RESTART:
7549 case SPOOLSS_JOB_CONTROL_RESUME:
7550 errcode = print_job_resume(session_info, p->msg_ctx,
7551 snum, r->in.job_id);
7552 break;
7553 case SPOOLSS_JOB_CONTROL_NOOP:
7554 errcode = WERR_OK;
7555 break;
7556 default:
7557 return WERR_UNKNOWN_LEVEL;
7560 if (!W_ERROR_IS_OK(errcode)) {
7561 return errcode;
7564 if (r->in.ctr == NULL) {
7565 return errcode;
7568 switch (r->in.ctr->level) {
7569 case 1:
7570 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7571 lp_const_servicename(snum),
7572 r->in.job_id,
7573 r->in.ctr->info.info1);
7574 break;
7575 case 2:
7576 case 3:
7577 case 4:
7578 default:
7579 return WERR_UNKNOWN_LEVEL;
7582 return errcode;
7585 /****************************************************************************
7586 Enumerates all printer drivers by level and architecture.
7587 ****************************************************************************/
7589 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7590 const struct auth_session_info *session_info,
7591 struct messaging_context *msg_ctx,
7592 const char *servername,
7593 const char *architecture,
7594 uint32_t level,
7595 union spoolss_DriverInfo **info_p,
7596 uint32_t *count_p)
7598 int i;
7599 uint32_t version;
7600 struct spoolss_DriverInfo8 *driver;
7601 union spoolss_DriverInfo *info = NULL;
7602 uint32_t count = 0;
7603 WERROR result = WERR_OK;
7604 uint32_t num_drivers;
7605 const char **drivers;
7606 struct dcerpc_binding_handle *b;
7607 TALLOC_CTX *tmp_ctx = NULL;
7609 *count_p = 0;
7610 *info_p = NULL;
7612 tmp_ctx = talloc_new(mem_ctx);
7613 if (!tmp_ctx) {
7614 return WERR_NOMEM;
7617 result = winreg_printer_binding_handle(tmp_ctx,
7618 session_info,
7619 msg_ctx,
7620 &b);
7621 if (!W_ERROR_IS_OK(result)) {
7622 goto out;
7625 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7626 result = winreg_get_driver_list(tmp_ctx, b,
7627 architecture, version,
7628 &num_drivers, &drivers);
7629 if (!W_ERROR_IS_OK(result)) {
7630 goto out;
7632 DEBUG(4, ("we have:[%d] drivers in environment"
7633 " [%s] and version [%d]\n",
7634 num_drivers, architecture, version));
7636 if (num_drivers != 0) {
7637 info = talloc_realloc(tmp_ctx, info,
7638 union spoolss_DriverInfo,
7639 count + num_drivers);
7640 if (!info) {
7641 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7642 "failed to enlarge driver info buffer!\n"));
7643 result = WERR_NOMEM;
7644 goto out;
7648 for (i = 0; i < num_drivers; i++) {
7649 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7651 result = winreg_get_driver(tmp_ctx, b,
7652 architecture, drivers[i],
7653 version, &driver);
7654 if (!W_ERROR_IS_OK(result)) {
7655 goto out;
7658 switch (level) {
7659 case 1:
7660 result = fill_printer_driver_info1(info, &info[count+i].info1,
7661 driver, servername);
7662 break;
7663 case 2:
7664 result = fill_printer_driver_info2(info, &info[count+i].info2,
7665 driver, servername);
7666 break;
7667 case 3:
7668 result = fill_printer_driver_info3(info, &info[count+i].info3,
7669 driver, servername);
7670 break;
7671 case 4:
7672 result = fill_printer_driver_info4(info, &info[count+i].info4,
7673 driver, servername);
7674 break;
7675 case 5:
7676 result = fill_printer_driver_info5(info, &info[count+i].info5,
7677 driver, servername);
7678 break;
7679 case 6:
7680 result = fill_printer_driver_info6(info, &info[count+i].info6,
7681 driver, servername);
7682 break;
7683 case 8:
7684 result = fill_printer_driver_info8(info, &info[count+i].info8,
7685 driver, servername);
7686 break;
7687 default:
7688 result = WERR_UNKNOWN_LEVEL;
7689 break;
7692 TALLOC_FREE(driver);
7694 if (!W_ERROR_IS_OK(result)) {
7695 goto out;
7699 count += num_drivers;
7700 TALLOC_FREE(drivers);
7703 out:
7704 if (W_ERROR_IS_OK(result)) {
7705 *info_p = talloc_move(mem_ctx, &info);
7706 *count_p = count;
7709 talloc_free(tmp_ctx);
7710 return result;
7713 /****************************************************************************
7714 Enumerates all printer drivers by level.
7715 ****************************************************************************/
7717 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7718 const struct auth_session_info *session_info,
7719 struct messaging_context *msg_ctx,
7720 const char *servername,
7721 const char *architecture,
7722 uint32_t level,
7723 union spoolss_DriverInfo **info_p,
7724 uint32_t *count_p)
7726 uint32_t a,i;
7727 WERROR result = WERR_OK;
7729 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7731 for (a=0; archi_table[a].long_archi != NULL; a++) {
7733 union spoolss_DriverInfo *info = NULL;
7734 uint32_t count = 0;
7736 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7737 session_info,
7738 msg_ctx,
7739 servername,
7740 archi_table[a].long_archi,
7741 level,
7742 &info,
7743 &count);
7744 if (!W_ERROR_IS_OK(result)) {
7745 continue;
7748 for (i=0; i < count; i++) {
7749 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7750 info[i], info_p, count_p);
7754 return result;
7757 return enumprinterdrivers_level_by_architecture(mem_ctx,
7758 session_info,
7759 msg_ctx,
7760 servername,
7761 architecture,
7762 level,
7763 info_p,
7764 count_p);
7767 /****************************************************************
7768 _spoolss_EnumPrinterDrivers
7769 ****************************************************************/
7771 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7772 struct spoolss_EnumPrinterDrivers *r)
7774 const char *cservername;
7775 WERROR result;
7777 /* that's an [in out] buffer */
7779 if (!r->in.buffer && (r->in.offered != 0)) {
7780 return WERR_INVALID_PARAM;
7783 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7785 *r->out.needed = 0;
7786 *r->out.count = 0;
7787 *r->out.info = NULL;
7789 cservername = canon_servername(r->in.server);
7791 if (!is_myname_or_ipaddr(cservername)) {
7792 return WERR_UNKNOWN_PRINTER_DRIVER;
7795 result = enumprinterdrivers_level(p->mem_ctx,
7796 get_session_info_system(),
7797 p->msg_ctx,
7798 cservername,
7799 r->in.environment,
7800 r->in.level,
7801 r->out.info,
7802 r->out.count);
7803 if (!W_ERROR_IS_OK(result)) {
7804 return result;
7807 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7808 spoolss_EnumPrinterDrivers,
7809 *r->out.info, r->in.level,
7810 *r->out.count);
7811 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7812 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7814 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7817 /****************************************************************
7818 _spoolss_EnumForms
7819 ****************************************************************/
7821 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7822 struct spoolss_EnumForms *r)
7824 WERROR result;
7826 *r->out.count = 0;
7827 *r->out.needed = 0;
7828 *r->out.info = NULL;
7830 /* that's an [in out] buffer */
7832 if (!r->in.buffer && (r->in.offered != 0) ) {
7833 return WERR_INVALID_PARAM;
7836 DEBUG(4,("_spoolss_EnumForms\n"));
7837 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7838 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7840 switch (r->in.level) {
7841 case 1:
7842 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7843 get_session_info_system(),
7844 p->msg_ctx,
7845 r->out.count,
7846 r->out.info);
7847 break;
7848 default:
7849 result = WERR_UNKNOWN_LEVEL;
7850 break;
7853 if (!W_ERROR_IS_OK(result)) {
7854 return result;
7857 if (*r->out.count == 0) {
7858 return WERR_NO_MORE_ITEMS;
7861 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7862 spoolss_EnumForms,
7863 *r->out.info, r->in.level,
7864 *r->out.count);
7865 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7866 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7868 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7871 /****************************************************************
7872 _spoolss_GetForm
7873 ****************************************************************/
7875 WERROR _spoolss_GetForm(struct pipes_struct *p,
7876 struct spoolss_GetForm *r)
7878 WERROR result;
7880 /* that's an [in out] buffer */
7882 if (!r->in.buffer && (r->in.offered != 0)) {
7883 TALLOC_FREE(r->out.info);
7884 return WERR_INVALID_PARAM;
7887 DEBUG(4,("_spoolss_GetForm\n"));
7888 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7889 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7891 switch (r->in.level) {
7892 case 1:
7893 result = winreg_printer_getform1_internal(p->mem_ctx,
7894 get_session_info_system(),
7895 p->msg_ctx,
7896 r->in.form_name,
7897 &r->out.info->info1);
7898 break;
7899 default:
7900 result = WERR_UNKNOWN_LEVEL;
7901 break;
7904 if (!W_ERROR_IS_OK(result)) {
7905 TALLOC_FREE(r->out.info);
7906 return result;
7909 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7910 r->out.info, r->in.level);
7911 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7913 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7916 /****************************************************************************
7917 ****************************************************************************/
7919 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7920 struct spoolss_PortInfo1 *r,
7921 const char *name)
7923 r->port_name = talloc_strdup(mem_ctx, name);
7924 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7926 return WERR_OK;
7929 /****************************************************************************
7930 TODO: This probably needs distinguish between TCP/IP and Local ports
7931 somehow.
7932 ****************************************************************************/
7934 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7935 struct spoolss_PortInfo2 *r,
7936 const char *name)
7938 r->port_name = talloc_strdup(mem_ctx, name);
7939 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7941 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7942 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7944 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7945 W_ERROR_HAVE_NO_MEMORY(r->description);
7947 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7948 r->reserved = 0;
7950 return WERR_OK;
7954 /****************************************************************************
7955 wrapper around the enumer ports command
7956 ****************************************************************************/
7958 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7960 char *cmd = lp_enumports_command(talloc_tos());
7961 char **qlines = NULL;
7962 char *command = NULL;
7963 int numlines;
7964 int ret;
7965 int fd;
7967 *count = 0;
7968 *lines = NULL;
7970 /* if no hook then just fill in the default port */
7972 if ( !*cmd ) {
7973 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7974 return WERR_NOMEM;
7976 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7977 TALLOC_FREE(qlines);
7978 return WERR_NOMEM;
7980 qlines[1] = NULL;
7981 numlines = 1;
7983 else {
7984 /* we have a valid enumport command */
7986 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7987 if (!command) {
7988 return WERR_NOMEM;
7991 DEBUG(10,("Running [%s]\n", command));
7992 ret = smbrun(command, &fd);
7993 DEBUG(10,("Returned [%d]\n", ret));
7994 TALLOC_FREE(command);
7995 if (ret != 0) {
7996 if (fd != -1) {
7997 close(fd);
7999 return WERR_ACCESS_DENIED;
8002 numlines = 0;
8003 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8004 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8005 close(fd);
8008 *count = numlines;
8009 *lines = qlines;
8011 return WERR_OK;
8014 /****************************************************************************
8015 enumports level 1.
8016 ****************************************************************************/
8018 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8019 union spoolss_PortInfo **info_p,
8020 uint32_t *count)
8022 union spoolss_PortInfo *info = NULL;
8023 int i=0;
8024 WERROR result = WERR_OK;
8025 char **qlines = NULL;
8026 int numlines = 0;
8028 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8029 if (!W_ERROR_IS_OK(result)) {
8030 goto out;
8033 if (numlines) {
8034 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8035 if (!info) {
8036 DEBUG(10,("Returning WERR_NOMEM\n"));
8037 result = WERR_NOMEM;
8038 goto out;
8041 for (i=0; i<numlines; i++) {
8042 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8043 result = fill_port_1(info, &info[i].info1, qlines[i]);
8044 if (!W_ERROR_IS_OK(result)) {
8045 goto out;
8049 TALLOC_FREE(qlines);
8051 out:
8052 if (!W_ERROR_IS_OK(result)) {
8053 TALLOC_FREE(info);
8054 TALLOC_FREE(qlines);
8055 *count = 0;
8056 *info_p = NULL;
8057 return result;
8060 *info_p = info;
8061 *count = numlines;
8063 return WERR_OK;
8066 /****************************************************************************
8067 enumports level 2.
8068 ****************************************************************************/
8070 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8071 union spoolss_PortInfo **info_p,
8072 uint32_t *count)
8074 union spoolss_PortInfo *info = NULL;
8075 int i=0;
8076 WERROR result = WERR_OK;
8077 char **qlines = NULL;
8078 int numlines = 0;
8080 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8081 if (!W_ERROR_IS_OK(result)) {
8082 goto out;
8085 if (numlines) {
8086 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8087 if (!info) {
8088 DEBUG(10,("Returning WERR_NOMEM\n"));
8089 result = WERR_NOMEM;
8090 goto out;
8093 for (i=0; i<numlines; i++) {
8094 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8095 result = fill_port_2(info, &info[i].info2, qlines[i]);
8096 if (!W_ERROR_IS_OK(result)) {
8097 goto out;
8101 TALLOC_FREE(qlines);
8103 out:
8104 if (!W_ERROR_IS_OK(result)) {
8105 TALLOC_FREE(info);
8106 TALLOC_FREE(qlines);
8107 *count = 0;
8108 *info_p = NULL;
8109 return result;
8112 *info_p = info;
8113 *count = numlines;
8115 return WERR_OK;
8118 /****************************************************************
8119 _spoolss_EnumPorts
8120 ****************************************************************/
8122 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8123 struct spoolss_EnumPorts *r)
8125 WERROR result;
8127 /* that's an [in out] buffer */
8129 if (!r->in.buffer && (r->in.offered != 0)) {
8130 return WERR_INVALID_PARAM;
8133 DEBUG(4,("_spoolss_EnumPorts\n"));
8135 *r->out.count = 0;
8136 *r->out.needed = 0;
8137 *r->out.info = NULL;
8139 switch (r->in.level) {
8140 case 1:
8141 result = enumports_level_1(p->mem_ctx, r->out.info,
8142 r->out.count);
8143 break;
8144 case 2:
8145 result = enumports_level_2(p->mem_ctx, r->out.info,
8146 r->out.count);
8147 break;
8148 default:
8149 return WERR_UNKNOWN_LEVEL;
8152 if (!W_ERROR_IS_OK(result)) {
8153 return result;
8156 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8157 spoolss_EnumPorts,
8158 *r->out.info, r->in.level,
8159 *r->out.count);
8160 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8161 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8163 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8166 /****************************************************************************
8167 ****************************************************************************/
8169 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8170 const char *server,
8171 struct spoolss_SetPrinterInfoCtr *info_ctr,
8172 struct spoolss_DeviceMode *devmode,
8173 struct security_descriptor *secdesc,
8174 struct spoolss_UserLevelCtr *user_ctr,
8175 struct policy_handle *handle)
8177 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8178 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8179 int snum;
8180 WERROR err = WERR_OK;
8182 /* samba does not have a concept of local, non-shared printers yet, so
8183 * make sure we always setup sharename - gd */
8184 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8185 (info2->printername != NULL && info2->printername[0] != '\0')) {
8186 DEBUG(5, ("spoolss_addprinterex_level_2: "
8187 "no sharename has been set, setting printername %s as sharename\n",
8188 info2->printername));
8189 info2->sharename = info2->printername;
8192 /* check to see if the printer already exists */
8193 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8194 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8195 info2->sharename));
8196 return WERR_PRINTER_ALREADY_EXISTS;
8199 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8200 if ((snum = print_queue_snum(info2->printername)) != -1) {
8201 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8202 info2->printername));
8203 return WERR_PRINTER_ALREADY_EXISTS;
8207 /* validate printer info struct */
8208 if (!info2->printername || strlen(info2->printername) == 0) {
8209 return WERR_INVALID_PRINTER_NAME;
8211 if (!info2->portname || strlen(info2->portname) == 0) {
8212 return WERR_UNKNOWN_PORT;
8214 if (!info2->drivername || strlen(info2->drivername) == 0) {
8215 return WERR_UNKNOWN_PRINTER_DRIVER;
8217 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8218 return WERR_UNKNOWN_PRINTPROCESSOR;
8221 /* FIXME!!! smbd should check to see if the driver is installed before
8222 trying to add a printer like this --jerry */
8224 if (*lp_addprinter_command(talloc_tos()) ) {
8225 char *raddr;
8227 raddr = tsocket_address_inet_addr_string(p->remote_address,
8228 p->mem_ctx);
8229 if (raddr == NULL) {
8230 return WERR_NOMEM;
8233 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8234 info2, raddr,
8235 p->msg_ctx) ) {
8236 return WERR_ACCESS_DENIED;
8238 } else {
8239 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8240 "smb.conf parameter \"addprinter command\" is defined. This "
8241 "parameter must exist for this call to succeed\n",
8242 info2->sharename ));
8245 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8246 return WERR_ACCESS_DENIED;
8249 /* you must be a printer admin to add a new printer */
8250 if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8251 p->msg_ctx,
8252 snum,
8253 PRINTER_ACCESS_ADMINISTER))) {
8254 return WERR_ACCESS_DENIED;
8258 * Do sanity check on the requested changes for Samba.
8261 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8262 return WERR_INVALID_PARAM;
8265 if (devmode == NULL) {
8266 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8269 err = update_dsspooler(p->mem_ctx,
8270 get_session_info_system(),
8271 p->msg_ctx,
8273 info2,
8274 NULL);
8275 if (!W_ERROR_IS_OK(err)) {
8276 return err;
8279 err = winreg_update_printer_internal(p->mem_ctx,
8280 get_session_info_system(),
8281 p->msg_ctx,
8282 info2->sharename,
8283 info2_mask,
8284 info2,
8285 devmode,
8286 secdesc);
8287 if (!W_ERROR_IS_OK(err)) {
8288 return err;
8291 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8292 if (!W_ERROR_IS_OK(err)) {
8293 /* Handle open failed - remove addition. */
8294 ZERO_STRUCTP(handle);
8295 return err;
8298 return WERR_OK;
8301 /****************************************************************
8302 _spoolss_AddPrinterEx
8303 ****************************************************************/
8305 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8306 struct spoolss_AddPrinterEx *r)
8308 switch (r->in.info_ctr->level) {
8309 case 1:
8310 /* we don't handle yet */
8311 /* but I know what to do ... */
8312 return WERR_UNKNOWN_LEVEL;
8313 case 2:
8314 return spoolss_addprinterex_level_2(p, r->in.server,
8315 r->in.info_ctr,
8316 r->in.devmode_ctr->devmode,
8317 r->in.secdesc_ctr->sd,
8318 r->in.userlevel_ctr,
8319 r->out.handle);
8320 default:
8321 return WERR_UNKNOWN_LEVEL;
8325 /****************************************************************
8326 _spoolss_AddPrinter
8327 ****************************************************************/
8329 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8330 struct spoolss_AddPrinter *r)
8332 struct spoolss_AddPrinterEx a;
8333 struct spoolss_UserLevelCtr userlevel_ctr;
8335 ZERO_STRUCT(userlevel_ctr);
8337 userlevel_ctr.level = 1;
8339 a.in.server = r->in.server;
8340 a.in.info_ctr = r->in.info_ctr;
8341 a.in.devmode_ctr = r->in.devmode_ctr;
8342 a.in.secdesc_ctr = r->in.secdesc_ctr;
8343 a.in.userlevel_ctr = &userlevel_ctr;
8344 a.out.handle = r->out.handle;
8346 return _spoolss_AddPrinterEx(p, &a);
8349 /****************************************************************
8350 _spoolss_AddPrinterDriverEx
8351 ****************************************************************/
8353 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8354 struct spoolss_AddPrinterDriverEx *r)
8356 WERROR err = WERR_OK;
8357 const char *driver_name = NULL;
8358 uint32_t version;
8359 const char *fn;
8361 switch (p->opnum) {
8362 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8363 fn = "_spoolss_AddPrinterDriver";
8364 break;
8365 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8366 fn = "_spoolss_AddPrinterDriverEx";
8367 break;
8368 default:
8369 return WERR_INVALID_PARAM;
8373 * we only support the semantics of AddPrinterDriver()
8374 * i.e. only copy files that are newer than existing ones
8377 if (r->in.flags == 0) {
8378 return WERR_INVALID_PARAM;
8381 if (r->in.flags != APD_COPY_NEW_FILES) {
8382 return WERR_ACCESS_DENIED;
8385 /* FIXME */
8386 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8387 /* Clever hack from Martin Zielinski <mz@seh.de>
8388 * to allow downgrade from level 8 (Vista).
8390 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8391 r->in.info_ctr->level));
8392 return WERR_UNKNOWN_LEVEL;
8395 DEBUG(5,("Cleaning driver's information\n"));
8396 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8397 if (!W_ERROR_IS_OK(err))
8398 goto done;
8400 DEBUG(5,("Moving driver to final destination\n"));
8401 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8402 if (!W_ERROR_IS_OK(err)) {
8403 goto done;
8406 err = winreg_add_driver_internal(p->mem_ctx,
8407 get_session_info_system(),
8408 p->msg_ctx,
8409 r->in.info_ctr,
8410 &driver_name,
8411 &version);
8412 if (!W_ERROR_IS_OK(err)) {
8413 goto done;
8417 * I think this is where he DrvUpgradePrinter() hook would be
8418 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8419 * server. Right now, we just need to send ourselves a message
8420 * to update each printer bound to this driver. --jerry
8423 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8424 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8425 fn, driver_name));
8428 done:
8429 return err;
8432 /****************************************************************
8433 _spoolss_AddPrinterDriver
8434 ****************************************************************/
8436 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8437 struct spoolss_AddPrinterDriver *r)
8439 struct spoolss_AddPrinterDriverEx a;
8441 switch (r->in.info_ctr->level) {
8442 case 2:
8443 case 3:
8444 case 4:
8445 case 5:
8446 break;
8447 default:
8448 return WERR_UNKNOWN_LEVEL;
8451 a.in.servername = r->in.servername;
8452 a.in.info_ctr = r->in.info_ctr;
8453 a.in.flags = APD_COPY_NEW_FILES;
8455 return _spoolss_AddPrinterDriverEx(p, &a);
8458 /****************************************************************************
8459 ****************************************************************************/
8461 struct _spoolss_paths {
8462 int type;
8463 const char *share;
8464 const char *dir;
8467 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8469 static const struct _spoolss_paths spoolss_paths[]= {
8470 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8471 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8474 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8475 const char *servername,
8476 const char *environment,
8477 int component,
8478 char **path)
8480 const char *pservername = NULL;
8481 const char *long_archi;
8482 const char *short_archi;
8484 *path = NULL;
8486 /* environment may be empty */
8487 if (environment && strlen(environment)) {
8488 long_archi = environment;
8489 } else {
8490 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8491 "spoolss", "architecture",
8492 SPOOLSS_ARCHITECTURE_NT_X86);
8495 /* servername may be empty */
8496 if (servername && strlen(servername)) {
8497 pservername = canon_servername(servername);
8499 if (!is_myname_or_ipaddr(pservername)) {
8500 return WERR_INVALID_PARAM;
8504 if (!(short_archi = get_short_archi(long_archi))) {
8505 return WERR_INVALID_ENVIRONMENT;
8508 switch (component) {
8509 case SPOOLSS_PRTPROCS_PATH:
8510 case SPOOLSS_DRIVER_PATH:
8511 if (pservername) {
8512 *path = talloc_asprintf(mem_ctx,
8513 "\\\\%s\\%s\\%s",
8514 pservername,
8515 spoolss_paths[component].share,
8516 short_archi);
8517 } else {
8518 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8519 SPOOLSS_DEFAULT_SERVER_PATH,
8520 spoolss_paths[component].dir,
8521 short_archi);
8523 break;
8524 default:
8525 return WERR_INVALID_PARAM;
8528 if (!*path) {
8529 return WERR_NOMEM;
8532 return WERR_OK;
8535 /****************************************************************************
8536 ****************************************************************************/
8538 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8539 const char *servername,
8540 const char *environment,
8541 struct spoolss_DriverDirectoryInfo1 *r)
8543 WERROR werr;
8544 char *path = NULL;
8546 werr = compose_spoolss_server_path(mem_ctx,
8547 servername,
8548 environment,
8549 SPOOLSS_DRIVER_PATH,
8550 &path);
8551 if (!W_ERROR_IS_OK(werr)) {
8552 return werr;
8555 DEBUG(4,("printer driver directory: [%s]\n", path));
8557 r->directory_name = path;
8559 return WERR_OK;
8562 /****************************************************************
8563 _spoolss_GetPrinterDriverDirectory
8564 ****************************************************************/
8566 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8567 struct spoolss_GetPrinterDriverDirectory *r)
8569 WERROR werror;
8571 /* that's an [in out] buffer */
8573 if (!r->in.buffer && (r->in.offered != 0)) {
8574 TALLOC_FREE(r->out.info);
8575 return WERR_INVALID_PARAM;
8578 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8579 r->in.level));
8581 *r->out.needed = 0;
8583 /* r->in.level is ignored */
8585 werror = getprinterdriverdir_level_1(p->mem_ctx,
8586 r->in.server,
8587 r->in.environment,
8588 &r->out.info->info1);
8589 if (!W_ERROR_IS_OK(werror)) {
8590 TALLOC_FREE(r->out.info);
8591 return werror;
8594 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8595 r->out.info, r->in.level);
8596 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8598 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8601 /****************************************************************
8602 _spoolss_EnumPrinterData
8603 ****************************************************************/
8605 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8606 struct spoolss_EnumPrinterData *r)
8608 WERROR result;
8609 struct spoolss_EnumPrinterDataEx r2;
8610 uint32_t count;
8611 struct spoolss_PrinterEnumValues *info, *val = NULL;
8612 uint32_t needed;
8614 r2.in.handle = r->in.handle;
8615 r2.in.key_name = "PrinterDriverData";
8616 r2.in.offered = 0;
8617 r2.out.count = &count;
8618 r2.out.info = &info;
8619 r2.out.needed = &needed;
8621 result = _spoolss_EnumPrinterDataEx(p, &r2);
8622 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8623 r2.in.offered = needed;
8624 result = _spoolss_EnumPrinterDataEx(p, &r2);
8626 if (!W_ERROR_IS_OK(result)) {
8627 return result;
8631 * The NT machine wants to know the biggest size of value and data
8633 * cf: MSDN EnumPrinterData remark section
8636 if (!r->in.value_offered && !r->in.data_offered) {
8637 uint32_t biggest_valuesize = 0;
8638 uint32_t biggest_datasize = 0;
8639 int i, name_length;
8641 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8643 for (i=0; i<count; i++) {
8645 name_length = strlen(info[i].value_name);
8646 if (strlen(info[i].value_name) > biggest_valuesize) {
8647 biggest_valuesize = name_length;
8650 if (info[i].data_length > biggest_datasize) {
8651 biggest_datasize = info[i].data_length;
8654 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8655 biggest_datasize));
8658 /* the value is an UNICODE string but real_value_size is the length
8659 in bytes including the trailing 0 */
8661 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8662 *r->out.data_needed = biggest_datasize;
8664 DEBUG(6,("final values: [%d], [%d]\n",
8665 *r->out.value_needed, *r->out.data_needed));
8667 return WERR_OK;
8670 if (r->in.enum_index < count) {
8671 val = &info[r->in.enum_index];
8674 if (val == NULL) {
8675 /* out_value should default to "" or else NT4 has
8676 problems unmarshalling the response */
8678 if (r->in.value_offered) {
8679 *r->out.value_needed = 1;
8680 r->out.value_name = talloc_strdup(r, "");
8681 if (!r->out.value_name) {
8682 return WERR_NOMEM;
8684 } else {
8685 r->out.value_name = NULL;
8686 *r->out.value_needed = 0;
8689 /* the data is counted in bytes */
8691 *r->out.data_needed = r->in.data_offered;
8693 result = WERR_NO_MORE_ITEMS;
8694 } else {
8696 * the value is:
8697 * - counted in bytes in the request
8698 * - counted in UNICODE chars in the max reply
8699 * - counted in bytes in the real size
8701 * take a pause *before* coding not *during* coding
8704 /* name */
8705 if (r->in.value_offered) {
8706 r->out.value_name = talloc_strdup(r, val->value_name);
8707 if (!r->out.value_name) {
8708 return WERR_NOMEM;
8710 *r->out.value_needed = val->value_name_len;
8711 } else {
8712 r->out.value_name = NULL;
8713 *r->out.value_needed = 0;
8716 /* type */
8718 *r->out.type = val->type;
8720 /* data - counted in bytes */
8723 * See the section "Dynamically Typed Query Parameters"
8724 * in MS-RPRN.
8727 if (r->out.data && val->data && val->data->data &&
8728 val->data_length && r->in.data_offered) {
8729 memcpy(r->out.data, val->data->data,
8730 MIN(val->data_length,r->in.data_offered));
8733 *r->out.data_needed = val->data_length;
8735 result = WERR_OK;
8738 return result;
8741 /****************************************************************
8742 _spoolss_SetPrinterData
8743 ****************************************************************/
8745 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8746 struct spoolss_SetPrinterData *r)
8748 struct spoolss_SetPrinterDataEx r2;
8750 r2.in.handle = r->in.handle;
8751 r2.in.key_name = "PrinterDriverData";
8752 r2.in.value_name = r->in.value_name;
8753 r2.in.type = r->in.type;
8754 r2.in.data = r->in.data;
8755 r2.in.offered = r->in.offered;
8757 return _spoolss_SetPrinterDataEx(p, &r2);
8760 /****************************************************************
8761 _spoolss_ResetPrinter
8762 ****************************************************************/
8764 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8765 struct spoolss_ResetPrinter *r)
8767 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8768 int snum;
8770 DEBUG(5,("_spoolss_ResetPrinter\n"));
8773 * All we do is to check to see if the handle and queue is valid.
8774 * This call really doesn't mean anything to us because we only
8775 * support RAW printing. --jerry
8778 if (!Printer) {
8779 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8780 OUR_HANDLE(r->in.handle)));
8781 return WERR_BADFID;
8784 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8785 return WERR_BADFID;
8788 /* blindly return success */
8789 return WERR_OK;
8792 /****************************************************************
8793 _spoolss_DeletePrinterData
8794 ****************************************************************/
8796 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8797 struct spoolss_DeletePrinterData *r)
8799 struct spoolss_DeletePrinterDataEx r2;
8801 r2.in.handle = r->in.handle;
8802 r2.in.key_name = "PrinterDriverData";
8803 r2.in.value_name = r->in.value_name;
8805 return _spoolss_DeletePrinterDataEx(p, &r2);
8808 /****************************************************************
8809 _spoolss_AddForm
8810 ****************************************************************/
8812 WERROR _spoolss_AddForm(struct pipes_struct *p,
8813 struct spoolss_AddForm *r)
8815 struct spoolss_AddFormInfo1 *form;
8816 int snum = -1;
8817 WERROR status = WERR_OK;
8818 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8819 struct dcerpc_binding_handle *b;
8820 TALLOC_CTX *tmp_ctx = NULL;
8822 DEBUG(5,("_spoolss_AddForm\n"));
8824 if (!Printer) {
8825 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8826 OUR_HANDLE(r->in.handle)));
8827 return WERR_BADFID;
8830 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8831 and not a printer admin, then fail */
8833 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8834 !security_token_has_privilege(p->session_info->security_token,
8835 SEC_PRIV_PRINT_OPERATOR)) {
8836 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8837 return WERR_ACCESS_DENIED;
8840 if (r->in.info_ctr->level != 1) {
8841 return WERR_INVALID_LEVEL;
8844 form = r->in.info_ctr->info.info1;
8845 if (!form) {
8846 return WERR_INVALID_PARAM;
8849 switch (form->flags) {
8850 case SPOOLSS_FORM_USER:
8851 case SPOOLSS_FORM_BUILTIN:
8852 case SPOOLSS_FORM_PRINTER:
8853 break;
8854 default:
8855 return WERR_INVALID_PARAM;
8858 tmp_ctx = talloc_new(p->mem_ctx);
8859 if (!tmp_ctx) {
8860 return WERR_NOMEM;
8863 status = winreg_printer_binding_handle(tmp_ctx,
8864 get_session_info_system(),
8865 p->msg_ctx,
8866 &b);
8867 if (!W_ERROR_IS_OK(status)) {
8868 goto done;
8871 status = winreg_printer_addform1(tmp_ctx, b, form);
8872 if (!W_ERROR_IS_OK(status)) {
8873 goto done;
8877 * ChangeID must always be set if this is a printer
8879 if (Printer->printer_type == SPLHND_PRINTER) {
8880 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8881 status = WERR_BADFID;
8882 goto done;
8885 status = winreg_printer_update_changeid(tmp_ctx, b,
8886 lp_const_servicename(snum));
8889 done:
8890 talloc_free(tmp_ctx);
8891 return status;
8894 /****************************************************************
8895 _spoolss_DeleteForm
8896 ****************************************************************/
8898 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8899 struct spoolss_DeleteForm *r)
8901 const char *form_name = r->in.form_name;
8902 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8903 int snum = -1;
8904 WERROR status = WERR_OK;
8905 struct dcerpc_binding_handle *b;
8906 TALLOC_CTX *tmp_ctx = NULL;
8908 DEBUG(5,("_spoolss_DeleteForm\n"));
8910 if (!Printer) {
8911 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8912 OUR_HANDLE(r->in.handle)));
8913 return WERR_BADFID;
8916 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8917 !security_token_has_privilege(p->session_info->security_token,
8918 SEC_PRIV_PRINT_OPERATOR)) {
8919 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8920 return WERR_ACCESS_DENIED;
8923 tmp_ctx = talloc_new(p->mem_ctx);
8924 if (!tmp_ctx) {
8925 return WERR_NOMEM;
8928 status = winreg_printer_binding_handle(tmp_ctx,
8929 get_session_info_system(),
8930 p->msg_ctx,
8931 &b);
8932 if (!W_ERROR_IS_OK(status)) {
8933 goto done;
8936 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8937 if (!W_ERROR_IS_OK(status)) {
8938 goto done;
8942 * ChangeID must always be set if this is a printer
8944 if (Printer->printer_type == SPLHND_PRINTER) {
8945 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8946 status = WERR_BADFID;
8947 goto done;
8950 status = winreg_printer_update_changeid(tmp_ctx, b,
8951 lp_const_servicename(snum));
8954 done:
8955 talloc_free(tmp_ctx);
8956 return status;
8959 /****************************************************************
8960 _spoolss_SetForm
8961 ****************************************************************/
8963 WERROR _spoolss_SetForm(struct pipes_struct *p,
8964 struct spoolss_SetForm *r)
8966 struct spoolss_AddFormInfo1 *form;
8967 const char *form_name = r->in.form_name;
8968 int snum = -1;
8969 WERROR status = WERR_OK;
8970 struct dcerpc_binding_handle *b;
8971 TALLOC_CTX *tmp_ctx = NULL;
8973 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8975 DEBUG(5,("_spoolss_SetForm\n"));
8977 if (!Printer) {
8978 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8979 OUR_HANDLE(r->in.handle)));
8980 return WERR_BADFID;
8983 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8984 and not a printer admin, then fail */
8986 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8987 !security_token_has_privilege(p->session_info->security_token,
8988 SEC_PRIV_PRINT_OPERATOR)) {
8989 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8990 return WERR_ACCESS_DENIED;
8993 if (r->in.info_ctr->level != 1) {
8994 return WERR_INVALID_LEVEL;
8997 form = r->in.info_ctr->info.info1;
8998 if (!form) {
8999 return WERR_INVALID_PARAM;
9002 tmp_ctx = talloc_new(p->mem_ctx);
9003 if (!tmp_ctx) {
9004 return WERR_NOMEM;
9007 status = winreg_printer_binding_handle(tmp_ctx,
9008 get_session_info_system(),
9009 p->msg_ctx,
9010 &b);
9011 if (!W_ERROR_IS_OK(status)) {
9012 goto done;
9015 status = winreg_printer_setform1(tmp_ctx, b,
9016 form_name,
9017 form);
9018 if (!W_ERROR_IS_OK(status)) {
9019 goto done;
9023 * ChangeID must always be set if this is a printer
9025 if (Printer->printer_type == SPLHND_PRINTER) {
9026 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9027 status = WERR_BADFID;
9028 goto done;
9031 status = winreg_printer_update_changeid(tmp_ctx, b,
9032 lp_const_servicename(snum));
9035 done:
9036 talloc_free(tmp_ctx);
9037 return status;
9040 /****************************************************************************
9041 fill_print_processor1
9042 ****************************************************************************/
9044 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9045 struct spoolss_PrintProcessorInfo1 *r,
9046 const char *print_processor_name)
9048 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9049 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9051 return WERR_OK;
9054 /****************************************************************************
9055 enumprintprocessors level 1.
9056 ****************************************************************************/
9058 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9059 union spoolss_PrintProcessorInfo **info_p,
9060 uint32_t *count)
9062 union spoolss_PrintProcessorInfo *info;
9063 WERROR result;
9065 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9066 W_ERROR_HAVE_NO_MEMORY(info);
9068 *count = 1;
9070 result = fill_print_processor1(info, &info[0].info1, "winprint");
9071 if (!W_ERROR_IS_OK(result)) {
9072 goto out;
9075 out:
9076 if (!W_ERROR_IS_OK(result)) {
9077 TALLOC_FREE(info);
9078 *count = 0;
9079 return result;
9082 *info_p = info;
9084 return WERR_OK;
9087 /****************************************************************
9088 _spoolss_EnumPrintProcessors
9089 ****************************************************************/
9091 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9092 struct spoolss_EnumPrintProcessors *r)
9094 WERROR result;
9096 /* that's an [in out] buffer */
9098 if (!r->in.buffer && (r->in.offered != 0)) {
9099 return WERR_INVALID_PARAM;
9102 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9105 * Enumerate the print processors ...
9107 * Just reply with "winprint", to keep NT happy
9108 * and I can use my nice printer checker.
9111 *r->out.count = 0;
9112 *r->out.needed = 0;
9113 *r->out.info = NULL;
9115 if (!get_short_archi(r->in.environment)) {
9116 return WERR_INVALID_ENVIRONMENT;
9119 switch (r->in.level) {
9120 case 1:
9121 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9122 r->out.count);
9123 break;
9124 default:
9125 return WERR_UNKNOWN_LEVEL;
9128 if (!W_ERROR_IS_OK(result)) {
9129 return result;
9132 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9133 spoolss_EnumPrintProcessors,
9134 *r->out.info, r->in.level,
9135 *r->out.count);
9136 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9137 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9139 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9142 /****************************************************************************
9143 fill_printprocdatatype1
9144 ****************************************************************************/
9146 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9147 struct spoolss_PrintProcDataTypesInfo1 *r,
9148 const char *name_array)
9150 r->name_array = talloc_strdup(mem_ctx, name_array);
9151 W_ERROR_HAVE_NO_MEMORY(r->name_array);
9153 return WERR_OK;
9156 /****************************************************************************
9157 enumprintprocdatatypes level 1.
9158 ****************************************************************************/
9160 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9161 union spoolss_PrintProcDataTypesInfo **info_p,
9162 uint32_t *count)
9164 WERROR result;
9165 union spoolss_PrintProcDataTypesInfo *info;
9167 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9168 W_ERROR_HAVE_NO_MEMORY(info);
9170 *count = 1;
9172 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9173 if (!W_ERROR_IS_OK(result)) {
9174 goto out;
9177 out:
9178 if (!W_ERROR_IS_OK(result)) {
9179 TALLOC_FREE(info);
9180 *count = 0;
9181 return result;
9184 *info_p = info;
9186 return WERR_OK;
9189 /****************************************************************
9190 _spoolss_EnumPrintProcDataTypes
9191 ****************************************************************/
9193 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9194 struct spoolss_EnumPrintProcDataTypes *r)
9196 WERROR result;
9198 /* that's an [in out] buffer */
9200 if (!r->in.buffer && (r->in.offered != 0)) {
9201 return WERR_INVALID_PARAM;
9204 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9206 *r->out.count = 0;
9207 *r->out.needed = 0;
9208 *r->out.info = NULL;
9210 if (r->in.print_processor_name == NULL ||
9211 !strequal(r->in.print_processor_name, "winprint")) {
9212 return WERR_UNKNOWN_PRINTPROCESSOR;
9215 switch (r->in.level) {
9216 case 1:
9217 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9218 r->out.count);
9219 break;
9220 default:
9221 return WERR_UNKNOWN_LEVEL;
9224 if (!W_ERROR_IS_OK(result)) {
9225 return result;
9228 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9229 spoolss_EnumPrintProcDataTypes,
9230 *r->out.info, r->in.level,
9231 *r->out.count);
9232 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9233 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9235 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9238 /****************************************************************************
9239 fill_monitor_1
9240 ****************************************************************************/
9242 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9243 struct spoolss_MonitorInfo1 *r,
9244 const char *monitor_name)
9246 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9247 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9249 return WERR_OK;
9252 /****************************************************************************
9253 fill_monitor_2
9254 ****************************************************************************/
9256 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9257 struct spoolss_MonitorInfo2 *r,
9258 const char *monitor_name,
9259 const char *environment,
9260 const char *dll_name)
9262 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9263 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9264 r->environment = talloc_strdup(mem_ctx, environment);
9265 W_ERROR_HAVE_NO_MEMORY(r->environment);
9266 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9267 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9269 return WERR_OK;
9272 /****************************************************************************
9273 enumprintmonitors level 1.
9274 ****************************************************************************/
9276 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9277 union spoolss_MonitorInfo **info_p,
9278 uint32_t *count)
9280 union spoolss_MonitorInfo *info;
9281 WERROR result = WERR_OK;
9283 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9284 W_ERROR_HAVE_NO_MEMORY(info);
9286 *count = 2;
9288 result = fill_monitor_1(info, &info[0].info1,
9289 SPL_LOCAL_PORT);
9290 if (!W_ERROR_IS_OK(result)) {
9291 goto out;
9294 result = fill_monitor_1(info, &info[1].info1,
9295 SPL_TCPIP_PORT);
9296 if (!W_ERROR_IS_OK(result)) {
9297 goto out;
9300 out:
9301 if (!W_ERROR_IS_OK(result)) {
9302 TALLOC_FREE(info);
9303 *count = 0;
9304 return result;
9307 *info_p = info;
9309 return WERR_OK;
9312 /****************************************************************************
9313 enumprintmonitors level 2.
9314 ****************************************************************************/
9316 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9317 union spoolss_MonitorInfo **info_p,
9318 uint32_t *count)
9320 union spoolss_MonitorInfo *info;
9321 WERROR result = WERR_OK;
9323 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9324 W_ERROR_HAVE_NO_MEMORY(info);
9326 *count = 2;
9328 result = fill_monitor_2(info, &info[0].info2,
9329 SPL_LOCAL_PORT,
9330 "Windows NT X86", /* FIXME */
9331 "localmon.dll");
9332 if (!W_ERROR_IS_OK(result)) {
9333 goto out;
9336 result = fill_monitor_2(info, &info[1].info2,
9337 SPL_TCPIP_PORT,
9338 "Windows NT X86", /* FIXME */
9339 "tcpmon.dll");
9340 if (!W_ERROR_IS_OK(result)) {
9341 goto out;
9344 out:
9345 if (!W_ERROR_IS_OK(result)) {
9346 TALLOC_FREE(info);
9347 *count = 0;
9348 return result;
9351 *info_p = info;
9353 return WERR_OK;
9356 /****************************************************************
9357 _spoolss_EnumMonitors
9358 ****************************************************************/
9360 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9361 struct spoolss_EnumMonitors *r)
9363 WERROR result;
9365 /* that's an [in out] buffer */
9367 if (!r->in.buffer && (r->in.offered != 0)) {
9368 return WERR_INVALID_PARAM;
9371 DEBUG(5,("_spoolss_EnumMonitors\n"));
9374 * Enumerate the print monitors ...
9376 * Just reply with "Local Port", to keep NT happy
9377 * and I can use my nice printer checker.
9380 *r->out.count = 0;
9381 *r->out.needed = 0;
9382 *r->out.info = NULL;
9384 switch (r->in.level) {
9385 case 1:
9386 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9387 r->out.count);
9388 break;
9389 case 2:
9390 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9391 r->out.count);
9392 break;
9393 default:
9394 return WERR_UNKNOWN_LEVEL;
9397 if (!W_ERROR_IS_OK(result)) {
9398 return result;
9401 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9402 spoolss_EnumMonitors,
9403 *r->out.info, r->in.level,
9404 *r->out.count);
9405 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9406 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9408 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9411 /****************************************************************************
9412 ****************************************************************************/
9414 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9415 const print_queue_struct *queue,
9416 int count, int snum,
9417 struct spoolss_PrinterInfo2 *pinfo2,
9418 uint32_t jobid,
9419 int sysjob,
9420 struct spoolss_JobInfo1 *r)
9422 int i = 0;
9423 bool found = false;
9425 for (i=0; i<count; i++) {
9426 if (queue[i].sysjob == sysjob) {
9427 found = true;
9428 break;
9432 if (found == false) {
9433 /* NT treats not found as bad param... yet another bad choice */
9434 return WERR_INVALID_PARAM;
9437 return fill_job_info1(mem_ctx,
9439 &queue[i],
9440 jobid,
9442 snum,
9443 pinfo2);
9446 /****************************************************************************
9447 ****************************************************************************/
9449 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9450 const print_queue_struct *queue,
9451 int count, int snum,
9452 struct spoolss_PrinterInfo2 *pinfo2,
9453 uint32_t jobid,
9454 int sysjob,
9455 struct spoolss_JobInfo2 *r)
9457 int i = 0;
9458 bool found = false;
9459 struct spoolss_DeviceMode *devmode;
9460 WERROR result;
9462 for (i=0; i<count; i++) {
9463 if (queue[i].sysjob == sysjob) {
9464 found = true;
9465 break;
9469 if (found == false) {
9470 /* NT treats not found as bad param... yet another bad
9471 choice */
9472 return WERR_INVALID_PARAM;
9476 * if the print job does not have a DEVMODE associated with it,
9477 * just use the one for the printer. A NULL devicemode is not
9478 * a failure condition
9481 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9482 if (!devmode) {
9483 result = spoolss_create_default_devmode(mem_ctx,
9484 pinfo2->printername,
9485 &devmode);
9486 if (!W_ERROR_IS_OK(result)) {
9487 DEBUG(3, ("Can't proceed w/o a devmode!"));
9488 return result;
9492 return fill_job_info2(mem_ctx,
9494 &queue[i],
9495 jobid,
9497 snum,
9498 pinfo2,
9499 devmode);
9502 /****************************************************************
9503 _spoolss_GetJob
9504 ****************************************************************/
9506 WERROR _spoolss_GetJob(struct pipes_struct *p,
9507 struct spoolss_GetJob *r)
9509 WERROR result = WERR_OK;
9510 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9511 const char *svc_name;
9512 int sysjob;
9513 int snum;
9514 int count;
9515 struct tdb_print_db *pdb;
9516 print_queue_struct *queue = NULL;
9517 print_status_struct prt_status;
9519 /* that's an [in out] buffer */
9521 if (!r->in.buffer && (r->in.offered != 0)) {
9522 result = WERR_INVALID_PARAM;
9523 goto err_jinfo_free;
9526 DEBUG(5,("_spoolss_GetJob\n"));
9528 *r->out.needed = 0;
9530 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9531 result = WERR_BADFID;
9532 goto err_jinfo_free;
9535 svc_name = lp_const_servicename(snum);
9536 if (svc_name == NULL) {
9537 result = WERR_INVALID_PARAM;
9538 goto err_jinfo_free;
9541 result = winreg_get_printer_internal(p->mem_ctx,
9542 get_session_info_system(),
9543 p->msg_ctx,
9544 svc_name,
9545 &pinfo2);
9546 if (!W_ERROR_IS_OK(result)) {
9547 goto err_jinfo_free;
9550 pdb = get_print_db_byname(svc_name);
9551 if (pdb == NULL) {
9552 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9553 result = WERR_INVALID_PARAM;
9554 goto err_pinfo_free;
9557 sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9558 release_print_db(pdb);
9559 if (sysjob == -1) {
9560 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9561 result = WERR_INVALID_PARAM;
9562 goto err_pinfo_free;
9565 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9567 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9568 count, prt_status.status, prt_status.message));
9570 switch (r->in.level) {
9571 case 1:
9572 result = getjob_level_1(p->mem_ctx,
9573 queue, count, snum, pinfo2,
9574 r->in.job_id, sysjob,
9575 &r->out.info->info1);
9576 break;
9577 case 2:
9578 result = getjob_level_2(p->mem_ctx,
9579 queue, count, snum, pinfo2,
9580 r->in.job_id, sysjob,
9581 &r->out.info->info2);
9582 break;
9583 default:
9584 result = WERR_UNKNOWN_LEVEL;
9585 break;
9588 SAFE_FREE(queue);
9589 TALLOC_FREE(pinfo2);
9591 if (!W_ERROR_IS_OK(result)) {
9592 goto err_jinfo_free;
9595 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9596 r->in.level);
9597 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9599 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9601 err_pinfo_free:
9602 TALLOC_FREE(pinfo2);
9603 err_jinfo_free:
9604 TALLOC_FREE(r->out.info);
9605 return result;
9608 /****************************************************************
9609 _spoolss_GetPrinterDataEx
9610 ****************************************************************/
9612 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9613 struct spoolss_GetPrinterDataEx *r)
9616 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9617 const char *printer;
9618 int snum = 0;
9619 WERROR result = WERR_OK;
9620 DATA_BLOB blob;
9621 enum winreg_Type val_type = REG_NONE;
9622 uint8_t *val_data = NULL;
9623 uint32_t val_size = 0;
9624 struct dcerpc_binding_handle *b;
9625 TALLOC_CTX *tmp_ctx;
9627 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9629 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9630 r->in.key_name, r->in.value_name));
9632 /* in case of problem, return some default values */
9634 *r->out.needed = 0;
9635 *r->out.type = REG_NONE;
9637 tmp_ctx = talloc_new(p->mem_ctx);
9638 if (!tmp_ctx) {
9639 return WERR_NOMEM;
9642 if (!Printer) {
9643 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9644 OUR_HANDLE(r->in.handle)));
9645 result = WERR_BADFID;
9646 goto done;
9649 /* check to see if the keyname is valid */
9650 if (!strlen(r->in.key_name)) {
9651 result = WERR_INVALID_PARAM;
9652 goto done;
9655 /* Is the handle to a printer or to the server? */
9657 if (Printer->printer_type == SPLHND_SERVER) {
9659 union spoolss_PrinterData data;
9661 result = getprinterdata_printer_server(tmp_ctx,
9662 r->in.value_name,
9663 r->out.type,
9664 &data);
9665 if (!W_ERROR_IS_OK(result)) {
9666 goto done;
9669 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9670 *r->out.type, &data);
9671 if (!W_ERROR_IS_OK(result)) {
9672 goto done;
9675 *r->out.needed = blob.length;
9677 if (r->in.offered >= *r->out.needed) {
9678 memcpy(r->out.data, blob.data, blob.length);
9681 result = WERR_OK;
9682 goto done;
9685 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9686 result = WERR_BADFID;
9687 goto done;
9689 printer = lp_const_servicename(snum);
9691 result = winreg_printer_binding_handle(tmp_ctx,
9692 get_session_info_system(),
9693 p->msg_ctx,
9694 &b);
9695 if (!W_ERROR_IS_OK(result)) {
9696 goto done;
9699 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9700 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9701 strequal(r->in.value_name, "ChangeId")) {
9702 *r->out.type = REG_DWORD;
9703 *r->out.needed = 4;
9704 if (r->in.offered >= *r->out.needed) {
9705 uint32_t changeid = 0;
9707 result = winreg_printer_get_changeid(tmp_ctx, b,
9708 printer,
9709 &changeid);
9710 if (!W_ERROR_IS_OK(result)) {
9711 goto done;
9714 SIVAL(r->out.data, 0, changeid);
9715 result = WERR_OK;
9717 goto done;
9720 result = winreg_get_printer_dataex(tmp_ctx, b,
9721 printer,
9722 r->in.key_name,
9723 r->in.value_name,
9724 &val_type,
9725 &val_data,
9726 &val_size);
9727 if (!W_ERROR_IS_OK(result)) {
9728 goto done;
9731 *r->out.needed = val_size;
9732 *r->out.type = val_type;
9734 if (r->in.offered >= *r->out.needed) {
9735 memcpy(r->out.data, val_data, val_size);
9738 done:
9739 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9741 if (W_ERROR_IS_OK(result)) {
9742 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9745 talloc_free(tmp_ctx);
9746 return result;
9749 /****************************************************************
9750 _spoolss_SetPrinterDataEx
9751 ****************************************************************/
9753 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9754 struct spoolss_SetPrinterDataEx *r)
9756 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9757 int snum = 0;
9758 WERROR result = WERR_OK;
9759 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9760 char *oid_string;
9761 struct dcerpc_binding_handle *b;
9762 TALLOC_CTX *tmp_ctx;
9764 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9766 /* From MSDN documentation of SetPrinterDataEx: pass request to
9767 SetPrinterData if key is "PrinterDriverData" */
9769 if (!Printer) {
9770 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9771 OUR_HANDLE(r->in.handle)));
9772 return WERR_BADFID;
9775 if (Printer->printer_type == SPLHND_SERVER) {
9776 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9777 "Not implemented for server handles yet\n"));
9778 return WERR_INVALID_PARAM;
9781 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9782 return WERR_BADFID;
9786 * Access check : NT returns "access denied" if you make a
9787 * SetPrinterData call without the necessary privildge.
9788 * we were originally returning OK if nothing changed
9789 * which made Win2k issue **a lot** of SetPrinterData
9790 * when connecting to a printer --jerry
9793 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9794 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9795 "change denied by handle access permissions\n"));
9796 return WERR_ACCESS_DENIED;
9799 tmp_ctx = talloc_new(p->mem_ctx);
9800 if (!tmp_ctx) {
9801 return WERR_NOMEM;
9804 result = winreg_printer_binding_handle(tmp_ctx,
9805 get_session_info_system(),
9806 p->msg_ctx,
9807 &b);
9808 if (!W_ERROR_IS_OK(result)) {
9809 goto done;
9812 result = winreg_get_printer(tmp_ctx, b,
9813 lp_servicename(talloc_tos(), snum),
9814 &pinfo2);
9815 if (!W_ERROR_IS_OK(result)) {
9816 goto done;
9819 /* check for OID in valuename */
9821 oid_string = strchr(r->in.value_name, ',');
9822 if (oid_string) {
9823 *oid_string = '\0';
9824 oid_string++;
9827 /* save the registry data */
9829 result = winreg_set_printer_dataex(tmp_ctx, b,
9830 pinfo2->sharename,
9831 r->in.key_name,
9832 r->in.value_name,
9833 r->in.type,
9834 r->in.data,
9835 r->in.offered);
9837 if (W_ERROR_IS_OK(result)) {
9838 /* save the OID if one was specified */
9839 if (oid_string) {
9840 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9841 r->in.key_name, SPOOL_OID_KEY);
9842 if (!str) {
9843 result = WERR_NOMEM;
9844 goto done;
9848 * I'm not checking the status here on purpose. Don't know
9849 * if this is right, but I'm returning the status from the
9850 * previous set_printer_dataex() call. I have no idea if
9851 * this is right. --jerry
9853 winreg_set_printer_dataex(tmp_ctx, b,
9854 pinfo2->sharename,
9855 str,
9856 r->in.value_name,
9857 REG_SZ,
9858 (uint8_t *) oid_string,
9859 strlen(oid_string) + 1);
9862 result = winreg_printer_update_changeid(tmp_ctx, b,
9863 lp_const_servicename(snum));
9867 done:
9868 talloc_free(tmp_ctx);
9869 return result;
9872 /****************************************************************
9873 _spoolss_DeletePrinterDataEx
9874 ****************************************************************/
9876 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9877 struct spoolss_DeletePrinterDataEx *r)
9879 const char *printer;
9880 int snum=0;
9881 WERROR status = WERR_OK;
9882 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9884 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9886 if (!Printer) {
9887 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9888 "Invalid handle (%s:%u:%u).\n",
9889 OUR_HANDLE(r->in.handle)));
9890 return WERR_BADFID;
9893 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9894 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9895 "printer properties change denied by handle\n"));
9896 return WERR_ACCESS_DENIED;
9899 if (!r->in.value_name || !r->in.key_name) {
9900 return WERR_NOMEM;
9903 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9904 return WERR_BADFID;
9906 printer = lp_const_servicename(snum);
9908 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9909 get_session_info_system(),
9910 p->msg_ctx,
9911 printer,
9912 r->in.key_name,
9913 r->in.value_name);
9914 if (W_ERROR_IS_OK(status)) {
9915 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9916 get_session_info_system(),
9917 p->msg_ctx,
9918 printer);
9921 return status;
9924 /****************************************************************
9925 _spoolss_EnumPrinterKey
9926 ****************************************************************/
9928 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9929 struct spoolss_EnumPrinterKey *r)
9931 uint32_t num_keys;
9932 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9933 int snum = 0;
9934 WERROR result = WERR_BADFILE;
9935 const char **array = NULL;
9936 DATA_BLOB blob;
9938 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9940 if (!Printer) {
9941 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9942 OUR_HANDLE(r->in.handle)));
9943 return WERR_BADFID;
9946 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9947 return WERR_BADFID;
9950 result = winreg_enum_printer_key_internal(p->mem_ctx,
9951 get_session_info_system(),
9952 p->msg_ctx,
9953 lp_const_servicename(snum),
9954 r->in.key_name,
9955 &num_keys,
9956 &array);
9957 if (!W_ERROR_IS_OK(result)) {
9958 goto done;
9961 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9962 result = WERR_NOMEM;
9963 goto done;
9966 *r->out._ndr_size = r->in.offered / 2;
9967 *r->out.needed = blob.length;
9969 if (r->in.offered < *r->out.needed) {
9970 result = WERR_MORE_DATA;
9971 } else {
9972 result = WERR_OK;
9973 r->out.key_buffer->string_array = array;
9976 done:
9977 if (!W_ERROR_IS_OK(result)) {
9978 TALLOC_FREE(array);
9979 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9980 *r->out.needed = 0;
9984 return result;
9987 /****************************************************************
9988 _spoolss_DeletePrinterKey
9989 ****************************************************************/
9991 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9992 struct spoolss_DeletePrinterKey *r)
9994 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9995 int snum=0;
9996 WERROR status;
9997 const char *printer;
9998 struct dcerpc_binding_handle *b;
9999 TALLOC_CTX *tmp_ctx;
10001 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10003 if (!Printer) {
10004 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10005 OUR_HANDLE(r->in.handle)));
10006 return WERR_BADFID;
10009 /* if keyname == NULL, return error */
10010 if ( !r->in.key_name )
10011 return WERR_INVALID_PARAM;
10013 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10014 return WERR_BADFID;
10017 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10018 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10019 "printer properties change denied by handle\n"));
10020 return WERR_ACCESS_DENIED;
10023 printer = lp_const_servicename(snum);
10025 tmp_ctx = talloc_new(p->mem_ctx);
10026 if (!tmp_ctx) {
10027 return WERR_NOMEM;
10030 status = winreg_printer_binding_handle(tmp_ctx,
10031 get_session_info_system(),
10032 p->msg_ctx,
10033 &b);
10034 if (!W_ERROR_IS_OK(status)) {
10035 goto done;
10038 /* delete the key and all subkeys */
10039 status = winreg_delete_printer_key(tmp_ctx, b,
10040 printer,
10041 r->in.key_name);
10042 if (W_ERROR_IS_OK(status)) {
10043 status = winreg_printer_update_changeid(tmp_ctx, b,
10044 printer);
10047 done:
10048 talloc_free(tmp_ctx);
10049 return status;
10052 /****************************************************************
10053 _spoolss_EnumPrinterDataEx
10054 ****************************************************************/
10056 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10057 struct spoolss_EnumPrinterDataEx *r)
10059 uint32_t count = 0;
10060 struct spoolss_PrinterEnumValues *info = NULL;
10061 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10062 int snum;
10063 WERROR result;
10065 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10067 *r->out.count = 0;
10068 *r->out.needed = 0;
10069 *r->out.info = NULL;
10071 if (!Printer) {
10072 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10073 OUR_HANDLE(r->in.handle)));
10074 return WERR_BADFID;
10078 * first check for a keyname of NULL or "". Win2k seems to send
10079 * this a lot and we should send back WERR_INVALID_PARAM
10080 * no need to spend time looking up the printer in this case.
10081 * --jerry
10084 if (!strlen(r->in.key_name)) {
10085 result = WERR_INVALID_PARAM;
10086 goto done;
10089 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10090 return WERR_BADFID;
10093 /* now look for a match on the key name */
10094 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10095 get_session_info_system(),
10096 p->msg_ctx,
10097 lp_const_servicename(snum),
10098 r->in.key_name,
10099 &count,
10100 &info);
10101 if (!W_ERROR_IS_OK(result)) {
10102 goto done;
10105 #if 0 /* FIXME - gd */
10106 /* housekeeping information in the reply */
10108 /* Fix from Martin Zielinski <mz@seh.de> - ensure
10109 * the hand marshalled container size is a multiple
10110 * of 4 bytes for RPC alignment.
10113 if (needed % 4) {
10114 needed += 4-(needed % 4);
10116 #endif
10117 *r->out.count = count;
10118 *r->out.info = info;
10120 done:
10121 if (!W_ERROR_IS_OK(result)) {
10122 return result;
10125 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10126 spoolss_EnumPrinterDataEx,
10127 *r->out.info,
10128 *r->out.count);
10129 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10130 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10132 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10135 /****************************************************************************
10136 ****************************************************************************/
10138 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10139 const char *servername,
10140 const char *environment,
10141 struct spoolss_PrintProcessorDirectoryInfo1 *r)
10143 WERROR werr;
10144 char *path = NULL;
10146 werr = compose_spoolss_server_path(mem_ctx,
10147 servername,
10148 environment,
10149 SPOOLSS_PRTPROCS_PATH,
10150 &path);
10151 if (!W_ERROR_IS_OK(werr)) {
10152 return werr;
10155 DEBUG(4,("print processor directory: [%s]\n", path));
10157 r->directory_name = path;
10159 return WERR_OK;
10162 /****************************************************************
10163 _spoolss_GetPrintProcessorDirectory
10164 ****************************************************************/
10166 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10167 struct spoolss_GetPrintProcessorDirectory *r)
10169 WERROR result;
10170 char *prnproc_share = NULL;
10171 bool prnproc_share_exists = false;
10172 int snum;
10174 /* that's an [in out] buffer */
10176 if (!r->in.buffer && (r->in.offered != 0)) {
10177 result = WERR_INVALID_PARAM;
10178 goto err_info_free;
10181 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10182 r->in.level));
10184 *r->out.needed = 0;
10186 /* r->in.level is ignored */
10188 /* We always should reply with a local print processor directory so that
10189 * users are not forced to have a [prnproc$] share on the Samba spoolss
10190 * server, if users decide to do so, lets announce it though - Guenther */
10192 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10193 if (!prnproc_share) {
10194 result = WERR_NOMEM;
10195 goto err_info_free;
10197 if (snum != -1) {
10198 prnproc_share_exists = true;
10201 result = getprintprocessordirectory_level_1(p->mem_ctx,
10202 prnproc_share_exists ? r->in.server : NULL,
10203 r->in.environment,
10204 &r->out.info->info1);
10205 if (!W_ERROR_IS_OK(result)) {
10206 goto err_info_free;
10209 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10210 r->out.info, r->in.level);
10211 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10213 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10215 err_info_free:
10216 TALLOC_FREE(r->out.info);
10217 return result;
10220 /*******************************************************************
10221 ********************************************************************/
10223 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10224 const char *dllname)
10226 enum ndr_err_code ndr_err;
10227 struct spoolss_MonitorUi ui;
10229 ui.dll_name = dllname;
10231 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10232 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10233 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10234 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10236 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10239 /*******************************************************************
10240 Streams the monitor UI DLL name in UNICODE
10241 *******************************************************************/
10243 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10244 struct security_token *token, DATA_BLOB *in,
10245 DATA_BLOB *out, uint32_t *needed)
10247 const char *dllname = "tcpmonui.dll";
10249 *needed = (strlen(dllname)+1) * 2;
10251 if (out->length < *needed) {
10252 return WERR_INSUFFICIENT_BUFFER;
10255 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10256 return WERR_NOMEM;
10259 return WERR_OK;
10262 /*******************************************************************
10263 ********************************************************************/
10265 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10266 struct spoolss_PortData1 *port1,
10267 const DATA_BLOB *buf)
10269 enum ndr_err_code ndr_err;
10270 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10271 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10272 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10273 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10275 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10278 /*******************************************************************
10279 ********************************************************************/
10281 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10282 struct spoolss_PortData2 *port2,
10283 const DATA_BLOB *buf)
10285 enum ndr_err_code ndr_err;
10286 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10287 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10288 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10289 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10291 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10294 /*******************************************************************
10295 Create a new TCP/IP port
10296 *******************************************************************/
10298 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10299 struct security_token *token, DATA_BLOB *in,
10300 DATA_BLOB *out, uint32_t *needed)
10302 struct spoolss_PortData1 port1;
10303 struct spoolss_PortData2 port2;
10304 char *device_uri = NULL;
10305 uint32_t version;
10307 const char *portname;
10308 const char *hostaddress;
10309 const char *queue;
10310 uint32_t port_number;
10311 uint32_t protocol;
10313 /* peek for spoolss_PortData version */
10315 if (!in || (in->length < (128 + 4))) {
10316 return WERR_GENERAL_FAILURE;
10319 version = IVAL(in->data, 128);
10321 switch (version) {
10322 case 1:
10323 ZERO_STRUCT(port1);
10325 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10326 return WERR_NOMEM;
10329 portname = port1.portname;
10330 hostaddress = port1.hostaddress;
10331 queue = port1.queue;
10332 protocol = port1.protocol;
10333 port_number = port1.port_number;
10335 break;
10336 case 2:
10337 ZERO_STRUCT(port2);
10339 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10340 return WERR_NOMEM;
10343 portname = port2.portname;
10344 hostaddress = port2.hostaddress;
10345 queue = port2.queue;
10346 protocol = port2.protocol;
10347 port_number = port2.port_number;
10349 break;
10350 default:
10351 DEBUG(1,("xcvtcp_addport: "
10352 "unknown version of port_data: %d\n", version));
10353 return WERR_UNKNOWN_PORT;
10356 /* create the device URI and call the add_port_hook() */
10358 switch (protocol) {
10359 case PROTOCOL_RAWTCP_TYPE:
10360 device_uri = talloc_asprintf(mem_ctx,
10361 "socket://%s:%d/", hostaddress,
10362 port_number);
10363 break;
10365 case PROTOCOL_LPR_TYPE:
10366 device_uri = talloc_asprintf(mem_ctx,
10367 "lpr://%s/%s", hostaddress, queue );
10368 break;
10370 default:
10371 return WERR_UNKNOWN_PORT;
10374 if (!device_uri) {
10375 return WERR_NOMEM;
10378 return add_port_hook(mem_ctx, token, portname, device_uri);
10381 /*******************************************************************
10382 *******************************************************************/
10384 struct xcv_api_table xcvtcp_cmds[] = {
10385 { "MonitorUI", xcvtcp_monitorui },
10386 { "AddPort", xcvtcp_addport},
10387 { NULL, NULL }
10390 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10391 struct security_token *token, const char *command,
10392 DATA_BLOB *inbuf,
10393 DATA_BLOB *outbuf,
10394 uint32_t *needed )
10396 int i;
10398 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10400 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10401 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10402 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10405 return WERR_BADFUNC;
10408 /*******************************************************************
10409 *******************************************************************/
10410 #if 0 /* don't support management using the "Local Port" monitor */
10412 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10413 struct security_token *token, DATA_BLOB *in,
10414 DATA_BLOB *out, uint32_t *needed)
10416 const char *dllname = "localui.dll";
10418 *needed = (strlen(dllname)+1) * 2;
10420 if (out->length < *needed) {
10421 return WERR_INSUFFICIENT_BUFFER;
10424 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10425 return WERR_NOMEM;
10428 return WERR_OK;
10431 /*******************************************************************
10432 *******************************************************************/
10434 struct xcv_api_table xcvlocal_cmds[] = {
10435 { "MonitorUI", xcvlocal_monitorui },
10436 { NULL, NULL }
10438 #else
10439 struct xcv_api_table xcvlocal_cmds[] = {
10440 { NULL, NULL }
10442 #endif
10446 /*******************************************************************
10447 *******************************************************************/
10449 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10450 struct security_token *token, const char *command,
10451 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10452 uint32_t *needed)
10454 int i;
10456 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10458 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10459 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10460 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10462 return WERR_BADFUNC;
10465 /****************************************************************
10466 _spoolss_XcvData
10467 ****************************************************************/
10469 WERROR _spoolss_XcvData(struct pipes_struct *p,
10470 struct spoolss_XcvData *r)
10472 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10473 DATA_BLOB out_data = data_blob_null;
10474 WERROR werror;
10476 if (!Printer) {
10477 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10478 OUR_HANDLE(r->in.handle)));
10479 return WERR_BADFID;
10482 /* Has to be a handle to the TCP/IP port monitor */
10484 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10485 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10486 return WERR_BADFID;
10489 /* requires administrative access to the server */
10491 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10492 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10493 return WERR_ACCESS_DENIED;
10496 /* Allocate the outgoing buffer */
10498 if (r->in.out_data_size) {
10499 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10500 if (out_data.data == NULL) {
10501 return WERR_NOMEM;
10505 switch ( Printer->printer_type ) {
10506 case SPLHND_PORTMON_TCP:
10507 werror = process_xcvtcp_command(p->mem_ctx,
10508 p->session_info->security_token,
10509 r->in.function_name,
10510 &r->in.in_data, &out_data,
10511 r->out.needed);
10512 break;
10513 case SPLHND_PORTMON_LOCAL:
10514 werror = process_xcvlocal_command(p->mem_ctx,
10515 p->session_info->security_token,
10516 r->in.function_name,
10517 &r->in.in_data, &out_data,
10518 r->out.needed);
10519 break;
10520 default:
10521 werror = WERR_INVALID_PRINT_MONITOR;
10524 if (!W_ERROR_IS_OK(werror)) {
10525 return werror;
10528 *r->out.status_code = 0;
10530 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10531 memcpy(r->out.out_data, out_data.data,
10532 MIN(r->in.out_data_size, out_data.length));
10535 return WERR_OK;
10538 /****************************************************************
10539 _spoolss_AddPrintProcessor
10540 ****************************************************************/
10542 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10543 struct spoolss_AddPrintProcessor *r)
10545 /* for now, just indicate success and ignore the add. We'll
10546 automatically set the winprint processor for printer
10547 entries later. Used to debug the LexMark Optra S 1855 PCL
10548 driver --jerry */
10550 return WERR_OK;
10553 /****************************************************************
10554 _spoolss_AddPort
10555 ****************************************************************/
10557 WERROR _spoolss_AddPort(struct pipes_struct *p,
10558 struct spoolss_AddPort *r)
10560 /* do what w2k3 does */
10562 return WERR_NOT_SUPPORTED;
10565 /****************************************************************
10566 _spoolss_GetPrinterDriver
10567 ****************************************************************/
10569 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10570 struct spoolss_GetPrinterDriver *r)
10572 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10573 return WERR_NOT_SUPPORTED;
10576 /****************************************************************
10577 _spoolss_ReadPrinter
10578 ****************************************************************/
10580 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10581 struct spoolss_ReadPrinter *r)
10583 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10584 return WERR_NOT_SUPPORTED;
10587 /****************************************************************
10588 _spoolss_WaitForPrinterChange
10589 ****************************************************************/
10591 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10592 struct spoolss_WaitForPrinterChange *r)
10594 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10595 return WERR_NOT_SUPPORTED;
10598 /****************************************************************
10599 _spoolss_ConfigurePort
10600 ****************************************************************/
10602 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10603 struct spoolss_ConfigurePort *r)
10605 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10606 return WERR_NOT_SUPPORTED;
10609 /****************************************************************
10610 _spoolss_DeletePort
10611 ****************************************************************/
10613 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10614 struct spoolss_DeletePort *r)
10616 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10617 return WERR_NOT_SUPPORTED;
10620 /****************************************************************
10621 _spoolss_CreatePrinterIC
10622 ****************************************************************/
10624 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10625 struct spoolss_CreatePrinterIC *r)
10627 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10628 return WERR_NOT_SUPPORTED;
10631 /****************************************************************
10632 _spoolss_PlayGDIScriptOnPrinterIC
10633 ****************************************************************/
10635 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10636 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10638 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10639 return WERR_NOT_SUPPORTED;
10642 /****************************************************************
10643 _spoolss_DeletePrinterIC
10644 ****************************************************************/
10646 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10647 struct spoolss_DeletePrinterIC *r)
10649 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10650 return WERR_NOT_SUPPORTED;
10653 /****************************************************************
10654 _spoolss_AddPrinterConnection
10655 ****************************************************************/
10657 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10658 struct spoolss_AddPrinterConnection *r)
10660 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10661 return WERR_NOT_SUPPORTED;
10664 /****************************************************************
10665 _spoolss_DeletePrinterConnection
10666 ****************************************************************/
10668 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10669 struct spoolss_DeletePrinterConnection *r)
10671 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10672 return WERR_NOT_SUPPORTED;
10675 /****************************************************************
10676 _spoolss_PrinterMessageBox
10677 ****************************************************************/
10679 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10680 struct spoolss_PrinterMessageBox *r)
10682 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10683 return WERR_NOT_SUPPORTED;
10686 /****************************************************************
10687 _spoolss_AddMonitor
10688 ****************************************************************/
10690 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10691 struct spoolss_AddMonitor *r)
10693 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10694 return WERR_NOT_SUPPORTED;
10697 /****************************************************************
10698 _spoolss_DeleteMonitor
10699 ****************************************************************/
10701 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10702 struct spoolss_DeleteMonitor *r)
10704 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10705 return WERR_NOT_SUPPORTED;
10708 /****************************************************************
10709 _spoolss_DeletePrintProcessor
10710 ****************************************************************/
10712 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10713 struct spoolss_DeletePrintProcessor *r)
10715 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10716 return WERR_NOT_SUPPORTED;
10719 /****************************************************************
10720 _spoolss_AddPrintProvidor
10721 ****************************************************************/
10723 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10724 struct spoolss_AddPrintProvidor *r)
10726 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10727 return WERR_NOT_SUPPORTED;
10730 /****************************************************************
10731 _spoolss_DeletePrintProvidor
10732 ****************************************************************/
10734 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10735 struct spoolss_DeletePrintProvidor *r)
10737 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10738 return WERR_NOT_SUPPORTED;
10741 /****************************************************************
10742 _spoolss_FindFirstPrinterChangeNotification
10743 ****************************************************************/
10745 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10746 struct spoolss_FindFirstPrinterChangeNotification *r)
10748 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10749 return WERR_NOT_SUPPORTED;
10752 /****************************************************************
10753 _spoolss_FindNextPrinterChangeNotification
10754 ****************************************************************/
10756 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10757 struct spoolss_FindNextPrinterChangeNotification *r)
10759 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10760 return WERR_NOT_SUPPORTED;
10763 /****************************************************************
10764 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10765 ****************************************************************/
10767 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10768 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10770 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10771 return WERR_NOT_SUPPORTED;
10774 /****************************************************************
10775 _spoolss_ReplyOpenPrinter
10776 ****************************************************************/
10778 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10779 struct spoolss_ReplyOpenPrinter *r)
10781 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10782 return WERR_NOT_SUPPORTED;
10785 /****************************************************************
10786 _spoolss_RouterReplyPrinter
10787 ****************************************************************/
10789 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10790 struct spoolss_RouterReplyPrinter *r)
10792 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10793 return WERR_NOT_SUPPORTED;
10796 /****************************************************************
10797 _spoolss_ReplyClosePrinter
10798 ****************************************************************/
10800 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10801 struct spoolss_ReplyClosePrinter *r)
10803 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10804 return WERR_NOT_SUPPORTED;
10807 /****************************************************************
10808 _spoolss_AddPortEx
10809 ****************************************************************/
10811 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10812 struct spoolss_AddPortEx *r)
10814 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10815 return WERR_NOT_SUPPORTED;
10818 /****************************************************************
10819 _spoolss_RouterFindFirstPrinterChangeNotification
10820 ****************************************************************/
10822 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10823 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10825 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10826 return WERR_NOT_SUPPORTED;
10829 /****************************************************************
10830 _spoolss_SpoolerInit
10831 ****************************************************************/
10833 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10834 struct spoolss_SpoolerInit *r)
10836 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10837 return WERR_NOT_SUPPORTED;
10840 /****************************************************************
10841 _spoolss_ResetPrinterEx
10842 ****************************************************************/
10844 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10845 struct spoolss_ResetPrinterEx *r)
10847 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10848 return WERR_NOT_SUPPORTED;
10851 /****************************************************************
10852 _spoolss_RouterReplyPrinterEx
10853 ****************************************************************/
10855 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10856 struct spoolss_RouterReplyPrinterEx *r)
10858 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10859 return WERR_NOT_SUPPORTED;
10862 /****************************************************************
10863 _spoolss_44
10864 ****************************************************************/
10866 WERROR _spoolss_44(struct pipes_struct *p,
10867 struct spoolss_44 *r)
10869 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10870 return WERR_NOT_SUPPORTED;
10873 /****************************************************************
10874 _spoolss_SetPort
10875 ****************************************************************/
10877 WERROR _spoolss_SetPort(struct pipes_struct *p,
10878 struct spoolss_SetPort *r)
10880 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10881 return WERR_NOT_SUPPORTED;
10884 /****************************************************************
10885 _spoolss_4a
10886 ****************************************************************/
10888 WERROR _spoolss_4a(struct pipes_struct *p,
10889 struct spoolss_4a *r)
10891 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10892 return WERR_NOT_SUPPORTED;
10895 /****************************************************************
10896 _spoolss_4b
10897 ****************************************************************/
10899 WERROR _spoolss_4b(struct pipes_struct *p,
10900 struct spoolss_4b *r)
10902 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10903 return WERR_NOT_SUPPORTED;
10906 /****************************************************************
10907 _spoolss_4c
10908 ****************************************************************/
10910 WERROR _spoolss_4c(struct pipes_struct *p,
10911 struct spoolss_4c *r)
10913 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10914 return WERR_NOT_SUPPORTED;
10917 /****************************************************************
10918 _spoolss_53
10919 ****************************************************************/
10921 WERROR _spoolss_53(struct pipes_struct *p,
10922 struct spoolss_53 *r)
10924 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10925 return WERR_NOT_SUPPORTED;
10928 /****************************************************************
10929 _spoolss_AddPerMachineConnection
10930 ****************************************************************/
10932 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10933 struct spoolss_AddPerMachineConnection *r)
10935 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10936 return WERR_NOT_SUPPORTED;
10939 /****************************************************************
10940 _spoolss_DeletePerMachineConnection
10941 ****************************************************************/
10943 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10944 struct spoolss_DeletePerMachineConnection *r)
10946 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10947 return WERR_NOT_SUPPORTED;
10950 /****************************************************************
10951 _spoolss_EnumPerMachineConnections
10952 ****************************************************************/
10954 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10955 struct spoolss_EnumPerMachineConnections *r)
10957 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10958 return WERR_NOT_SUPPORTED;
10961 /****************************************************************
10962 _spoolss_5a
10963 ****************************************************************/
10965 WERROR _spoolss_5a(struct pipes_struct *p,
10966 struct spoolss_5a *r)
10968 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10969 return WERR_NOT_SUPPORTED;
10972 /****************************************************************
10973 _spoolss_5b
10974 ****************************************************************/
10976 WERROR _spoolss_5b(struct pipes_struct *p,
10977 struct spoolss_5b *r)
10979 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10980 return WERR_NOT_SUPPORTED;
10983 /****************************************************************
10984 _spoolss_5c
10985 ****************************************************************/
10987 WERROR _spoolss_5c(struct pipes_struct *p,
10988 struct spoolss_5c *r)
10990 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10991 return WERR_NOT_SUPPORTED;
10994 /****************************************************************
10995 _spoolss_5d
10996 ****************************************************************/
10998 WERROR _spoolss_5d(struct pipes_struct *p,
10999 struct spoolss_5d *r)
11001 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11002 return WERR_NOT_SUPPORTED;
11005 /****************************************************************
11006 _spoolss_5e
11007 ****************************************************************/
11009 WERROR _spoolss_5e(struct pipes_struct *p,
11010 struct spoolss_5e *r)
11012 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11013 return WERR_NOT_SUPPORTED;
11016 /****************************************************************
11017 _spoolss_5f
11018 ****************************************************************/
11020 WERROR _spoolss_5f(struct pipes_struct *p,
11021 struct spoolss_5f *r)
11023 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11024 return WERR_NOT_SUPPORTED;
11027 /****************************************************************
11028 _spoolss_60
11029 ****************************************************************/
11031 WERROR _spoolss_60(struct pipes_struct *p,
11032 struct spoolss_60 *r)
11034 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11035 return WERR_NOT_SUPPORTED;
11038 /****************************************************************
11039 _spoolss_RpcSendRecvBidiData
11040 ****************************************************************/
11042 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
11043 struct spoolss_RpcSendRecvBidiData *r)
11045 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11046 return WERR_NOT_SUPPORTED;
11049 /****************************************************************
11050 _spoolss_62
11051 ****************************************************************/
11053 WERROR _spoolss_62(struct pipes_struct *p,
11054 struct spoolss_62 *r)
11056 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11057 return WERR_NOT_SUPPORTED;
11060 /****************************************************************
11061 _spoolss_63
11062 ****************************************************************/
11064 WERROR _spoolss_63(struct pipes_struct *p,
11065 struct spoolss_63 *r)
11067 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11068 return WERR_NOT_SUPPORTED;
11071 /****************************************************************
11072 _spoolss_64
11073 ****************************************************************/
11075 WERROR _spoolss_64(struct pipes_struct *p,
11076 struct spoolss_64 *r)
11078 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11079 return WERR_NOT_SUPPORTED;
11082 /****************************************************************
11083 _spoolss_65
11084 ****************************************************************/
11086 WERROR _spoolss_65(struct pipes_struct *p,
11087 struct spoolss_65 *r)
11089 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11090 return WERR_NOT_SUPPORTED;
11093 /****************************************************************
11094 _spoolss_GetCorePrinterDrivers
11095 ****************************************************************/
11097 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11098 struct spoolss_GetCorePrinterDrivers *r)
11100 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11101 return WERR_NOT_SUPPORTED;
11104 /****************************************************************
11105 _spoolss_67
11106 ****************************************************************/
11108 WERROR _spoolss_67(struct pipes_struct *p,
11109 struct spoolss_67 *r)
11111 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11112 return WERR_NOT_SUPPORTED;
11115 /****************************************************************
11116 _spoolss_GetPrinterDriverPackagePath
11117 ****************************************************************/
11119 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11120 struct spoolss_GetPrinterDriverPackagePath *r)
11122 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11123 return WERR_NOT_SUPPORTED;
11126 /****************************************************************
11127 _spoolss_69
11128 ****************************************************************/
11130 WERROR _spoolss_69(struct pipes_struct *p,
11131 struct spoolss_69 *r)
11133 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11134 return WERR_NOT_SUPPORTED;
11137 /****************************************************************
11138 _spoolss_6a
11139 ****************************************************************/
11141 WERROR _spoolss_6a(struct pipes_struct *p,
11142 struct spoolss_6a *r)
11144 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11145 return WERR_NOT_SUPPORTED;
11148 /****************************************************************
11149 _spoolss_6b
11150 ****************************************************************/
11152 WERROR _spoolss_6b(struct pipes_struct *p,
11153 struct spoolss_6b *r)
11155 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11156 return WERR_NOT_SUPPORTED;
11159 /****************************************************************
11160 _spoolss_6c
11161 ****************************************************************/
11163 WERROR _spoolss_6c(struct pipes_struct *p,
11164 struct spoolss_6c *r)
11166 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11167 return WERR_NOT_SUPPORTED;
11170 /****************************************************************
11171 _spoolss_6d
11172 ****************************************************************/
11174 WERROR _spoolss_6d(struct pipes_struct *p,
11175 struct spoolss_6d *r)
11177 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11178 return WERR_NOT_SUPPORTED;
11181 /****************************************************************
11182 _spoolss_RpcGetJobNamedPropertyValue
11183 ****************************************************************/
11185 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11186 struct spoolss_RpcGetJobNamedPropertyValue *r)
11188 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11189 return WERR_NOT_SUPPORTED;
11192 /****************************************************************
11193 _spoolss_RpcSetJobNamedProperty
11194 ****************************************************************/
11196 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11197 struct spoolss_RpcSetJobNamedProperty *r)
11199 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11200 return WERR_NOT_SUPPORTED;
11203 /****************************************************************
11204 _spoolss_RpcDeleteJobNamedProperty
11205 ****************************************************************/
11207 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11208 struct spoolss_RpcDeleteJobNamedProperty *r)
11210 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11211 return WERR_NOT_SUPPORTED;
11214 /****************************************************************
11215 _spoolss_RpcEnumJobNamedProperties
11216 ****************************************************************/
11218 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11219 struct spoolss_RpcEnumJobNamedProperties *r)
11221 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11222 return WERR_NOT_SUPPORTED;