s3: printing: Fix problem with server taking too long to respond to a MSG_PRINTER_DRV...
[Samba/wip.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob1305b1006e65c9c2325a530df49ea9021deca18d
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 jobid; /* jobid in printing backend */
90 int printer_type;
91 const char *servername;
92 fstring sharename;
93 uint32 type;
94 uint32 access_granted;
95 struct {
96 uint32 flags;
97 uint32 options;
98 fstring localmachine;
99 uint32 printerlocal;
100 struct spoolss_NotifyOption *option;
101 struct policy_handle cli_hnd;
102 struct notify_back_channel *cli_chan;
103 uint32 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;
626 * With hundreds of printers, the "for" loop iterating all
627 * shares can be quite expensive, as it is done on every
628 * OpenPrinter. The loop maps "aprinter" to "sname", the
629 * result of which we cache in gencache.
632 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
633 aprinter);
634 if ((cache_key != NULL) &&
635 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 if (cache_key != NULL) {
707 gencache_set(cache_key, printer_not_found,
708 time(NULL)+300);
709 TALLOC_FREE(cache_key);
711 DEBUGADD(4,("Printer not found\n"));
712 return WERR_INVALID_PRINTER_NAME;
715 if (cache_key != NULL) {
716 gencache_set(cache_key, sname, time(NULL)+300);
717 TALLOC_FREE(cache_key);
720 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
722 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
724 return WERR_OK;
727 /****************************************************************************
728 Find first available printer slot. creates a printer handle for you.
729 ****************************************************************************/
731 static WERROR open_printer_hnd(struct pipes_struct *p,
732 struct policy_handle *hnd,
733 const char *name,
734 uint32_t access_granted)
736 struct printer_handle *new_printer;
737 WERROR result;
739 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
741 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
742 if (new_printer == NULL) {
743 return WERR_NOMEM;
745 talloc_set_destructor(new_printer, printer_entry_destructor);
747 /* This also steals the printer_handle on the policy_handle */
748 if (!create_policy_hnd(p, hnd, new_printer)) {
749 TALLOC_FREE(new_printer);
750 return WERR_INVALID_HANDLE;
753 /* Add to the internal list. */
754 DLIST_ADD(printers_list, new_printer);
756 new_printer->notify.option=NULL;
758 if (!set_printer_hnd_printertype(new_printer, name)) {
759 close_printer_handle(p, hnd);
760 return WERR_INVALID_HANDLE;
763 result = set_printer_hnd_name(p->mem_ctx,
764 get_session_info_system(),
765 p->msg_ctx,
766 new_printer, name);
767 if (!W_ERROR_IS_OK(result)) {
768 close_printer_handle(p, hnd);
769 return result;
772 new_printer->access_granted = access_granted;
774 DEBUG(5, ("%d printer handles active\n",
775 (int)num_pipe_handles(p)));
777 return WERR_OK;
780 /***************************************************************************
781 check to see if the client motify handle is monitoring the notification
782 given by (notify_type, notify_field).
783 **************************************************************************/
785 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
786 uint16_t notify_field)
788 return true;
791 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
792 uint16_t notify_field)
794 struct spoolss_NotifyOption *option = p->notify.option;
795 uint32_t i, j;
798 * Flags should always be zero when the change notify
799 * is registered by the client's spooler. A user Win32 app
800 * might use the flags though instead of the NOTIFY_OPTION_INFO
801 * --jerry
804 if (!option) {
805 return false;
808 if (p->notify.flags)
809 return is_monitoring_event_flags(
810 p->notify.flags, notify_type, notify_field);
812 for (i = 0; i < option->count; i++) {
814 /* Check match for notify_type */
816 if (option->types[i].type != notify_type)
817 continue;
819 /* Check match for field */
821 for (j = 0; j < option->types[i].count; j++) {
822 if (option->types[i].fields[j].field == notify_field) {
823 return true;
828 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
829 p->servername, p->sharename, notify_type, notify_field));
831 return false;
834 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
835 _data->data.integer[0] = _integer; \
836 _data->data.integer[1] = 0;
839 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
840 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
841 if (!_data->data.string.string) {\
842 _data->data.string.size = 0; \
844 _data->data.string.size = strlen_m_term(_p) * 2;
846 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
847 _data->data.devmode.devmode = _devmode;
849 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
850 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
851 if (!_data->data.sd.sd) { \
852 _data->data.sd.sd_size = 0; \
854 _data->data.sd.sd_size = \
855 ndr_size_security_descriptor(_data->data.sd.sd, 0);
857 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
858 struct tm *t,
859 const char **pp,
860 uint32_t *plen)
862 struct spoolss_Time st;
863 uint32_t len = 16;
864 char *p;
866 if (!init_systemtime(&st, t)) {
867 return;
870 p = talloc_array(mem_ctx, char, len);
871 if (!p) {
872 return;
876 * Systemtime must be linearized as a set of UINT16's.
877 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
880 SSVAL(p, 0, st.year);
881 SSVAL(p, 2, st.month);
882 SSVAL(p, 4, st.day_of_week);
883 SSVAL(p, 6, st.day);
884 SSVAL(p, 8, st.hour);
885 SSVAL(p, 10, st.minute);
886 SSVAL(p, 12, st.second);
887 SSVAL(p, 14, st.millisecond);
889 *pp = p;
890 *plen = len;
893 /* Convert a notification message to a struct spoolss_Notify */
895 static void notify_one_value(struct spoolss_notify_msg *msg,
896 struct spoolss_Notify *data,
897 TALLOC_CTX *mem_ctx)
899 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
902 static void notify_string(struct spoolss_notify_msg *msg,
903 struct spoolss_Notify *data,
904 TALLOC_CTX *mem_ctx)
906 /* The length of the message includes the trailing \0 */
908 data->data.string.size = msg->len * 2;
909 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
910 if (!data->data.string.string) {
911 data->data.string.size = 0;
912 return;
916 static void notify_system_time(struct spoolss_notify_msg *msg,
917 struct spoolss_Notify *data,
918 TALLOC_CTX *mem_ctx)
920 data->data.string.string = NULL;
921 data->data.string.size = 0;
923 if (msg->len != sizeof(time_t)) {
924 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
925 msg->len));
926 return;
929 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
930 &data->data.string.string,
931 &data->data.string.size);
934 struct notify2_message_table {
935 const char *name;
936 void (*fn)(struct spoolss_notify_msg *msg,
937 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
940 static struct notify2_message_table printer_notify_table[] = {
941 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
942 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
943 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
944 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
945 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
946 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
947 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
948 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
949 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
950 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
951 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
952 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
953 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
955 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
956 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
957 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
958 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
959 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
962 static struct notify2_message_table job_notify_table[] = {
963 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
964 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
965 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
966 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
967 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
968 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
969 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
970 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
971 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
972 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
973 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
974 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
975 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
976 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
977 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
978 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
979 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
980 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
981 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
982 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
983 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
984 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
985 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
986 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
990 /***********************************************************************
991 Allocate talloc context for container object
992 **********************************************************************/
994 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
996 if ( !ctr )
997 return;
999 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1001 return;
1004 /***********************************************************************
1005 release all allocated memory and zero out structure
1006 **********************************************************************/
1008 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1010 if ( !ctr )
1011 return;
1013 if ( ctr->ctx )
1014 talloc_destroy(ctr->ctx);
1016 ZERO_STRUCTP(ctr);
1018 return;
1021 /***********************************************************************
1022 **********************************************************************/
1024 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1026 if ( !ctr )
1027 return NULL;
1029 return ctr->ctx;
1032 /***********************************************************************
1033 **********************************************************************/
1035 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1037 if ( !ctr || !ctr->msg_groups )
1038 return NULL;
1040 if ( idx >= ctr->num_groups )
1041 return NULL;
1043 return &ctr->msg_groups[idx];
1047 /***********************************************************************
1048 How many groups of change messages do we have ?
1049 **********************************************************************/
1051 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1053 if ( !ctr )
1054 return 0;
1056 return ctr->num_groups;
1059 /***********************************************************************
1060 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1061 **********************************************************************/
1063 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1065 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1066 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1067 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1068 int i, new_slot;
1070 if ( !ctr || !msg )
1071 return 0;
1073 /* loop over all groups looking for a matching printer name */
1075 for ( i=0; i<ctr->num_groups; i++ ) {
1076 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1077 break;
1080 /* add a new group? */
1082 if ( i == ctr->num_groups ) {
1083 ctr->num_groups++;
1085 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1086 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1087 return 0;
1089 ctr->msg_groups = groups;
1091 /* clear the new entry and set the printer name */
1093 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1094 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1097 /* add the change messages; 'i' is the correct index now regardless */
1099 msg_grp = &ctr->msg_groups[i];
1101 msg_grp->num_msgs++;
1103 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1104 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1105 return 0;
1107 msg_grp->msgs = msg_list;
1109 new_slot = msg_grp->num_msgs-1;
1110 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1112 /* need to allocate own copy of data */
1114 if ( msg->len != 0 )
1115 msg_grp->msgs[new_slot].notify.data = (char *)
1116 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1118 return ctr->num_groups;
1121 static void construct_info_data(struct spoolss_Notify *info_data,
1122 enum spoolss_NotifyType type,
1123 uint16_t field, int id);
1125 /***********************************************************************
1126 Send a change notication message on all handles which have a call
1127 back registered
1128 **********************************************************************/
1130 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1131 struct printer_handle *prn_hnd,
1132 SPOOLSS_NOTIFY_MSG *messages,
1133 uint32_t num_msgs,
1134 struct spoolss_Notify **_notifies,
1135 int *_count)
1137 struct spoolss_Notify *notifies;
1138 SPOOLSS_NOTIFY_MSG *msg;
1139 int count = 0;
1140 uint32_t id;
1141 int i;
1143 notifies = talloc_zero_array(mem_ctx,
1144 struct spoolss_Notify, num_msgs);
1145 if (!notifies) {
1146 return ENOMEM;
1149 for (i = 0; i < num_msgs; i++) {
1151 msg = &messages[i];
1153 /* Are we monitoring this event? */
1155 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1156 continue;
1159 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1160 "for printer [%s]\n",
1161 msg->type, msg->field, prn_hnd->sharename));
1164 * if the is a printer notification handle and not a job
1165 * notification type, then set the id to 0.
1166 * Otherwise just use what was specified in the message.
1168 * When registering change notification on a print server
1169 * handle we always need to send back the id (snum) matching
1170 * the printer for which the change took place.
1171 * For change notify registered on a printer handle,
1172 * this does not matter and the id should be 0.
1174 * --jerry
1177 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1178 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1179 id = 0;
1180 } else {
1181 id = msg->id;
1184 /* Convert unix jobid to smb jobid */
1186 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1187 id = sysjob_to_jobid(msg->id);
1189 if (id == -1) {
1190 DEBUG(3, ("no such unix jobid %d\n",
1191 msg->id));
1192 continue;
1196 construct_info_data(&notifies[count],
1197 msg->type, msg->field, id);
1199 switch(msg->type) {
1200 case PRINTER_NOTIFY_TYPE:
1201 if (printer_notify_table[msg->field].fn) {
1202 printer_notify_table[msg->field].fn(msg,
1203 &notifies[count], mem_ctx);
1205 break;
1207 case JOB_NOTIFY_TYPE:
1208 if (job_notify_table[msg->field].fn) {
1209 job_notify_table[msg->field].fn(msg,
1210 &notifies[count], mem_ctx);
1212 break;
1214 default:
1215 DEBUG(5, ("Unknown notification type %d\n",
1216 msg->type));
1217 continue;
1220 count++;
1223 *_notifies = notifies;
1224 *_count = count;
1226 return 0;
1229 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1230 struct printer_handle *prn_hnd,
1231 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1233 struct spoolss_Notify *notifies;
1234 int count = 0;
1235 union spoolss_ReplyPrinterInfo info;
1236 struct spoolss_NotifyInfo info0;
1237 uint32_t reply_result;
1238 NTSTATUS status;
1239 WERROR werr;
1240 int ret;
1242 /* Is there notification on this handle? */
1243 if (prn_hnd->notify.cli_chan == NULL ||
1244 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1245 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1246 prn_hnd->notify.cli_chan->active_connections == 0) {
1247 return 0;
1250 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1251 prn_hnd->servername, prn_hnd->sharename));
1253 /* For this printer? Print servers always receive notifications. */
1254 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1255 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1256 return 0;
1259 DEBUG(10,("Our printer\n"));
1261 /* build the array of change notifications */
1262 ret = build_notify2_messages(mem_ctx, prn_hnd,
1263 msg_group->msgs,
1264 msg_group->num_msgs,
1265 &notifies, &count);
1266 if (ret) {
1267 return ret;
1270 info0.version = 0x2;
1271 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1272 info0.count = count;
1273 info0.notifies = notifies;
1275 info.info0 = &info0;
1277 status = dcerpc_spoolss_RouterReplyPrinterEx(
1278 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1279 mem_ctx,
1280 &prn_hnd->notify.cli_hnd,
1281 prn_hnd->notify.change, /* color */
1282 prn_hnd->notify.flags,
1283 &reply_result,
1284 0, /* reply_type, must be 0 */
1285 info, &werr);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1288 "failed: %s\n",
1289 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1290 nt_errstr(status)));
1291 werr = ntstatus_to_werror(status);
1292 } else if (!W_ERROR_IS_OK(werr)) {
1293 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1294 "failed: %s\n",
1295 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1296 win_errstr(werr)));
1298 switch (reply_result) {
1299 case 0:
1300 break;
1301 case PRINTER_NOTIFY_INFO_DISCARDED:
1302 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1303 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1304 break;
1305 default:
1306 break;
1309 return 0;
1312 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1314 struct printer_handle *p;
1315 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1316 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1317 int ret;
1319 if ( !msg_group ) {
1320 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1321 return;
1324 if (!msg_group->msgs) {
1325 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1326 return;
1329 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1331 /* loop over all printers */
1333 for (p = printers_list; p; p = p->next) {
1334 ret = send_notify2_printer(mem_ctx, p, msg_group);
1335 if (ret) {
1336 goto done;
1340 done:
1341 DEBUG(8,("send_notify2_changes: Exit...\n"));
1342 return;
1345 /***********************************************************************
1346 **********************************************************************/
1348 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1351 uint32_t tv_sec, tv_usec;
1352 size_t offset = 0;
1354 /* Unpack message */
1356 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1357 msg->printer);
1359 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1360 &tv_sec, &tv_usec,
1361 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1363 if (msg->len == 0)
1364 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1365 &msg->notify.value[0], &msg->notify.value[1]);
1366 else
1367 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1368 &msg->len, &msg->notify.data);
1370 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1371 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1373 tv->tv_sec = tv_sec;
1374 tv->tv_usec = tv_usec;
1376 if (msg->len == 0)
1377 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1378 msg->notify.value[1]));
1379 else
1380 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1382 return true;
1385 /********************************************************************
1386 Receive a notify2 message list
1387 ********************************************************************/
1389 static void receive_notify2_message_list(struct messaging_context *msg,
1390 void *private_data,
1391 uint32_t msg_type,
1392 struct server_id server_id,
1393 DATA_BLOB *data)
1395 size_t msg_count, i;
1396 char *buf = (char *)data->data;
1397 char *msg_ptr;
1398 size_t msg_len;
1399 SPOOLSS_NOTIFY_MSG notify;
1400 SPOOLSS_NOTIFY_MSG_CTR messages;
1401 int num_groups;
1403 if (data->length < 4) {
1404 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1405 return;
1408 msg_count = IVAL(buf, 0);
1409 msg_ptr = buf + 4;
1411 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1413 if (msg_count == 0) {
1414 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1415 return;
1418 /* initialize the container */
1420 ZERO_STRUCT( messages );
1421 notify_msg_ctr_init( &messages );
1424 * build message groups for each printer identified
1425 * in a change_notify msg. Remember that a PCN message
1426 * includes the handle returned for the srv_spoolss_replyopenprinter()
1427 * call. Therefore messages are grouped according to printer handle.
1430 for ( i=0; i<msg_count; i++ ) {
1431 struct timeval msg_tv;
1433 if (msg_ptr + 4 - buf > data->length) {
1434 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1435 return;
1438 msg_len = IVAL(msg_ptr,0);
1439 msg_ptr += 4;
1441 if (msg_ptr + msg_len - buf > data->length) {
1442 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1443 return;
1446 /* unpack messages */
1448 ZERO_STRUCT( notify );
1449 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1450 msg_ptr += msg_len;
1452 /* add to correct list in container */
1454 notify_msg_ctr_addmsg( &messages, &notify );
1456 /* free memory that might have been allocated by notify2_unpack_msg() */
1458 if ( notify.len != 0 )
1459 SAFE_FREE( notify.notify.data );
1462 /* process each group of messages */
1464 num_groups = notify_msg_ctr_numgroups( &messages );
1465 for ( i=0; i<num_groups; i++ )
1466 send_notify2_changes( &messages, i );
1469 /* cleanup */
1471 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1472 (uint32_t)msg_count ));
1474 notify_msg_ctr_destroy( &messages );
1476 return;
1479 /********************************************************************
1480 Send a message to ourself about new driver being installed
1481 so we can upgrade the information for each printer bound to this
1482 driver
1483 ********************************************************************/
1485 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1486 struct messaging_context *msg_ctx)
1488 int len = strlen(drivername);
1490 if (!len)
1491 return false;
1493 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1494 drivername));
1496 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1497 MSG_PRINTER_DRVUPGRADE,
1498 (const uint8_t *)drivername, len+1);
1500 return true;
1503 void srv_spoolss_cleanup(void)
1505 struct printer_session_counter *session_counter;
1507 for (session_counter = counter_list;
1508 session_counter != NULL;
1509 session_counter = counter_list) {
1510 DLIST_REMOVE(counter_list, session_counter);
1511 TALLOC_FREE(session_counter);
1515 /**********************************************************************
1516 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1517 over all printers, upgrading ones as necessary
1518 This is now *ONLY* called inside the background lpq updater. JRA.
1519 **********************************************************************/
1521 void do_drv_upgrade_printer(struct messaging_context *msg,
1522 void *private_data,
1523 uint32_t msg_type,
1524 struct server_id server_id,
1525 DATA_BLOB *data)
1527 TALLOC_CTX *tmp_ctx;
1528 const struct auth_session_info *session_info = get_session_info_system();
1529 struct spoolss_PrinterInfo2 *pinfo2;
1530 WERROR result;
1531 const char *drivername;
1532 int snum;
1533 int n_services = lp_numservices();
1534 struct dcerpc_binding_handle *b = NULL;
1536 tmp_ctx = talloc_new(NULL);
1537 if (!tmp_ctx) return;
1539 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1540 if (!drivername) {
1541 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1542 goto done;
1545 DEBUG(10, ("do_drv_upgrade_printer: "
1546 "Got message for new driver [%s]\n", drivername));
1548 /* Iterate the printer list */
1550 for (snum = 0; snum < n_services; snum++) {
1551 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1552 continue;
1555 /* ignore [printers] share */
1556 if (strequal(lp_const_servicename(snum), "printers")) {
1557 continue;
1560 if (b == NULL) {
1561 result = winreg_printer_binding_handle(tmp_ctx,
1562 session_info,
1563 msg,
1564 &b);
1565 if (!W_ERROR_IS_OK(result)) {
1566 break;
1570 result = winreg_get_printer(tmp_ctx, b,
1571 lp_const_servicename(snum),
1572 &pinfo2);
1574 if (!W_ERROR_IS_OK(result)) {
1575 continue;
1578 if (!pinfo2->drivername) {
1579 continue;
1582 if (strcmp(drivername, pinfo2->drivername) != 0) {
1583 continue;
1586 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1588 /* all we care about currently is the change_id */
1589 result = winreg_printer_update_changeid(tmp_ctx, b,
1590 pinfo2->printername);
1592 if (!W_ERROR_IS_OK(result)) {
1593 DEBUG(3, ("do_drv_upgrade_printer: "
1594 "Failed to update changeid [%s]\n",
1595 win_errstr(result)));
1599 /* all done */
1600 done:
1601 talloc_free(tmp_ctx);
1604 /********************************************************************
1605 Update the cache for all printq's with a registered client
1606 connection
1607 ********************************************************************/
1609 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1611 struct printer_handle *printer = printers_list;
1612 int snum;
1614 /* loop through all printers and update the cache where
1615 a client is connected */
1616 while (printer) {
1617 if ((printer->printer_type == SPLHND_PRINTER) &&
1618 ((printer->notify.cli_chan != NULL) &&
1619 (printer->notify.cli_chan->active_connections > 0))) {
1620 snum = print_queue_snum(printer->sharename);
1621 print_queue_status(msg_ctx, snum, NULL, NULL);
1624 printer = printer->next;
1627 return;
1630 /****************************************************************
1631 _spoolss_OpenPrinter
1632 ****************************************************************/
1634 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1635 struct spoolss_OpenPrinter *r)
1637 struct spoolss_OpenPrinterEx e;
1638 struct spoolss_UserLevel1 level1;
1639 WERROR werr;
1641 ZERO_STRUCT(level1);
1643 e.in.printername = r->in.printername;
1644 e.in.datatype = r->in.datatype;
1645 e.in.devmode_ctr = r->in.devmode_ctr;
1646 e.in.access_mask = r->in.access_mask;
1647 e.in.userlevel_ctr.level = 1;
1648 e.in.userlevel_ctr.user_info.level1 = &level1;
1650 e.out.handle = r->out.handle;
1652 werr = _spoolss_OpenPrinterEx(p, &e);
1654 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1655 /* OpenPrinterEx returns this for a bad
1656 * printer name. We must return WERR_INVALID_PRINTER_NAME
1657 * instead.
1659 werr = WERR_INVALID_PRINTER_NAME;
1662 return werr;
1665 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1666 struct spoolss_DeviceMode *orig,
1667 struct spoolss_DeviceMode **dest)
1669 struct spoolss_DeviceMode *dm;
1671 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1672 if (!dm) {
1673 return WERR_NOMEM;
1676 /* copy all values, then duplicate strings and structs */
1677 *dm = *orig;
1679 dm->devicename = talloc_strdup(dm, orig->devicename);
1680 if (!dm->devicename) {
1681 return WERR_NOMEM;
1683 dm->formname = talloc_strdup(dm, orig->formname);
1684 if (!dm->formname) {
1685 return WERR_NOMEM;
1687 if (orig->driverextra_data.data) {
1688 dm->driverextra_data.data =
1689 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1690 orig->driverextra_data.length);
1691 if (!dm->driverextra_data.data) {
1692 return WERR_NOMEM;
1696 *dest = dm;
1697 return WERR_OK;
1700 /****************************************************************
1701 _spoolss_OpenPrinterEx
1702 ****************************************************************/
1704 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1705 struct spoolss_OpenPrinterEx *r)
1707 int snum;
1708 char *raddr;
1709 char *rhost;
1710 struct printer_handle *Printer=NULL;
1711 WERROR result;
1712 int rc;
1714 if (!r->in.printername) {
1715 return WERR_INVALID_PARAM;
1718 if (!*r->in.printername) {
1719 return WERR_INVALID_PARAM;
1722 if (r->in.userlevel_ctr.level > 3) {
1723 return WERR_INVALID_PARAM;
1725 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1726 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1727 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1728 return WERR_INVALID_PARAM;
1731 /* some sanity check because you can open a printer or a print server */
1732 /* aka: \\server\printer or \\server */
1734 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1736 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1737 if (!W_ERROR_IS_OK(result)) {
1738 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1739 "for printer %s\n", r->in.printername));
1740 ZERO_STRUCTP(r->out.handle);
1741 return result;
1744 Printer = find_printer_index_by_hnd(p, r->out.handle);
1745 if ( !Printer ) {
1746 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1747 "handle we created for printer %s\n", r->in.printername));
1748 close_printer_handle(p, r->out.handle);
1749 ZERO_STRUCTP(r->out.handle);
1750 return WERR_INVALID_PARAM;
1754 * First case: the user is opening the print server:
1756 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1757 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1759 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1760 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1761 * or if the user is listed in the smb.conf printer admin parameter.
1763 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1764 * client view printer folder, but does not show the MSAPW.
1766 * Note: this test needs code to check access rights here too. Jeremy
1767 * could you look at this?
1769 * Second case: the user is opening a printer:
1770 * NT doesn't let us connect to a printer if the connecting user
1771 * doesn't have print permission.
1773 * Third case: user is opening a Port Monitor
1774 * access checks same as opening a handle to the print server.
1777 switch (Printer->printer_type )
1779 case SPLHND_SERVER:
1780 case SPLHND_PORTMON_TCP:
1781 case SPLHND_PORTMON_LOCAL:
1782 /* Printserver handles use global struct... */
1784 snum = -1;
1786 /* Map standard access rights to object specific access rights */
1788 se_map_standard(&r->in.access_mask,
1789 &printserver_std_mapping);
1791 /* Deny any object specific bits that don't apply to print
1792 servers (i.e printer and job specific bits) */
1794 r->in.access_mask &= SEC_MASK_SPECIFIC;
1796 if (r->in.access_mask &
1797 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1798 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1799 close_printer_handle(p, r->out.handle);
1800 ZERO_STRUCTP(r->out.handle);
1801 return WERR_ACCESS_DENIED;
1804 /* Allow admin access */
1806 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1808 if (!lp_show_add_printer_wizard()) {
1809 close_printer_handle(p, r->out.handle);
1810 ZERO_STRUCTP(r->out.handle);
1811 return WERR_ACCESS_DENIED;
1814 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1815 and not a printer admin, then fail */
1817 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1818 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1819 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1820 p->session_info->security_token)) {
1821 close_printer_handle(p, r->out.handle);
1822 ZERO_STRUCTP(r->out.handle);
1823 DEBUG(3,("access DENIED as user is not root, "
1824 "has no printoperator privilege, "
1825 "not a member of the printoperator builtin group and "
1826 "is not in printer admin list"));
1827 return WERR_ACCESS_DENIED;
1830 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1832 else
1834 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1837 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1838 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1840 /* We fall through to return WERR_OK */
1841 break;
1843 case SPLHND_PRINTER:
1844 /* NT doesn't let us connect to a printer if the connecting user
1845 doesn't have print permission. */
1847 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1848 close_printer_handle(p, r->out.handle);
1849 ZERO_STRUCTP(r->out.handle);
1850 return WERR_BADFID;
1853 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1854 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1857 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1859 /* map an empty access mask to the minimum access mask */
1860 if (r->in.access_mask == 0x0)
1861 r->in.access_mask = PRINTER_ACCESS_USE;
1864 * If we are not serving the printer driver for this printer,
1865 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1866 * will keep NT clients happy --jerry
1869 if (lp_use_client_driver(snum)
1870 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1872 r->in.access_mask = PRINTER_ACCESS_USE;
1875 /* check smb.conf parameters and the the sec_desc */
1876 raddr = tsocket_address_inet_addr_string(p->remote_address,
1877 p->mem_ctx);
1878 if (raddr == NULL) {
1879 return WERR_NOMEM;
1882 rc = get_remote_hostname(p->remote_address,
1883 &rhost,
1884 p->mem_ctx);
1885 if (rc < 0) {
1886 return WERR_NOMEM;
1888 if (strequal(rhost, "UNKNOWN")) {
1889 rhost = raddr;
1892 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1893 rhost, raddr)) {
1894 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1895 ZERO_STRUCTP(r->out.handle);
1896 return WERR_ACCESS_DENIED;
1899 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1900 p->session_info->security_token, snum) ||
1901 !W_ERROR_IS_OK(print_access_check(p->session_info,
1902 p->msg_ctx,
1903 snum,
1904 r->in.access_mask))) {
1905 DEBUG(3, ("access DENIED for printer open\n"));
1906 close_printer_handle(p, r->out.handle);
1907 ZERO_STRUCTP(r->out.handle);
1908 return WERR_ACCESS_DENIED;
1911 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1912 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1913 close_printer_handle(p, r->out.handle);
1914 ZERO_STRUCTP(r->out.handle);
1915 return WERR_ACCESS_DENIED;
1918 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1919 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1920 else
1921 r->in.access_mask = PRINTER_ACCESS_USE;
1923 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1924 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1926 winreg_create_printer_internal(p->mem_ctx,
1927 get_session_info_system(),
1928 p->msg_ctx,
1929 lp_const_servicename(snum));
1931 break;
1933 default:
1934 /* sanity check to prevent programmer error */
1935 ZERO_STRUCTP(r->out.handle);
1936 return WERR_BADFID;
1939 Printer->access_granted = r->in.access_mask;
1942 * If the client sent a devmode in the OpenPrinter() call, then
1943 * save it here in case we get a job submission on this handle
1946 if ((Printer->printer_type != SPLHND_SERVER)
1947 && (r->in.devmode_ctr.devmode != NULL)) {
1948 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1949 &Printer->devmode);
1952 return WERR_OK;
1955 /****************************************************************
1956 _spoolss_ClosePrinter
1957 ****************************************************************/
1959 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1960 struct spoolss_ClosePrinter *r)
1962 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1964 if (Printer && Printer->document_started) {
1965 struct spoolss_EndDocPrinter e;
1967 e.in.handle = r->in.handle;
1969 _spoolss_EndDocPrinter(p, &e);
1972 if (!close_printer_handle(p, r->in.handle))
1973 return WERR_BADFID;
1975 /* clear the returned printer handle. Observed behavior
1976 from Win2k server. Don't think this really matters.
1977 Previous code just copied the value of the closed
1978 handle. --jerry */
1980 ZERO_STRUCTP(r->out.handle);
1982 return WERR_OK;
1985 /****************************************************************
1986 _spoolss_DeletePrinter
1987 ****************************************************************/
1989 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1990 struct spoolss_DeletePrinter *r)
1992 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1993 WERROR result;
1994 int snum;
1996 if (Printer && Printer->document_started) {
1997 struct spoolss_EndDocPrinter e;
1999 e.in.handle = r->in.handle;
2001 _spoolss_EndDocPrinter(p, &e);
2004 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2005 winreg_delete_printer_key_internal(p->mem_ctx,
2006 get_session_info_system(),
2007 p->msg_ctx,
2008 lp_const_servicename(snum),
2009 "");
2012 result = delete_printer_handle(p, r->in.handle);
2014 return result;
2017 /*******************************************************************
2018 * static function to lookup the version id corresponding to an
2019 * long architecture string
2020 ******************************************************************/
2022 static const struct print_architecture_table_node archi_table[]= {
2024 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2025 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2026 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2027 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2028 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2029 {"Windows IA64", SPL_ARCH_IA64, 3 },
2030 {"Windows x64", SPL_ARCH_X64, 3 },
2031 {NULL, "", -1 }
2034 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2035 SPOOLSS_DRIVER_VERSION_NT35,
2036 SPOOLSS_DRIVER_VERSION_NT4,
2037 SPOOLSS_DRIVER_VERSION_200X,
2038 -1};
2040 static int get_version_id(const char *arch)
2042 int i;
2044 for (i=0; archi_table[i].long_archi != NULL; i++)
2046 if (strcmp(arch, archi_table[i].long_archi) == 0)
2047 return (archi_table[i].version);
2050 return -1;
2053 /****************************************************************
2054 _spoolss_DeletePrinterDriver
2055 ****************************************************************/
2057 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2058 struct spoolss_DeletePrinterDriver *r)
2061 struct spoolss_DriverInfo8 *info = NULL;
2062 int version;
2063 WERROR status;
2064 struct dcerpc_binding_handle *b;
2065 TALLOC_CTX *tmp_ctx = NULL;
2066 int i;
2067 bool found;
2069 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2070 and not a printer admin, then fail */
2072 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2073 !security_token_has_privilege(p->session_info->security_token,
2074 SEC_PRIV_PRINT_OPERATOR)) {
2075 return WERR_ACCESS_DENIED;
2078 /* check that we have a valid driver name first */
2080 if ((version = get_version_id(r->in.architecture)) == -1) {
2081 return WERR_INVALID_ENVIRONMENT;
2084 tmp_ctx = talloc_new(p->mem_ctx);
2085 if (!tmp_ctx) {
2086 return WERR_NOMEM;
2089 status = winreg_printer_binding_handle(tmp_ctx,
2090 get_session_info_system(),
2091 p->msg_ctx,
2092 &b);
2093 if (!W_ERROR_IS_OK(status)) {
2094 goto done;
2097 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2098 status = winreg_get_driver(tmp_ctx, b,
2099 r->in.architecture, r->in.driver,
2100 drv_cversion[i], &info);
2101 if (!W_ERROR_IS_OK(status)) {
2102 DEBUG(5, ("skipping del of driver with version %d\n",
2103 drv_cversion[i]));
2104 continue;
2106 found = true;
2108 if (printer_driver_in_use(tmp_ctx, b, info)) {
2109 status = WERR_PRINTER_DRIVER_IN_USE;
2110 goto done;
2113 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2114 if (!W_ERROR_IS_OK(status)) {
2115 DEBUG(0, ("failed del of driver with version %d\n",
2116 drv_cversion[i]));
2117 goto done;
2120 if (found == false) {
2121 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2122 status = WERR_UNKNOWN_PRINTER_DRIVER;
2123 } else {
2124 status = WERR_OK;
2127 done:
2128 talloc_free(tmp_ctx);
2130 return status;
2133 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2134 struct pipes_struct *p,
2135 struct spoolss_DeletePrinterDriverEx *r,
2136 struct dcerpc_binding_handle *b,
2137 struct spoolss_DriverInfo8 *info)
2139 WERROR status;
2140 bool delete_files;
2142 if (printer_driver_in_use(mem_ctx, b, info)) {
2143 status = WERR_PRINTER_DRIVER_IN_USE;
2144 goto done;
2148 * we have a couple of cases to consider.
2149 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2150 * then the delete should fail if **any** files overlap with
2151 * other drivers
2152 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2153 * non-overlapping files
2154 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2155 * are set, then do not delete any files
2156 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2159 delete_files = r->in.delete_flags
2160 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2163 if (delete_files) {
2164 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2165 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2166 status = WERR_PRINTER_DRIVER_IN_USE;
2167 goto done;
2170 * printer_driver_files_in_use() has trimmed overlapping files
2171 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2176 status = winreg_del_driver(mem_ctx, b, info, info->version);
2177 if (!W_ERROR_IS_OK(status)) {
2178 goto done;
2182 * now delete any associated files if delete_files is
2183 * true. Even if this part failes, we return succes
2184 * because the driver doesn not exist any more
2186 if (delete_files) {
2187 delete_driver_files(p->session_info, info);
2190 done:
2191 return status;
2194 /****************************************************************
2195 _spoolss_DeletePrinterDriverEx
2196 ****************************************************************/
2198 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2199 struct spoolss_DeletePrinterDriverEx *r)
2201 struct spoolss_DriverInfo8 *info = NULL;
2202 WERROR status;
2203 struct dcerpc_binding_handle *b;
2204 TALLOC_CTX *tmp_ctx = NULL;
2205 int i;
2206 bool found;
2208 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2209 and not a printer admin, then fail */
2211 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2212 !security_token_has_privilege(p->session_info->security_token,
2213 SEC_PRIV_PRINT_OPERATOR)) {
2214 return WERR_ACCESS_DENIED;
2217 /* check that we have a valid driver name first */
2218 if (get_version_id(r->in.architecture) == -1) {
2219 /* this is what NT returns */
2220 return WERR_INVALID_ENVIRONMENT;
2223 tmp_ctx = talloc_new(p->mem_ctx);
2224 if (!tmp_ctx) {
2225 return WERR_NOMEM;
2228 status = winreg_printer_binding_handle(tmp_ctx,
2229 get_session_info_system(),
2230 p->msg_ctx,
2231 &b);
2232 if (!W_ERROR_IS_OK(status)) {
2233 goto done;
2236 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2237 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2238 && (drv_cversion[i] != r->in.version)) {
2239 continue;
2242 /* check if a driver with this version exists before delete */
2243 status = winreg_get_driver(tmp_ctx, b,
2244 r->in.architecture, r->in.driver,
2245 drv_cversion[i], &info);
2246 if (!W_ERROR_IS_OK(status)) {
2247 DEBUG(5, ("skipping del of driver with version %d\n",
2248 drv_cversion[i]));
2249 continue;
2251 found = true;
2253 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2254 if (!W_ERROR_IS_OK(status)) {
2255 DEBUG(0, ("failed to delete driver with version %d\n",
2256 drv_cversion[i]));
2257 goto done;
2260 if (found == false) {
2261 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2262 status = WERR_UNKNOWN_PRINTER_DRIVER;
2263 } else {
2264 status = WERR_OK;
2267 done:
2268 talloc_free(tmp_ctx);
2269 return status;
2273 /********************************************************************
2274 GetPrinterData on a printer server Handle.
2275 ********************************************************************/
2277 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2278 const char *value,
2279 enum winreg_Type *type,
2280 union spoolss_PrinterData *data)
2282 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2284 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2285 *type = REG_DWORD;
2286 SIVAL(&data->value, 0, 0x00);
2287 return WERR_OK;
2290 if (!strcasecmp_m(value, "BeepEnabled")) {
2291 *type = REG_DWORD;
2292 SIVAL(&data->value, 0, 0x00);
2293 return WERR_OK;
2296 if (!strcasecmp_m(value, "EventLog")) {
2297 *type = REG_DWORD;
2298 /* formally was 0x1b */
2299 SIVAL(&data->value, 0, 0x00);
2300 return WERR_OK;
2303 if (!strcasecmp_m(value, "NetPopup")) {
2304 *type = REG_DWORD;
2305 SIVAL(&data->value, 0, 0x00);
2306 return WERR_OK;
2309 if (!strcasecmp_m(value, "MajorVersion")) {
2310 *type = REG_DWORD;
2312 /* Windows NT 4.0 seems to not allow uploading of drivers
2313 to a server that reports 0x3 as the MajorVersion.
2314 need to investigate more how Win2k gets around this .
2315 -- jerry */
2317 if (RA_WINNT == get_remote_arch()) {
2318 SIVAL(&data->value, 0, 0x02);
2319 } else {
2320 SIVAL(&data->value, 0, 0x03);
2323 return WERR_OK;
2326 if (!strcasecmp_m(value, "MinorVersion")) {
2327 *type = REG_DWORD;
2328 SIVAL(&data->value, 0, 0x00);
2329 return WERR_OK;
2332 /* REG_BINARY
2333 * uint32_t size = 0x114
2334 * uint32_t major = 5
2335 * uint32_t minor = [0|1]
2336 * uint32_t build = [2195|2600]
2337 * extra unicode string = e.g. "Service Pack 3"
2339 if (!strcasecmp_m(value, "OSVersion")) {
2340 DATA_BLOB blob;
2341 enum ndr_err_code ndr_err;
2342 struct spoolss_OSVersion os;
2344 os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2345 "spoolss", "os_major", 5);
2346 /* Windows 2000 == 5.0 */
2347 os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2348 "spoolss", "os_minor", 0);
2349 os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2350 "spoolss", "os_build", 2195);
2351 os.extra_string = ""; /* leave extra string empty */
2353 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2354 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2355 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2356 return WERR_GENERAL_FAILURE;
2359 if (DEBUGLEVEL >= 10) {
2360 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2363 *type = REG_BINARY;
2364 data->binary = blob;
2366 return WERR_OK;
2370 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2371 *type = REG_SZ;
2373 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2374 W_ERROR_HAVE_NO_MEMORY(data->string);
2376 return WERR_OK;
2379 if (!strcasecmp_m(value, "Architecture")) {
2380 *type = REG_SZ;
2381 data->string = talloc_strdup(mem_ctx,
2382 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2383 W_ERROR_HAVE_NO_MEMORY(data->string);
2385 return WERR_OK;
2388 if (!strcasecmp_m(value, "DsPresent")) {
2389 *type = REG_DWORD;
2391 /* only show the publish check box if we are a
2392 member of a AD domain */
2394 if (lp_security() == SEC_ADS) {
2395 SIVAL(&data->value, 0, 0x01);
2396 } else {
2397 SIVAL(&data->value, 0, 0x00);
2399 return WERR_OK;
2402 if (!strcasecmp_m(value, "DNSMachineName")) {
2403 const char *hostname = get_mydnsfullname();
2405 if (!hostname) {
2406 return WERR_BADFILE;
2409 *type = REG_SZ;
2410 data->string = talloc_strdup(mem_ctx, hostname);
2411 W_ERROR_HAVE_NO_MEMORY(data->string);
2413 return WERR_OK;
2416 *type = REG_NONE;
2418 return WERR_INVALID_PARAM;
2421 /****************************************************************
2422 _spoolss_GetPrinterData
2423 ****************************************************************/
2425 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2426 struct spoolss_GetPrinterData *r)
2428 struct spoolss_GetPrinterDataEx r2;
2430 r2.in.handle = r->in.handle;
2431 r2.in.key_name = "PrinterDriverData";
2432 r2.in.value_name = r->in.value_name;
2433 r2.in.offered = r->in.offered;
2434 r2.out.type = r->out.type;
2435 r2.out.data = r->out.data;
2436 r2.out.needed = r->out.needed;
2438 return _spoolss_GetPrinterDataEx(p, &r2);
2441 /*********************************************************
2442 Connect to the client machine.
2443 **********************************************************/
2445 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2446 struct sockaddr_storage *client_ss, const char *remote_machine)
2448 NTSTATUS ret;
2449 struct sockaddr_storage rm_addr;
2450 char addr[INET6_ADDRSTRLEN];
2452 if ( is_zero_addr(client_ss) ) {
2453 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2454 remote_machine));
2455 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2456 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2457 return false;
2459 print_sockaddr(addr, sizeof(addr), &rm_addr);
2460 } else {
2461 rm_addr = *client_ss;
2462 print_sockaddr(addr, sizeof(addr), &rm_addr);
2463 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2464 addr));
2467 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2468 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2469 addr));
2470 return false;
2473 /* setup the connection */
2474 ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2475 &rm_addr, 0, "IPC$", "IPC",
2476 "", /* username */
2477 "", /* domain */
2478 "", /* password */
2479 0, lp_client_signing());
2481 if ( !NT_STATUS_IS_OK( ret ) ) {
2482 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2483 remote_machine ));
2484 return false;
2487 if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2488 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2489 cli_shutdown(*pp_cli);
2490 return false;
2494 * Ok - we have an anonymous connection to the IPC$ share.
2495 * Now start the NT Domain stuff :-).
2498 ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2499 if (!NT_STATUS_IS_OK(ret)) {
2500 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2501 remote_machine, nt_errstr(ret)));
2502 cli_shutdown(*pp_cli);
2503 return false;
2506 return true;
2509 /***************************************************************************
2510 Connect to the client.
2511 ****************************************************************************/
2513 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2514 uint32_t localprinter,
2515 enum winreg_Type type,
2516 struct policy_handle *handle,
2517 struct notify_back_channel **_chan,
2518 struct sockaddr_storage *client_ss,
2519 struct messaging_context *msg_ctx)
2521 WERROR result;
2522 NTSTATUS status;
2523 struct notify_back_channel *chan;
2525 for (chan = back_channels; chan; chan = chan->next) {
2526 if (memcmp(&chan->client_address, client_ss,
2527 sizeof(struct sockaddr_storage)) == 0) {
2528 break;
2533 * If it's the first connection, contact the client
2534 * and connect to the IPC$ share anonymously
2536 if (!chan) {
2537 fstring unix_printer;
2539 /* the +2 is to strip the leading 2 backslashs */
2540 fstrcpy(unix_printer, printer + 2);
2542 chan = talloc_zero(NULL, struct notify_back_channel);
2543 if (!chan) {
2544 return false;
2546 chan->client_address = *client_ss;
2548 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2549 TALLOC_FREE(chan);
2550 return false;
2553 DLIST_ADD(back_channels, chan);
2555 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2556 receive_notify2_message_list);
2559 if (chan->cli_pipe == NULL ||
2560 chan->cli_pipe->binding_handle == NULL) {
2561 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2562 "NULL %s for printer %s\n",
2563 chan->cli_pipe == NULL ?
2564 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2565 printer));
2566 return false;
2570 * Tell the specific printing tdb we want messages for this printer
2571 * by registering our PID.
2574 if (!print_notify_register_pid(snum)) {
2575 DEBUG(0, ("Failed to register our pid for printer %s\n",
2576 printer));
2579 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2580 talloc_tos(),
2581 printer,
2582 localprinter,
2583 type,
2585 NULL,
2586 handle,
2587 &result);
2588 if (!NT_STATUS_IS_OK(status)) {
2589 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2590 result = ntstatus_to_werror(status);
2591 } else if (!W_ERROR_IS_OK(result)) {
2592 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2595 chan->active_connections++;
2596 *_chan = chan;
2598 return (W_ERROR_IS_OK(result));
2601 /****************************************************************
2602 ****************************************************************/
2604 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2605 const struct spoolss_NotifyOption *r)
2607 struct spoolss_NotifyOption *option;
2608 uint32_t i,k;
2610 if (!r) {
2611 return NULL;
2614 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2615 if (!option) {
2616 return NULL;
2619 *option = *r;
2621 if (!option->count) {
2622 return option;
2625 option->types = talloc_zero_array(option,
2626 struct spoolss_NotifyOptionType, option->count);
2627 if (!option->types) {
2628 talloc_free(option);
2629 return NULL;
2632 for (i=0; i < option->count; i++) {
2633 option->types[i] = r->types[i];
2635 if (option->types[i].count) {
2636 option->types[i].fields = talloc_zero_array(option,
2637 union spoolss_Field, option->types[i].count);
2638 if (!option->types[i].fields) {
2639 talloc_free(option);
2640 return NULL;
2642 for (k=0; k<option->types[i].count; k++) {
2643 option->types[i].fields[k] =
2644 r->types[i].fields[k];
2649 return option;
2652 /****************************************************************
2653 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2655 * before replying OK: status=0 a rpc call is made to the workstation
2656 * asking ReplyOpenPrinter
2658 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2659 * called from api_spoolss_rffpcnex
2660 ****************************************************************/
2662 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2663 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2665 int snum = -1;
2666 struct spoolss_NotifyOption *option = r->in.notify_options;
2667 struct sockaddr_storage client_ss;
2668 ssize_t client_len;
2670 /* store the notify value in the printer struct */
2672 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2674 if (!Printer) {
2675 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2676 "Invalid handle (%s:%u:%u).\n",
2677 OUR_HANDLE(r->in.handle)));
2678 return WERR_BADFID;
2681 Printer->notify.flags = r->in.flags;
2682 Printer->notify.options = r->in.options;
2683 Printer->notify.printerlocal = r->in.printer_local;
2684 Printer->notify.msg_ctx = p->msg_ctx;
2686 TALLOC_FREE(Printer->notify.option);
2687 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2689 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2691 /* Connect to the client machine and send a ReplyOpenPrinter */
2693 if ( Printer->printer_type == SPLHND_SERVER)
2694 snum = -1;
2695 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2696 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2697 return WERR_BADFID;
2699 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2700 "remote_address is %s\n",
2701 tsocket_address_string(p->remote_address, p->mem_ctx)));
2703 if (!lp_print_notify_backchannel(snum)) {
2704 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2705 "backchannel disabled\n"));
2706 return WERR_SERVER_UNAVAILABLE;
2709 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2710 (struct sockaddr *) &client_ss,
2711 sizeof(struct sockaddr_storage));
2712 if (client_len < 0) {
2713 return WERR_NOMEM;
2716 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2717 Printer->notify.printerlocal, REG_SZ,
2718 &Printer->notify.cli_hnd,
2719 &Printer->notify.cli_chan,
2720 &client_ss, p->msg_ctx)) {
2721 return WERR_SERVER_UNAVAILABLE;
2724 return WERR_OK;
2727 /*******************************************************************
2728 * fill a notify_info_data with the servername
2729 ********************************************************************/
2731 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2732 int snum,
2733 struct spoolss_Notify *data,
2734 print_queue_struct *queue,
2735 struct spoolss_PrinterInfo2 *pinfo2,
2736 TALLOC_CTX *mem_ctx)
2738 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2741 /*******************************************************************
2742 * fill a notify_info_data with the printername (not including the servername).
2743 ********************************************************************/
2745 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2746 int snum,
2747 struct spoolss_Notify *data,
2748 print_queue_struct *queue,
2749 struct spoolss_PrinterInfo2 *pinfo2,
2750 TALLOC_CTX *mem_ctx)
2752 /* the notify name should not contain the \\server\ part */
2753 const char *p = strrchr(pinfo2->printername, '\\');
2755 if (!p) {
2756 p = pinfo2->printername;
2757 } else {
2758 p++;
2761 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2764 /*******************************************************************
2765 * fill a notify_info_data with the servicename
2766 ********************************************************************/
2768 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2769 int snum,
2770 struct spoolss_Notify *data,
2771 print_queue_struct *queue,
2772 struct spoolss_PrinterInfo2 *pinfo2,
2773 TALLOC_CTX *mem_ctx)
2775 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2778 /*******************************************************************
2779 * fill a notify_info_data with the port name
2780 ********************************************************************/
2782 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2783 int snum,
2784 struct spoolss_Notify *data,
2785 print_queue_struct *queue,
2786 struct spoolss_PrinterInfo2 *pinfo2,
2787 TALLOC_CTX *mem_ctx)
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2792 /*******************************************************************
2793 * fill a notify_info_data with the printername
2794 * but it doesn't exist, have to see what to do
2795 ********************************************************************/
2797 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2798 int snum,
2799 struct spoolss_Notify *data,
2800 print_queue_struct *queue,
2801 struct spoolss_PrinterInfo2 *pinfo2,
2802 TALLOC_CTX *mem_ctx)
2804 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2807 /*******************************************************************
2808 * fill a notify_info_data with the comment
2809 ********************************************************************/
2811 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2812 int snum,
2813 struct spoolss_Notify *data,
2814 print_queue_struct *queue,
2815 struct spoolss_PrinterInfo2 *pinfo2,
2816 TALLOC_CTX *mem_ctx)
2818 const char *p;
2820 if (*pinfo2->comment == '\0') {
2821 p = lp_comment(talloc_tos(), snum);
2822 } else {
2823 p = pinfo2->comment;
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2829 /*******************************************************************
2830 * fill a notify_info_data with the comment
2831 * location = "Room 1, floor 2, building 3"
2832 ********************************************************************/
2834 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2835 int snum,
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 struct spoolss_PrinterInfo2 *pinfo2,
2839 TALLOC_CTX *mem_ctx)
2841 const char *loc = pinfo2->location;
2842 NTSTATUS status;
2844 status = printer_list_get_printer(mem_ctx,
2845 pinfo2->sharename,
2846 NULL,
2847 &loc,
2848 NULL);
2849 if (NT_STATUS_IS_OK(status)) {
2850 if (loc == NULL) {
2851 loc = pinfo2->location;
2855 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2858 /*******************************************************************
2859 * fill a notify_info_data with the device mode
2860 * jfm:xxxx don't to it for know but that's a real problem !!!
2861 ********************************************************************/
2863 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2864 int snum,
2865 struct spoolss_Notify *data,
2866 print_queue_struct *queue,
2867 struct spoolss_PrinterInfo2 *pinfo2,
2868 TALLOC_CTX *mem_ctx)
2870 /* for a dummy implementation we have to zero the fields */
2871 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2874 /*******************************************************************
2875 * fill a notify_info_data with the separator file name
2876 ********************************************************************/
2878 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2879 int snum,
2880 struct spoolss_Notify *data,
2881 print_queue_struct *queue,
2882 struct spoolss_PrinterInfo2 *pinfo2,
2883 TALLOC_CTX *mem_ctx)
2885 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2888 /*******************************************************************
2889 * fill a notify_info_data with the print processor
2890 * jfm:xxxx return always winprint to indicate we don't do anything to it
2891 ********************************************************************/
2893 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2894 int snum,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 struct spoolss_PrinterInfo2 *pinfo2,
2898 TALLOC_CTX *mem_ctx)
2900 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2903 /*******************************************************************
2904 * fill a notify_info_data with the print processor options
2905 * jfm:xxxx send an empty string
2906 ********************************************************************/
2908 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2909 int snum,
2910 struct spoolss_Notify *data,
2911 print_queue_struct *queue,
2912 struct spoolss_PrinterInfo2 *pinfo2,
2913 TALLOC_CTX *mem_ctx)
2915 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2918 /*******************************************************************
2919 * fill a notify_info_data with the data type
2920 * jfm:xxxx always send RAW as data type
2921 ********************************************************************/
2923 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2924 int snum,
2925 struct spoolss_Notify *data,
2926 print_queue_struct *queue,
2927 struct spoolss_PrinterInfo2 *pinfo2,
2928 TALLOC_CTX *mem_ctx)
2930 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2933 /*******************************************************************
2934 * fill a notify_info_data with the security descriptor
2935 * jfm:xxxx send an null pointer to say no security desc
2936 * have to implement security before !
2937 ********************************************************************/
2939 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2940 int snum,
2941 struct spoolss_Notify *data,
2942 print_queue_struct *queue,
2943 struct spoolss_PrinterInfo2 *pinfo2,
2944 TALLOC_CTX *mem_ctx)
2946 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2949 /*******************************************************************
2950 * fill a notify_info_data with the attributes
2951 * jfm:xxxx a samba printer is always shared
2952 ********************************************************************/
2954 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2955 int snum,
2956 struct spoolss_Notify *data,
2957 print_queue_struct *queue,
2958 struct spoolss_PrinterInfo2 *pinfo2,
2959 TALLOC_CTX *mem_ctx)
2961 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2964 /*******************************************************************
2965 * fill a notify_info_data with the priority
2966 ********************************************************************/
2968 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2969 int snum,
2970 struct spoolss_Notify *data,
2971 print_queue_struct *queue,
2972 struct spoolss_PrinterInfo2 *pinfo2,
2973 TALLOC_CTX *mem_ctx)
2975 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2978 /*******************************************************************
2979 * fill a notify_info_data with the default priority
2980 ********************************************************************/
2982 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2983 int snum,
2984 struct spoolss_Notify *data,
2985 print_queue_struct *queue,
2986 struct spoolss_PrinterInfo2 *pinfo2,
2987 TALLOC_CTX *mem_ctx)
2989 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2992 /*******************************************************************
2993 * fill a notify_info_data with the start time
2994 ********************************************************************/
2996 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2997 int snum,
2998 struct spoolss_Notify *data,
2999 print_queue_struct *queue,
3000 struct spoolss_PrinterInfo2 *pinfo2,
3001 TALLOC_CTX *mem_ctx)
3003 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3006 /*******************************************************************
3007 * fill a notify_info_data with the until time
3008 ********************************************************************/
3010 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3011 int snum,
3012 struct spoolss_Notify *data,
3013 print_queue_struct *queue,
3014 struct spoolss_PrinterInfo2 *pinfo2,
3015 TALLOC_CTX *mem_ctx)
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3020 /*******************************************************************
3021 * fill a notify_info_data with the status
3022 ********************************************************************/
3024 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3025 int snum,
3026 struct spoolss_Notify *data,
3027 print_queue_struct *queue,
3028 struct spoolss_PrinterInfo2 *pinfo2,
3029 TALLOC_CTX *mem_ctx)
3031 print_status_struct status;
3033 print_queue_length(msg_ctx, snum, &status);
3034 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3037 /*******************************************************************
3038 * fill a notify_info_data with the number of jobs queued
3039 ********************************************************************/
3041 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3042 int snum,
3043 struct spoolss_Notify *data,
3044 print_queue_struct *queue,
3045 struct spoolss_PrinterInfo2 *pinfo2,
3046 TALLOC_CTX *mem_ctx)
3048 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3049 data, print_queue_length(msg_ctx, snum, NULL));
3052 /*******************************************************************
3053 * fill a notify_info_data with the average ppm
3054 ********************************************************************/
3056 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3057 int snum,
3058 struct spoolss_Notify *data,
3059 print_queue_struct *queue,
3060 struct spoolss_PrinterInfo2 *pinfo2,
3061 TALLOC_CTX *mem_ctx)
3063 /* always respond 8 pages per minutes */
3064 /* a little hard ! */
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3068 /*******************************************************************
3069 * fill a notify_info_data with username
3070 ********************************************************************/
3072 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3073 int snum,
3074 struct spoolss_Notify *data,
3075 print_queue_struct *queue,
3076 struct spoolss_PrinterInfo2 *pinfo2,
3077 TALLOC_CTX *mem_ctx)
3079 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3082 /*******************************************************************
3083 * fill a notify_info_data with job status
3084 ********************************************************************/
3086 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3087 int snum,
3088 struct spoolss_Notify *data,
3089 print_queue_struct *queue,
3090 struct spoolss_PrinterInfo2 *pinfo2,
3091 TALLOC_CTX *mem_ctx)
3093 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3096 /*******************************************************************
3097 * fill a notify_info_data with job name
3098 ********************************************************************/
3100 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3101 int snum,
3102 struct spoolss_Notify *data,
3103 print_queue_struct *queue,
3104 struct spoolss_PrinterInfo2 *pinfo2,
3105 TALLOC_CTX *mem_ctx)
3107 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3110 /*******************************************************************
3111 * fill a notify_info_data with job status
3112 ********************************************************************/
3114 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3115 int snum,
3116 struct spoolss_Notify *data,
3117 print_queue_struct *queue,
3118 struct spoolss_PrinterInfo2 *pinfo2,
3119 TALLOC_CTX *mem_ctx)
3122 * Now we're returning job status codes we just return a "" here. JRA.
3125 const char *p = "";
3127 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3128 p = "unknown";
3130 switch (queue->status) {
3131 case LPQ_QUEUED:
3132 p = "Queued";
3133 break;
3134 case LPQ_PAUSED:
3135 p = ""; /* NT provides the paused string */
3136 break;
3137 case LPQ_SPOOLING:
3138 p = "Spooling";
3139 break;
3140 case LPQ_PRINTING:
3141 p = "Printing";
3142 break;
3144 #endif /* NO LONGER NEEDED. */
3146 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3149 /*******************************************************************
3150 * fill a notify_info_data with job time
3151 ********************************************************************/
3153 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3154 int snum,
3155 struct spoolss_Notify *data,
3156 print_queue_struct *queue,
3157 struct spoolss_PrinterInfo2 *pinfo2,
3158 TALLOC_CTX *mem_ctx)
3160 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3163 /*******************************************************************
3164 * fill a notify_info_data with job size
3165 ********************************************************************/
3167 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3168 int snum,
3169 struct spoolss_Notify *data,
3170 print_queue_struct *queue,
3171 struct spoolss_PrinterInfo2 *pinfo2,
3172 TALLOC_CTX *mem_ctx)
3174 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3177 /*******************************************************************
3178 * fill a notify_info_data with page info
3179 ********************************************************************/
3180 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3181 int snum,
3182 struct spoolss_Notify *data,
3183 print_queue_struct *queue,
3184 struct spoolss_PrinterInfo2 *pinfo2,
3185 TALLOC_CTX *mem_ctx)
3187 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3190 /*******************************************************************
3191 * fill a notify_info_data with pages printed info.
3192 ********************************************************************/
3193 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3194 int snum,
3195 struct spoolss_Notify *data,
3196 print_queue_struct *queue,
3197 struct spoolss_PrinterInfo2 *pinfo2,
3198 TALLOC_CTX *mem_ctx)
3200 /* Add code when back-end tracks this */
3201 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3204 /*******************************************************************
3205 Fill a notify_info_data with job position.
3206 ********************************************************************/
3208 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3209 int snum,
3210 struct spoolss_Notify *data,
3211 print_queue_struct *queue,
3212 struct spoolss_PrinterInfo2 *pinfo2,
3213 TALLOC_CTX *mem_ctx)
3215 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3218 /*******************************************************************
3219 Fill a notify_info_data with submitted time.
3220 ********************************************************************/
3222 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3223 int snum,
3224 struct spoolss_Notify *data,
3225 print_queue_struct *queue,
3226 struct spoolss_PrinterInfo2 *pinfo2,
3227 TALLOC_CTX *mem_ctx)
3229 data->data.string.string = NULL;
3230 data->data.string.size = 0;
3232 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3233 &data->data.string.string,
3234 &data->data.string.size);
3238 struct s_notify_info_data_table
3240 enum spoolss_NotifyType type;
3241 uint16_t field;
3242 const char *name;
3243 enum spoolss_NotifyTable variable_type;
3244 void (*fn) (struct messaging_context *msg_ctx,
3245 int snum, struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 struct spoolss_PrinterInfo2 *pinfo2,
3248 TALLOC_CTX *mem_ctx);
3251 /* A table describing the various print notification constants and
3252 whether the notification data is a pointer to a variable sized
3253 buffer, a one value uint32_t or a two value uint32_t. */
3255 static const struct s_notify_info_data_table notify_info_data_table[] =
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3308 /*******************************************************************
3309 Return the variable_type of info_data structure.
3310 ********************************************************************/
3312 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3313 uint16_t field)
3315 int i=0;
3317 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3318 if ( (notify_info_data_table[i].type == type) &&
3319 (notify_info_data_table[i].field == field) ) {
3320 return notify_info_data_table[i].variable_type;
3324 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3326 return (enum spoolss_NotifyTable) 0;
3329 /****************************************************************************
3330 ****************************************************************************/
3332 static bool search_notify(enum spoolss_NotifyType type,
3333 uint16_t field,
3334 int *value)
3336 int i;
3338 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3339 if (notify_info_data_table[i].type == type &&
3340 notify_info_data_table[i].field == field &&
3341 notify_info_data_table[i].fn != NULL) {
3342 *value = i;
3343 return true;
3347 return false;
3350 /****************************************************************************
3351 ****************************************************************************/
3353 static void construct_info_data(struct spoolss_Notify *info_data,
3354 enum spoolss_NotifyType type,
3355 uint16_t field, int id)
3357 info_data->type = type;
3358 info_data->field.field = field;
3359 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3360 info_data->job_id = id;
3363 /*******************************************************************
3365 * fill a notify_info struct with info asked
3367 ********************************************************************/
3369 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3370 struct printer_handle *print_hnd,
3371 struct spoolss_NotifyInfo *info,
3372 struct spoolss_PrinterInfo2 *pinfo2,
3373 int snum,
3374 const struct spoolss_NotifyOptionType *option_type,
3375 uint32_t id,
3376 TALLOC_CTX *mem_ctx)
3378 int field_num,j;
3379 enum spoolss_NotifyType type;
3380 uint16_t field;
3382 struct spoolss_Notify *current_data;
3384 type = option_type->type;
3386 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3387 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3388 option_type->count, lp_servicename(talloc_tos(), snum)));
3390 for(field_num=0; field_num < option_type->count; field_num++) {
3391 field = option_type->fields[field_num].field;
3393 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3395 if (!search_notify(type, field, &j) )
3396 continue;
3398 info->notifies = talloc_realloc(info, info->notifies,
3399 struct spoolss_Notify,
3400 info->count + 1);
3401 if (info->notifies == NULL) {
3402 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3403 return false;
3406 current_data = &info->notifies[info->count];
3408 construct_info_data(current_data, type, field, id);
3410 DEBUG(10, ("construct_notify_printer_info: "
3411 "calling [%s] snum=%d printername=[%s])\n",
3412 notify_info_data_table[j].name, snum,
3413 pinfo2->printername));
3415 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3416 NULL, pinfo2, mem_ctx);
3418 info->count++;
3421 return true;
3424 /*******************************************************************
3426 * fill a notify_info struct with info asked
3428 ********************************************************************/
3430 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3431 print_queue_struct *queue,
3432 struct spoolss_NotifyInfo *info,
3433 struct spoolss_PrinterInfo2 *pinfo2,
3434 int snum,
3435 const struct spoolss_NotifyOptionType *option_type,
3436 uint32_t id,
3437 TALLOC_CTX *mem_ctx)
3439 int field_num,j;
3440 enum spoolss_NotifyType type;
3441 uint16_t field;
3442 struct spoolss_Notify *current_data;
3444 DEBUG(4,("construct_notify_jobs_info\n"));
3446 type = option_type->type;
3448 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3449 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3450 option_type->count));
3452 for(field_num=0; field_num<option_type->count; field_num++) {
3453 field = option_type->fields[field_num].field;
3455 if (!search_notify(type, field, &j) )
3456 continue;
3458 info->notifies = talloc_realloc(info, info->notifies,
3459 struct spoolss_Notify,
3460 info->count + 1);
3461 if (info->notifies == NULL) {
3462 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3463 return false;
3466 current_data=&(info->notifies[info->count]);
3468 construct_info_data(current_data, type, field, id);
3469 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3470 queue, pinfo2, mem_ctx);
3471 info->count++;
3474 return true;
3478 * JFM: The enumeration is not that simple, it's even non obvious.
3480 * let's take an example: I want to monitor the PRINTER SERVER for
3481 * the printer's name and the number of jobs currently queued.
3482 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3483 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3485 * I have 3 printers on the back of my server.
3487 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3488 * structures.
3489 * Number Data Id
3490 * 1 printer 1 name 1
3491 * 2 printer 1 cjob 1
3492 * 3 printer 2 name 2
3493 * 4 printer 2 cjob 2
3494 * 5 printer 3 name 3
3495 * 6 printer 3 name 3
3497 * that's the print server case, the printer case is even worse.
3500 /*******************************************************************
3502 * enumerate all printers on the printserver
3503 * fill a notify_info struct with info asked
3505 ********************************************************************/
3507 static WERROR printserver_notify_info(struct pipes_struct *p,
3508 struct policy_handle *hnd,
3509 struct spoolss_NotifyInfo *info,
3510 TALLOC_CTX *mem_ctx)
3512 int snum;
3513 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3514 int n_services=lp_numservices();
3515 int i;
3516 struct spoolss_NotifyOption *option;
3517 struct spoolss_NotifyOptionType option_type;
3518 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3519 WERROR result;
3521 DEBUG(4,("printserver_notify_info\n"));
3523 if (!Printer)
3524 return WERR_BADFID;
3526 option = Printer->notify.option;
3528 info->version = 2;
3529 info->notifies = NULL;
3530 info->count = 0;
3532 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3533 sending a ffpcn() request first */
3535 if ( !option )
3536 return WERR_BADFID;
3538 for (i=0; i<option->count; i++) {
3539 option_type = option->types[i];
3541 if (option_type.type != PRINTER_NOTIFY_TYPE)
3542 continue;
3544 for (snum = 0; snum < n_services; snum++) {
3545 if (!lp_browseable(snum) ||
3546 !lp_snum_ok(snum) ||
3547 !lp_printable(snum)) {
3548 continue; /* skip */
3551 /* Maybe we should use the SYSTEM session_info here... */
3552 result = winreg_get_printer_internal(mem_ctx,
3553 get_session_info_system(),
3554 p->msg_ctx,
3555 lp_servicename(talloc_tos(), snum),
3556 &pinfo2);
3557 if (!W_ERROR_IS_OK(result)) {
3558 DEBUG(4, ("printserver_notify_info: "
3559 "Failed to get printer [%s]\n",
3560 lp_servicename(talloc_tos(), snum)));
3561 continue;
3565 construct_notify_printer_info(p->msg_ctx,
3566 Printer, info,
3567 pinfo2, snum,
3568 &option_type, snum,
3569 mem_ctx);
3571 TALLOC_FREE(pinfo2);
3575 #if 0
3577 * Debugging information, don't delete.
3580 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3581 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3582 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3584 for (i=0; i<info->count; i++) {
3585 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3586 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3587 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3589 #endif
3591 return WERR_OK;
3594 /*******************************************************************
3596 * fill a notify_info struct with info asked
3598 ********************************************************************/
3600 static WERROR printer_notify_info(struct pipes_struct *p,
3601 struct policy_handle *hnd,
3602 struct spoolss_NotifyInfo *info,
3603 TALLOC_CTX *mem_ctx)
3605 int snum;
3606 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3607 int i;
3608 uint32_t id;
3609 struct spoolss_NotifyOption *option;
3610 struct spoolss_NotifyOptionType option_type;
3611 int count,j;
3612 print_queue_struct *queue=NULL;
3613 print_status_struct status;
3614 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3615 WERROR result;
3616 struct tdb_print_db *pdb;
3618 DEBUG(4,("printer_notify_info\n"));
3620 if (!Printer)
3621 return WERR_BADFID;
3623 option = Printer->notify.option;
3624 id = 0x0;
3626 info->version = 2;
3627 info->notifies = NULL;
3628 info->count = 0;
3630 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3631 sending a ffpcn() request first */
3633 if ( !option )
3634 return WERR_BADFID;
3636 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3637 return WERR_BADFID;
3640 pdb = get_print_db_byname(Printer->sharename);
3641 if (pdb == NULL) {
3642 return WERR_BADFID;
3645 /* Maybe we should use the SYSTEM session_info here... */
3646 result = winreg_get_printer_internal(mem_ctx,
3647 get_session_info_system(),
3648 p->msg_ctx,
3649 lp_servicename(talloc_tos(), snum), &pinfo2);
3650 if (!W_ERROR_IS_OK(result)) {
3651 result = WERR_BADFID;
3652 goto err_pdb_drop;
3656 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3657 * correct servername.
3659 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3660 if (pinfo2->servername == NULL) {
3661 result = WERR_NOMEM;
3662 goto err_pdb_drop;
3665 for (i = 0; i < option->count; i++) {
3666 option_type = option->types[i];
3668 switch (option_type.type) {
3669 case PRINTER_NOTIFY_TYPE:
3670 if (construct_notify_printer_info(p->msg_ctx,
3671 Printer, info,
3672 pinfo2, snum,
3673 &option_type, id,
3674 mem_ctx)) {
3675 id--;
3677 break;
3679 case JOB_NOTIFY_TYPE:
3681 count = print_queue_status(p->msg_ctx, snum, &queue,
3682 &status);
3684 for (j = 0; j < count; j++) {
3685 uint32_t jobid;
3686 jobid = sysjob_to_jobid_pdb(pdb,
3687 queue[j].sysjob);
3688 if (jobid == (uint32_t)-1) {
3689 DEBUG(2, ("ignoring untracked job %d\n",
3690 queue[j].sysjob));
3691 continue;
3693 /* FIXME check return value */
3694 construct_notify_jobs_info(p->msg_ctx,
3695 &queue[j], info,
3696 pinfo2, snum,
3697 &option_type,
3698 jobid,
3699 mem_ctx);
3702 SAFE_FREE(queue);
3703 break;
3708 * Debugging information, don't delete.
3711 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3712 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3713 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3715 for (i=0; i<info->count; i++) {
3716 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3717 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3718 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3722 talloc_free(pinfo2);
3723 result = WERR_OK;
3724 err_pdb_drop:
3725 release_print_db(pdb);
3726 return result;
3729 /****************************************************************
3730 _spoolss_RouterRefreshPrinterChangeNotify
3731 ****************************************************************/
3733 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3734 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3736 struct spoolss_NotifyInfo *info;
3738 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3739 WERROR result = WERR_BADFID;
3741 /* we always have a spoolss_NotifyInfo struct */
3742 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3743 if (!info) {
3744 result = WERR_NOMEM;
3745 goto done;
3748 *r->out.info = info;
3750 if (!Printer) {
3751 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3752 "Invalid handle (%s:%u:%u).\n",
3753 OUR_HANDLE(r->in.handle)));
3754 goto done;
3757 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3760 * We are now using the change value, and
3761 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3762 * I don't have a global notification system, I'm sending back all the
3763 * information even when _NOTHING_ has changed.
3766 /* We need to keep track of the change value to send back in
3767 RRPCN replies otherwise our updates are ignored. */
3769 Printer->notify.fnpcn = true;
3771 if (Printer->notify.cli_chan != NULL &&
3772 Printer->notify.cli_chan->active_connections > 0) {
3773 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3774 "Saving change value in request [%x]\n",
3775 r->in.change_low));
3776 Printer->notify.change = r->in.change_low;
3779 /* just ignore the spoolss_NotifyOption */
3781 switch (Printer->printer_type) {
3782 case SPLHND_SERVER:
3783 result = printserver_notify_info(p, r->in.handle,
3784 info, p->mem_ctx);
3785 break;
3787 case SPLHND_PRINTER:
3788 result = printer_notify_info(p, r->in.handle,
3789 info, p->mem_ctx);
3790 break;
3793 Printer->notify.fnpcn = false;
3795 done:
3796 return result;
3799 /********************************************************************
3800 ********************************************************************/
3802 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3803 const char *servername,
3804 const char *printername,
3805 const char **printername_p)
3807 /* FIXME: add lp_force_printername() */
3809 if (servername == NULL) {
3810 *printername_p = talloc_strdup(mem_ctx, printername);
3811 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3812 return WERR_OK;
3815 if (servername[0] == '\\' && servername[1] == '\\') {
3816 servername += 2;
3819 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3820 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3822 return WERR_OK;
3825 /********************************************************************
3826 ********************************************************************/
3828 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3829 const char *printername)
3831 if (dm == NULL) {
3832 return;
3835 dm->devicename = talloc_strndup(dm, printername,
3836 MIN(strlen(printername), 31));
3839 /********************************************************************
3840 * construct_printer_info_0
3841 * fill a printer_info_0 struct
3842 ********************************************************************/
3844 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3845 const struct auth_session_info *session_info,
3846 struct messaging_context *msg_ctx,
3847 struct spoolss_PrinterInfo2 *info2,
3848 const char *servername,
3849 struct spoolss_PrinterInfo0 *r,
3850 int snum)
3852 int count;
3853 struct printer_session_counter *session_counter;
3854 struct timeval setuptime;
3855 print_status_struct status;
3856 WERROR result;
3858 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3859 if (!W_ERROR_IS_OK(result)) {
3860 return result;
3863 if (servername) {
3864 r->servername = talloc_strdup(mem_ctx, servername);
3865 W_ERROR_HAVE_NO_MEMORY(r->servername);
3866 } else {
3867 r->servername = NULL;
3870 count = print_queue_length(msg_ctx, snum, &status);
3872 /* check if we already have a counter for this printer */
3873 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3874 if (session_counter->snum == snum)
3875 break;
3878 /* it's the first time, add it to the list */
3879 if (session_counter == NULL) {
3880 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3881 W_ERROR_HAVE_NO_MEMORY(session_counter);
3882 session_counter->snum = snum;
3883 session_counter->counter = 0;
3884 DLIST_ADD(counter_list, session_counter);
3887 /* increment it */
3888 session_counter->counter++;
3890 r->cjobs = count;
3891 r->total_jobs = 0;
3892 r->total_bytes = 0;
3894 get_startup_time(&setuptime);
3895 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3897 /* JFM:
3898 * the global_counter should be stored in a TDB as it's common to all the clients
3899 * and should be zeroed on samba startup
3901 r->global_counter = session_counter->counter;
3902 r->total_pages = 0;
3903 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3904 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3905 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3906 r->free_build = SPOOLSS_RELEASE_BUILD;
3907 r->spooling = 0;
3908 r->max_spooling = 0;
3909 r->session_counter = session_counter->counter;
3910 r->num_error_out_of_paper = 0x0;
3911 r->num_error_not_ready = 0x0; /* number of print failure */
3912 r->job_error = 0x0;
3913 r->number_of_processors = 0x1;
3914 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3915 r->high_part_total_bytes = 0x0;
3917 /* ChangeID in milliseconds*/
3918 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3919 info2->sharename, &r->change_id);
3921 r->last_error = WERR_OK;
3922 r->status = nt_printq_status(status.status);
3923 r->enumerate_network_printers = 0x0;
3924 r->c_setprinter = 0x0;
3925 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3926 r->processor_level = 0x6; /* 6 ???*/
3927 r->ref_ic = 0;
3928 r->reserved2 = 0;
3929 r->reserved3 = 0;
3931 return WERR_OK;
3935 /********************************************************************
3936 * construct_printer_info1
3937 * fill a spoolss_PrinterInfo1 struct
3938 ********************************************************************/
3940 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3941 const struct spoolss_PrinterInfo2 *info2,
3942 uint32_t flags,
3943 const char *servername,
3944 struct spoolss_PrinterInfo1 *r,
3945 int snum)
3947 WERROR result;
3949 r->flags = flags;
3951 if (info2->comment == NULL || info2->comment[0] == '\0') {
3952 r->comment = lp_comment(mem_ctx, snum);
3953 } else {
3954 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3956 W_ERROR_HAVE_NO_MEMORY(r->comment);
3958 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3959 if (!W_ERROR_IS_OK(result)) {
3960 return result;
3963 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3964 r->name,
3965 info2->drivername,
3966 r->comment);
3967 W_ERROR_HAVE_NO_MEMORY(r->description);
3969 return WERR_OK;
3972 /********************************************************************
3973 * construct_printer_info2
3974 * fill a spoolss_PrinterInfo2 struct
3975 ********************************************************************/
3977 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3978 struct messaging_context *msg_ctx,
3979 const struct spoolss_PrinterInfo2 *info2,
3980 const char *servername,
3981 struct spoolss_PrinterInfo2 *r,
3982 int snum)
3984 int count;
3985 print_status_struct status;
3986 WERROR result;
3988 count = print_queue_length(msg_ctx, snum, &status);
3990 if (servername) {
3991 r->servername = talloc_strdup(mem_ctx, servername);
3992 W_ERROR_HAVE_NO_MEMORY(r->servername);
3993 } else {
3994 r->servername = NULL;
3997 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3998 if (!W_ERROR_IS_OK(result)) {
3999 return result;
4002 r->sharename = lp_servicename(mem_ctx, snum);
4003 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4004 r->portname = talloc_strdup(mem_ctx, info2->portname);
4005 W_ERROR_HAVE_NO_MEMORY(r->portname);
4006 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4007 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4009 if (info2->comment[0] == '\0') {
4010 r->comment = lp_comment(mem_ctx, snum);
4011 } else {
4012 r->comment = talloc_strdup(mem_ctx, info2->comment);
4014 W_ERROR_HAVE_NO_MEMORY(r->comment);
4016 r->location = talloc_strdup(mem_ctx, info2->location);
4017 if (info2->location[0] == '\0') {
4018 const char *loc = NULL;
4019 NTSTATUS nt_status;
4021 nt_status = printer_list_get_printer(mem_ctx,
4022 info2->sharename,
4023 NULL,
4024 &loc,
4025 NULL);
4026 if (NT_STATUS_IS_OK(nt_status)) {
4027 if (loc != NULL) {
4028 r->location = talloc_strdup(mem_ctx, loc);
4032 W_ERROR_HAVE_NO_MEMORY(r->location);
4034 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4035 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4036 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4037 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4038 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4039 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4040 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4041 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4043 r->attributes = info2->attributes;
4045 r->priority = info2->priority;
4046 r->defaultpriority = info2->defaultpriority;
4047 r->starttime = info2->starttime;
4048 r->untiltime = info2->untiltime;
4049 r->status = nt_printq_status(status.status);
4050 r->cjobs = count;
4051 r->averageppm = info2->averageppm;
4053 if (info2->devmode != NULL) {
4054 result = copy_devicemode(mem_ctx,
4055 info2->devmode,
4056 &r->devmode);
4057 if (!W_ERROR_IS_OK(result)) {
4058 return result;
4060 } else if (lp_default_devmode(snum)) {
4061 result = spoolss_create_default_devmode(mem_ctx,
4062 info2->printername,
4063 &r->devmode);
4064 if (!W_ERROR_IS_OK(result)) {
4065 return result;
4067 } else {
4068 r->devmode = NULL;
4069 DEBUG(8,("Returning NULL Devicemode!\n"));
4072 compose_devicemode_devicename(r->devmode, r->printername);
4074 r->secdesc = NULL;
4076 if (info2->secdesc != NULL) {
4077 /* don't use talloc_steal() here unless you do a deep steal of all
4078 the SEC_DESC members */
4080 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4083 return WERR_OK;
4086 /********************************************************************
4087 * construct_printer_info3
4088 * fill a spoolss_PrinterInfo3 struct
4089 ********************************************************************/
4091 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4092 const struct spoolss_PrinterInfo2 *info2,
4093 const char *servername,
4094 struct spoolss_PrinterInfo3 *r,
4095 int snum)
4097 /* These are the components of the SD we are returning. */
4099 if (info2->secdesc != NULL) {
4100 /* don't use talloc_steal() here unless you do a deep steal of all
4101 the SEC_DESC members */
4103 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4104 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4107 return WERR_OK;
4110 /********************************************************************
4111 * construct_printer_info4
4112 * fill a spoolss_PrinterInfo4 struct
4113 ********************************************************************/
4115 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4116 const struct spoolss_PrinterInfo2 *info2,
4117 const char *servername,
4118 struct spoolss_PrinterInfo4 *r,
4119 int snum)
4121 WERROR result;
4123 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4124 if (!W_ERROR_IS_OK(result)) {
4125 return result;
4128 if (servername) {
4129 r->servername = talloc_strdup(mem_ctx, servername);
4130 W_ERROR_HAVE_NO_MEMORY(r->servername);
4131 } else {
4132 r->servername = NULL;
4135 r->attributes = info2->attributes;
4137 return WERR_OK;
4140 /********************************************************************
4141 * construct_printer_info5
4142 * fill a spoolss_PrinterInfo5 struct
4143 ********************************************************************/
4145 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4146 const struct spoolss_PrinterInfo2 *info2,
4147 const char *servername,
4148 struct spoolss_PrinterInfo5 *r,
4149 int snum)
4151 WERROR result;
4153 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4154 if (!W_ERROR_IS_OK(result)) {
4155 return result;
4158 r->portname = talloc_strdup(mem_ctx, info2->portname);
4159 W_ERROR_HAVE_NO_MEMORY(r->portname);
4161 r->attributes = info2->attributes;
4163 /* these two are not used by NT+ according to MSDN */
4164 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4165 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4167 return WERR_OK;
4170 /********************************************************************
4171 * construct_printer_info_6
4172 * fill a spoolss_PrinterInfo6 struct
4173 ********************************************************************/
4175 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4176 struct messaging_context *msg_ctx,
4177 const struct spoolss_PrinterInfo2 *info2,
4178 const char *servername,
4179 struct spoolss_PrinterInfo6 *r,
4180 int snum)
4182 print_status_struct status;
4184 print_queue_length(msg_ctx, snum, &status);
4186 r->status = nt_printq_status(status.status);
4188 return WERR_OK;
4191 /********************************************************************
4192 * construct_printer_info7
4193 * fill a spoolss_PrinterInfo7 struct
4194 ********************************************************************/
4196 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4197 struct messaging_context *msg_ctx,
4198 const char *servername,
4199 struct spoolss_PrinterInfo7 *r,
4200 int snum)
4202 const struct auth_session_info *session_info;
4203 char *printer;
4204 WERROR werr;
4205 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4206 if (tmp_ctx == NULL) {
4207 return WERR_NOMEM;
4210 session_info = get_session_info_system();
4211 SMB_ASSERT(session_info != NULL);
4213 printer = lp_servicename(tmp_ctx, snum);
4214 if (printer == NULL) {
4215 DEBUG(0, ("invalid printer snum %d\n", snum));
4216 werr = WERR_INVALID_PARAM;
4217 goto out_tmp_free;
4220 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4221 servername, printer, NULL)) {
4222 struct GUID guid;
4223 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4224 printer, &guid);
4225 if (!W_ERROR_IS_OK(werr)) {
4226 goto out_tmp_free;
4228 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4229 r->action = DSPRINT_PUBLISH;
4230 } else {
4231 r->guid = talloc_strdup(mem_ctx, "");
4232 r->action = DSPRINT_UNPUBLISH;
4234 if (r->guid == NULL) {
4235 werr = WERR_NOMEM;
4236 goto out_tmp_free;
4239 werr = WERR_OK;
4240 out_tmp_free:
4241 talloc_free(tmp_ctx);
4242 return werr;
4245 /********************************************************************
4246 * construct_printer_info8
4247 * fill a spoolss_PrinterInfo8 struct
4248 ********************************************************************/
4250 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4251 const struct spoolss_PrinterInfo2 *info2,
4252 const char *servername,
4253 struct spoolss_DeviceModeInfo *r,
4254 int snum)
4256 WERROR result;
4257 const char *printername;
4259 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4260 if (!W_ERROR_IS_OK(result)) {
4261 return result;
4264 if (info2->devmode != NULL) {
4265 result = copy_devicemode(mem_ctx,
4266 info2->devmode,
4267 &r->devmode);
4268 if (!W_ERROR_IS_OK(result)) {
4269 return result;
4271 } else if (lp_default_devmode(snum)) {
4272 result = spoolss_create_default_devmode(mem_ctx,
4273 info2->printername,
4274 &r->devmode);
4275 if (!W_ERROR_IS_OK(result)) {
4276 return result;
4278 } else {
4279 r->devmode = NULL;
4280 DEBUG(8,("Returning NULL Devicemode!\n"));
4283 compose_devicemode_devicename(r->devmode, printername);
4285 return WERR_OK;
4289 /********************************************************************
4290 ********************************************************************/
4292 static bool snum_is_shared_printer(int snum)
4294 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_printable(snum));
4297 /********************************************************************
4298 Spoolss_enumprinters.
4299 ********************************************************************/
4301 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4302 const struct auth_session_info *session_info,
4303 struct messaging_context *msg_ctx,
4304 const char *servername,
4305 uint32_t level,
4306 uint32_t flags,
4307 union spoolss_PrinterInfo **info_p,
4308 uint32_t *count_p)
4310 int snum;
4311 int n_services = lp_numservices();
4312 union spoolss_PrinterInfo *info = NULL;
4313 uint32_t count = 0;
4314 WERROR result = WERR_OK;
4315 struct dcerpc_binding_handle *b = NULL;
4316 TALLOC_CTX *tmp_ctx = NULL;
4318 tmp_ctx = talloc_new(mem_ctx);
4319 if (!tmp_ctx) {
4320 return WERR_NOMEM;
4323 *count_p = 0;
4324 *info_p = NULL;
4326 for (snum = 0; snum < n_services; snum++) {
4328 const char *printer;
4329 struct spoolss_PrinterInfo2 *info2;
4331 if (!snum_is_shared_printer(snum)) {
4332 continue;
4335 printer = lp_const_servicename(snum);
4337 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4338 printer, snum));
4340 if (b == NULL) {
4341 result = winreg_printer_binding_handle(tmp_ctx,
4342 session_info,
4343 msg_ctx,
4344 &b);
4345 if (!W_ERROR_IS_OK(result)) {
4346 goto out;
4350 result = winreg_create_printer(tmp_ctx, b,
4351 printer);
4352 if (!W_ERROR_IS_OK(result)) {
4353 goto out;
4356 info = talloc_realloc(tmp_ctx, info,
4357 union spoolss_PrinterInfo,
4358 count + 1);
4359 if (!info) {
4360 result = WERR_NOMEM;
4361 goto out;
4364 result = winreg_get_printer(tmp_ctx, b,
4365 printer, &info2);
4366 if (!W_ERROR_IS_OK(result)) {
4367 goto out;
4370 switch (level) {
4371 case 0:
4372 result = construct_printer_info0(info, session_info,
4373 msg_ctx, info2,
4374 servername,
4375 &info[count].info0, snum);
4376 break;
4377 case 1:
4378 result = construct_printer_info1(info, info2, flags,
4379 servername,
4380 &info[count].info1, snum);
4381 break;
4382 case 2:
4383 result = construct_printer_info2(info, msg_ctx, info2,
4384 servername,
4385 &info[count].info2, snum);
4386 break;
4387 case 4:
4388 result = construct_printer_info4(info, info2,
4389 servername,
4390 &info[count].info4, snum);
4391 break;
4392 case 5:
4393 result = construct_printer_info5(info, info2,
4394 servername,
4395 &info[count].info5, snum);
4396 break;
4398 default:
4399 result = WERR_UNKNOWN_LEVEL;
4400 goto out;
4403 if (!W_ERROR_IS_OK(result)) {
4404 goto out;
4407 count++;
4410 out:
4411 if (W_ERROR_IS_OK(result)) {
4412 *info_p = talloc_move(mem_ctx, &info);
4413 *count_p = count;
4416 talloc_free(tmp_ctx);
4418 return result;
4421 /********************************************************************
4422 * handle enumeration of printers at level 0
4423 ********************************************************************/
4425 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4426 const struct auth_session_info *session_info,
4427 struct messaging_context *msg_ctx,
4428 uint32_t flags,
4429 const char *servername,
4430 union spoolss_PrinterInfo **info,
4431 uint32_t *count)
4433 DEBUG(4,("enum_all_printers_info_0\n"));
4435 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4436 servername, 0, flags, info, count);
4440 /********************************************************************
4441 ********************************************************************/
4443 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4444 const struct auth_session_info *session_info,
4445 struct messaging_context *msg_ctx,
4446 const char *servername,
4447 uint32_t flags,
4448 union spoolss_PrinterInfo **info,
4449 uint32_t *count)
4451 DEBUG(4,("enum_all_printers_info_1\n"));
4453 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4454 servername, 1, flags, info, count);
4457 /********************************************************************
4458 enum_all_printers_info_1_local.
4459 *********************************************************************/
4461 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4462 const struct auth_session_info *session_info,
4463 struct messaging_context *msg_ctx,
4464 const char *servername,
4465 union spoolss_PrinterInfo **info,
4466 uint32_t *count)
4468 DEBUG(4,("enum_all_printers_info_1_local\n"));
4470 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4471 servername, PRINTER_ENUM_ICON8, info, count);
4474 /********************************************************************
4475 enum_all_printers_info_1_name.
4476 *********************************************************************/
4478 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4479 const struct auth_session_info *session_info,
4480 struct messaging_context *msg_ctx,
4481 const char *servername,
4482 union spoolss_PrinterInfo **info,
4483 uint32_t *count)
4485 const char *s = servername;
4487 DEBUG(4,("enum_all_printers_info_1_name\n"));
4489 if (servername != NULL &&
4490 (servername[0] == '\\') && (servername[1] == '\\')) {
4491 s = servername + 2;
4494 if (!is_myname_or_ipaddr(s)) {
4495 return WERR_INVALID_NAME;
4498 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4499 servername, PRINTER_ENUM_ICON8, info, count);
4502 /********************************************************************
4503 enum_all_printers_info_1_network.
4504 *********************************************************************/
4506 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4507 const struct auth_session_info *session_info,
4508 struct messaging_context *msg_ctx,
4509 const char *servername,
4510 union spoolss_PrinterInfo **info,
4511 uint32_t *count)
4513 const char *s = servername;
4515 DEBUG(4,("enum_all_printers_info_1_network\n"));
4517 /* If we respond to a enum_printers level 1 on our name with flags
4518 set to PRINTER_ENUM_REMOTE with a list of printers then these
4519 printers incorrectly appear in the APW browse list.
4520 Specifically the printers for the server appear at the workgroup
4521 level where all the other servers in the domain are
4522 listed. Windows responds to this call with a
4523 WERR_CAN_NOT_COMPLETE so we should do the same. */
4525 if (servername != NULL &&
4526 (servername[0] == '\\') && (servername[1] == '\\')) {
4527 s = servername + 2;
4530 if (is_myname_or_ipaddr(s)) {
4531 return WERR_CAN_NOT_COMPLETE;
4534 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4535 servername, PRINTER_ENUM_NAME, info, count);
4538 /********************************************************************
4539 * api_spoolss_enumprinters
4541 * called from api_spoolss_enumprinters (see this to understand)
4542 ********************************************************************/
4544 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4545 const struct auth_session_info *session_info,
4546 struct messaging_context *msg_ctx,
4547 const char *servername,
4548 union spoolss_PrinterInfo **info,
4549 uint32_t *count)
4551 DEBUG(4,("enum_all_printers_info_2\n"));
4553 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4554 servername, 2, 0, info, count);
4557 /********************************************************************
4558 * handle enumeration of printers at level 1
4559 ********************************************************************/
4561 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4562 const struct auth_session_info *session_info,
4563 struct messaging_context *msg_ctx,
4564 uint32_t flags,
4565 const char *servername,
4566 union spoolss_PrinterInfo **info,
4567 uint32_t *count)
4569 /* Not all the flags are equals */
4571 if (flags & PRINTER_ENUM_LOCAL) {
4572 return enum_all_printers_info_1_local(mem_ctx, session_info,
4573 msg_ctx, servername, info, count);
4576 if (flags & PRINTER_ENUM_NAME) {
4577 return enum_all_printers_info_1_name(mem_ctx, session_info,
4578 msg_ctx, servername, info,
4579 count);
4582 if (flags & PRINTER_ENUM_NETWORK) {
4583 return enum_all_printers_info_1_network(mem_ctx, session_info,
4584 msg_ctx, servername, info,
4585 count);
4588 return WERR_OK; /* NT4sp5 does that */
4591 /********************************************************************
4592 * handle enumeration of printers at level 2
4593 ********************************************************************/
4595 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4596 const struct auth_session_info *session_info,
4597 struct messaging_context *msg_ctx,
4598 uint32_t flags,
4599 const char *servername,
4600 union spoolss_PrinterInfo **info,
4601 uint32_t *count)
4603 if (flags & PRINTER_ENUM_LOCAL) {
4605 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4606 servername,
4607 info, count);
4610 if (flags & PRINTER_ENUM_NAME) {
4611 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4612 return WERR_INVALID_NAME;
4615 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4616 servername,
4617 info, count);
4620 if (flags & PRINTER_ENUM_REMOTE) {
4621 return WERR_UNKNOWN_LEVEL;
4624 return WERR_OK;
4627 /********************************************************************
4628 * handle enumeration of printers at level 4
4629 ********************************************************************/
4631 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4632 const struct auth_session_info *session_info,
4633 struct messaging_context *msg_ctx,
4634 uint32_t flags,
4635 const char *servername,
4636 union spoolss_PrinterInfo **info,
4637 uint32_t *count)
4639 DEBUG(4,("enum_all_printers_info_4\n"));
4641 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4642 servername, 4, flags, info, count);
4646 /********************************************************************
4647 * handle enumeration of printers at level 5
4648 ********************************************************************/
4650 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4651 const struct auth_session_info *session_info,
4652 struct messaging_context *msg_ctx,
4653 uint32_t flags,
4654 const char *servername,
4655 union spoolss_PrinterInfo **info,
4656 uint32_t *count)
4658 DEBUG(4,("enum_all_printers_info_5\n"));
4660 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4661 servername, 5, flags, info, count);
4664 /****************************************************************
4665 _spoolss_EnumPrinters
4666 ****************************************************************/
4668 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4669 struct spoolss_EnumPrinters *r)
4671 const struct auth_session_info *session_info = get_session_info_system();
4672 WERROR result;
4674 /* that's an [in out] buffer */
4676 if (!r->in.buffer && (r->in.offered != 0)) {
4677 return WERR_INVALID_PARAM;
4680 DEBUG(4,("_spoolss_EnumPrinters\n"));
4682 *r->out.needed = 0;
4683 *r->out.count = 0;
4684 *r->out.info = NULL;
4687 * Level 1:
4688 * flags==PRINTER_ENUM_NAME
4689 * if name=="" then enumerates all printers
4690 * if name!="" then enumerate the printer
4691 * flags==PRINTER_ENUM_REMOTE
4692 * name is NULL, enumerate printers
4693 * Level 2: name!="" enumerates printers, name can't be NULL
4694 * Level 3: doesn't exist
4695 * Level 4: does a local registry lookup
4696 * Level 5: same as Level 2
4699 if (r->in.server && r->in.server[0] == '\0') {
4700 r->in.server = NULL;
4703 switch (r->in.level) {
4704 case 0:
4705 result = enumprinters_level0(p->mem_ctx, session_info,
4706 p->msg_ctx, r->in.flags,
4707 r->in.server,
4708 r->out.info, r->out.count);
4709 break;
4710 case 1:
4711 result = enumprinters_level1(p->mem_ctx, session_info,
4712 p->msg_ctx, r->in.flags,
4713 r->in.server,
4714 r->out.info, r->out.count);
4715 break;
4716 case 2:
4717 result = enumprinters_level2(p->mem_ctx, session_info,
4718 p->msg_ctx, r->in.flags,
4719 r->in.server,
4720 r->out.info, r->out.count);
4721 break;
4722 case 4:
4723 result = enumprinters_level4(p->mem_ctx, session_info,
4724 p->msg_ctx, r->in.flags,
4725 r->in.server,
4726 r->out.info, r->out.count);
4727 break;
4728 case 5:
4729 result = enumprinters_level5(p->mem_ctx, session_info,
4730 p->msg_ctx, r->in.flags,
4731 r->in.server,
4732 r->out.info, r->out.count);
4733 break;
4734 default:
4735 return WERR_UNKNOWN_LEVEL;
4738 if (!W_ERROR_IS_OK(result)) {
4739 return result;
4742 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4743 spoolss_EnumPrinters,
4744 *r->out.info, r->in.level,
4745 *r->out.count);
4746 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4747 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4749 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4752 /****************************************************************
4753 _spoolss_GetPrinter
4754 ****************************************************************/
4756 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4757 struct spoolss_GetPrinter *r)
4759 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4760 struct spoolss_PrinterInfo2 *info2 = NULL;
4761 WERROR result = WERR_OK;
4762 int snum;
4764 /* that's an [in out] buffer */
4766 if (!r->in.buffer && (r->in.offered != 0)) {
4767 return WERR_INVALID_PARAM;
4770 *r->out.needed = 0;
4772 if (Printer == NULL) {
4773 return WERR_BADFID;
4776 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4777 return WERR_BADFID;
4780 result = winreg_get_printer_internal(p->mem_ctx,
4781 get_session_info_system(),
4782 p->msg_ctx,
4783 lp_const_servicename(snum),
4784 &info2);
4785 if (!W_ERROR_IS_OK(result)) {
4786 goto out;
4789 switch (r->in.level) {
4790 case 0:
4791 result = construct_printer_info0(p->mem_ctx,
4792 get_session_info_system(),
4793 p->msg_ctx,
4794 info2,
4795 Printer->servername,
4796 &r->out.info->info0,
4797 snum);
4798 break;
4799 case 1:
4800 result = construct_printer_info1(p->mem_ctx, info2,
4801 PRINTER_ENUM_ICON8,
4802 Printer->servername,
4803 &r->out.info->info1, snum);
4804 break;
4805 case 2:
4806 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4807 Printer->servername,
4808 &r->out.info->info2, snum);
4809 break;
4810 case 3:
4811 result = construct_printer_info3(p->mem_ctx, info2,
4812 Printer->servername,
4813 &r->out.info->info3, snum);
4814 break;
4815 case 4:
4816 result = construct_printer_info4(p->mem_ctx, info2,
4817 Printer->servername,
4818 &r->out.info->info4, snum);
4819 break;
4820 case 5:
4821 result = construct_printer_info5(p->mem_ctx, info2,
4822 Printer->servername,
4823 &r->out.info->info5, snum);
4824 break;
4825 case 6:
4826 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4827 Printer->servername,
4828 &r->out.info->info6, snum);
4829 break;
4830 case 7:
4831 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4832 Printer->servername,
4833 &r->out.info->info7, snum);
4834 break;
4835 case 8:
4836 result = construct_printer_info8(p->mem_ctx, info2,
4837 Printer->servername,
4838 &r->out.info->info8, snum);
4839 break;
4840 default:
4841 result = WERR_UNKNOWN_LEVEL;
4842 break;
4844 TALLOC_FREE(info2);
4846 out:
4847 if (!W_ERROR_IS_OK(result)) {
4848 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4849 r->in.level, win_errstr(result)));
4850 TALLOC_FREE(r->out.info);
4851 return result;
4854 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4855 r->out.info, r->in.level);
4856 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4858 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4861 /********************************************************************
4862 ********************************************************************/
4864 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4865 do { \
4866 if (in && strlen(in)) { \
4867 out = talloc_strdup(mem_ctx, in); \
4868 } else { \
4869 out = talloc_strdup(mem_ctx, ""); \
4871 W_ERROR_HAVE_NO_MEMORY(out); \
4872 } while (0);
4874 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4875 do { \
4876 if (in && strlen(in)) { \
4877 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4878 } else { \
4879 out = talloc_strdup(mem_ctx, ""); \
4881 W_ERROR_HAVE_NO_MEMORY(out); \
4882 } while (0);
4884 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4885 const char **string_array,
4886 const char ***presult,
4887 const char *cservername,
4888 const char *arch,
4889 int version)
4891 int i, num_strings = 0;
4892 const char **array = NULL;
4894 if (string_array == NULL) {
4895 return WERR_INVALID_PARAMETER;
4898 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4899 const char *str = NULL;
4901 if (cservername == NULL || arch == NULL) {
4902 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4903 } else {
4904 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4907 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4908 TALLOC_FREE(array);
4909 return WERR_NOMEM;
4913 if (i > 0) {
4914 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4915 &array, &num_strings);
4918 if (presult != NULL) {
4919 *presult = array;
4920 } else {
4921 talloc_free(array);
4924 return WERR_OK;
4927 /********************************************************************
4928 * fill a spoolss_DriverInfo1 struct
4929 ********************************************************************/
4931 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4932 struct spoolss_DriverInfo1 *r,
4933 const struct spoolss_DriverInfo8 *driver,
4934 const char *servername)
4936 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4937 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4939 return WERR_OK;
4942 /********************************************************************
4943 * fill a spoolss_DriverInfo2 struct
4944 ********************************************************************/
4946 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4947 struct spoolss_DriverInfo2 *r,
4948 const struct spoolss_DriverInfo8 *driver,
4949 const char *servername)
4952 const char *cservername = canon_servername(servername);
4954 r->version = driver->version;
4956 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4957 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4958 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4959 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4961 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4962 driver->architecture,
4963 driver->version,
4964 driver->driver_path,
4965 r->driver_path);
4967 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4968 driver->architecture,
4969 driver->version,
4970 driver->data_file,
4971 r->data_file);
4973 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4974 driver->architecture,
4975 driver->version,
4976 driver->config_file,
4977 r->config_file);
4979 return WERR_OK;
4982 /********************************************************************
4983 * fill a spoolss_DriverInfo3 struct
4984 ********************************************************************/
4986 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4987 struct spoolss_DriverInfo3 *r,
4988 const struct spoolss_DriverInfo8 *driver,
4989 const char *servername)
4991 const char *cservername = canon_servername(servername);
4993 r->version = driver->version;
4995 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4996 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4997 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4998 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5000 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001 driver->architecture,
5002 driver->version,
5003 driver->driver_path,
5004 r->driver_path);
5006 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5007 driver->architecture,
5008 driver->version,
5009 driver->data_file,
5010 r->data_file);
5012 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013 driver->architecture,
5014 driver->version,
5015 driver->config_file,
5016 r->config_file);
5018 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5019 driver->architecture,
5020 driver->version,
5021 driver->help_file,
5022 r->help_file);
5024 FILL_DRIVER_STRING(mem_ctx,
5025 driver->monitor_name,
5026 r->monitor_name);
5028 FILL_DRIVER_STRING(mem_ctx,
5029 driver->default_datatype,
5030 r->default_datatype);
5032 return string_array_from_driver_info(mem_ctx,
5033 driver->dependent_files,
5034 &r->dependent_files,
5035 cservername,
5036 driver->architecture,
5037 driver->version);
5040 /********************************************************************
5041 * fill a spoolss_DriverInfo4 struct
5042 ********************************************************************/
5044 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5045 struct spoolss_DriverInfo4 *r,
5046 const struct spoolss_DriverInfo8 *driver,
5047 const char *servername)
5049 const char *cservername = canon_servername(servername);
5050 WERROR result;
5052 r->version = driver->version;
5054 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5055 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5056 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5057 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5059 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5060 driver->architecture,
5061 driver->version,
5062 driver->driver_path,
5063 r->driver_path);
5065 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5066 driver->architecture,
5067 driver->version,
5068 driver->data_file,
5069 r->data_file);
5071 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5072 driver->architecture,
5073 driver->version,
5074 driver->config_file,
5075 r->config_file);
5077 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5078 driver->architecture,
5079 driver->version,
5080 driver->help_file,
5081 r->help_file);
5083 result = string_array_from_driver_info(mem_ctx,
5084 driver->dependent_files,
5085 &r->dependent_files,
5086 cservername,
5087 driver->architecture,
5088 driver->version);
5089 if (!W_ERROR_IS_OK(result)) {
5090 return result;
5093 FILL_DRIVER_STRING(mem_ctx,
5094 driver->monitor_name,
5095 r->monitor_name);
5097 FILL_DRIVER_STRING(mem_ctx,
5098 driver->default_datatype,
5099 r->default_datatype);
5102 result = string_array_from_driver_info(mem_ctx,
5103 driver->previous_names,
5104 &r->previous_names,
5105 NULL, NULL, 0);
5107 return result;
5110 /********************************************************************
5111 * fill a spoolss_DriverInfo5 struct
5112 ********************************************************************/
5114 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5115 struct spoolss_DriverInfo5 *r,
5116 const struct spoolss_DriverInfo8 *driver,
5117 const char *servername)
5119 const char *cservername = canon_servername(servername);
5121 r->version = driver->version;
5123 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5124 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5125 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5126 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5128 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5129 driver->architecture,
5130 driver->version,
5131 driver->driver_path,
5132 r->driver_path);
5134 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5135 driver->architecture,
5136 driver->version,
5137 driver->data_file,
5138 r->data_file);
5140 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5141 driver->architecture,
5142 driver->version,
5143 driver->config_file,
5144 r->config_file);
5146 r->driver_attributes = 0;
5147 r->config_version = 0;
5148 r->driver_version = 0;
5150 return WERR_OK;
5152 /********************************************************************
5153 * fill a spoolss_DriverInfo6 struct
5154 ********************************************************************/
5156 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5157 struct spoolss_DriverInfo6 *r,
5158 const struct spoolss_DriverInfo8 *driver,
5159 const char *servername)
5161 const char *cservername = canon_servername(servername);
5162 WERROR result;
5164 r->version = driver->version;
5166 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5167 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5168 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5169 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5171 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5172 driver->architecture,
5173 driver->version,
5174 driver->driver_path,
5175 r->driver_path);
5177 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5178 driver->architecture,
5179 driver->version,
5180 driver->data_file,
5181 r->data_file);
5183 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5184 driver->architecture,
5185 driver->version,
5186 driver->config_file,
5187 r->config_file);
5189 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5190 driver->architecture,
5191 driver->version,
5192 driver->help_file,
5193 r->help_file);
5195 FILL_DRIVER_STRING(mem_ctx,
5196 driver->monitor_name,
5197 r->monitor_name);
5199 FILL_DRIVER_STRING(mem_ctx,
5200 driver->default_datatype,
5201 r->default_datatype);
5203 result = string_array_from_driver_info(mem_ctx,
5204 driver->dependent_files,
5205 &r->dependent_files,
5206 cservername,
5207 driver->architecture,
5208 driver->version);
5209 if (!W_ERROR_IS_OK(result)) {
5210 return result;
5213 result = string_array_from_driver_info(mem_ctx,
5214 driver->previous_names,
5215 &r->previous_names,
5216 NULL, NULL, 0);
5217 if (!W_ERROR_IS_OK(result)) {
5218 return result;
5221 r->driver_date = driver->driver_date;
5222 r->driver_version = driver->driver_version;
5224 FILL_DRIVER_STRING(mem_ctx,
5225 driver->manufacturer_name,
5226 r->manufacturer_name);
5227 FILL_DRIVER_STRING(mem_ctx,
5228 driver->manufacturer_url,
5229 r->manufacturer_url);
5230 FILL_DRIVER_STRING(mem_ctx,
5231 driver->hardware_id,
5232 r->hardware_id);
5233 FILL_DRIVER_STRING(mem_ctx,
5234 driver->provider,
5235 r->provider);
5237 return WERR_OK;
5240 /********************************************************************
5241 * fill a spoolss_DriverInfo8 struct
5242 ********************************************************************/
5244 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5245 struct spoolss_DriverInfo8 *r,
5246 const struct spoolss_DriverInfo8 *driver,
5247 const char *servername)
5249 const char *cservername = canon_servername(servername);
5250 WERROR result;
5252 r->version = driver->version;
5254 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5255 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5256 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5257 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5259 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5260 driver->architecture,
5261 driver->version,
5262 driver->driver_path,
5263 r->driver_path);
5265 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5266 driver->architecture,
5267 driver->version,
5268 driver->data_file,
5269 r->data_file);
5271 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5272 driver->architecture,
5273 driver->version,
5274 driver->config_file,
5275 r->config_file);
5277 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5278 driver->architecture,
5279 driver->version,
5280 driver->help_file,
5281 r->help_file);
5283 FILL_DRIVER_STRING(mem_ctx,
5284 driver->monitor_name,
5285 r->monitor_name);
5287 FILL_DRIVER_STRING(mem_ctx,
5288 driver->default_datatype,
5289 r->default_datatype);
5291 result = string_array_from_driver_info(mem_ctx,
5292 driver->dependent_files,
5293 &r->dependent_files,
5294 cservername,
5295 driver->architecture,
5296 driver->version);
5297 if (!W_ERROR_IS_OK(result)) {
5298 return result;
5301 result = string_array_from_driver_info(mem_ctx,
5302 driver->previous_names,
5303 &r->previous_names,
5304 NULL, NULL, 0);
5305 if (!W_ERROR_IS_OK(result)) {
5306 return result;
5309 r->driver_date = driver->driver_date;
5310 r->driver_version = driver->driver_version;
5312 FILL_DRIVER_STRING(mem_ctx,
5313 driver->manufacturer_name,
5314 r->manufacturer_name);
5315 FILL_DRIVER_STRING(mem_ctx,
5316 driver->manufacturer_url,
5317 r->manufacturer_url);
5318 FILL_DRIVER_STRING(mem_ctx,
5319 driver->hardware_id,
5320 r->hardware_id);
5321 FILL_DRIVER_STRING(mem_ctx,
5322 driver->provider,
5323 r->provider);
5325 FILL_DRIVER_STRING(mem_ctx,
5326 driver->print_processor,
5327 r->print_processor);
5328 FILL_DRIVER_STRING(mem_ctx,
5329 driver->vendor_setup,
5330 r->vendor_setup);
5332 result = string_array_from_driver_info(mem_ctx,
5333 driver->color_profiles,
5334 &r->color_profiles,
5335 NULL, NULL, 0);
5336 if (!W_ERROR_IS_OK(result)) {
5337 return result;
5340 FILL_DRIVER_STRING(mem_ctx,
5341 driver->inf_path,
5342 r->inf_path);
5344 r->printer_driver_attributes = driver->printer_driver_attributes;
5346 result = string_array_from_driver_info(mem_ctx,
5347 driver->core_driver_dependencies,
5348 &r->core_driver_dependencies,
5349 NULL, NULL, 0);
5350 if (!W_ERROR_IS_OK(result)) {
5351 return result;
5354 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5355 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5357 return WERR_OK;
5360 #if 0 /* disabled until marshalling issues are resolved - gd */
5361 /********************************************************************
5362 ********************************************************************/
5364 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5365 struct spoolss_DriverFileInfo *r,
5366 const char *cservername,
5367 const char *file_name,
5368 enum spoolss_DriverFileType file_type,
5369 uint32_t file_version)
5371 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5372 cservername, file_name);
5373 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5374 r->file_type = file_type;
5375 r->file_version = file_version;
5377 return WERR_OK;
5380 /********************************************************************
5381 ********************************************************************/
5383 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5384 const struct spoolss_DriverInfo8 *driver,
5385 const char *cservername,
5386 struct spoolss_DriverFileInfo **info_p,
5387 uint32_t *count_p)
5389 struct spoolss_DriverFileInfo *info = NULL;
5390 uint32_t count = 0;
5391 WERROR result;
5392 uint32_t i;
5394 *info_p = NULL;
5395 *count_p = 0;
5397 if (strlen(driver->driver_path)) {
5398 info = talloc_realloc(mem_ctx, info,
5399 struct spoolss_DriverFileInfo,
5400 count + 1);
5401 W_ERROR_HAVE_NO_MEMORY(info);
5402 result = fill_spoolss_DriverFileInfo(info,
5403 &info[count],
5404 cservername,
5405 driver->driver_path,
5406 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5408 W_ERROR_NOT_OK_RETURN(result);
5409 count++;
5412 if (strlen(driver->config_file)) {
5413 info = talloc_realloc(mem_ctx, info,
5414 struct spoolss_DriverFileInfo,
5415 count + 1);
5416 W_ERROR_HAVE_NO_MEMORY(info);
5417 result = fill_spoolss_DriverFileInfo(info,
5418 &info[count],
5419 cservername,
5420 driver->config_file,
5421 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5423 W_ERROR_NOT_OK_RETURN(result);
5424 count++;
5427 if (strlen(driver->data_file)) {
5428 info = talloc_realloc(mem_ctx, info,
5429 struct spoolss_DriverFileInfo,
5430 count + 1);
5431 W_ERROR_HAVE_NO_MEMORY(info);
5432 result = fill_spoolss_DriverFileInfo(info,
5433 &info[count],
5434 cservername,
5435 driver->data_file,
5436 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5438 W_ERROR_NOT_OK_RETURN(result);
5439 count++;
5442 if (strlen(driver->help_file)) {
5443 info = talloc_realloc(mem_ctx, info,
5444 struct spoolss_DriverFileInfo,
5445 count + 1);
5446 W_ERROR_HAVE_NO_MEMORY(info);
5447 result = fill_spoolss_DriverFileInfo(info,
5448 &info[count],
5449 cservername,
5450 driver->help_file,
5451 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5453 W_ERROR_NOT_OK_RETURN(result);
5454 count++;
5457 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5458 info = talloc_realloc(mem_ctx, info,
5459 struct spoolss_DriverFileInfo,
5460 count + 1);
5461 W_ERROR_HAVE_NO_MEMORY(info);
5462 result = fill_spoolss_DriverFileInfo(info,
5463 &info[count],
5464 cservername,
5465 driver->dependent_files[i],
5466 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5468 W_ERROR_NOT_OK_RETURN(result);
5469 count++;
5472 *info_p = info;
5473 *count_p = count;
5475 return WERR_OK;
5478 /********************************************************************
5479 * fill a spoolss_DriverInfo101 struct
5480 ********************************************************************/
5482 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5483 struct spoolss_DriverInfo101 *r,
5484 const struct spoolss_DriverInfo8 *driver,
5485 const char *servername)
5487 const char *cservername = canon_servername(servername);
5488 WERROR result;
5490 r->version = driver->version;
5492 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5493 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5494 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5495 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5497 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5498 cservername,
5499 &r->file_info,
5500 &r->file_count);
5501 if (!W_ERROR_IS_OK(result)) {
5502 return result;
5505 FILL_DRIVER_STRING(mem_ctx,
5506 driver->monitor_name,
5507 r->monitor_name);
5509 FILL_DRIVER_STRING(mem_ctx,
5510 driver->default_datatype,
5511 r->default_datatype);
5513 result = string_array_from_driver_info(mem_ctx,
5514 driver->previous_names,
5515 &r->previous_names,
5516 NULL, NULL, 0);
5517 if (!W_ERROR_IS_OK(result)) {
5518 return result;
5521 r->driver_date = driver->driver_date;
5522 r->driver_version = driver->driver_version;
5524 FILL_DRIVER_STRING(mem_ctx,
5525 driver->manufacturer_name,
5526 r->manufacturer_name);
5527 FILL_DRIVER_STRING(mem_ctx,
5528 driver->manufacturer_url,
5529 r->manufacturer_url);
5530 FILL_DRIVER_STRING(mem_ctx,
5531 driver->hardware_id,
5532 r->hardware_id);
5533 FILL_DRIVER_STRING(mem_ctx,
5534 driver->provider,
5535 r->provider);
5537 return WERR_OK;
5539 #endif
5540 /********************************************************************
5541 ********************************************************************/
5543 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5544 const struct auth_session_info *session_info,
5545 struct messaging_context *msg_ctx,
5546 uint32_t level,
5547 union spoolss_DriverInfo *r,
5548 int snum,
5549 const char *servername,
5550 const char *architecture,
5551 uint32_t version)
5553 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5554 struct spoolss_DriverInfo8 *driver;
5555 WERROR result;
5556 struct dcerpc_binding_handle *b;
5557 TALLOC_CTX *tmp_ctx = NULL;
5559 if (level == 101) {
5560 return WERR_UNKNOWN_LEVEL;
5563 tmp_ctx = talloc_new(mem_ctx);
5564 if (!tmp_ctx) {
5565 return WERR_NOMEM;
5568 result = winreg_printer_binding_handle(tmp_ctx,
5569 session_info,
5570 msg_ctx,
5571 &b);
5572 if (!W_ERROR_IS_OK(result)) {
5573 goto done;
5576 result = winreg_get_printer(tmp_ctx, b,
5577 lp_const_servicename(snum),
5578 &pinfo2);
5580 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5581 win_errstr(result)));
5583 if (!W_ERROR_IS_OK(result)) {
5584 result = WERR_INVALID_PRINTER_NAME;
5585 goto done;
5588 result = winreg_get_driver(tmp_ctx, b,
5589 architecture,
5590 pinfo2->drivername, version, &driver);
5592 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5593 win_errstr(result)));
5595 if (!W_ERROR_IS_OK(result)) {
5597 * Is this a W2k client ?
5600 if (version < 3) {
5601 result = WERR_UNKNOWN_PRINTER_DRIVER;
5602 goto done;
5605 /* Yes - try again with a WinNT driver. */
5606 version = 2;
5607 result = winreg_get_driver(tmp_ctx, b,
5608 architecture,
5609 pinfo2->drivername,
5610 version, &driver);
5611 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5612 win_errstr(result)));
5613 if (!W_ERROR_IS_OK(result)) {
5614 result = WERR_UNKNOWN_PRINTER_DRIVER;
5615 goto done;
5619 /* these are allocated on mem_ctx and not tmp_ctx because they are
5620 * the 'return value' and need to utlive this call */
5621 switch (level) {
5622 case 1:
5623 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5624 break;
5625 case 2:
5626 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5627 break;
5628 case 3:
5629 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5630 break;
5631 case 4:
5632 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5633 break;
5634 case 5:
5635 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5636 break;
5637 case 6:
5638 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5639 break;
5640 case 8:
5641 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5642 break;
5643 #if 0 /* disabled until marshalling issues are resolved - gd */
5644 case 101:
5645 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5646 break;
5647 #endif
5648 default:
5649 result = WERR_UNKNOWN_LEVEL;
5650 break;
5653 done:
5654 talloc_free(tmp_ctx);
5655 return result;
5658 /****************************************************************
5659 _spoolss_GetPrinterDriver2
5660 ****************************************************************/
5662 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5663 struct spoolss_GetPrinterDriver2 *r)
5665 struct printer_handle *printer;
5666 WERROR result;
5667 uint32_t version = r->in.client_major_version;
5669 int snum;
5671 /* that's an [in out] buffer */
5673 if (!r->in.buffer && (r->in.offered != 0)) {
5674 return WERR_INVALID_PARAM;
5677 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5679 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5680 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5681 return WERR_INVALID_PRINTER_NAME;
5684 *r->out.needed = 0;
5685 *r->out.server_major_version = 0;
5686 *r->out.server_minor_version = 0;
5688 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5689 return WERR_BADFID;
5692 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5693 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5694 "downgrading to v3\n"));
5695 version = SPOOLSS_DRIVER_VERSION_200X;
5698 result = construct_printer_driver_info_level(p->mem_ctx,
5699 get_session_info_system(),
5700 p->msg_ctx,
5701 r->in.level, r->out.info,
5702 snum, printer->servername,
5703 r->in.architecture,
5704 version);
5705 if (!W_ERROR_IS_OK(result)) {
5706 TALLOC_FREE(r->out.info);
5707 return result;
5710 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5711 r->out.info, r->in.level);
5712 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5714 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5718 /****************************************************************
5719 _spoolss_StartPagePrinter
5720 ****************************************************************/
5722 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5723 struct spoolss_StartPagePrinter *r)
5725 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5727 if (!Printer) {
5728 DEBUG(3,("_spoolss_StartPagePrinter: "
5729 "Error in startpageprinter printer handle\n"));
5730 return WERR_BADFID;
5733 Printer->page_started = true;
5734 return WERR_OK;
5737 /****************************************************************
5738 _spoolss_EndPagePrinter
5739 ****************************************************************/
5741 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5742 struct spoolss_EndPagePrinter *r)
5744 int snum;
5746 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5748 if (!Printer) {
5749 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5750 OUR_HANDLE(r->in.handle)));
5751 return WERR_BADFID;
5754 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5755 return WERR_BADFID;
5757 Printer->page_started = false;
5758 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5760 return WERR_OK;
5763 /****************************************************************
5764 _spoolss_StartDocPrinter
5765 ****************************************************************/
5767 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5768 struct spoolss_StartDocPrinter *r)
5770 struct spoolss_DocumentInfo1 *info_1;
5771 int snum;
5772 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5773 WERROR werr;
5774 char *rhost;
5775 int rc;
5777 if (!Printer) {
5778 DEBUG(2,("_spoolss_StartDocPrinter: "
5779 "Invalid handle (%s:%u:%u)\n",
5780 OUR_HANDLE(r->in.handle)));
5781 return WERR_BADFID;
5784 if (Printer->jobid) {
5785 DEBUG(2, ("_spoolss_StartDocPrinter: "
5786 "StartDocPrinter called twice! "
5787 "(existing jobid = %d)\n", Printer->jobid));
5788 return WERR_INVALID_HANDLE;
5791 if (r->in.info_ctr->level != 1) {
5792 return WERR_UNKNOWN_LEVEL;
5795 info_1 = r->in.info_ctr->info.info1;
5798 * a nice thing with NT is it doesn't listen to what you tell it.
5799 * when asked to send _only_ RAW datas, it tries to send datas
5800 * in EMF format.
5802 * So I add checks like in NT Server ...
5805 if (info_1->datatype) {
5807 * The v4 driver model used in Windows 8 declares print jobs
5808 * intended to bypass the XPS processing layer by setting
5809 * datatype to "XPS_PASS" instead of "RAW".
5811 if ((strcmp(info_1->datatype, "RAW") != 0)
5812 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5813 *r->out.job_id = 0;
5814 return WERR_INVALID_DATATYPE;
5818 /* get the share number of the printer */
5819 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5820 return WERR_BADFID;
5823 rc = get_remote_hostname(p->remote_address,
5824 &rhost,
5825 p->mem_ctx);
5826 if (rc < 0) {
5827 return WERR_NOMEM;
5829 if (strequal(rhost,"UNKNOWN")) {
5830 rhost = tsocket_address_inet_addr_string(p->remote_address,
5831 p->mem_ctx);
5832 if (rhost == NULL) {
5833 return WERR_NOMEM;
5837 werr = print_job_start(p->session_info,
5838 p->msg_ctx,
5839 rhost,
5840 snum,
5841 info_1->document_name,
5842 info_1->output_file,
5843 Printer->devmode,
5844 &Printer->jobid);
5846 /* An error occured in print_job_start() so return an appropriate
5847 NT error code. */
5849 if (!W_ERROR_IS_OK(werr)) {
5850 return werr;
5853 Printer->document_started = true;
5854 *r->out.job_id = Printer->jobid;
5856 return WERR_OK;
5859 /****************************************************************
5860 _spoolss_EndDocPrinter
5861 ****************************************************************/
5863 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5864 struct spoolss_EndDocPrinter *r)
5866 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5867 NTSTATUS status;
5868 int snum;
5870 if (!Printer) {
5871 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5872 OUR_HANDLE(r->in.handle)));
5873 return WERR_BADFID;
5876 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5877 return WERR_BADFID;
5880 Printer->document_started = false;
5881 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5882 if (!NT_STATUS_IS_OK(status)) {
5883 DEBUG(2, ("_spoolss_EndDocPrinter: "
5884 "print_job_end failed [%s]\n",
5885 nt_errstr(status)));
5888 Printer->jobid = 0;
5889 return ntstatus_to_werror(status);
5892 /****************************************************************
5893 _spoolss_WritePrinter
5894 ****************************************************************/
5896 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5897 struct spoolss_WritePrinter *r)
5899 ssize_t buffer_written;
5900 int snum;
5901 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5903 if (!Printer) {
5904 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5905 OUR_HANDLE(r->in.handle)));
5906 *r->out.num_written = r->in._data_size;
5907 return WERR_BADFID;
5910 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5911 return WERR_BADFID;
5913 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5914 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5915 snum, Printer->jobid,
5916 (const char *)r->in.data.data,
5917 (size_t)r->in._data_size);
5918 if (buffer_written == (ssize_t)-1) {
5919 *r->out.num_written = 0;
5920 if (errno == ENOSPC)
5921 return WERR_NO_SPOOL_SPACE;
5922 else
5923 return WERR_ACCESS_DENIED;
5926 *r->out.num_written = r->in._data_size;
5928 return WERR_OK;
5931 /********************************************************************
5932 * api_spoolss_getprinter
5933 * called from the spoolss dispatcher
5935 ********************************************************************/
5937 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5938 struct pipes_struct *p)
5940 const struct auth_session_info *session_info = p->session_info;
5941 int snum;
5942 WERROR errcode = WERR_BADFUNC;
5943 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5945 if (!Printer) {
5946 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5947 OUR_HANDLE(handle)));
5948 return WERR_BADFID;
5951 if (!get_printer_snum(p, handle, &snum, NULL))
5952 return WERR_BADFID;
5954 switch (command) {
5955 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5956 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5957 break;
5958 case SPOOLSS_PRINTER_CONTROL_RESUME:
5959 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5960 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5961 break;
5962 case SPOOLSS_PRINTER_CONTROL_PURGE:
5963 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5964 break;
5965 default:
5966 return WERR_UNKNOWN_LEVEL;
5969 return errcode;
5973 /****************************************************************
5974 _spoolss_AbortPrinter
5975 * From MSDN: "Deletes printer's spool file if printer is configured
5976 * for spooling"
5977 ****************************************************************/
5979 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5980 struct spoolss_AbortPrinter *r)
5982 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5983 int snum;
5984 WERROR errcode = WERR_OK;
5986 if (!Printer) {
5987 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5988 OUR_HANDLE(r->in.handle)));
5989 return WERR_BADFID;
5992 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5993 return WERR_BADFID;
5995 if (!Printer->document_started) {
5996 return WERR_SPL_NO_STARTDOC;
5999 errcode = print_job_delete(p->session_info,
6000 p->msg_ctx,
6001 snum,
6002 Printer->jobid);
6004 return errcode;
6007 /********************************************************************
6008 * called by spoolss_api_setprinter
6009 * when updating a printer description
6010 ********************************************************************/
6012 static WERROR update_printer_sec(struct policy_handle *handle,
6013 struct pipes_struct *p,
6014 struct sec_desc_buf *secdesc_ctr)
6016 struct spoolss_security_descriptor *new_secdesc = NULL;
6017 struct spoolss_security_descriptor *old_secdesc = NULL;
6018 const char *printer;
6019 WERROR result;
6020 int snum;
6021 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6022 struct dcerpc_binding_handle *b;
6023 TALLOC_CTX *tmp_ctx = NULL;
6025 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6026 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6027 OUR_HANDLE(handle)));
6029 result = WERR_BADFID;
6030 goto done;
6033 if (secdesc_ctr == NULL) {
6034 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6035 result = WERR_INVALID_PARAM;
6036 goto done;
6038 printer = lp_const_servicename(snum);
6040 /* Check the user has permissions to change the security
6041 descriptor. By experimentation with two NT machines, the user
6042 requires Full Access to the printer to change security
6043 information. */
6045 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6046 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6047 result = WERR_ACCESS_DENIED;
6048 goto done;
6051 tmp_ctx = talloc_new(p->mem_ctx);
6052 if (!tmp_ctx) {
6053 return WERR_NOMEM;
6056 result = winreg_printer_binding_handle(tmp_ctx,
6057 get_session_info_system(),
6058 p->msg_ctx,
6059 &b);
6060 if (!W_ERROR_IS_OK(result)) {
6061 goto done;
6064 /* NT seems to like setting the security descriptor even though
6065 nothing may have actually changed. */
6066 result = winreg_get_printer_secdesc(tmp_ctx, b,
6067 printer,
6068 &old_secdesc);
6069 if (!W_ERROR_IS_OK(result)) {
6070 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6071 result = WERR_BADFID;
6072 goto done;
6075 if (DEBUGLEVEL >= 10) {
6076 struct security_acl *the_acl;
6077 int i;
6079 the_acl = old_secdesc->dacl;
6080 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6081 printer, the_acl->num_aces));
6083 for (i = 0; i < the_acl->num_aces; i++) {
6084 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6085 &the_acl->aces[i].trustee),
6086 the_acl->aces[i].access_mask));
6089 the_acl = secdesc_ctr->sd->dacl;
6091 if (the_acl) {
6092 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6093 printer, the_acl->num_aces));
6095 for (i = 0; i < the_acl->num_aces; i++) {
6096 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6097 &the_acl->aces[i].trustee),
6098 the_acl->aces[i].access_mask));
6100 } else {
6101 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6105 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6106 if (new_secdesc == NULL) {
6107 result = WERR_NOMEM;
6108 goto done;
6111 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6112 result = WERR_OK;
6113 goto done;
6116 result = winreg_set_printer_secdesc(tmp_ctx, b,
6117 printer,
6118 new_secdesc);
6120 done:
6121 talloc_free(tmp_ctx);
6122 return result;
6125 /********************************************************************
6126 Canonicalize printer info from a client
6127 ********************************************************************/
6129 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6130 struct spoolss_SetPrinterInfo2 *info2,
6131 int snum)
6133 fstring printername;
6134 const char *p;
6136 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6137 "portname=%s drivername=%s comment=%s location=%s\n",
6138 info2->servername, info2->printername, info2->sharename,
6139 info2->portname, info2->drivername, info2->comment,
6140 info2->location));
6142 /* we force some elements to "correct" values */
6143 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6144 if (info2->servername == NULL) {
6145 return false;
6147 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6148 if (info2->sharename == NULL) {
6149 return false;
6152 /* check to see if we allow printername != sharename */
6153 if (lp_force_printername(snum)) {
6154 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6155 lp_netbios_name(), info2->sharename);
6156 } else {
6157 /* make sure printername is in \\server\printername format */
6158 fstrcpy(printername, info2->printername);
6159 p = printername;
6160 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6161 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6162 p++;
6165 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6166 lp_netbios_name(), p);
6168 if (info2->printername == NULL) {
6169 return false;
6172 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6173 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6175 return true;
6178 /****************************************************************************
6179 ****************************************************************************/
6181 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6183 char *cmd = lp_addport_command(talloc_tos());
6184 char *command = NULL;
6185 int ret;
6186 bool is_print_op = false;
6188 if ( !*cmd ) {
6189 return WERR_ACCESS_DENIED;
6192 command = talloc_asprintf(ctx,
6193 "%s \"%s\" \"%s\"", cmd, portname, uri );
6194 if (!command) {
6195 return WERR_NOMEM;
6198 if ( token )
6199 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6201 DEBUG(10,("Running [%s]\n", command));
6203 /********* BEGIN SePrintOperatorPrivilege **********/
6205 if ( is_print_op )
6206 become_root();
6208 ret = smbrun(command, NULL);
6210 if ( is_print_op )
6211 unbecome_root();
6213 /********* END SePrintOperatorPrivilege **********/
6215 DEBUGADD(10,("returned [%d]\n", ret));
6217 TALLOC_FREE(command);
6219 if ( ret != 0 ) {
6220 return WERR_ACCESS_DENIED;
6223 return WERR_OK;
6226 /****************************************************************************
6227 ****************************************************************************/
6229 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6230 int snum)
6233 * As we do not know if we are embedded in the file server process
6234 * or not, we have to pretend that all shares are in use.
6236 return true;
6239 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6240 struct spoolss_SetPrinterInfo2 *info2,
6241 const char *remote_machine,
6242 struct messaging_context *msg_ctx)
6244 char *cmd = lp_addprinter_command(talloc_tos());
6245 char **qlines;
6246 char *command = NULL;
6247 int numlines;
6248 int ret;
6249 int fd;
6250 bool is_print_op = false;
6252 if (!remote_machine) {
6253 return false;
6256 command = talloc_asprintf(ctx,
6257 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6258 cmd, info2->printername, info2->sharename,
6259 info2->portname, info2->drivername,
6260 info2->location, info2->comment, remote_machine);
6261 if (!command) {
6262 return false;
6265 if ( token )
6266 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6268 DEBUG(10,("Running [%s]\n", command));
6270 /********* BEGIN SePrintOperatorPrivilege **********/
6272 if ( is_print_op )
6273 become_root();
6275 if ( (ret = smbrun(command, &fd)) == 0 ) {
6276 /* Tell everyone we updated smb.conf. */
6277 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6280 if ( is_print_op )
6281 unbecome_root();
6283 /********* END SePrintOperatorPrivilege **********/
6285 DEBUGADD(10,("returned [%d]\n", ret));
6287 TALLOC_FREE(command);
6289 if ( ret != 0 ) {
6290 if (fd != -1)
6291 close(fd);
6292 return false;
6295 /* reload our services immediately */
6296 become_root();
6297 reload_services(NULL, spoolss_conn_snum_used, false);
6298 unbecome_root();
6300 numlines = 0;
6301 /* Get lines and convert them back to dos-codepage */
6302 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6303 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6304 close(fd);
6306 /* Set the portname to what the script says the portname should be. */
6307 /* but don't require anything to be return from the script exit a good error code */
6309 if (numlines) {
6310 /* Set the portname to what the script says the portname should be. */
6311 info2->portname = talloc_strdup(ctx, qlines[0]);
6312 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6315 TALLOC_FREE(qlines);
6316 return true;
6319 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6320 const struct auth_session_info *session_info,
6321 struct messaging_context *msg_ctx,
6322 int snum,
6323 struct spoolss_SetPrinterInfo2 *printer,
6324 struct spoolss_PrinterInfo2 *old_printer)
6326 bool force_update = (old_printer == NULL);
6327 const char *dnsdomname;
6328 const char *longname;
6329 const char *uncname;
6330 const char *spooling;
6331 DATA_BLOB buffer;
6332 WERROR result = WERR_OK;
6333 struct dcerpc_binding_handle *b;
6334 TALLOC_CTX *tmp_ctx;
6335 bool ok;
6337 tmp_ctx = talloc_new(mem_ctx);
6338 if (!tmp_ctx) {
6339 return WERR_NOMEM;
6342 result = winreg_printer_binding_handle(tmp_ctx,
6343 session_info,
6344 msg_ctx,
6345 &b);
6346 if (!W_ERROR_IS_OK(result)) {
6347 goto done;
6350 if (printer->drivername != NULL &&
6351 (force_update ||
6352 !strequal(printer->drivername, old_printer->drivername))) {
6353 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6354 if (!ok) {
6355 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6356 result = WERR_INVALID_DATA;
6357 goto done;
6359 result = winreg_set_printer_dataex(tmp_ctx, b,
6360 printer->sharename,
6361 SPOOL_DSSPOOLER_KEY,
6362 SPOOL_REG_DRIVERNAME,
6363 REG_SZ,
6364 buffer.data,
6365 buffer.length);
6366 if (!W_ERROR_IS_OK(result)) {
6367 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6368 goto done;
6371 if (!force_update) {
6372 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6373 printer->drivername));
6375 notify_printer_driver(server_event_context(), msg_ctx,
6376 snum, printer->drivername ?
6377 printer->drivername : "");
6381 if (printer->comment != NULL &&
6382 (force_update ||
6383 !strequal(printer->comment, old_printer->comment))) {
6384 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6385 if (!ok) {
6386 DEBUG(0, ("comment data corrupted\n"));
6387 result = WERR_INVALID_DATA;
6388 goto done;
6390 result = winreg_set_printer_dataex(tmp_ctx, b,
6391 printer->sharename,
6392 SPOOL_DSSPOOLER_KEY,
6393 SPOOL_REG_DESCRIPTION,
6394 REG_SZ,
6395 buffer.data,
6396 buffer.length);
6397 if (!W_ERROR_IS_OK(result)) {
6398 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6399 goto done;
6402 if (!force_update) {
6403 notify_printer_comment(server_event_context(), msg_ctx,
6404 snum, printer->comment ?
6405 printer->comment : "");
6409 if (printer->sharename != NULL &&
6410 (force_update ||
6411 !strequal(printer->sharename, old_printer->sharename))) {
6412 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6413 if (!ok) {
6414 DEBUG(0, ("sharename data corrupted\n"));
6415 result = WERR_INVALID_DATA;
6416 goto done;
6418 result = winreg_set_printer_dataex(tmp_ctx, b,
6419 printer->sharename,
6420 SPOOL_DSSPOOLER_KEY,
6421 SPOOL_REG_PRINTSHARENAME,
6422 REG_SZ,
6423 buffer.data,
6424 buffer.length);
6425 if (!W_ERROR_IS_OK(result)) {
6426 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6427 goto done;
6430 if (!force_update) {
6431 notify_printer_sharename(server_event_context(),
6432 msg_ctx,
6433 snum, printer->sharename ?
6434 printer->sharename : "");
6438 if (printer->printername != NULL &&
6439 (force_update ||
6440 !strequal(printer->printername, old_printer->printername))) {
6441 const char *p;
6443 p = strrchr(printer->printername, '\\' );
6444 if (p != NULL) {
6445 p++;
6446 } else {
6447 p = printer->printername;
6450 ok = push_reg_sz(tmp_ctx, &buffer, p);
6451 if (!ok) {
6452 DEBUG(0, ("printername data corrupted\n"));
6453 result = WERR_INVALID_DATA;
6454 goto done;
6456 result = winreg_set_printer_dataex(tmp_ctx, b,
6457 printer->sharename,
6458 SPOOL_DSSPOOLER_KEY,
6459 SPOOL_REG_PRINTERNAME,
6460 REG_SZ,
6461 buffer.data,
6462 buffer.length);
6463 if (!W_ERROR_IS_OK(result)) {
6464 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6465 goto done;
6468 if (!force_update) {
6469 notify_printer_printername(server_event_context(),
6470 msg_ctx, snum, p ? p : "");
6474 if (printer->portname != NULL &&
6475 (force_update ||
6476 !strequal(printer->portname, old_printer->portname))) {
6477 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6478 if (!ok) {
6479 DEBUG(0, ("portname data corrupted\n"));
6480 result = WERR_INVALID_DATA;
6481 goto done;
6483 result = winreg_set_printer_dataex(tmp_ctx, b,
6484 printer->sharename,
6485 SPOOL_DSSPOOLER_KEY,
6486 SPOOL_REG_PORTNAME,
6487 REG_SZ,
6488 buffer.data,
6489 buffer.length);
6490 if (!W_ERROR_IS_OK(result)) {
6491 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6492 goto done;
6495 if (!force_update) {
6496 notify_printer_port(server_event_context(),
6497 msg_ctx, snum, printer->portname ?
6498 printer->portname : "");
6502 if (printer->location != NULL &&
6503 (force_update ||
6504 !strequal(printer->location, old_printer->location))) {
6505 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6506 if (!ok) {
6507 DEBUG(0, ("location data corrupted\n"));
6508 result = WERR_INVALID_DATA;
6509 goto done;
6511 result = winreg_set_printer_dataex(tmp_ctx, b,
6512 printer->sharename,
6513 SPOOL_DSSPOOLER_KEY,
6514 SPOOL_REG_LOCATION,
6515 REG_SZ,
6516 buffer.data,
6517 buffer.length);
6518 if (!W_ERROR_IS_OK(result)) {
6519 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6520 goto done;
6523 if (!force_update) {
6524 notify_printer_location(server_event_context(),
6525 msg_ctx, snum,
6526 printer->location ?
6527 printer->location : "");
6531 if (printer->sepfile != NULL &&
6532 (force_update ||
6533 !strequal(printer->sepfile, old_printer->sepfile))) {
6534 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6535 if (!ok) {
6536 DEBUG(0, ("sepfile data corrupted\n"));
6537 result = WERR_INVALID_DATA;
6538 goto done;
6540 result = winreg_set_printer_dataex(tmp_ctx, b,
6541 printer->sharename,
6542 SPOOL_DSSPOOLER_KEY,
6543 SPOOL_REG_PRINTSEPARATORFILE,
6544 REG_SZ,
6545 buffer.data,
6546 buffer.length);
6547 if (!W_ERROR_IS_OK(result)) {
6548 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6549 goto done;
6552 if (!force_update) {
6553 notify_printer_sepfile(server_event_context(),
6554 msg_ctx, snum,
6555 printer->sepfile ?
6556 printer->sepfile : "");
6560 if (printer->starttime != 0 &&
6561 (force_update ||
6562 printer->starttime != old_printer->starttime)) {
6563 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6564 SIVAL(buffer.data, 0, printer->starttime);
6565 result = winreg_set_printer_dataex(tmp_ctx, b,
6566 printer->sharename,
6567 SPOOL_DSSPOOLER_KEY,
6568 SPOOL_REG_PRINTSTARTTIME,
6569 REG_DWORD,
6570 buffer.data,
6571 buffer.length);
6572 if (!W_ERROR_IS_OK(result)) {
6573 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6574 goto done;
6578 if (printer->untiltime != 0 &&
6579 (force_update ||
6580 printer->untiltime != old_printer->untiltime)) {
6581 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6582 SIVAL(buffer.data, 0, printer->untiltime);
6583 result = winreg_set_printer_dataex(tmp_ctx, b,
6584 printer->sharename,
6585 SPOOL_DSSPOOLER_KEY,
6586 SPOOL_REG_PRINTENDTIME,
6587 REG_DWORD,
6588 buffer.data,
6589 buffer.length);
6590 if (!W_ERROR_IS_OK(result)) {
6591 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6592 goto done;
6596 if (force_update || printer->priority != old_printer->priority) {
6597 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6598 SIVAL(buffer.data, 0, printer->priority);
6599 result = winreg_set_printer_dataex(tmp_ctx, b,
6600 printer->sharename,
6601 SPOOL_DSSPOOLER_KEY,
6602 SPOOL_REG_PRIORITY,
6603 REG_DWORD,
6604 buffer.data,
6605 buffer.length);
6606 if (!W_ERROR_IS_OK(result)) {
6607 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6608 goto done;
6612 if (force_update || printer->attributes != old_printer->attributes) {
6613 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6614 SIVAL(buffer.data, 0, (printer->attributes &
6615 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6616 result = winreg_set_printer_dataex(tmp_ctx, b,
6617 printer->sharename,
6618 SPOOL_DSSPOOLER_KEY,
6619 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6620 REG_DWORD,
6621 buffer.data,
6622 buffer.length);
6623 if (!W_ERROR_IS_OK(result)) {
6624 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6625 goto done;
6628 switch (printer->attributes & 0x3) {
6629 case 0:
6630 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6631 break;
6632 case 1:
6633 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6634 break;
6635 case 2:
6636 spooling = SPOOL_REGVAL_PRINTDIRECT;
6637 break;
6638 default:
6639 spooling = "unknown";
6641 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6642 if (!ok) {
6643 DEBUG(0, ("printSpooling data corrupted\n"));
6644 result = WERR_INVALID_DATA;
6645 goto done;
6647 winreg_set_printer_dataex(tmp_ctx, b,
6648 printer->sharename,
6649 SPOOL_DSSPOOLER_KEY,
6650 SPOOL_REG_PRINTSPOOLING,
6651 REG_SZ,
6652 buffer.data,
6653 buffer.length);
6656 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6657 if (!ok) {
6658 DEBUG(0, ("shortServerName data corrupted\n"));
6659 result = WERR_INVALID_DATA;
6660 goto done;
6662 result = winreg_set_printer_dataex(tmp_ctx, b,
6663 printer->sharename,
6664 SPOOL_DSSPOOLER_KEY,
6665 SPOOL_REG_SHORTSERVERNAME,
6666 REG_SZ,
6667 buffer.data,
6668 buffer.length);
6669 if (!W_ERROR_IS_OK(result)) {
6670 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6671 goto done;
6674 dnsdomname = get_mydnsfullname();
6675 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6676 longname = talloc_strdup(tmp_ctx, dnsdomname);
6677 } else {
6678 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6680 if (longname == NULL) {
6681 result = WERR_NOMEM;
6682 goto done;
6685 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6686 if (!ok) {
6687 DEBUG(0, ("longname data corrupted\n"));
6688 result = WERR_INVALID_DATA;
6689 goto done;
6691 result = winreg_set_printer_dataex(tmp_ctx, b,
6692 printer->sharename,
6693 SPOOL_DSSPOOLER_KEY,
6694 SPOOL_REG_SERVERNAME,
6695 REG_SZ,
6696 buffer.data,
6697 buffer.length);
6698 if (!W_ERROR_IS_OK(result)) {
6699 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6700 goto done;
6703 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6704 lp_netbios_name(), printer->sharename);
6705 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6706 if (!ok) {
6707 DEBUG(0, ("uncName data corrupted\n"));
6708 result = WERR_INVALID_DATA;
6709 goto done;
6711 result = winreg_set_printer_dataex(tmp_ctx, b,
6712 printer->sharename,
6713 SPOOL_DSSPOOLER_KEY,
6714 SPOOL_REG_UNCNAME,
6715 REG_SZ,
6716 buffer.data,
6717 buffer.length);
6718 if (!W_ERROR_IS_OK(result)) {
6719 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6720 goto done;
6723 done:
6724 talloc_free(tmp_ctx);
6725 return result;
6728 /********************************************************************
6729 * Called by spoolss_api_setprinter
6730 * when updating a printer description.
6731 ********************************************************************/
6733 static WERROR update_printer(struct pipes_struct *p,
6734 struct policy_handle *handle,
6735 struct spoolss_SetPrinterInfoCtr *info_ctr,
6736 struct spoolss_DeviceMode *devmode)
6738 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6739 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6740 struct spoolss_PrinterInfo2 *old_printer;
6741 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6742 int snum;
6743 WERROR result = WERR_OK;
6744 TALLOC_CTX *tmp_ctx;
6745 struct dcerpc_binding_handle *b;
6747 DEBUG(8,("update_printer\n"));
6749 tmp_ctx = talloc_new(p->mem_ctx);
6750 if (tmp_ctx == NULL) {
6751 return WERR_NOMEM;
6754 if (!Printer) {
6755 result = WERR_BADFID;
6756 goto done;
6759 if (!get_printer_snum(p, handle, &snum, NULL)) {
6760 result = WERR_BADFID;
6761 goto done;
6764 result = winreg_printer_binding_handle(tmp_ctx,
6765 get_session_info_system(),
6766 p->msg_ctx,
6767 &b);
6768 if (!W_ERROR_IS_OK(result)) {
6769 goto done;
6772 result = winreg_get_printer(tmp_ctx, b,
6773 lp_const_servicename(snum),
6774 &old_printer);
6775 if (!W_ERROR_IS_OK(result)) {
6776 result = WERR_BADFID;
6777 goto done;
6780 /* Do sanity check on the requested changes for Samba */
6781 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6782 result = WERR_INVALID_PARAM;
6783 goto done;
6786 /* FIXME!!! If the driver has changed we really should verify that
6787 it is installed before doing much else --jerry */
6789 /* Check calling user has permission to update printer description */
6790 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6791 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6792 result = WERR_ACCESS_DENIED;
6793 goto done;
6796 /* Call addprinter hook */
6797 /* Check changes to see if this is really needed */
6799 if (*lp_addprinter_command(talloc_tos()) &&
6800 (!strequal(printer->drivername, old_printer->drivername) ||
6801 !strequal(printer->comment, old_printer->comment) ||
6802 !strequal(printer->portname, old_printer->portname) ||
6803 !strequal(printer->location, old_printer->location)) )
6805 char *raddr;
6807 raddr = tsocket_address_inet_addr_string(p->remote_address,
6808 p->mem_ctx);
6809 if (raddr == NULL) {
6810 return WERR_NOMEM;
6813 /* add_printer_hook() will call reload_services() */
6814 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6815 printer, raddr,
6816 p->msg_ctx)) {
6817 result = WERR_ACCESS_DENIED;
6818 goto done;
6822 result = update_dsspooler(tmp_ctx,
6823 get_session_info_system(),
6824 p->msg_ctx,
6825 snum,
6826 printer,
6827 old_printer);
6828 if (!W_ERROR_IS_OK(result)) {
6829 goto done;
6832 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6834 if (devmode == NULL) {
6835 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6837 result = winreg_update_printer(tmp_ctx, b,
6838 printer->sharename,
6839 printer_mask,
6840 printer,
6841 devmode,
6842 NULL);
6844 done:
6845 talloc_free(tmp_ctx);
6847 return result;
6850 /****************************************************************************
6851 ****************************************************************************/
6852 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6853 struct policy_handle *handle,
6854 struct spoolss_SetPrinterInfo7 *info7)
6856 #ifdef HAVE_ADS
6857 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6858 WERROR result;
6859 int snum;
6860 struct printer_handle *Printer;
6862 if ( lp_security() != SEC_ADS ) {
6863 return WERR_UNKNOWN_LEVEL;
6866 Printer = find_printer_index_by_hnd(p, handle);
6868 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6870 if (!Printer)
6871 return WERR_BADFID;
6873 if (!get_printer_snum(p, handle, &snum, NULL))
6874 return WERR_BADFID;
6876 result = winreg_get_printer_internal(p->mem_ctx,
6877 get_session_info_system(),
6878 p->msg_ctx,
6879 lp_servicename(talloc_tos(), snum),
6880 &pinfo2);
6881 if (!W_ERROR_IS_OK(result)) {
6882 return WERR_BADFID;
6885 nt_printer_publish(pinfo2,
6886 get_session_info_system(),
6887 p->msg_ctx,
6888 pinfo2,
6889 info7->action);
6891 TALLOC_FREE(pinfo2);
6892 return WERR_OK;
6893 #else
6894 return WERR_UNKNOWN_LEVEL;
6895 #endif
6898 /********************************************************************
6899 ********************************************************************/
6901 static WERROR update_printer_devmode(struct pipes_struct *p,
6902 struct policy_handle *handle,
6903 struct spoolss_DeviceMode *devmode)
6905 int snum;
6906 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6907 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6909 DEBUG(8,("update_printer_devmode\n"));
6911 if (!Printer) {
6912 return WERR_BADFID;
6915 if (!get_printer_snum(p, handle, &snum, NULL)) {
6916 return WERR_BADFID;
6919 /* Check calling user has permission to update printer description */
6920 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6921 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6922 return WERR_ACCESS_DENIED;
6925 return winreg_update_printer_internal(p->mem_ctx,
6926 get_session_info_system(),
6927 p->msg_ctx,
6928 lp_const_servicename(snum),
6929 info2_mask,
6930 NULL,
6931 devmode,
6932 NULL);
6936 /****************************************************************
6937 _spoolss_SetPrinter
6938 ****************************************************************/
6940 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6941 struct spoolss_SetPrinter *r)
6943 WERROR result;
6945 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6947 if (!Printer) {
6948 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6949 OUR_HANDLE(r->in.handle)));
6950 return WERR_BADFID;
6953 /* check the level */
6954 switch (r->in.info_ctr->level) {
6955 case 0:
6956 return control_printer(r->in.handle, r->in.command, p);
6957 case 2:
6958 result = update_printer(p, r->in.handle,
6959 r->in.info_ctr,
6960 r->in.devmode_ctr->devmode);
6961 if (!W_ERROR_IS_OK(result))
6962 return result;
6963 if (r->in.secdesc_ctr->sd)
6964 result = update_printer_sec(r->in.handle, p,
6965 r->in.secdesc_ctr);
6966 return result;
6967 case 3:
6968 return update_printer_sec(r->in.handle, p,
6969 r->in.secdesc_ctr);
6970 case 7:
6971 return publish_or_unpublish_printer(p, r->in.handle,
6972 r->in.info_ctr->info.info7);
6973 case 8:
6974 return update_printer_devmode(p, r->in.handle,
6975 r->in.devmode_ctr->devmode);
6976 default:
6977 return WERR_UNKNOWN_LEVEL;
6981 /****************************************************************
6982 _spoolss_FindClosePrinterNotify
6983 ****************************************************************/
6985 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6986 struct spoolss_FindClosePrinterNotify *r)
6988 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6990 if (!Printer) {
6991 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6992 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6993 return WERR_BADFID;
6996 if (Printer->notify.cli_chan != NULL &&
6997 Printer->notify.cli_chan->active_connections > 0) {
6998 int snum = -1;
7000 if (Printer->printer_type == SPLHND_PRINTER) {
7001 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7002 return WERR_BADFID;
7006 srv_spoolss_replycloseprinter(snum, Printer);
7009 Printer->notify.flags=0;
7010 Printer->notify.options=0;
7011 Printer->notify.localmachine[0]='\0';
7012 Printer->notify.printerlocal=0;
7013 TALLOC_FREE(Printer->notify.option);
7015 return WERR_OK;
7018 /****************************************************************
7019 _spoolss_AddJob
7020 ****************************************************************/
7022 WERROR _spoolss_AddJob(struct pipes_struct *p,
7023 struct spoolss_AddJob *r)
7025 if (!r->in.buffer && (r->in.offered != 0)) {
7026 return WERR_INVALID_PARAM;
7029 /* this is what a NT server returns for AddJob. AddJob must fail on
7030 * non-local printers */
7032 if (r->in.level != 1) {
7033 return WERR_UNKNOWN_LEVEL;
7036 return WERR_INVALID_PARAM;
7039 /****************************************************************************
7040 fill_job_info1
7041 ****************************************************************************/
7043 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7044 struct spoolss_JobInfo1 *r,
7045 const print_queue_struct *queue,
7046 int position, int snum,
7047 struct spoolss_PrinterInfo2 *pinfo2)
7049 struct tm *t;
7051 t = gmtime(&queue->time);
7053 r->job_id = queue->sysjob;
7055 r->printer_name = lp_servicename(mem_ctx, snum);
7056 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7057 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7058 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7059 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7060 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7061 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7062 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7063 r->data_type = talloc_strdup(mem_ctx, "RAW");
7064 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7065 r->text_status = talloc_strdup(mem_ctx, "");
7066 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7068 r->status = nt_printj_status(queue->status);
7069 r->priority = queue->priority;
7070 r->position = position;
7071 r->total_pages = queue->page_count;
7072 r->pages_printed = 0; /* ??? */
7074 init_systemtime(&r->submitted, t);
7076 return WERR_OK;
7079 /****************************************************************************
7080 fill_job_info2
7081 ****************************************************************************/
7083 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7084 struct spoolss_JobInfo2 *r,
7085 const print_queue_struct *queue,
7086 int position, int snum,
7087 struct spoolss_PrinterInfo2 *pinfo2,
7088 struct spoolss_DeviceMode *devmode)
7090 struct tm *t;
7092 t = gmtime(&queue->time);
7094 r->job_id = queue->sysjob;
7096 r->printer_name = lp_servicename(mem_ctx, snum);
7097 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7098 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7099 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7100 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7101 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7102 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7103 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7104 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7105 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7106 r->data_type = talloc_strdup(mem_ctx, "RAW");
7107 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7108 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7109 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7110 r->parameters = talloc_strdup(mem_ctx, "");
7111 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7112 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7113 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7115 r->devmode = devmode;
7117 r->text_status = talloc_strdup(mem_ctx, "");
7118 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7120 r->secdesc = NULL;
7122 r->status = nt_printj_status(queue->status);
7123 r->priority = queue->priority;
7124 r->position = position;
7125 r->start_time = 0;
7126 r->until_time = 0;
7127 r->total_pages = queue->page_count;
7128 r->size = queue->size;
7129 init_systemtime(&r->submitted, t);
7130 r->time = 0;
7131 r->pages_printed = 0; /* ??? */
7133 return WERR_OK;
7136 /****************************************************************************
7137 fill_job_info3
7138 ****************************************************************************/
7140 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7141 struct spoolss_JobInfo3 *r,
7142 const print_queue_struct *queue,
7143 const print_queue_struct *next_queue,
7144 int position, int snum,
7145 struct spoolss_PrinterInfo2 *pinfo2)
7147 r->job_id = queue->sysjob;
7148 r->next_job_id = 0;
7149 if (next_queue) {
7150 r->next_job_id = next_queue->sysjob;
7152 r->reserved = 0;
7154 return WERR_OK;
7157 /****************************************************************************
7158 Enumjobs at level 1.
7159 ****************************************************************************/
7161 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7162 const print_queue_struct *queue,
7163 uint32_t num_queues, int snum,
7164 struct spoolss_PrinterInfo2 *pinfo2,
7165 union spoolss_JobInfo **info_p,
7166 uint32_t *count)
7168 union spoolss_JobInfo *info;
7169 int i;
7170 WERROR result = WERR_OK;
7172 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7173 W_ERROR_HAVE_NO_MEMORY(info);
7175 *count = num_queues;
7177 for (i=0; i<*count; i++) {
7178 result = fill_job_info1(info,
7179 &info[i].info1,
7180 &queue[i],
7182 snum,
7183 pinfo2);
7184 if (!W_ERROR_IS_OK(result)) {
7185 goto out;
7189 out:
7190 if (!W_ERROR_IS_OK(result)) {
7191 TALLOC_FREE(info);
7192 *count = 0;
7193 return result;
7196 *info_p = info;
7198 return WERR_OK;
7201 /****************************************************************************
7202 Enumjobs at level 2.
7203 ****************************************************************************/
7205 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7206 const print_queue_struct *queue,
7207 uint32_t num_queues, int snum,
7208 struct spoolss_PrinterInfo2 *pinfo2,
7209 union spoolss_JobInfo **info_p,
7210 uint32_t *count)
7212 union spoolss_JobInfo *info;
7213 int i;
7214 WERROR result = WERR_OK;
7216 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7217 W_ERROR_HAVE_NO_MEMORY(info);
7219 *count = num_queues;
7221 for (i=0; i<*count; i++) {
7222 struct spoolss_DeviceMode *devmode;
7224 result = spoolss_create_default_devmode(info,
7225 pinfo2->printername,
7226 &devmode);
7227 if (!W_ERROR_IS_OK(result)) {
7228 DEBUG(3, ("Can't proceed w/o a devmode!"));
7229 goto out;
7232 result = fill_job_info2(info,
7233 &info[i].info2,
7234 &queue[i],
7236 snum,
7237 pinfo2,
7238 devmode);
7239 if (!W_ERROR_IS_OK(result)) {
7240 goto out;
7244 out:
7245 if (!W_ERROR_IS_OK(result)) {
7246 TALLOC_FREE(info);
7247 *count = 0;
7248 return result;
7251 *info_p = info;
7253 return WERR_OK;
7256 /****************************************************************************
7257 Enumjobs at level 3.
7258 ****************************************************************************/
7260 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7261 const print_queue_struct *queue,
7262 uint32_t num_queues, int snum,
7263 struct spoolss_PrinterInfo2 *pinfo2,
7264 union spoolss_JobInfo **info_p,
7265 uint32_t *count)
7267 union spoolss_JobInfo *info;
7268 int i;
7269 WERROR result = WERR_OK;
7271 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7272 W_ERROR_HAVE_NO_MEMORY(info);
7274 *count = num_queues;
7276 for (i=0; i<*count; i++) {
7277 const print_queue_struct *next_queue = NULL;
7279 if (i+1 < *count) {
7280 next_queue = &queue[i+1];
7283 result = fill_job_info3(info,
7284 &info[i].info3,
7285 &queue[i],
7286 next_queue,
7288 snum,
7289 pinfo2);
7290 if (!W_ERROR_IS_OK(result)) {
7291 goto out;
7295 out:
7296 if (!W_ERROR_IS_OK(result)) {
7297 TALLOC_FREE(info);
7298 *count = 0;
7299 return result;
7302 *info_p = info;
7304 return WERR_OK;
7307 /****************************************************************
7308 _spoolss_EnumJobs
7309 ****************************************************************/
7311 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7312 struct spoolss_EnumJobs *r)
7314 WERROR result;
7315 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7316 int snum;
7317 print_status_struct prt_status;
7318 print_queue_struct *queue = NULL;
7319 uint32_t count;
7321 /* that's an [in out] buffer */
7323 if (!r->in.buffer && (r->in.offered != 0)) {
7324 return WERR_INVALID_PARAM;
7327 DEBUG(4,("_spoolss_EnumJobs\n"));
7329 *r->out.needed = 0;
7330 *r->out.count = 0;
7331 *r->out.info = NULL;
7333 /* lookup the printer snum and tdb entry */
7335 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7336 return WERR_BADFID;
7339 result = winreg_get_printer_internal(p->mem_ctx,
7340 get_session_info_system(),
7341 p->msg_ctx,
7342 lp_const_servicename(snum),
7343 &pinfo2);
7344 if (!W_ERROR_IS_OK(result)) {
7345 return result;
7348 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7349 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7350 count, prt_status.status, prt_status.message));
7352 if (count == 0) {
7353 SAFE_FREE(queue);
7354 TALLOC_FREE(pinfo2);
7355 return WERR_OK;
7358 switch (r->in.level) {
7359 case 1:
7360 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7361 pinfo2, r->out.info, r->out.count);
7362 break;
7363 case 2:
7364 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7365 pinfo2, r->out.info, r->out.count);
7366 break;
7367 case 3:
7368 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7369 pinfo2, r->out.info, r->out.count);
7370 break;
7371 default:
7372 result = WERR_UNKNOWN_LEVEL;
7373 break;
7376 SAFE_FREE(queue);
7377 TALLOC_FREE(pinfo2);
7379 if (!W_ERROR_IS_OK(result)) {
7380 return result;
7383 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7384 spoolss_EnumJobs,
7385 *r->out.info, r->in.level,
7386 *r->out.count);
7387 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7388 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7390 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7393 /****************************************************************
7394 _spoolss_ScheduleJob
7395 ****************************************************************/
7397 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7398 struct spoolss_ScheduleJob *r)
7400 return WERR_OK;
7403 /****************************************************************
7404 ****************************************************************/
7406 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7407 struct messaging_context *msg_ctx,
7408 const char *printer_name,
7409 uint32_t job_id,
7410 struct spoolss_SetJobInfo1 *r)
7412 char *old_doc_name;
7414 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7415 return WERR_BADFID;
7418 if (strequal(old_doc_name, r->document_name)) {
7419 return WERR_OK;
7422 if (!print_job_set_name(server_event_context(), msg_ctx,
7423 printer_name, job_id, r->document_name)) {
7424 return WERR_BADFID;
7427 return WERR_OK;
7430 /****************************************************************
7431 _spoolss_SetJob
7432 ****************************************************************/
7434 WERROR _spoolss_SetJob(struct pipes_struct *p,
7435 struct spoolss_SetJob *r)
7437 const struct auth_session_info *session_info = p->session_info;
7438 int snum;
7439 WERROR errcode = WERR_BADFUNC;
7441 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7442 return WERR_BADFID;
7445 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7446 return WERR_INVALID_PRINTER_NAME;
7449 switch (r->in.command) {
7450 case SPOOLSS_JOB_CONTROL_CANCEL:
7451 case SPOOLSS_JOB_CONTROL_DELETE:
7452 errcode = print_job_delete(session_info, p->msg_ctx,
7453 snum, r->in.job_id);
7454 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7455 errcode = WERR_OK;
7457 break;
7458 case SPOOLSS_JOB_CONTROL_PAUSE:
7459 errcode = print_job_pause(session_info, p->msg_ctx,
7460 snum, r->in.job_id);
7461 break;
7462 case SPOOLSS_JOB_CONTROL_RESTART:
7463 case SPOOLSS_JOB_CONTROL_RESUME:
7464 errcode = print_job_resume(session_info, p->msg_ctx,
7465 snum, r->in.job_id);
7466 break;
7467 case 0:
7468 errcode = WERR_OK;
7469 break;
7470 default:
7471 return WERR_UNKNOWN_LEVEL;
7474 if (!W_ERROR_IS_OK(errcode)) {
7475 return errcode;
7478 if (r->in.ctr == NULL) {
7479 return errcode;
7482 switch (r->in.ctr->level) {
7483 case 1:
7484 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7485 lp_const_servicename(snum),
7486 r->in.job_id,
7487 r->in.ctr->info.info1);
7488 break;
7489 case 2:
7490 case 3:
7491 case 4:
7492 default:
7493 return WERR_UNKNOWN_LEVEL;
7496 return errcode;
7499 /****************************************************************************
7500 Enumerates all printer drivers by level and architecture.
7501 ****************************************************************************/
7503 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7504 const struct auth_session_info *session_info,
7505 struct messaging_context *msg_ctx,
7506 const char *servername,
7507 const char *architecture,
7508 uint32_t level,
7509 union spoolss_DriverInfo **info_p,
7510 uint32_t *count_p)
7512 int i;
7513 uint32_t version;
7514 struct spoolss_DriverInfo8 *driver;
7515 union spoolss_DriverInfo *info = NULL;
7516 uint32_t count = 0;
7517 WERROR result = WERR_OK;
7518 uint32_t num_drivers;
7519 const char **drivers;
7520 struct dcerpc_binding_handle *b;
7521 TALLOC_CTX *tmp_ctx = NULL;
7523 *count_p = 0;
7524 *info_p = NULL;
7526 tmp_ctx = talloc_new(mem_ctx);
7527 if (!tmp_ctx) {
7528 return WERR_NOMEM;
7531 result = winreg_printer_binding_handle(tmp_ctx,
7532 session_info,
7533 msg_ctx,
7534 &b);
7535 if (!W_ERROR_IS_OK(result)) {
7536 goto out;
7539 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7540 result = winreg_get_driver_list(tmp_ctx, b,
7541 architecture, version,
7542 &num_drivers, &drivers);
7543 if (!W_ERROR_IS_OK(result)) {
7544 goto out;
7546 DEBUG(4, ("we have:[%d] drivers in environment"
7547 " [%s] and version [%d]\n",
7548 num_drivers, architecture, version));
7550 if (num_drivers != 0) {
7551 info = talloc_realloc(tmp_ctx, info,
7552 union spoolss_DriverInfo,
7553 count + num_drivers);
7554 if (!info) {
7555 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7556 "failed to enlarge driver info buffer!\n"));
7557 result = WERR_NOMEM;
7558 goto out;
7562 for (i = 0; i < num_drivers; i++) {
7563 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7565 result = winreg_get_driver(tmp_ctx, b,
7566 architecture, drivers[i],
7567 version, &driver);
7568 if (!W_ERROR_IS_OK(result)) {
7569 goto out;
7572 switch (level) {
7573 case 1:
7574 result = fill_printer_driver_info1(info, &info[count+i].info1,
7575 driver, servername);
7576 break;
7577 case 2:
7578 result = fill_printer_driver_info2(info, &info[count+i].info2,
7579 driver, servername);
7580 break;
7581 case 3:
7582 result = fill_printer_driver_info3(info, &info[count+i].info3,
7583 driver, servername);
7584 break;
7585 case 4:
7586 result = fill_printer_driver_info4(info, &info[count+i].info4,
7587 driver, servername);
7588 break;
7589 case 5:
7590 result = fill_printer_driver_info5(info, &info[count+i].info5,
7591 driver, servername);
7592 break;
7593 case 6:
7594 result = fill_printer_driver_info6(info, &info[count+i].info6,
7595 driver, servername);
7596 break;
7597 case 8:
7598 result = fill_printer_driver_info8(info, &info[count+i].info8,
7599 driver, servername);
7600 break;
7601 default:
7602 result = WERR_UNKNOWN_LEVEL;
7603 break;
7606 TALLOC_FREE(driver);
7608 if (!W_ERROR_IS_OK(result)) {
7609 goto out;
7613 count += num_drivers;
7614 TALLOC_FREE(drivers);
7617 out:
7618 if (W_ERROR_IS_OK(result)) {
7619 *info_p = talloc_move(mem_ctx, &info);
7620 *count_p = count;
7623 talloc_free(tmp_ctx);
7624 return result;
7627 /****************************************************************************
7628 Enumerates all printer drivers by level.
7629 ****************************************************************************/
7631 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7632 const struct auth_session_info *session_info,
7633 struct messaging_context *msg_ctx,
7634 const char *servername,
7635 const char *architecture,
7636 uint32_t level,
7637 union spoolss_DriverInfo **info_p,
7638 uint32_t *count_p)
7640 uint32_t a,i;
7641 WERROR result = WERR_OK;
7643 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7645 for (a=0; archi_table[a].long_archi != NULL; a++) {
7647 union spoolss_DriverInfo *info = NULL;
7648 uint32_t count = 0;
7650 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7651 session_info,
7652 msg_ctx,
7653 servername,
7654 archi_table[a].long_archi,
7655 level,
7656 &info,
7657 &count);
7658 if (!W_ERROR_IS_OK(result)) {
7659 continue;
7662 for (i=0; i < count; i++) {
7663 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7664 info[i], info_p, count_p);
7668 return result;
7671 return enumprinterdrivers_level_by_architecture(mem_ctx,
7672 session_info,
7673 msg_ctx,
7674 servername,
7675 architecture,
7676 level,
7677 info_p,
7678 count_p);
7681 /****************************************************************
7682 _spoolss_EnumPrinterDrivers
7683 ****************************************************************/
7685 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7686 struct spoolss_EnumPrinterDrivers *r)
7688 const char *cservername;
7689 WERROR result;
7691 /* that's an [in out] buffer */
7693 if (!r->in.buffer && (r->in.offered != 0)) {
7694 return WERR_INVALID_PARAM;
7697 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7699 *r->out.needed = 0;
7700 *r->out.count = 0;
7701 *r->out.info = NULL;
7703 cservername = canon_servername(r->in.server);
7705 if (!is_myname_or_ipaddr(cservername)) {
7706 return WERR_UNKNOWN_PRINTER_DRIVER;
7709 result = enumprinterdrivers_level(p->mem_ctx,
7710 get_session_info_system(),
7711 p->msg_ctx,
7712 cservername,
7713 r->in.environment,
7714 r->in.level,
7715 r->out.info,
7716 r->out.count);
7717 if (!W_ERROR_IS_OK(result)) {
7718 return result;
7721 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7722 spoolss_EnumPrinterDrivers,
7723 *r->out.info, r->in.level,
7724 *r->out.count);
7725 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7726 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7728 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7731 /****************************************************************
7732 _spoolss_EnumForms
7733 ****************************************************************/
7735 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7736 struct spoolss_EnumForms *r)
7738 WERROR result;
7740 *r->out.count = 0;
7741 *r->out.needed = 0;
7742 *r->out.info = NULL;
7744 /* that's an [in out] buffer */
7746 if (!r->in.buffer && (r->in.offered != 0) ) {
7747 return WERR_INVALID_PARAM;
7750 DEBUG(4,("_spoolss_EnumForms\n"));
7751 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7752 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7754 switch (r->in.level) {
7755 case 1:
7756 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7757 get_session_info_system(),
7758 p->msg_ctx,
7759 r->out.count,
7760 r->out.info);
7761 break;
7762 default:
7763 result = WERR_UNKNOWN_LEVEL;
7764 break;
7767 if (!W_ERROR_IS_OK(result)) {
7768 return result;
7771 if (*r->out.count == 0) {
7772 return WERR_NO_MORE_ITEMS;
7775 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7776 spoolss_EnumForms,
7777 *r->out.info, r->in.level,
7778 *r->out.count);
7779 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7780 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7782 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7785 /****************************************************************
7786 _spoolss_GetForm
7787 ****************************************************************/
7789 WERROR _spoolss_GetForm(struct pipes_struct *p,
7790 struct spoolss_GetForm *r)
7792 WERROR result;
7794 /* that's an [in out] buffer */
7796 if (!r->in.buffer && (r->in.offered != 0)) {
7797 return WERR_INVALID_PARAM;
7800 DEBUG(4,("_spoolss_GetForm\n"));
7801 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7802 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7804 switch (r->in.level) {
7805 case 1:
7806 result = winreg_printer_getform1_internal(p->mem_ctx,
7807 get_session_info_system(),
7808 p->msg_ctx,
7809 r->in.form_name,
7810 &r->out.info->info1);
7811 break;
7812 default:
7813 result = WERR_UNKNOWN_LEVEL;
7814 break;
7817 if (!W_ERROR_IS_OK(result)) {
7818 TALLOC_FREE(r->out.info);
7819 return result;
7822 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7823 r->out.info, r->in.level);
7824 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7826 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7829 /****************************************************************************
7830 ****************************************************************************/
7832 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7833 struct spoolss_PortInfo1 *r,
7834 const char *name)
7836 r->port_name = talloc_strdup(mem_ctx, name);
7837 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7839 return WERR_OK;
7842 /****************************************************************************
7843 TODO: This probably needs distinguish between TCP/IP and Local ports
7844 somehow.
7845 ****************************************************************************/
7847 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7848 struct spoolss_PortInfo2 *r,
7849 const char *name)
7851 r->port_name = talloc_strdup(mem_ctx, name);
7852 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7854 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7855 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7857 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7858 W_ERROR_HAVE_NO_MEMORY(r->description);
7860 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7861 r->reserved = 0;
7863 return WERR_OK;
7867 /****************************************************************************
7868 wrapper around the enumer ports command
7869 ****************************************************************************/
7871 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7873 char *cmd = lp_enumports_command(talloc_tos());
7874 char **qlines = NULL;
7875 char *command = NULL;
7876 int numlines;
7877 int ret;
7878 int fd;
7880 *count = 0;
7881 *lines = NULL;
7883 /* if no hook then just fill in the default port */
7885 if ( !*cmd ) {
7886 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7887 return WERR_NOMEM;
7889 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7890 TALLOC_FREE(qlines);
7891 return WERR_NOMEM;
7893 qlines[1] = NULL;
7894 numlines = 1;
7896 else {
7897 /* we have a valid enumport command */
7899 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7900 if (!command) {
7901 return WERR_NOMEM;
7904 DEBUG(10,("Running [%s]\n", command));
7905 ret = smbrun(command, &fd);
7906 DEBUG(10,("Returned [%d]\n", ret));
7907 TALLOC_FREE(command);
7908 if (ret != 0) {
7909 if (fd != -1) {
7910 close(fd);
7912 return WERR_ACCESS_DENIED;
7915 numlines = 0;
7916 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7917 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7918 close(fd);
7921 *count = numlines;
7922 *lines = qlines;
7924 return WERR_OK;
7927 /****************************************************************************
7928 enumports level 1.
7929 ****************************************************************************/
7931 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7932 union spoolss_PortInfo **info_p,
7933 uint32_t *count)
7935 union spoolss_PortInfo *info = NULL;
7936 int i=0;
7937 WERROR result = WERR_OK;
7938 char **qlines = NULL;
7939 int numlines = 0;
7941 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7942 if (!W_ERROR_IS_OK(result)) {
7943 goto out;
7946 if (numlines) {
7947 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7948 if (!info) {
7949 DEBUG(10,("Returning WERR_NOMEM\n"));
7950 result = WERR_NOMEM;
7951 goto out;
7954 for (i=0; i<numlines; i++) {
7955 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7956 result = fill_port_1(info, &info[i].info1, qlines[i]);
7957 if (!W_ERROR_IS_OK(result)) {
7958 goto out;
7962 TALLOC_FREE(qlines);
7964 out:
7965 if (!W_ERROR_IS_OK(result)) {
7966 TALLOC_FREE(info);
7967 TALLOC_FREE(qlines);
7968 *count = 0;
7969 *info_p = NULL;
7970 return result;
7973 *info_p = info;
7974 *count = numlines;
7976 return WERR_OK;
7979 /****************************************************************************
7980 enumports level 2.
7981 ****************************************************************************/
7983 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7984 union spoolss_PortInfo **info_p,
7985 uint32_t *count)
7987 union spoolss_PortInfo *info = NULL;
7988 int i=0;
7989 WERROR result = WERR_OK;
7990 char **qlines = NULL;
7991 int numlines = 0;
7993 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7994 if (!W_ERROR_IS_OK(result)) {
7995 goto out;
7998 if (numlines) {
7999 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8000 if (!info) {
8001 DEBUG(10,("Returning WERR_NOMEM\n"));
8002 result = WERR_NOMEM;
8003 goto out;
8006 for (i=0; i<numlines; i++) {
8007 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8008 result = fill_port_2(info, &info[i].info2, qlines[i]);
8009 if (!W_ERROR_IS_OK(result)) {
8010 goto out;
8014 TALLOC_FREE(qlines);
8016 out:
8017 if (!W_ERROR_IS_OK(result)) {
8018 TALLOC_FREE(info);
8019 TALLOC_FREE(qlines);
8020 *count = 0;
8021 *info_p = NULL;
8022 return result;
8025 *info_p = info;
8026 *count = numlines;
8028 return WERR_OK;
8031 /****************************************************************
8032 _spoolss_EnumPorts
8033 ****************************************************************/
8035 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8036 struct spoolss_EnumPorts *r)
8038 WERROR result;
8040 /* that's an [in out] buffer */
8042 if (!r->in.buffer && (r->in.offered != 0)) {
8043 return WERR_INVALID_PARAM;
8046 DEBUG(4,("_spoolss_EnumPorts\n"));
8048 *r->out.count = 0;
8049 *r->out.needed = 0;
8050 *r->out.info = NULL;
8052 switch (r->in.level) {
8053 case 1:
8054 result = enumports_level_1(p->mem_ctx, r->out.info,
8055 r->out.count);
8056 break;
8057 case 2:
8058 result = enumports_level_2(p->mem_ctx, r->out.info,
8059 r->out.count);
8060 break;
8061 default:
8062 return WERR_UNKNOWN_LEVEL;
8065 if (!W_ERROR_IS_OK(result)) {
8066 return result;
8069 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8070 spoolss_EnumPorts,
8071 *r->out.info, r->in.level,
8072 *r->out.count);
8073 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8074 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8076 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8079 /****************************************************************************
8080 ****************************************************************************/
8082 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8083 const char *server,
8084 struct spoolss_SetPrinterInfoCtr *info_ctr,
8085 struct spoolss_DeviceMode *devmode,
8086 struct security_descriptor *secdesc,
8087 struct spoolss_UserLevelCtr *user_ctr,
8088 struct policy_handle *handle)
8090 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8091 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8092 int snum;
8093 WERROR err = WERR_OK;
8095 /* samba does not have a concept of local, non-shared printers yet, so
8096 * make sure we always setup sharename - gd */
8097 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8098 (info2->printername != NULL && info2->printername[0] != '\0')) {
8099 DEBUG(5, ("spoolss_addprinterex_level_2: "
8100 "no sharename has been set, setting printername %s as sharename\n",
8101 info2->printername));
8102 info2->sharename = info2->printername;
8105 /* check to see if the printer already exists */
8106 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8107 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8108 info2->sharename));
8109 return WERR_PRINTER_ALREADY_EXISTS;
8112 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8113 if ((snum = print_queue_snum(info2->printername)) != -1) {
8114 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8115 info2->printername));
8116 return WERR_PRINTER_ALREADY_EXISTS;
8120 /* validate printer info struct */
8121 if (!info2->printername || strlen(info2->printername) == 0) {
8122 return WERR_INVALID_PRINTER_NAME;
8124 if (!info2->portname || strlen(info2->portname) == 0) {
8125 return WERR_UNKNOWN_PORT;
8127 if (!info2->drivername || strlen(info2->drivername) == 0) {
8128 return WERR_UNKNOWN_PRINTER_DRIVER;
8130 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8131 return WERR_UNKNOWN_PRINTPROCESSOR;
8134 /* FIXME!!! smbd should check to see if the driver is installed before
8135 trying to add a printer like this --jerry */
8137 if (*lp_addprinter_command(talloc_tos()) ) {
8138 char *raddr;
8140 raddr = tsocket_address_inet_addr_string(p->remote_address,
8141 p->mem_ctx);
8142 if (raddr == NULL) {
8143 return WERR_NOMEM;
8146 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8147 info2, raddr,
8148 p->msg_ctx) ) {
8149 return WERR_ACCESS_DENIED;
8151 } else {
8152 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8153 "smb.conf parameter \"addprinter command\" is defined. This "
8154 "parameter must exist for this call to succeed\n",
8155 info2->sharename ));
8158 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8159 return WERR_ACCESS_DENIED;
8162 /* you must be a printer admin to add a new printer */
8163 if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8164 p->msg_ctx,
8165 snum,
8166 PRINTER_ACCESS_ADMINISTER))) {
8167 return WERR_ACCESS_DENIED;
8171 * Do sanity check on the requested changes for Samba.
8174 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8175 return WERR_INVALID_PARAM;
8178 if (devmode == NULL) {
8179 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8182 err = update_dsspooler(p->mem_ctx,
8183 get_session_info_system(),
8184 p->msg_ctx,
8186 info2,
8187 NULL);
8188 if (!W_ERROR_IS_OK(err)) {
8189 return err;
8192 err = winreg_update_printer_internal(p->mem_ctx,
8193 get_session_info_system(),
8194 p->msg_ctx,
8195 info2->sharename,
8196 info2_mask,
8197 info2,
8198 devmode,
8199 secdesc);
8200 if (!W_ERROR_IS_OK(err)) {
8201 return err;
8204 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8205 if (!W_ERROR_IS_OK(err)) {
8206 /* Handle open failed - remove addition. */
8207 ZERO_STRUCTP(handle);
8208 return err;
8211 return WERR_OK;
8214 /****************************************************************
8215 _spoolss_AddPrinterEx
8216 ****************************************************************/
8218 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8219 struct spoolss_AddPrinterEx *r)
8221 switch (r->in.info_ctr->level) {
8222 case 1:
8223 /* we don't handle yet */
8224 /* but I know what to do ... */
8225 return WERR_UNKNOWN_LEVEL;
8226 case 2:
8227 return spoolss_addprinterex_level_2(p, r->in.server,
8228 r->in.info_ctr,
8229 r->in.devmode_ctr->devmode,
8230 r->in.secdesc_ctr->sd,
8231 r->in.userlevel_ctr,
8232 r->out.handle);
8233 default:
8234 return WERR_UNKNOWN_LEVEL;
8238 /****************************************************************
8239 _spoolss_AddPrinter
8240 ****************************************************************/
8242 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8243 struct spoolss_AddPrinter *r)
8245 struct spoolss_AddPrinterEx a;
8246 struct spoolss_UserLevelCtr userlevel_ctr;
8248 ZERO_STRUCT(userlevel_ctr);
8250 userlevel_ctr.level = 1;
8252 a.in.server = r->in.server;
8253 a.in.info_ctr = r->in.info_ctr;
8254 a.in.devmode_ctr = r->in.devmode_ctr;
8255 a.in.secdesc_ctr = r->in.secdesc_ctr;
8256 a.in.userlevel_ctr = &userlevel_ctr;
8257 a.out.handle = r->out.handle;
8259 return _spoolss_AddPrinterEx(p, &a);
8262 /****************************************************************
8263 _spoolss_AddPrinterDriverEx
8264 ****************************************************************/
8266 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8267 struct spoolss_AddPrinterDriverEx *r)
8269 WERROR err = WERR_OK;
8270 const char *driver_name = NULL;
8271 uint32_t version;
8272 const char *fn;
8274 switch (p->opnum) {
8275 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8276 fn = "_spoolss_AddPrinterDriver";
8277 break;
8278 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8279 fn = "_spoolss_AddPrinterDriverEx";
8280 break;
8281 default:
8282 return WERR_INVALID_PARAM;
8286 * we only support the semantics of AddPrinterDriver()
8287 * i.e. only copy files that are newer than existing ones
8290 if (r->in.flags == 0) {
8291 return WERR_INVALID_PARAM;
8294 if (r->in.flags != APD_COPY_NEW_FILES) {
8295 return WERR_ACCESS_DENIED;
8298 /* FIXME */
8299 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8300 /* Clever hack from Martin Zielinski <mz@seh.de>
8301 * to allow downgrade from level 8 (Vista).
8303 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8304 r->in.info_ctr->level));
8305 return WERR_UNKNOWN_LEVEL;
8308 DEBUG(5,("Cleaning driver's information\n"));
8309 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8310 if (!W_ERROR_IS_OK(err))
8311 goto done;
8313 DEBUG(5,("Moving driver to final destination\n"));
8314 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8315 if (!W_ERROR_IS_OK(err)) {
8316 goto done;
8319 err = winreg_add_driver_internal(p->mem_ctx,
8320 get_session_info_system(),
8321 p->msg_ctx,
8322 r->in.info_ctr,
8323 &driver_name,
8324 &version);
8325 if (!W_ERROR_IS_OK(err)) {
8326 goto done;
8330 * I think this is where he DrvUpgradePrinter() hook would be
8331 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8332 * server. Right now, we just need to send ourselves a message
8333 * to update each printer bound to this driver. --jerry
8336 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8337 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8338 fn, driver_name));
8341 done:
8342 return err;
8345 /****************************************************************
8346 _spoolss_AddPrinterDriver
8347 ****************************************************************/
8349 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8350 struct spoolss_AddPrinterDriver *r)
8352 struct spoolss_AddPrinterDriverEx a;
8354 switch (r->in.info_ctr->level) {
8355 case 2:
8356 case 3:
8357 case 4:
8358 case 5:
8359 break;
8360 default:
8361 return WERR_UNKNOWN_LEVEL;
8364 a.in.servername = r->in.servername;
8365 a.in.info_ctr = r->in.info_ctr;
8366 a.in.flags = APD_COPY_NEW_FILES;
8368 return _spoolss_AddPrinterDriverEx(p, &a);
8371 /****************************************************************************
8372 ****************************************************************************/
8374 struct _spoolss_paths {
8375 int type;
8376 const char *share;
8377 const char *dir;
8380 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8382 static const struct _spoolss_paths spoolss_paths[]= {
8383 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8384 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8387 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8388 const char *servername,
8389 const char *environment,
8390 int component,
8391 char **path)
8393 const char *pservername = NULL;
8394 const char *long_archi;
8395 const char *short_archi;
8397 *path = NULL;
8399 /* environment may be empty */
8400 if (environment && strlen(environment)) {
8401 long_archi = environment;
8402 } else {
8403 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8404 "spoolss", "architecture",
8405 SPOOLSS_ARCHITECTURE_NT_X86);
8408 /* servername may be empty */
8409 if (servername && strlen(servername)) {
8410 pservername = canon_servername(servername);
8412 if (!is_myname_or_ipaddr(pservername)) {
8413 return WERR_INVALID_PARAM;
8417 if (!(short_archi = get_short_archi(long_archi))) {
8418 return WERR_INVALID_ENVIRONMENT;
8421 switch (component) {
8422 case SPOOLSS_PRTPROCS_PATH:
8423 case SPOOLSS_DRIVER_PATH:
8424 if (pservername) {
8425 *path = talloc_asprintf(mem_ctx,
8426 "\\\\%s\\%s\\%s",
8427 pservername,
8428 spoolss_paths[component].share,
8429 short_archi);
8430 } else {
8431 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8432 SPOOLSS_DEFAULT_SERVER_PATH,
8433 spoolss_paths[component].dir,
8434 short_archi);
8436 break;
8437 default:
8438 return WERR_INVALID_PARAM;
8441 if (!*path) {
8442 return WERR_NOMEM;
8445 return WERR_OK;
8448 /****************************************************************************
8449 ****************************************************************************/
8451 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8452 const char *servername,
8453 const char *environment,
8454 struct spoolss_DriverDirectoryInfo1 *r)
8456 WERROR werr;
8457 char *path = NULL;
8459 werr = compose_spoolss_server_path(mem_ctx,
8460 servername,
8461 environment,
8462 SPOOLSS_DRIVER_PATH,
8463 &path);
8464 if (!W_ERROR_IS_OK(werr)) {
8465 return werr;
8468 DEBUG(4,("printer driver directory: [%s]\n", path));
8470 r->directory_name = path;
8472 return WERR_OK;
8475 /****************************************************************
8476 _spoolss_GetPrinterDriverDirectory
8477 ****************************************************************/
8479 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8480 struct spoolss_GetPrinterDriverDirectory *r)
8482 WERROR werror;
8484 /* that's an [in out] buffer */
8486 if (!r->in.buffer && (r->in.offered != 0)) {
8487 return WERR_INVALID_PARAM;
8490 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8491 r->in.level));
8493 *r->out.needed = 0;
8495 /* r->in.level is ignored */
8497 werror = getprinterdriverdir_level_1(p->mem_ctx,
8498 r->in.server,
8499 r->in.environment,
8500 &r->out.info->info1);
8501 if (!W_ERROR_IS_OK(werror)) {
8502 TALLOC_FREE(r->out.info);
8503 return werror;
8506 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8507 r->out.info, r->in.level);
8508 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8510 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8513 /****************************************************************
8514 _spoolss_EnumPrinterData
8515 ****************************************************************/
8517 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8518 struct spoolss_EnumPrinterData *r)
8520 WERROR result;
8521 struct spoolss_EnumPrinterDataEx r2;
8522 uint32_t count;
8523 struct spoolss_PrinterEnumValues *info, *val = NULL;
8524 uint32_t needed;
8526 r2.in.handle = r->in.handle;
8527 r2.in.key_name = "PrinterDriverData";
8528 r2.in.offered = 0;
8529 r2.out.count = &count;
8530 r2.out.info = &info;
8531 r2.out.needed = &needed;
8533 result = _spoolss_EnumPrinterDataEx(p, &r2);
8534 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8535 r2.in.offered = needed;
8536 result = _spoolss_EnumPrinterDataEx(p, &r2);
8538 if (!W_ERROR_IS_OK(result)) {
8539 return result;
8543 * The NT machine wants to know the biggest size of value and data
8545 * cf: MSDN EnumPrinterData remark section
8548 if (!r->in.value_offered && !r->in.data_offered) {
8549 uint32_t biggest_valuesize = 0;
8550 uint32_t biggest_datasize = 0;
8551 int i, name_length;
8553 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8555 for (i=0; i<count; i++) {
8557 name_length = strlen(info[i].value_name);
8558 if (strlen(info[i].value_name) > biggest_valuesize) {
8559 biggest_valuesize = name_length;
8562 if (info[i].data_length > biggest_datasize) {
8563 biggest_datasize = info[i].data_length;
8566 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8567 biggest_datasize));
8570 /* the value is an UNICODE string but real_value_size is the length
8571 in bytes including the trailing 0 */
8573 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8574 *r->out.data_needed = biggest_datasize;
8576 DEBUG(6,("final values: [%d], [%d]\n",
8577 *r->out.value_needed, *r->out.data_needed));
8579 return WERR_OK;
8582 if (r->in.enum_index < count) {
8583 val = &info[r->in.enum_index];
8586 if (val == NULL) {
8587 /* out_value should default to "" or else NT4 has
8588 problems unmarshalling the response */
8590 if (r->in.value_offered) {
8591 *r->out.value_needed = 1;
8592 r->out.value_name = talloc_strdup(r, "");
8593 if (!r->out.value_name) {
8594 return WERR_NOMEM;
8596 } else {
8597 r->out.value_name = NULL;
8598 *r->out.value_needed = 0;
8601 /* the data is counted in bytes */
8603 *r->out.data_needed = r->in.data_offered;
8605 result = WERR_NO_MORE_ITEMS;
8606 } else {
8608 * the value is:
8609 * - counted in bytes in the request
8610 * - counted in UNICODE chars in the max reply
8611 * - counted in bytes in the real size
8613 * take a pause *before* coding not *during* coding
8616 /* name */
8617 if (r->in.value_offered) {
8618 r->out.value_name = talloc_strdup(r, val->value_name);
8619 if (!r->out.value_name) {
8620 return WERR_NOMEM;
8622 *r->out.value_needed = val->value_name_len;
8623 } else {
8624 r->out.value_name = NULL;
8625 *r->out.value_needed = 0;
8628 /* type */
8630 *r->out.type = val->type;
8632 /* data - counted in bytes */
8635 * See the section "Dynamically Typed Query Parameters"
8636 * in MS-RPRN.
8639 if (r->out.data && val->data && val->data->data &&
8640 val->data_length && r->in.data_offered) {
8641 memcpy(r->out.data, val->data->data,
8642 MIN(val->data_length,r->in.data_offered));
8645 *r->out.data_needed = val->data_length;
8647 result = WERR_OK;
8650 return result;
8653 /****************************************************************
8654 _spoolss_SetPrinterData
8655 ****************************************************************/
8657 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8658 struct spoolss_SetPrinterData *r)
8660 struct spoolss_SetPrinterDataEx r2;
8662 r2.in.handle = r->in.handle;
8663 r2.in.key_name = "PrinterDriverData";
8664 r2.in.value_name = r->in.value_name;
8665 r2.in.type = r->in.type;
8666 r2.in.data = r->in.data;
8667 r2.in.offered = r->in.offered;
8669 return _spoolss_SetPrinterDataEx(p, &r2);
8672 /****************************************************************
8673 _spoolss_ResetPrinter
8674 ****************************************************************/
8676 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8677 struct spoolss_ResetPrinter *r)
8679 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8680 int snum;
8682 DEBUG(5,("_spoolss_ResetPrinter\n"));
8685 * All we do is to check to see if the handle and queue is valid.
8686 * This call really doesn't mean anything to us because we only
8687 * support RAW printing. --jerry
8690 if (!Printer) {
8691 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8692 OUR_HANDLE(r->in.handle)));
8693 return WERR_BADFID;
8696 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8697 return WERR_BADFID;
8700 /* blindly return success */
8701 return WERR_OK;
8704 /****************************************************************
8705 _spoolss_DeletePrinterData
8706 ****************************************************************/
8708 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8709 struct spoolss_DeletePrinterData *r)
8711 struct spoolss_DeletePrinterDataEx r2;
8713 r2.in.handle = r->in.handle;
8714 r2.in.key_name = "PrinterDriverData";
8715 r2.in.value_name = r->in.value_name;
8717 return _spoolss_DeletePrinterDataEx(p, &r2);
8720 /****************************************************************
8721 _spoolss_AddForm
8722 ****************************************************************/
8724 WERROR _spoolss_AddForm(struct pipes_struct *p,
8725 struct spoolss_AddForm *r)
8727 struct spoolss_AddFormInfo1 *form;
8728 int snum = -1;
8729 WERROR status = WERR_OK;
8730 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8731 struct dcerpc_binding_handle *b;
8732 TALLOC_CTX *tmp_ctx = NULL;
8734 DEBUG(5,("_spoolss_AddForm\n"));
8736 if (!Printer) {
8737 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8738 OUR_HANDLE(r->in.handle)));
8739 return WERR_BADFID;
8742 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8743 and not a printer admin, then fail */
8745 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8746 !security_token_has_privilege(p->session_info->security_token,
8747 SEC_PRIV_PRINT_OPERATOR)) {
8748 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8749 return WERR_ACCESS_DENIED;
8752 if (r->in.info_ctr->level != 1) {
8753 return WERR_INVALID_LEVEL;
8756 form = r->in.info_ctr->info.info1;
8757 if (!form) {
8758 return WERR_INVALID_PARAM;
8761 switch (form->flags) {
8762 case SPOOLSS_FORM_USER:
8763 case SPOOLSS_FORM_BUILTIN:
8764 case SPOOLSS_FORM_PRINTER:
8765 break;
8766 default:
8767 return WERR_INVALID_PARAM;
8770 tmp_ctx = talloc_new(p->mem_ctx);
8771 if (!tmp_ctx) {
8772 return WERR_NOMEM;
8775 status = winreg_printer_binding_handle(tmp_ctx,
8776 get_session_info_system(),
8777 p->msg_ctx,
8778 &b);
8779 if (!W_ERROR_IS_OK(status)) {
8780 goto done;
8783 status = winreg_printer_addform1(tmp_ctx, b, form);
8784 if (!W_ERROR_IS_OK(status)) {
8785 goto done;
8789 * ChangeID must always be set if this is a printer
8791 if (Printer->printer_type == SPLHND_PRINTER) {
8792 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8793 status = WERR_BADFID;
8794 goto done;
8797 status = winreg_printer_update_changeid(tmp_ctx, b,
8798 lp_const_servicename(snum));
8801 done:
8802 talloc_free(tmp_ctx);
8803 return status;
8806 /****************************************************************
8807 _spoolss_DeleteForm
8808 ****************************************************************/
8810 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8811 struct spoolss_DeleteForm *r)
8813 const char *form_name = r->in.form_name;
8814 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8815 int snum = -1;
8816 WERROR status = WERR_OK;
8817 struct dcerpc_binding_handle *b;
8818 TALLOC_CTX *tmp_ctx = NULL;
8820 DEBUG(5,("_spoolss_DeleteForm\n"));
8822 if (!Printer) {
8823 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8824 OUR_HANDLE(r->in.handle)));
8825 return WERR_BADFID;
8828 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8829 !security_token_has_privilege(p->session_info->security_token,
8830 SEC_PRIV_PRINT_OPERATOR)) {
8831 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8832 return WERR_ACCESS_DENIED;
8835 tmp_ctx = talloc_new(p->mem_ctx);
8836 if (!tmp_ctx) {
8837 return WERR_NOMEM;
8840 status = winreg_printer_binding_handle(tmp_ctx,
8841 get_session_info_system(),
8842 p->msg_ctx,
8843 &b);
8844 if (!W_ERROR_IS_OK(status)) {
8845 goto done;
8848 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8849 if (!W_ERROR_IS_OK(status)) {
8850 goto done;
8854 * ChangeID must always be set if this is a printer
8856 if (Printer->printer_type == SPLHND_PRINTER) {
8857 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8858 status = WERR_BADFID;
8859 goto done;
8862 status = winreg_printer_update_changeid(tmp_ctx, b,
8863 lp_const_servicename(snum));
8866 done:
8867 talloc_free(tmp_ctx);
8868 return status;
8871 /****************************************************************
8872 _spoolss_SetForm
8873 ****************************************************************/
8875 WERROR _spoolss_SetForm(struct pipes_struct *p,
8876 struct spoolss_SetForm *r)
8878 struct spoolss_AddFormInfo1 *form;
8879 const char *form_name = r->in.form_name;
8880 int snum = -1;
8881 WERROR status = WERR_OK;
8882 struct dcerpc_binding_handle *b;
8883 TALLOC_CTX *tmp_ctx = NULL;
8885 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8887 DEBUG(5,("_spoolss_SetForm\n"));
8889 if (!Printer) {
8890 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8891 OUR_HANDLE(r->in.handle)));
8892 return WERR_BADFID;
8895 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8896 and not a printer admin, then fail */
8898 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8899 !security_token_has_privilege(p->session_info->security_token,
8900 SEC_PRIV_PRINT_OPERATOR)) {
8901 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8902 return WERR_ACCESS_DENIED;
8905 if (r->in.info_ctr->level != 1) {
8906 return WERR_INVALID_LEVEL;
8909 form = r->in.info_ctr->info.info1;
8910 if (!form) {
8911 return WERR_INVALID_PARAM;
8914 tmp_ctx = talloc_new(p->mem_ctx);
8915 if (!tmp_ctx) {
8916 return WERR_NOMEM;
8919 status = winreg_printer_binding_handle(tmp_ctx,
8920 get_session_info_system(),
8921 p->msg_ctx,
8922 &b);
8923 if (!W_ERROR_IS_OK(status)) {
8924 goto done;
8927 status = winreg_printer_setform1(tmp_ctx, b,
8928 form_name,
8929 form);
8930 if (!W_ERROR_IS_OK(status)) {
8931 goto done;
8935 * ChangeID must always be set if this is a printer
8937 if (Printer->printer_type == SPLHND_PRINTER) {
8938 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8939 status = WERR_BADFID;
8940 goto done;
8943 status = winreg_printer_update_changeid(tmp_ctx, b,
8944 lp_const_servicename(snum));
8947 done:
8948 talloc_free(tmp_ctx);
8949 return status;
8952 /****************************************************************************
8953 fill_print_processor1
8954 ****************************************************************************/
8956 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8957 struct spoolss_PrintProcessorInfo1 *r,
8958 const char *print_processor_name)
8960 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8961 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8963 return WERR_OK;
8966 /****************************************************************************
8967 enumprintprocessors level 1.
8968 ****************************************************************************/
8970 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8971 union spoolss_PrintProcessorInfo **info_p,
8972 uint32_t *count)
8974 union spoolss_PrintProcessorInfo *info;
8975 WERROR result;
8977 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8978 W_ERROR_HAVE_NO_MEMORY(info);
8980 *count = 1;
8982 result = fill_print_processor1(info, &info[0].info1, "winprint");
8983 if (!W_ERROR_IS_OK(result)) {
8984 goto out;
8987 out:
8988 if (!W_ERROR_IS_OK(result)) {
8989 TALLOC_FREE(info);
8990 *count = 0;
8991 return result;
8994 *info_p = info;
8996 return WERR_OK;
8999 /****************************************************************
9000 _spoolss_EnumPrintProcessors
9001 ****************************************************************/
9003 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9004 struct spoolss_EnumPrintProcessors *r)
9006 WERROR result;
9008 /* that's an [in out] buffer */
9010 if (!r->in.buffer && (r->in.offered != 0)) {
9011 return WERR_INVALID_PARAM;
9014 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9017 * Enumerate the print processors ...
9019 * Just reply with "winprint", to keep NT happy
9020 * and I can use my nice printer checker.
9023 *r->out.count = 0;
9024 *r->out.needed = 0;
9025 *r->out.info = NULL;
9027 if (!get_short_archi(r->in.environment)) {
9028 return WERR_INVALID_ENVIRONMENT;
9031 switch (r->in.level) {
9032 case 1:
9033 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9034 r->out.count);
9035 break;
9036 default:
9037 return WERR_UNKNOWN_LEVEL;
9040 if (!W_ERROR_IS_OK(result)) {
9041 return result;
9044 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9045 spoolss_EnumPrintProcessors,
9046 *r->out.info, r->in.level,
9047 *r->out.count);
9048 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9049 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9051 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9054 /****************************************************************************
9055 fill_printprocdatatype1
9056 ****************************************************************************/
9058 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9059 struct spoolss_PrintProcDataTypesInfo1 *r,
9060 const char *name_array)
9062 r->name_array = talloc_strdup(mem_ctx, name_array);
9063 W_ERROR_HAVE_NO_MEMORY(r->name_array);
9065 return WERR_OK;
9068 /****************************************************************************
9069 enumprintprocdatatypes level 1.
9070 ****************************************************************************/
9072 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9073 union spoolss_PrintProcDataTypesInfo **info_p,
9074 uint32_t *count)
9076 WERROR result;
9077 union spoolss_PrintProcDataTypesInfo *info;
9079 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9080 W_ERROR_HAVE_NO_MEMORY(info);
9082 *count = 1;
9084 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9085 if (!W_ERROR_IS_OK(result)) {
9086 goto out;
9089 out:
9090 if (!W_ERROR_IS_OK(result)) {
9091 TALLOC_FREE(info);
9092 *count = 0;
9093 return result;
9096 *info_p = info;
9098 return WERR_OK;
9101 /****************************************************************
9102 _spoolss_EnumPrintProcDataTypes
9103 ****************************************************************/
9105 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9106 struct spoolss_EnumPrintProcDataTypes *r)
9108 WERROR result;
9110 /* that's an [in out] buffer */
9112 if (!r->in.buffer && (r->in.offered != 0)) {
9113 return WERR_INVALID_PARAM;
9116 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9118 *r->out.count = 0;
9119 *r->out.needed = 0;
9120 *r->out.info = NULL;
9122 if (r->in.print_processor_name == NULL ||
9123 !strequal(r->in.print_processor_name, "winprint")) {
9124 return WERR_UNKNOWN_PRINTPROCESSOR;
9127 switch (r->in.level) {
9128 case 1:
9129 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9130 r->out.count);
9131 break;
9132 default:
9133 return WERR_UNKNOWN_LEVEL;
9136 if (!W_ERROR_IS_OK(result)) {
9137 return result;
9140 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9141 spoolss_EnumPrintProcDataTypes,
9142 *r->out.info, r->in.level,
9143 *r->out.count);
9144 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9145 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9147 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9150 /****************************************************************************
9151 fill_monitor_1
9152 ****************************************************************************/
9154 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9155 struct spoolss_MonitorInfo1 *r,
9156 const char *monitor_name)
9158 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9159 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9161 return WERR_OK;
9164 /****************************************************************************
9165 fill_monitor_2
9166 ****************************************************************************/
9168 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9169 struct spoolss_MonitorInfo2 *r,
9170 const char *monitor_name,
9171 const char *environment,
9172 const char *dll_name)
9174 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9175 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9176 r->environment = talloc_strdup(mem_ctx, environment);
9177 W_ERROR_HAVE_NO_MEMORY(r->environment);
9178 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9179 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9181 return WERR_OK;
9184 /****************************************************************************
9185 enumprintmonitors level 1.
9186 ****************************************************************************/
9188 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9189 union spoolss_MonitorInfo **info_p,
9190 uint32_t *count)
9192 union spoolss_MonitorInfo *info;
9193 WERROR result = WERR_OK;
9195 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9196 W_ERROR_HAVE_NO_MEMORY(info);
9198 *count = 2;
9200 result = fill_monitor_1(info, &info[0].info1,
9201 SPL_LOCAL_PORT);
9202 if (!W_ERROR_IS_OK(result)) {
9203 goto out;
9206 result = fill_monitor_1(info, &info[1].info1,
9207 SPL_TCPIP_PORT);
9208 if (!W_ERROR_IS_OK(result)) {
9209 goto out;
9212 out:
9213 if (!W_ERROR_IS_OK(result)) {
9214 TALLOC_FREE(info);
9215 *count = 0;
9216 return result;
9219 *info_p = info;
9221 return WERR_OK;
9224 /****************************************************************************
9225 enumprintmonitors level 2.
9226 ****************************************************************************/
9228 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9229 union spoolss_MonitorInfo **info_p,
9230 uint32_t *count)
9232 union spoolss_MonitorInfo *info;
9233 WERROR result = WERR_OK;
9235 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9236 W_ERROR_HAVE_NO_MEMORY(info);
9238 *count = 2;
9240 result = fill_monitor_2(info, &info[0].info2,
9241 SPL_LOCAL_PORT,
9242 "Windows NT X86", /* FIXME */
9243 "localmon.dll");
9244 if (!W_ERROR_IS_OK(result)) {
9245 goto out;
9248 result = fill_monitor_2(info, &info[1].info2,
9249 SPL_TCPIP_PORT,
9250 "Windows NT X86", /* FIXME */
9251 "tcpmon.dll");
9252 if (!W_ERROR_IS_OK(result)) {
9253 goto out;
9256 out:
9257 if (!W_ERROR_IS_OK(result)) {
9258 TALLOC_FREE(info);
9259 *count = 0;
9260 return result;
9263 *info_p = info;
9265 return WERR_OK;
9268 /****************************************************************
9269 _spoolss_EnumMonitors
9270 ****************************************************************/
9272 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9273 struct spoolss_EnumMonitors *r)
9275 WERROR result;
9277 /* that's an [in out] buffer */
9279 if (!r->in.buffer && (r->in.offered != 0)) {
9280 return WERR_INVALID_PARAM;
9283 DEBUG(5,("_spoolss_EnumMonitors\n"));
9286 * Enumerate the print monitors ...
9288 * Just reply with "Local Port", to keep NT happy
9289 * and I can use my nice printer checker.
9292 *r->out.count = 0;
9293 *r->out.needed = 0;
9294 *r->out.info = NULL;
9296 switch (r->in.level) {
9297 case 1:
9298 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9299 r->out.count);
9300 break;
9301 case 2:
9302 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9303 r->out.count);
9304 break;
9305 default:
9306 return WERR_UNKNOWN_LEVEL;
9309 if (!W_ERROR_IS_OK(result)) {
9310 return result;
9313 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9314 spoolss_EnumMonitors,
9315 *r->out.info, r->in.level,
9316 *r->out.count);
9317 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9318 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9320 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9323 /****************************************************************************
9324 ****************************************************************************/
9326 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9327 const print_queue_struct *queue,
9328 int count, int snum,
9329 struct spoolss_PrinterInfo2 *pinfo2,
9330 uint32_t jobid,
9331 struct spoolss_JobInfo1 *r)
9333 int i = 0;
9334 bool found = false;
9336 for (i=0; i<count; i++) {
9337 if (queue[i].sysjob == (int)jobid) {
9338 found = true;
9339 break;
9343 if (found == false) {
9344 /* NT treats not found as bad param... yet another bad choice */
9345 return WERR_INVALID_PARAM;
9348 return fill_job_info1(mem_ctx,
9350 &queue[i],
9352 snum,
9353 pinfo2);
9356 /****************************************************************************
9357 ****************************************************************************/
9359 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9360 const print_queue_struct *queue,
9361 int count, int snum,
9362 struct spoolss_PrinterInfo2 *pinfo2,
9363 uint32_t jobid,
9364 struct spoolss_JobInfo2 *r)
9366 int i = 0;
9367 bool found = false;
9368 struct spoolss_DeviceMode *devmode;
9369 WERROR result;
9371 for (i=0; i<count; i++) {
9372 if (queue[i].sysjob == (int)jobid) {
9373 found = true;
9374 break;
9378 if (found == false) {
9379 /* NT treats not found as bad param... yet another bad
9380 choice */
9381 return WERR_INVALID_PARAM;
9385 * if the print job does not have a DEVMODE associated with it,
9386 * just use the one for the printer. A NULL devicemode is not
9387 * a failure condition
9390 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9391 if (!devmode) {
9392 result = spoolss_create_default_devmode(mem_ctx,
9393 pinfo2->printername,
9394 &devmode);
9395 if (!W_ERROR_IS_OK(result)) {
9396 DEBUG(3, ("Can't proceed w/o a devmode!"));
9397 return result;
9401 return fill_job_info2(mem_ctx,
9403 &queue[i],
9405 snum,
9406 pinfo2,
9407 devmode);
9410 /****************************************************************
9411 _spoolss_GetJob
9412 ****************************************************************/
9414 WERROR _spoolss_GetJob(struct pipes_struct *p,
9415 struct spoolss_GetJob *r)
9417 WERROR result = WERR_OK;
9418 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9419 int snum;
9420 int count;
9421 print_queue_struct *queue = NULL;
9422 print_status_struct prt_status;
9424 /* that's an [in out] buffer */
9426 if (!r->in.buffer && (r->in.offered != 0)) {
9427 return WERR_INVALID_PARAM;
9430 DEBUG(5,("_spoolss_GetJob\n"));
9432 *r->out.needed = 0;
9434 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9435 return WERR_BADFID;
9438 result = winreg_get_printer_internal(p->mem_ctx,
9439 get_session_info_system(),
9440 p->msg_ctx,
9441 lp_const_servicename(snum),
9442 &pinfo2);
9443 if (!W_ERROR_IS_OK(result)) {
9444 return result;
9447 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9449 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9450 count, prt_status.status, prt_status.message));
9452 switch (r->in.level) {
9453 case 1:
9454 result = getjob_level_1(p->mem_ctx,
9455 queue, count, snum, pinfo2,
9456 r->in.job_id, &r->out.info->info1);
9457 break;
9458 case 2:
9459 result = getjob_level_2(p->mem_ctx,
9460 queue, count, snum, pinfo2,
9461 r->in.job_id, &r->out.info->info2);
9462 break;
9463 default:
9464 result = WERR_UNKNOWN_LEVEL;
9465 break;
9468 SAFE_FREE(queue);
9469 TALLOC_FREE(pinfo2);
9471 if (!W_ERROR_IS_OK(result)) {
9472 TALLOC_FREE(r->out.info);
9473 return result;
9476 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9477 r->in.level);
9478 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9480 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9483 /****************************************************************
9484 _spoolss_GetPrinterDataEx
9485 ****************************************************************/
9487 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9488 struct spoolss_GetPrinterDataEx *r)
9491 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9492 const char *printer;
9493 int snum = 0;
9494 WERROR result = WERR_OK;
9495 DATA_BLOB blob;
9496 enum winreg_Type val_type = REG_NONE;
9497 uint8_t *val_data = NULL;
9498 uint32_t val_size = 0;
9499 struct dcerpc_binding_handle *b;
9500 TALLOC_CTX *tmp_ctx;
9502 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9504 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9505 r->in.key_name, r->in.value_name));
9507 /* in case of problem, return some default values */
9509 *r->out.needed = 0;
9510 *r->out.type = REG_NONE;
9512 tmp_ctx = talloc_new(p->mem_ctx);
9513 if (!tmp_ctx) {
9514 return WERR_NOMEM;
9517 if (!Printer) {
9518 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9519 OUR_HANDLE(r->in.handle)));
9520 result = WERR_BADFID;
9521 goto done;
9524 /* check to see if the keyname is valid */
9525 if (!strlen(r->in.key_name)) {
9526 result = WERR_INVALID_PARAM;
9527 goto done;
9530 /* Is the handle to a printer or to the server? */
9532 if (Printer->printer_type == SPLHND_SERVER) {
9534 union spoolss_PrinterData data;
9536 result = getprinterdata_printer_server(tmp_ctx,
9537 r->in.value_name,
9538 r->out.type,
9539 &data);
9540 if (!W_ERROR_IS_OK(result)) {
9541 goto done;
9544 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9545 *r->out.type, &data);
9546 if (!W_ERROR_IS_OK(result)) {
9547 goto done;
9550 *r->out.needed = blob.length;
9552 if (r->in.offered >= *r->out.needed) {
9553 memcpy(r->out.data, blob.data, blob.length);
9556 result = WERR_OK;
9557 goto done;
9560 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9561 result = WERR_BADFID;
9562 goto done;
9564 printer = lp_const_servicename(snum);
9566 result = winreg_printer_binding_handle(tmp_ctx,
9567 get_session_info_system(),
9568 p->msg_ctx,
9569 &b);
9570 if (!W_ERROR_IS_OK(result)) {
9571 goto done;
9574 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9575 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9576 strequal(r->in.value_name, "ChangeId")) {
9577 *r->out.type = REG_DWORD;
9578 *r->out.needed = 4;
9579 if (r->in.offered >= *r->out.needed) {
9580 uint32_t changeid = 0;
9582 result = winreg_printer_get_changeid(tmp_ctx, b,
9583 printer,
9584 &changeid);
9585 if (!W_ERROR_IS_OK(result)) {
9586 goto done;
9589 SIVAL(r->out.data, 0, changeid);
9590 result = WERR_OK;
9592 goto done;
9595 result = winreg_get_printer_dataex(tmp_ctx, b,
9596 printer,
9597 r->in.key_name,
9598 r->in.value_name,
9599 &val_type,
9600 &val_data,
9601 &val_size);
9602 if (!W_ERROR_IS_OK(result)) {
9603 goto done;
9606 *r->out.needed = val_size;
9607 *r->out.type = val_type;
9609 if (r->in.offered >= *r->out.needed) {
9610 memcpy(r->out.data, val_data, val_size);
9613 done:
9614 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9616 if (W_ERROR_IS_OK(result)) {
9617 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9620 talloc_free(tmp_ctx);
9621 return result;
9624 /****************************************************************
9625 _spoolss_SetPrinterDataEx
9626 ****************************************************************/
9628 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9629 struct spoolss_SetPrinterDataEx *r)
9631 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9632 int snum = 0;
9633 WERROR result = WERR_OK;
9634 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9635 char *oid_string;
9636 struct dcerpc_binding_handle *b;
9637 TALLOC_CTX *tmp_ctx;
9639 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9641 /* From MSDN documentation of SetPrinterDataEx: pass request to
9642 SetPrinterData if key is "PrinterDriverData" */
9644 if (!Printer) {
9645 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9646 OUR_HANDLE(r->in.handle)));
9647 return WERR_BADFID;
9650 if (Printer->printer_type == SPLHND_SERVER) {
9651 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9652 "Not implemented for server handles yet\n"));
9653 return WERR_INVALID_PARAM;
9656 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9657 return WERR_BADFID;
9661 * Access check : NT returns "access denied" if you make a
9662 * SetPrinterData call without the necessary privildge.
9663 * we were originally returning OK if nothing changed
9664 * which made Win2k issue **a lot** of SetPrinterData
9665 * when connecting to a printer --jerry
9668 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9669 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9670 "change denied by handle access permissions\n"));
9671 return WERR_ACCESS_DENIED;
9674 tmp_ctx = talloc_new(p->mem_ctx);
9675 if (!tmp_ctx) {
9676 return WERR_NOMEM;
9679 result = winreg_printer_binding_handle(tmp_ctx,
9680 get_session_info_system(),
9681 p->msg_ctx,
9682 &b);
9683 if (!W_ERROR_IS_OK(result)) {
9684 goto done;
9687 result = winreg_get_printer(tmp_ctx, b,
9688 lp_servicename(talloc_tos(), snum),
9689 &pinfo2);
9690 if (!W_ERROR_IS_OK(result)) {
9691 goto done;
9694 /* check for OID in valuename */
9696 oid_string = strchr(r->in.value_name, ',');
9697 if (oid_string) {
9698 *oid_string = '\0';
9699 oid_string++;
9702 /* save the registry data */
9704 result = winreg_set_printer_dataex(tmp_ctx, b,
9705 pinfo2->sharename,
9706 r->in.key_name,
9707 r->in.value_name,
9708 r->in.type,
9709 r->in.data,
9710 r->in.offered);
9712 if (W_ERROR_IS_OK(result)) {
9713 /* save the OID if one was specified */
9714 if (oid_string) {
9715 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9716 r->in.key_name, SPOOL_OID_KEY);
9717 if (!str) {
9718 result = WERR_NOMEM;
9719 goto done;
9723 * I'm not checking the status here on purpose. Don't know
9724 * if this is right, but I'm returning the status from the
9725 * previous set_printer_dataex() call. I have no idea if
9726 * this is right. --jerry
9728 winreg_set_printer_dataex(tmp_ctx, b,
9729 pinfo2->sharename,
9730 str,
9731 r->in.value_name,
9732 REG_SZ,
9733 (uint8_t *) oid_string,
9734 strlen(oid_string) + 1);
9737 result = winreg_printer_update_changeid(tmp_ctx, b,
9738 lp_const_servicename(snum));
9742 done:
9743 talloc_free(tmp_ctx);
9744 return result;
9747 /****************************************************************
9748 _spoolss_DeletePrinterDataEx
9749 ****************************************************************/
9751 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9752 struct spoolss_DeletePrinterDataEx *r)
9754 const char *printer;
9755 int snum=0;
9756 WERROR status = WERR_OK;
9757 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9759 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9761 if (!Printer) {
9762 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9763 "Invalid handle (%s:%u:%u).\n",
9764 OUR_HANDLE(r->in.handle)));
9765 return WERR_BADFID;
9768 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9769 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9770 "printer properties change denied by handle\n"));
9771 return WERR_ACCESS_DENIED;
9774 if (!r->in.value_name || !r->in.key_name) {
9775 return WERR_NOMEM;
9778 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9779 return WERR_BADFID;
9781 printer = lp_const_servicename(snum);
9783 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9784 get_session_info_system(),
9785 p->msg_ctx,
9786 printer,
9787 r->in.key_name,
9788 r->in.value_name);
9789 if (W_ERROR_IS_OK(status)) {
9790 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9791 get_session_info_system(),
9792 p->msg_ctx,
9793 printer);
9796 return status;
9799 /****************************************************************
9800 _spoolss_EnumPrinterKey
9801 ****************************************************************/
9803 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9804 struct spoolss_EnumPrinterKey *r)
9806 uint32_t num_keys;
9807 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9808 int snum = 0;
9809 WERROR result = WERR_BADFILE;
9810 const char **array = NULL;
9811 DATA_BLOB blob;
9813 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9815 if (!Printer) {
9816 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9817 OUR_HANDLE(r->in.handle)));
9818 return WERR_BADFID;
9821 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9822 return WERR_BADFID;
9825 result = winreg_enum_printer_key_internal(p->mem_ctx,
9826 get_session_info_system(),
9827 p->msg_ctx,
9828 lp_const_servicename(snum),
9829 r->in.key_name,
9830 &num_keys,
9831 &array);
9832 if (!W_ERROR_IS_OK(result)) {
9833 goto done;
9836 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9837 result = WERR_NOMEM;
9838 goto done;
9841 *r->out._ndr_size = r->in.offered / 2;
9842 *r->out.needed = blob.length;
9844 if (r->in.offered < *r->out.needed) {
9845 result = WERR_MORE_DATA;
9846 } else {
9847 result = WERR_OK;
9848 r->out.key_buffer->string_array = array;
9851 done:
9852 if (!W_ERROR_IS_OK(result)) {
9853 TALLOC_FREE(array);
9854 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9855 *r->out.needed = 0;
9859 return result;
9862 /****************************************************************
9863 _spoolss_DeletePrinterKey
9864 ****************************************************************/
9866 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9867 struct spoolss_DeletePrinterKey *r)
9869 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9870 int snum=0;
9871 WERROR status;
9872 const char *printer;
9873 struct dcerpc_binding_handle *b;
9874 TALLOC_CTX *tmp_ctx;
9876 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9878 if (!Printer) {
9879 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9880 OUR_HANDLE(r->in.handle)));
9881 return WERR_BADFID;
9884 /* if keyname == NULL, return error */
9885 if ( !r->in.key_name )
9886 return WERR_INVALID_PARAM;
9888 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9889 return WERR_BADFID;
9892 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9893 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9894 "printer properties change denied by handle\n"));
9895 return WERR_ACCESS_DENIED;
9898 printer = lp_const_servicename(snum);
9900 tmp_ctx = talloc_new(p->mem_ctx);
9901 if (!tmp_ctx) {
9902 return WERR_NOMEM;
9905 status = winreg_printer_binding_handle(tmp_ctx,
9906 get_session_info_system(),
9907 p->msg_ctx,
9908 &b);
9909 if (!W_ERROR_IS_OK(status)) {
9910 goto done;
9913 /* delete the key and all subkeys */
9914 status = winreg_delete_printer_key(tmp_ctx, b,
9915 printer,
9916 r->in.key_name);
9917 if (W_ERROR_IS_OK(status)) {
9918 status = winreg_printer_update_changeid(tmp_ctx, b,
9919 printer);
9922 done:
9923 talloc_free(tmp_ctx);
9924 return status;
9927 /****************************************************************
9928 _spoolss_EnumPrinterDataEx
9929 ****************************************************************/
9931 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9932 struct spoolss_EnumPrinterDataEx *r)
9934 uint32_t count = 0;
9935 struct spoolss_PrinterEnumValues *info = NULL;
9936 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9937 int snum;
9938 WERROR result;
9940 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9942 *r->out.count = 0;
9943 *r->out.needed = 0;
9944 *r->out.info = NULL;
9946 if (!Printer) {
9947 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9948 OUR_HANDLE(r->in.handle)));
9949 return WERR_BADFID;
9953 * first check for a keyname of NULL or "". Win2k seems to send
9954 * this a lot and we should send back WERR_INVALID_PARAM
9955 * no need to spend time looking up the printer in this case.
9956 * --jerry
9959 if (!strlen(r->in.key_name)) {
9960 result = WERR_INVALID_PARAM;
9961 goto done;
9964 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9965 return WERR_BADFID;
9968 /* now look for a match on the key name */
9969 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9970 get_session_info_system(),
9971 p->msg_ctx,
9972 lp_const_servicename(snum),
9973 r->in.key_name,
9974 &count,
9975 &info);
9976 if (!W_ERROR_IS_OK(result)) {
9977 goto done;
9980 #if 0 /* FIXME - gd */
9981 /* housekeeping information in the reply */
9983 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9984 * the hand marshalled container size is a multiple
9985 * of 4 bytes for RPC alignment.
9988 if (needed % 4) {
9989 needed += 4-(needed % 4);
9991 #endif
9992 *r->out.count = count;
9993 *r->out.info = info;
9995 done:
9996 if (!W_ERROR_IS_OK(result)) {
9997 return result;
10000 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10001 spoolss_EnumPrinterDataEx,
10002 *r->out.info,
10003 *r->out.count);
10004 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10005 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10007 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10010 /****************************************************************************
10011 ****************************************************************************/
10013 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10014 const char *servername,
10015 const char *environment,
10016 struct spoolss_PrintProcessorDirectoryInfo1 *r)
10018 WERROR werr;
10019 char *path = NULL;
10021 werr = compose_spoolss_server_path(mem_ctx,
10022 servername,
10023 environment,
10024 SPOOLSS_PRTPROCS_PATH,
10025 &path);
10026 if (!W_ERROR_IS_OK(werr)) {
10027 return werr;
10030 DEBUG(4,("print processor directory: [%s]\n", path));
10032 r->directory_name = path;
10034 return WERR_OK;
10037 /****************************************************************
10038 _spoolss_GetPrintProcessorDirectory
10039 ****************************************************************/
10041 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10042 struct spoolss_GetPrintProcessorDirectory *r)
10044 WERROR result;
10045 char *prnproc_share = NULL;
10046 bool prnproc_share_exists = false;
10047 int snum;
10049 /* that's an [in out] buffer */
10051 if (!r->in.buffer && (r->in.offered != 0)) {
10052 return WERR_INVALID_PARAM;
10055 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10056 r->in.level));
10058 *r->out.needed = 0;
10060 /* r->in.level is ignored */
10062 /* We always should reply with a local print processor directory so that
10063 * users are not forced to have a [prnproc$] share on the Samba spoolss
10064 * server, if users decide to do so, lets announce it though - Guenther */
10066 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10067 if (!prnproc_share) {
10068 return WERR_NOMEM;
10070 if (snum != -1) {
10071 prnproc_share_exists = true;
10074 result = getprintprocessordirectory_level_1(p->mem_ctx,
10075 prnproc_share_exists ? r->in.server : NULL,
10076 r->in.environment,
10077 &r->out.info->info1);
10078 if (!W_ERROR_IS_OK(result)) {
10079 TALLOC_FREE(r->out.info);
10080 return result;
10083 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10084 r->out.info, r->in.level);
10085 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10087 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10090 /*******************************************************************
10091 ********************************************************************/
10093 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10094 const char *dllname)
10096 enum ndr_err_code ndr_err;
10097 struct spoolss_MonitorUi ui;
10099 ui.dll_name = dllname;
10101 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10102 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10103 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10104 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10106 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10109 /*******************************************************************
10110 Streams the monitor UI DLL name in UNICODE
10111 *******************************************************************/
10113 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10114 struct security_token *token, DATA_BLOB *in,
10115 DATA_BLOB *out, uint32_t *needed)
10117 const char *dllname = "tcpmonui.dll";
10119 *needed = (strlen(dllname)+1) * 2;
10121 if (out->length < *needed) {
10122 return WERR_INSUFFICIENT_BUFFER;
10125 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10126 return WERR_NOMEM;
10129 return WERR_OK;
10132 /*******************************************************************
10133 ********************************************************************/
10135 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10136 struct spoolss_PortData1 *port1,
10137 const DATA_BLOB *buf)
10139 enum ndr_err_code ndr_err;
10140 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10141 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10142 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10143 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10145 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10148 /*******************************************************************
10149 ********************************************************************/
10151 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10152 struct spoolss_PortData2 *port2,
10153 const DATA_BLOB *buf)
10155 enum ndr_err_code ndr_err;
10156 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10157 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10158 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10159 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10161 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10164 /*******************************************************************
10165 Create a new TCP/IP port
10166 *******************************************************************/
10168 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10169 struct security_token *token, DATA_BLOB *in,
10170 DATA_BLOB *out, uint32_t *needed)
10172 struct spoolss_PortData1 port1;
10173 struct spoolss_PortData2 port2;
10174 char *device_uri = NULL;
10175 uint32_t version;
10177 const char *portname;
10178 const char *hostaddress;
10179 const char *queue;
10180 uint32_t port_number;
10181 uint32_t protocol;
10183 /* peek for spoolss_PortData version */
10185 if (!in || (in->length < (128 + 4))) {
10186 return WERR_GENERAL_FAILURE;
10189 version = IVAL(in->data, 128);
10191 switch (version) {
10192 case 1:
10193 ZERO_STRUCT(port1);
10195 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10196 return WERR_NOMEM;
10199 portname = port1.portname;
10200 hostaddress = port1.hostaddress;
10201 queue = port1.queue;
10202 protocol = port1.protocol;
10203 port_number = port1.port_number;
10205 break;
10206 case 2:
10207 ZERO_STRUCT(port2);
10209 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10210 return WERR_NOMEM;
10213 portname = port2.portname;
10214 hostaddress = port2.hostaddress;
10215 queue = port2.queue;
10216 protocol = port2.protocol;
10217 port_number = port2.port_number;
10219 break;
10220 default:
10221 DEBUG(1,("xcvtcp_addport: "
10222 "unknown version of port_data: %d\n", version));
10223 return WERR_UNKNOWN_PORT;
10226 /* create the device URI and call the add_port_hook() */
10228 switch (protocol) {
10229 case PROTOCOL_RAWTCP_TYPE:
10230 device_uri = talloc_asprintf(mem_ctx,
10231 "socket://%s:%d/", hostaddress,
10232 port_number);
10233 break;
10235 case PROTOCOL_LPR_TYPE:
10236 device_uri = talloc_asprintf(mem_ctx,
10237 "lpr://%s/%s", hostaddress, queue );
10238 break;
10240 default:
10241 return WERR_UNKNOWN_PORT;
10244 if (!device_uri) {
10245 return WERR_NOMEM;
10248 return add_port_hook(mem_ctx, token, portname, device_uri);
10251 /*******************************************************************
10252 *******************************************************************/
10254 struct xcv_api_table xcvtcp_cmds[] = {
10255 { "MonitorUI", xcvtcp_monitorui },
10256 { "AddPort", xcvtcp_addport},
10257 { NULL, NULL }
10260 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10261 struct security_token *token, const char *command,
10262 DATA_BLOB *inbuf,
10263 DATA_BLOB *outbuf,
10264 uint32_t *needed )
10266 int i;
10268 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10270 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10271 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10272 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10275 return WERR_BADFUNC;
10278 /*******************************************************************
10279 *******************************************************************/
10280 #if 0 /* don't support management using the "Local Port" monitor */
10282 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10283 struct security_token *token, DATA_BLOB *in,
10284 DATA_BLOB *out, uint32_t *needed)
10286 const char *dllname = "localui.dll";
10288 *needed = (strlen(dllname)+1) * 2;
10290 if (out->length < *needed) {
10291 return WERR_INSUFFICIENT_BUFFER;
10294 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10295 return WERR_NOMEM;
10298 return WERR_OK;
10301 /*******************************************************************
10302 *******************************************************************/
10304 struct xcv_api_table xcvlocal_cmds[] = {
10305 { "MonitorUI", xcvlocal_monitorui },
10306 { NULL, NULL }
10308 #else
10309 struct xcv_api_table xcvlocal_cmds[] = {
10310 { NULL, NULL }
10312 #endif
10316 /*******************************************************************
10317 *******************************************************************/
10319 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10320 struct security_token *token, const char *command,
10321 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10322 uint32_t *needed)
10324 int i;
10326 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10328 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10329 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10330 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10332 return WERR_BADFUNC;
10335 /****************************************************************
10336 _spoolss_XcvData
10337 ****************************************************************/
10339 WERROR _spoolss_XcvData(struct pipes_struct *p,
10340 struct spoolss_XcvData *r)
10342 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10343 DATA_BLOB out_data = data_blob_null;
10344 WERROR werror;
10346 if (!Printer) {
10347 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10348 OUR_HANDLE(r->in.handle)));
10349 return WERR_BADFID;
10352 /* Has to be a handle to the TCP/IP port monitor */
10354 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10355 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10356 return WERR_BADFID;
10359 /* requires administrative access to the server */
10361 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10362 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10363 return WERR_ACCESS_DENIED;
10366 /* Allocate the outgoing buffer */
10368 if (r->in.out_data_size) {
10369 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10370 if (out_data.data == NULL) {
10371 return WERR_NOMEM;
10375 switch ( Printer->printer_type ) {
10376 case SPLHND_PORTMON_TCP:
10377 werror = process_xcvtcp_command(p->mem_ctx,
10378 p->session_info->security_token,
10379 r->in.function_name,
10380 &r->in.in_data, &out_data,
10381 r->out.needed);
10382 break;
10383 case SPLHND_PORTMON_LOCAL:
10384 werror = process_xcvlocal_command(p->mem_ctx,
10385 p->session_info->security_token,
10386 r->in.function_name,
10387 &r->in.in_data, &out_data,
10388 r->out.needed);
10389 break;
10390 default:
10391 werror = WERR_INVALID_PRINT_MONITOR;
10394 if (!W_ERROR_IS_OK(werror)) {
10395 return werror;
10398 *r->out.status_code = 0;
10400 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10401 memcpy(r->out.out_data, out_data.data,
10402 MIN(r->in.out_data_size, out_data.length));
10405 return WERR_OK;
10408 /****************************************************************
10409 _spoolss_AddPrintProcessor
10410 ****************************************************************/
10412 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10413 struct spoolss_AddPrintProcessor *r)
10415 /* for now, just indicate success and ignore the add. We'll
10416 automatically set the winprint processor for printer
10417 entries later. Used to debug the LexMark Optra S 1855 PCL
10418 driver --jerry */
10420 return WERR_OK;
10423 /****************************************************************
10424 _spoolss_AddPort
10425 ****************************************************************/
10427 WERROR _spoolss_AddPort(struct pipes_struct *p,
10428 struct spoolss_AddPort *r)
10430 /* do what w2k3 does */
10432 return WERR_NOT_SUPPORTED;
10435 /****************************************************************
10436 _spoolss_GetPrinterDriver
10437 ****************************************************************/
10439 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10440 struct spoolss_GetPrinterDriver *r)
10442 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10443 return WERR_NOT_SUPPORTED;
10446 /****************************************************************
10447 _spoolss_ReadPrinter
10448 ****************************************************************/
10450 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10451 struct spoolss_ReadPrinter *r)
10453 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10454 return WERR_NOT_SUPPORTED;
10457 /****************************************************************
10458 _spoolss_WaitForPrinterChange
10459 ****************************************************************/
10461 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10462 struct spoolss_WaitForPrinterChange *r)
10464 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10465 return WERR_NOT_SUPPORTED;
10468 /****************************************************************
10469 _spoolss_ConfigurePort
10470 ****************************************************************/
10472 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10473 struct spoolss_ConfigurePort *r)
10475 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10476 return WERR_NOT_SUPPORTED;
10479 /****************************************************************
10480 _spoolss_DeletePort
10481 ****************************************************************/
10483 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10484 struct spoolss_DeletePort *r)
10486 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10487 return WERR_NOT_SUPPORTED;
10490 /****************************************************************
10491 _spoolss_CreatePrinterIC
10492 ****************************************************************/
10494 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10495 struct spoolss_CreatePrinterIC *r)
10497 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10498 return WERR_NOT_SUPPORTED;
10501 /****************************************************************
10502 _spoolss_PlayGDIScriptOnPrinterIC
10503 ****************************************************************/
10505 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10506 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10508 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10509 return WERR_NOT_SUPPORTED;
10512 /****************************************************************
10513 _spoolss_DeletePrinterIC
10514 ****************************************************************/
10516 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10517 struct spoolss_DeletePrinterIC *r)
10519 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10520 return WERR_NOT_SUPPORTED;
10523 /****************************************************************
10524 _spoolss_AddPrinterConnection
10525 ****************************************************************/
10527 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10528 struct spoolss_AddPrinterConnection *r)
10530 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10531 return WERR_NOT_SUPPORTED;
10534 /****************************************************************
10535 _spoolss_DeletePrinterConnection
10536 ****************************************************************/
10538 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10539 struct spoolss_DeletePrinterConnection *r)
10541 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10542 return WERR_NOT_SUPPORTED;
10545 /****************************************************************
10546 _spoolss_PrinterMessageBox
10547 ****************************************************************/
10549 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10550 struct spoolss_PrinterMessageBox *r)
10552 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10553 return WERR_NOT_SUPPORTED;
10556 /****************************************************************
10557 _spoolss_AddMonitor
10558 ****************************************************************/
10560 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10561 struct spoolss_AddMonitor *r)
10563 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10564 return WERR_NOT_SUPPORTED;
10567 /****************************************************************
10568 _spoolss_DeleteMonitor
10569 ****************************************************************/
10571 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10572 struct spoolss_DeleteMonitor *r)
10574 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10575 return WERR_NOT_SUPPORTED;
10578 /****************************************************************
10579 _spoolss_DeletePrintProcessor
10580 ****************************************************************/
10582 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10583 struct spoolss_DeletePrintProcessor *r)
10585 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10586 return WERR_NOT_SUPPORTED;
10589 /****************************************************************
10590 _spoolss_AddPrintProvidor
10591 ****************************************************************/
10593 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10594 struct spoolss_AddPrintProvidor *r)
10596 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10597 return WERR_NOT_SUPPORTED;
10600 /****************************************************************
10601 _spoolss_DeletePrintProvidor
10602 ****************************************************************/
10604 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10605 struct spoolss_DeletePrintProvidor *r)
10607 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10608 return WERR_NOT_SUPPORTED;
10611 /****************************************************************
10612 _spoolss_FindFirstPrinterChangeNotification
10613 ****************************************************************/
10615 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10616 struct spoolss_FindFirstPrinterChangeNotification *r)
10618 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10619 return WERR_NOT_SUPPORTED;
10622 /****************************************************************
10623 _spoolss_FindNextPrinterChangeNotification
10624 ****************************************************************/
10626 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10627 struct spoolss_FindNextPrinterChangeNotification *r)
10629 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10630 return WERR_NOT_SUPPORTED;
10633 /****************************************************************
10634 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10635 ****************************************************************/
10637 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10638 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10640 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10641 return WERR_NOT_SUPPORTED;
10644 /****************************************************************
10645 _spoolss_ReplyOpenPrinter
10646 ****************************************************************/
10648 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10649 struct spoolss_ReplyOpenPrinter *r)
10651 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10652 return WERR_NOT_SUPPORTED;
10655 /****************************************************************
10656 _spoolss_RouterReplyPrinter
10657 ****************************************************************/
10659 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10660 struct spoolss_RouterReplyPrinter *r)
10662 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10663 return WERR_NOT_SUPPORTED;
10666 /****************************************************************
10667 _spoolss_ReplyClosePrinter
10668 ****************************************************************/
10670 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10671 struct spoolss_ReplyClosePrinter *r)
10673 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10674 return WERR_NOT_SUPPORTED;
10677 /****************************************************************
10678 _spoolss_AddPortEx
10679 ****************************************************************/
10681 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10682 struct spoolss_AddPortEx *r)
10684 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10685 return WERR_NOT_SUPPORTED;
10688 /****************************************************************
10689 _spoolss_RouterFindFirstPrinterChangeNotification
10690 ****************************************************************/
10692 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10693 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10695 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10696 return WERR_NOT_SUPPORTED;
10699 /****************************************************************
10700 _spoolss_SpoolerInit
10701 ****************************************************************/
10703 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10704 struct spoolss_SpoolerInit *r)
10706 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10707 return WERR_NOT_SUPPORTED;
10710 /****************************************************************
10711 _spoolss_ResetPrinterEx
10712 ****************************************************************/
10714 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10715 struct spoolss_ResetPrinterEx *r)
10717 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10718 return WERR_NOT_SUPPORTED;
10721 /****************************************************************
10722 _spoolss_RouterReplyPrinterEx
10723 ****************************************************************/
10725 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10726 struct spoolss_RouterReplyPrinterEx *r)
10728 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10729 return WERR_NOT_SUPPORTED;
10732 /****************************************************************
10733 _spoolss_44
10734 ****************************************************************/
10736 WERROR _spoolss_44(struct pipes_struct *p,
10737 struct spoolss_44 *r)
10739 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10740 return WERR_NOT_SUPPORTED;
10743 /****************************************************************
10744 _spoolss_SetPort
10745 ****************************************************************/
10747 WERROR _spoolss_SetPort(struct pipes_struct *p,
10748 struct spoolss_SetPort *r)
10750 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10751 return WERR_NOT_SUPPORTED;
10754 /****************************************************************
10755 _spoolss_4a
10756 ****************************************************************/
10758 WERROR _spoolss_4a(struct pipes_struct *p,
10759 struct spoolss_4a *r)
10761 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10762 return WERR_NOT_SUPPORTED;
10765 /****************************************************************
10766 _spoolss_4b
10767 ****************************************************************/
10769 WERROR _spoolss_4b(struct pipes_struct *p,
10770 struct spoolss_4b *r)
10772 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10773 return WERR_NOT_SUPPORTED;
10776 /****************************************************************
10777 _spoolss_4c
10778 ****************************************************************/
10780 WERROR _spoolss_4c(struct pipes_struct *p,
10781 struct spoolss_4c *r)
10783 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10784 return WERR_NOT_SUPPORTED;
10787 /****************************************************************
10788 _spoolss_53
10789 ****************************************************************/
10791 WERROR _spoolss_53(struct pipes_struct *p,
10792 struct spoolss_53 *r)
10794 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10795 return WERR_NOT_SUPPORTED;
10798 /****************************************************************
10799 _spoolss_AddPerMachineConnection
10800 ****************************************************************/
10802 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10803 struct spoolss_AddPerMachineConnection *r)
10805 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10806 return WERR_NOT_SUPPORTED;
10809 /****************************************************************
10810 _spoolss_DeletePerMachineConnection
10811 ****************************************************************/
10813 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10814 struct spoolss_DeletePerMachineConnection *r)
10816 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10817 return WERR_NOT_SUPPORTED;
10820 /****************************************************************
10821 _spoolss_EnumPerMachineConnections
10822 ****************************************************************/
10824 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10825 struct spoolss_EnumPerMachineConnections *r)
10827 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10828 return WERR_NOT_SUPPORTED;
10831 /****************************************************************
10832 _spoolss_5a
10833 ****************************************************************/
10835 WERROR _spoolss_5a(struct pipes_struct *p,
10836 struct spoolss_5a *r)
10838 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10839 return WERR_NOT_SUPPORTED;
10842 /****************************************************************
10843 _spoolss_5b
10844 ****************************************************************/
10846 WERROR _spoolss_5b(struct pipes_struct *p,
10847 struct spoolss_5b *r)
10849 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10850 return WERR_NOT_SUPPORTED;
10853 /****************************************************************
10854 _spoolss_5c
10855 ****************************************************************/
10857 WERROR _spoolss_5c(struct pipes_struct *p,
10858 struct spoolss_5c *r)
10860 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10861 return WERR_NOT_SUPPORTED;
10864 /****************************************************************
10865 _spoolss_5d
10866 ****************************************************************/
10868 WERROR _spoolss_5d(struct pipes_struct *p,
10869 struct spoolss_5d *r)
10871 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10872 return WERR_NOT_SUPPORTED;
10875 /****************************************************************
10876 _spoolss_5e
10877 ****************************************************************/
10879 WERROR _spoolss_5e(struct pipes_struct *p,
10880 struct spoolss_5e *r)
10882 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10883 return WERR_NOT_SUPPORTED;
10886 /****************************************************************
10887 _spoolss_5f
10888 ****************************************************************/
10890 WERROR _spoolss_5f(struct pipes_struct *p,
10891 struct spoolss_5f *r)
10893 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10894 return WERR_NOT_SUPPORTED;
10897 /****************************************************************
10898 _spoolss_60
10899 ****************************************************************/
10901 WERROR _spoolss_60(struct pipes_struct *p,
10902 struct spoolss_60 *r)
10904 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10905 return WERR_NOT_SUPPORTED;
10908 /****************************************************************
10909 _spoolss_RpcSendRecvBidiData
10910 ****************************************************************/
10912 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
10913 struct spoolss_RpcSendRecvBidiData *r)
10915 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10916 return WERR_NOT_SUPPORTED;
10919 /****************************************************************
10920 _spoolss_62
10921 ****************************************************************/
10923 WERROR _spoolss_62(struct pipes_struct *p,
10924 struct spoolss_62 *r)
10926 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10927 return WERR_NOT_SUPPORTED;
10930 /****************************************************************
10931 _spoolss_63
10932 ****************************************************************/
10934 WERROR _spoolss_63(struct pipes_struct *p,
10935 struct spoolss_63 *r)
10937 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10938 return WERR_NOT_SUPPORTED;
10941 /****************************************************************
10942 _spoolss_64
10943 ****************************************************************/
10945 WERROR _spoolss_64(struct pipes_struct *p,
10946 struct spoolss_64 *r)
10948 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10949 return WERR_NOT_SUPPORTED;
10952 /****************************************************************
10953 _spoolss_65
10954 ****************************************************************/
10956 WERROR _spoolss_65(struct pipes_struct *p,
10957 struct spoolss_65 *r)
10959 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10960 return WERR_NOT_SUPPORTED;
10963 /****************************************************************
10964 _spoolss_GetCorePrinterDrivers
10965 ****************************************************************/
10967 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10968 struct spoolss_GetCorePrinterDrivers *r)
10970 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10971 return WERR_NOT_SUPPORTED;
10974 /****************************************************************
10975 _spoolss_67
10976 ****************************************************************/
10978 WERROR _spoolss_67(struct pipes_struct *p,
10979 struct spoolss_67 *r)
10981 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10982 return WERR_NOT_SUPPORTED;
10985 /****************************************************************
10986 _spoolss_GetPrinterDriverPackagePath
10987 ****************************************************************/
10989 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10990 struct spoolss_GetPrinterDriverPackagePath *r)
10992 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10993 return WERR_NOT_SUPPORTED;
10996 /****************************************************************
10997 _spoolss_69
10998 ****************************************************************/
11000 WERROR _spoolss_69(struct pipes_struct *p,
11001 struct spoolss_69 *r)
11003 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11004 return WERR_NOT_SUPPORTED;
11007 /****************************************************************
11008 _spoolss_6a
11009 ****************************************************************/
11011 WERROR _spoolss_6a(struct pipes_struct *p,
11012 struct spoolss_6a *r)
11014 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11015 return WERR_NOT_SUPPORTED;
11018 /****************************************************************
11019 _spoolss_6b
11020 ****************************************************************/
11022 WERROR _spoolss_6b(struct pipes_struct *p,
11023 struct spoolss_6b *r)
11025 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11026 return WERR_NOT_SUPPORTED;
11029 /****************************************************************
11030 _spoolss_6c
11031 ****************************************************************/
11033 WERROR _spoolss_6c(struct pipes_struct *p,
11034 struct spoolss_6c *r)
11036 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11037 return WERR_NOT_SUPPORTED;
11040 /****************************************************************
11041 _spoolss_6d
11042 ****************************************************************/
11044 WERROR _spoolss_6d(struct pipes_struct *p,
11045 struct spoolss_6d *r)
11047 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11048 return WERR_NOT_SUPPORTED;
11051 /****************************************************************
11052 _spoolss_RpcGetJobNamedPropertyValue
11053 ****************************************************************/
11055 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11056 struct spoolss_RpcGetJobNamedPropertyValue *r)
11058 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11059 return WERR_NOT_SUPPORTED;
11062 /****************************************************************
11063 _spoolss_RpcSetJobNamedProperty
11064 ****************************************************************/
11066 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11067 struct spoolss_RpcSetJobNamedProperty *r)
11069 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11070 return WERR_NOT_SUPPORTED;
11073 /****************************************************************
11074 _spoolss_RpcDeleteJobNamedProperty
11075 ****************************************************************/
11077 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11078 struct spoolss_RpcDeleteJobNamedProperty *r)
11080 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11081 return WERR_NOT_SUPPORTED;
11084 /****************************************************************
11085 _spoolss_RpcEnumJobNamedProperties
11086 ****************************************************************/
11088 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11089 struct spoolss_RpcEnumJobNamedProperties *r)
11091 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11092 return WERR_NOT_SUPPORTED;