spoolss: purge the printer name cache on name change
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob42caff1025ba2279b37a0b6597526d1b2c3ad52e
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 uint32_t active_connections;
144 static struct notify_back_channel *back_channels;
146 /* Map generic permissions to printer object specific permissions */
148 const struct standard_mapping printer_std_mapping = {
149 PRINTER_READ,
150 PRINTER_WRITE,
151 PRINTER_EXECUTE,
152 PRINTER_ALL_ACCESS
155 /* Map generic permissions to print server object specific permissions */
157 const struct standard_mapping printserver_std_mapping = {
158 SERVER_READ,
159 SERVER_WRITE,
160 SERVER_EXECUTE,
161 SERVER_ALL_ACCESS
164 /* API table for Xcv Monitor functions */
166 struct xcv_api_table {
167 const char *name;
168 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
171 static void prune_printername_cache(void);
173 /********************************************************************
174 * Canonicalize servername.
175 ********************************************************************/
177 static const char *canon_servername(const char *servername)
179 const char *pservername = servername;
180 while (*pservername == '\\') {
181 pservername++;
183 return pservername;
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
189 switch (v) {
190 case LPQ_QUEUED:
191 return 0;
192 case LPQ_PAUSED:
193 return JOB_STATUS_PAUSED;
194 case LPQ_SPOOLING:
195 return JOB_STATUS_SPOOLING;
196 case LPQ_PRINTING:
197 return JOB_STATUS_PRINTING;
198 case LPQ_ERROR:
199 return JOB_STATUS_ERROR;
200 case LPQ_DELETING:
201 return JOB_STATUS_DELETING;
202 case LPQ_OFFLINE:
203 return JOB_STATUS_OFFLINE;
204 case LPQ_PAPEROUT:
205 return JOB_STATUS_PAPEROUT;
206 case LPQ_PRINTED:
207 return JOB_STATUS_PRINTED;
208 case LPQ_DELETED:
209 return JOB_STATUS_DELETED;
210 case LPQ_BLOCKED:
211 return JOB_STATUS_BLOCKED_DEVQ;
212 case LPQ_USER_INTERVENTION:
213 return JOB_STATUS_USER_INTERVENTION;
215 return 0;
218 static int nt_printq_status(int v)
220 switch (v) {
221 case LPQ_PAUSED:
222 return PRINTER_STATUS_PAUSED;
223 case LPQ_QUEUED:
224 case LPQ_SPOOLING:
225 case LPQ_PRINTING:
226 return 0;
228 return 0;
231 /***************************************************************************
232 Disconnect from the client
233 ****************************************************************************/
235 static void srv_spoolss_replycloseprinter(int snum,
236 struct printer_handle *prn_hnd)
238 WERROR result;
239 NTSTATUS status;
242 * Tell the specific printing tdb we no longer want messages for this printer
243 * by deregistering our PID.
246 if (!print_notify_deregister_pid(snum)) {
247 DEBUG(0, ("Failed to register our pid for printer %s\n",
248 lp_const_servicename(snum)));
251 /* weird if the test succeeds !!! */
252 if (prn_hnd->notify.cli_chan == NULL ||
253 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255 prn_hnd->notify.cli_chan->active_connections == 0) {
256 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258 TALLOC_FREE(prn_hnd->notify.cli_chan);
259 return;
262 status = dcerpc_spoolss_ReplyClosePrinter(
263 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264 talloc_tos(),
265 &prn_hnd->notify.cli_hnd,
266 &result);
267 if (!NT_STATUS_IS_OK(status)) {
268 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269 nt_errstr(status)));
270 result = ntstatus_to_werror(status);
271 } else if (!W_ERROR_IS_OK(result)) {
272 DEBUG(0, ("reply_close_printer failed [%s].\n",
273 win_errstr(result)));
276 /* if it's the last connection, deconnect the IPC$ share */
277 if (prn_hnd->notify.cli_chan->active_connections == 1) {
279 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281 TALLOC_FREE(prn_hnd->notify.cli_chan);
283 if (prn_hnd->notify.msg_ctx != NULL) {
284 messaging_deregister(prn_hnd->notify.msg_ctx,
285 MSG_PRINTER_NOTIFY2, NULL);
289 if (prn_hnd->notify.cli_chan) {
290 prn_hnd->notify.cli_chan->active_connections--;
291 prn_hnd->notify.cli_chan = NULL;
295 /****************************************************************************
296 Functions to free a printer entry datastruct.
297 ****************************************************************************/
299 static int printer_entry_destructor(struct printer_handle *Printer)
301 if (Printer->notify.cli_chan != NULL &&
302 Printer->notify.cli_chan->active_connections > 0) {
303 int snum = -1;
305 switch(Printer->printer_type) {
306 case SPLHND_SERVER:
307 srv_spoolss_replycloseprinter(snum, Printer);
308 break;
310 case SPLHND_PRINTER:
311 snum = print_queue_snum(Printer->sharename);
312 if (snum != -1) {
313 srv_spoolss_replycloseprinter(snum, Printer);
315 break;
316 default:
317 break;
321 Printer->notify.flags=0;
322 Printer->notify.options=0;
323 Printer->notify.localmachine[0]='\0';
324 Printer->notify.printerlocal=0;
325 TALLOC_FREE(Printer->notify.option);
326 TALLOC_FREE(Printer->devmode);
328 /* Remove from the internal list. */
329 DLIST_REMOVE(printers_list, Printer);
330 return 0;
333 /****************************************************************************
334 find printer index by handle
335 ****************************************************************************/
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338 struct policy_handle *hnd)
340 struct printer_handle *find_printer = NULL;
342 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344 return NULL;
347 return find_printer;
350 /****************************************************************************
351 Close printer index by handle.
352 ****************************************************************************/
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358 if (!Printer) {
359 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360 OUR_HANDLE(hnd)));
361 return false;
364 close_policy_hnd(p, hnd);
366 return true;
369 /****************************************************************************
370 Delete a printer given a handle.
371 ****************************************************************************/
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374 const char *sharename,
375 struct messaging_context *msg_ctx)
377 char *cmd = lp_deleteprinter_cmd(talloc_tos());
378 char *command = NULL;
379 int ret;
380 bool is_print_op = false;
382 /* can't fail if we don't try */
384 if ( !*cmd )
385 return WERR_OK;
387 command = talloc_asprintf(ctx,
388 "%s \"%s\"",
389 cmd, sharename);
390 if (!command) {
391 return WERR_NOMEM;
393 if ( token )
394 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396 DEBUG(10,("Running [%s]\n", command));
398 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
400 if ( is_print_op )
401 become_root();
403 if ( (ret = smbrun(command, NULL)) == 0 ) {
404 /* Tell everyone we updated smb.conf. */
405 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
408 if ( is_print_op )
409 unbecome_root();
411 /********** END SePrintOperatorPrivlege BLOCK **********/
413 DEBUGADD(10,("returned [%d]\n", ret));
415 TALLOC_FREE(command);
417 if (ret != 0)
418 return WERR_BADFID; /* What to return here? */
420 return WERR_OK;
423 /****************************************************************************
424 Delete a printer given a handle.
425 ****************************************************************************/
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
429 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430 WERROR result;
432 if (!Printer) {
433 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434 OUR_HANDLE(hnd)));
435 return WERR_BADFID;
439 * It turns out that Windows allows delete printer on a handle
440 * opened by an admin user, then used on a pipe handle created
441 * by an anonymous user..... but they're working on security.... riiight !
442 * JRA.
445 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447 return WERR_ACCESS_DENIED;
450 /* this does not need a become root since the access check has been
451 done on the handle already */
453 result = winreg_delete_printer_key_internal(p->mem_ctx,
454 get_session_info_system(),
455 p->msg_ctx,
456 Printer->sharename,
457 "");
458 if (!W_ERROR_IS_OK(result)) {
459 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460 return WERR_BADFID;
463 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464 Printer->sharename, p->msg_ctx);
465 if (!W_ERROR_IS_OK(result)) {
466 return result;
468 prune_printername_cache();
469 return WERR_OK;
472 /****************************************************************************
473 Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477 int *number, struct share_params **params)
479 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
481 if (!Printer) {
482 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483 OUR_HANDLE(hnd)));
484 return false;
487 switch (Printer->printer_type) {
488 case SPLHND_PRINTER:
489 DEBUG(4,("short name:%s\n", Printer->sharename));
490 *number = print_queue_snum(Printer->sharename);
491 return (*number != -1);
492 case SPLHND_SERVER:
493 return false;
494 default:
495 return false;
499 /****************************************************************************
500 Set printer handle type.
501 Check if it's \\server or \\server\printer
502 ****************************************************************************/
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
506 DEBUG(3,("Setting printer type=%s\n", handlename));
508 /* it's a print server */
509 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510 DEBUGADD(4,("Printer is a print server\n"));
511 Printer->printer_type = SPLHND_SERVER;
513 /* it's a printer (set_printer_hnd_name() will handle port monitors */
514 else {
515 DEBUGADD(4,("Printer is a printer\n"));
516 Printer->printer_type = SPLHND_PRINTER;
519 return true;
522 static void prune_printername_cache_fn(const char *key, const char *value,
523 time_t timeout, void *private_data)
525 gencache_del(key);
528 static void prune_printername_cache(void)
530 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
533 /****************************************************************************
534 Set printer handle name.. Accept names like \\server, \\server\printer,
535 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
536 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537 XcvDataPort() interface.
538 ****************************************************************************/
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541 const struct auth_session_info *session_info,
542 struct messaging_context *msg_ctx,
543 struct printer_handle *Printer,
544 const char *handlename)
546 int snum;
547 int n_services=lp_numservices();
548 char *aprinter;
549 const char *printername;
550 const char *servername = NULL;
551 fstring sname;
552 bool found = false;
553 struct spoolss_PrinterInfo2 *info2 = NULL;
554 WERROR result;
555 char *p;
558 * Hopefully nobody names his printers like this. Maybe \ or ,
559 * are illegal in printer names even?
561 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562 char *cache_key;
563 char *tmp;
565 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566 (unsigned long)strlen(handlename)));
568 aprinter = discard_const_p(char, handlename);
569 if ( *handlename == '\\' ) {
570 servername = canon_servername(handlename);
571 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572 *aprinter = '\0';
573 aprinter++;
575 if (!is_myname_or_ipaddr(servername)) {
576 return WERR_INVALID_PRINTER_NAME;
578 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579 if (Printer->servername == NULL) {
580 return WERR_NOMEM;
584 if (Printer->printer_type == SPLHND_SERVER) {
585 return WERR_OK;
588 if (Printer->printer_type != SPLHND_PRINTER) {
589 return WERR_INVALID_HANDLE;
592 DEBUGADD(5, ("searching for [%s]\n", aprinter));
594 p = strchr(aprinter, ',');
595 if (p != NULL) {
596 char *p2 = p;
597 p++;
598 if (*p == ' ') {
599 p++;
601 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602 *p2 = '\0';
603 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604 *p2 = '\0';
608 if (p) {
609 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
612 /* check for the Port Monitor Interface */
613 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614 Printer->printer_type = SPLHND_PORTMON_TCP;
615 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616 found = true;
618 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621 found = true;
625 * With hundreds of printers, the "for" loop iterating all
626 * shares can be quite expensive, as it is done on every
627 * OpenPrinter. The loop maps "aprinter" to "sname", the
628 * result of which we cache in gencache.
631 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632 aprinter);
633 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
635 found = (strcmp(tmp, printer_not_found) != 0);
636 if (!found) {
637 DEBUG(4, ("Printer %s not found\n", aprinter));
638 SAFE_FREE(tmp);
639 return WERR_INVALID_PRINTER_NAME;
641 fstrcpy(sname, tmp);
642 SAFE_FREE(tmp);
645 /* Search all sharenames first as this is easier than pulling
646 the printer_info_2 off of disk. Don't use find_service() since
647 that calls out to map_username() */
649 /* do another loop to look for printernames */
650 for (snum = 0; !found && snum < n_services; snum++) {
651 const char *printer = lp_const_servicename(snum);
653 /* no point going on if this is not a printer */
654 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655 continue;
658 /* ignore [printers] share */
659 if (strequal(printer, "printers")) {
660 continue;
663 fstrcpy(sname, printer);
664 if (strequal(aprinter, printer)) {
665 found = true;
666 break;
669 /* no point looking up the printer object if
670 we aren't allowing printername != sharename */
671 if (lp_force_printername(snum)) {
672 continue;
675 result = winreg_get_printer_internal(mem_ctx,
676 session_info,
677 msg_ctx,
678 sname,
679 &info2);
680 if ( !W_ERROR_IS_OK(result) ) {
681 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682 sname, win_errstr(result)));
683 continue;
686 printername = strrchr(info2->printername, '\\');
687 if (printername == NULL) {
688 printername = info2->printername;
689 } else {
690 printername++;
693 if (strequal(printername, aprinter)) {
694 found = true;
695 break;
698 DEBUGADD(10, ("printername: %s\n", printername));
700 TALLOC_FREE(info2);
703 if ( !found ) {
704 if (cache_key != NULL) {
705 gencache_set(cache_key, printer_not_found,
706 time(NULL)+300);
707 TALLOC_FREE(cache_key);
709 DEBUGADD(4,("Printer not found\n"));
710 return WERR_INVALID_PRINTER_NAME;
713 if (cache_key != NULL) {
714 gencache_set(cache_key, sname, time(NULL)+300);
715 TALLOC_FREE(cache_key);
718 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
720 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
722 return WERR_OK;
725 /****************************************************************************
726 Find first available printer slot. creates a printer handle for you.
727 ****************************************************************************/
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730 struct policy_handle *hnd,
731 const char *name,
732 uint32_t access_granted)
734 struct printer_handle *new_printer;
735 WERROR result;
737 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
739 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740 if (new_printer == NULL) {
741 return WERR_NOMEM;
743 talloc_set_destructor(new_printer, printer_entry_destructor);
745 /* This also steals the printer_handle on the policy_handle */
746 if (!create_policy_hnd(p, hnd, new_printer)) {
747 TALLOC_FREE(new_printer);
748 return WERR_INVALID_HANDLE;
751 /* Add to the internal list. */
752 DLIST_ADD(printers_list, new_printer);
754 new_printer->notify.option=NULL;
756 if (!set_printer_hnd_printertype(new_printer, name)) {
757 close_printer_handle(p, hnd);
758 return WERR_INVALID_HANDLE;
761 result = set_printer_hnd_name(p->mem_ctx,
762 get_session_info_system(),
763 p->msg_ctx,
764 new_printer, name);
765 if (!W_ERROR_IS_OK(result)) {
766 close_printer_handle(p, hnd);
767 return result;
770 new_printer->access_granted = access_granted;
772 DEBUG(5, ("%d printer handles active\n",
773 (int)num_pipe_handles(p)));
775 return WERR_OK;
778 /***************************************************************************
779 check to see if the client motify handle is monitoring the notification
780 given by (notify_type, notify_field).
781 **************************************************************************/
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784 uint16_t notify_field)
786 return true;
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790 uint16_t notify_field)
792 struct spoolss_NotifyOption *option = p->notify.option;
793 uint32_t i, j;
796 * Flags should always be zero when the change notify
797 * is registered by the client's spooler. A user Win32 app
798 * might use the flags though instead of the NOTIFY_OPTION_INFO
799 * --jerry
802 if (!option) {
803 return false;
806 if (p->notify.flags)
807 return is_monitoring_event_flags(
808 p->notify.flags, notify_type, notify_field);
810 for (i = 0; i < option->count; i++) {
812 /* Check match for notify_type */
814 if (option->types[i].type != notify_type)
815 continue;
817 /* Check match for field */
819 for (j = 0; j < option->types[i].count; j++) {
820 if (option->types[i].fields[j].field == notify_field) {
821 return true;
826 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827 p->servername, p->sharename, notify_type, notify_field));
829 return false;
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833 _data->data.integer[0] = _integer; \
834 _data->data.integer[1] = 0;
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839 if (!_data->data.string.string) {\
840 _data->data.string.size = 0; \
842 _data->data.string.size = strlen_m_term(_p) * 2;
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845 _data->data.devmode.devmode = _devmode;
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849 if (!_data->data.sd.sd) { \
850 _data->data.sd.sd_size = 0; \
852 _data->data.sd.sd_size = \
853 ndr_size_security_descriptor(_data->data.sd.sd, 0);
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856 struct tm *t,
857 const char **pp,
858 uint32_t *plen)
860 struct spoolss_Time st;
861 uint32_t len = 16;
862 char *p;
864 if (!init_systemtime(&st, t)) {
865 return;
868 p = talloc_array(mem_ctx, char, len);
869 if (!p) {
870 return;
874 * Systemtime must be linearized as a set of UINT16's.
875 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878 SSVAL(p, 0, st.year);
879 SSVAL(p, 2, st.month);
880 SSVAL(p, 4, st.day_of_week);
881 SSVAL(p, 6, st.day);
882 SSVAL(p, 8, st.hour);
883 SSVAL(p, 10, st.minute);
884 SSVAL(p, 12, st.second);
885 SSVAL(p, 14, st.millisecond);
887 *pp = p;
888 *plen = len;
891 /* Convert a notification message to a struct spoolss_Notify */
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894 struct spoolss_Notify *data,
895 TALLOC_CTX *mem_ctx)
897 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
900 static void notify_string(struct spoolss_notify_msg *msg,
901 struct spoolss_Notify *data,
902 TALLOC_CTX *mem_ctx)
904 /* The length of the message includes the trailing \0 */
906 data->data.string.size = msg->len * 2;
907 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908 if (!data->data.string.string) {
909 data->data.string.size = 0;
910 return;
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915 struct spoolss_Notify *data,
916 TALLOC_CTX *mem_ctx)
918 data->data.string.string = NULL;
919 data->data.string.size = 0;
921 if (msg->len != sizeof(time_t)) {
922 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923 msg->len));
924 return;
927 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928 &data->data.string.string,
929 &data->data.string.size);
932 struct notify2_message_table {
933 const char *name;
934 void (*fn)(struct spoolss_notify_msg *msg,
935 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
938 static struct notify2_message_table printer_notify_table[] = {
939 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
960 static struct notify2_message_table job_notify_table[] = {
961 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
988 /***********************************************************************
989 Allocate talloc context for container object
990 **********************************************************************/
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
994 if ( !ctr )
995 return;
997 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
999 return;
1002 /***********************************************************************
1003 release all allocated memory and zero out structure
1004 **********************************************************************/
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1008 if ( !ctr )
1009 return;
1011 if ( ctr->ctx )
1012 talloc_destroy(ctr->ctx);
1014 ZERO_STRUCTP(ctr);
1016 return;
1019 /***********************************************************************
1020 **********************************************************************/
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1024 if ( !ctr )
1025 return NULL;
1027 return ctr->ctx;
1030 /***********************************************************************
1031 **********************************************************************/
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1035 if ( !ctr || !ctr->msg_groups )
1036 return NULL;
1038 if ( idx >= ctr->num_groups )
1039 return NULL;
1041 return &ctr->msg_groups[idx];
1045 /***********************************************************************
1046 How many groups of change messages do we have ?
1047 **********************************************************************/
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1051 if ( !ctr )
1052 return 0;
1054 return ctr->num_groups;
1057 /***********************************************************************
1058 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059 **********************************************************************/
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1063 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1064 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1065 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1066 int i, new_slot;
1068 if ( !ctr || !msg )
1069 return 0;
1071 /* loop over all groups looking for a matching printer name */
1073 for ( i=0; i<ctr->num_groups; i++ ) {
1074 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075 break;
1078 /* add a new group? */
1080 if ( i == ctr->num_groups ) {
1081 ctr->num_groups++;
1083 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085 return 0;
1087 ctr->msg_groups = groups;
1089 /* clear the new entry and set the printer name */
1091 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1095 /* add the change messages; 'i' is the correct index now regardless */
1097 msg_grp = &ctr->msg_groups[i];
1099 msg_grp->num_msgs++;
1101 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103 return 0;
1105 msg_grp->msgs = msg_list;
1107 new_slot = msg_grp->num_msgs-1;
1108 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1110 /* need to allocate own copy of data */
1112 if ( msg->len != 0 )
1113 msg_grp->msgs[new_slot].notify.data = (char *)
1114 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1116 return ctr->num_groups;
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120 enum spoolss_NotifyType type,
1121 uint16_t field, int id);
1123 /***********************************************************************
1124 Send a change notication message on all handles which have a call
1125 back registered
1126 **********************************************************************/
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129 struct printer_handle *prn_hnd,
1130 SPOOLSS_NOTIFY_MSG *messages,
1131 uint32_t num_msgs,
1132 struct spoolss_Notify **_notifies,
1133 int *_count)
1135 struct spoolss_Notify *notifies;
1136 SPOOLSS_NOTIFY_MSG *msg;
1137 int count = 0;
1138 uint32_t id;
1139 int i;
1141 notifies = talloc_zero_array(mem_ctx,
1142 struct spoolss_Notify, num_msgs);
1143 if (!notifies) {
1144 return ENOMEM;
1147 for (i = 0; i < num_msgs; i++) {
1149 msg = &messages[i];
1151 /* Are we monitoring this event? */
1153 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154 continue;
1157 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158 "for printer [%s]\n",
1159 msg->type, msg->field, prn_hnd->sharename));
1162 * if the is a printer notification handle and not a job
1163 * notification type, then set the id to 0.
1164 * Otherwise just use what was specified in the message.
1166 * When registering change notification on a print server
1167 * handle we always need to send back the id (snum) matching
1168 * the printer for which the change took place.
1169 * For change notify registered on a printer handle,
1170 * this does not matter and the id should be 0.
1172 * --jerry
1175 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177 id = 0;
1178 } else {
1179 id = msg->id;
1182 /* Convert unix jobid to smb jobid */
1184 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185 id = sysjob_to_jobid(msg->id);
1187 if (id == -1) {
1188 DEBUG(3, ("no such unix jobid %d\n",
1189 msg->id));
1190 continue;
1194 construct_info_data(&notifies[count],
1195 msg->type, msg->field, id);
1197 switch(msg->type) {
1198 case PRINTER_NOTIFY_TYPE:
1199 if (printer_notify_table[msg->field].fn) {
1200 printer_notify_table[msg->field].fn(msg,
1201 &notifies[count], mem_ctx);
1203 break;
1205 case JOB_NOTIFY_TYPE:
1206 if (job_notify_table[msg->field].fn) {
1207 job_notify_table[msg->field].fn(msg,
1208 &notifies[count], mem_ctx);
1210 break;
1212 default:
1213 DEBUG(5, ("Unknown notification type %d\n",
1214 msg->type));
1215 continue;
1218 count++;
1221 *_notifies = notifies;
1222 *_count = count;
1224 return 0;
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228 struct printer_handle *prn_hnd,
1229 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1231 struct spoolss_Notify *notifies;
1232 int count = 0;
1233 union spoolss_ReplyPrinterInfo info;
1234 struct spoolss_NotifyInfo info0;
1235 uint32_t reply_result;
1236 NTSTATUS status;
1237 WERROR werr;
1238 int ret;
1240 /* Is there notification on this handle? */
1241 if (prn_hnd->notify.cli_chan == NULL ||
1242 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244 prn_hnd->notify.cli_chan->active_connections == 0) {
1245 return 0;
1248 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249 prn_hnd->servername, prn_hnd->sharename));
1251 /* For this printer? Print servers always receive notifications. */
1252 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1253 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254 return 0;
1257 DEBUG(10,("Our printer\n"));
1259 /* build the array of change notifications */
1260 ret = build_notify2_messages(mem_ctx, prn_hnd,
1261 msg_group->msgs,
1262 msg_group->num_msgs,
1263 &notifies, &count);
1264 if (ret) {
1265 return ret;
1268 info0.version = 0x2;
1269 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270 info0.count = count;
1271 info0.notifies = notifies;
1273 info.info0 = &info0;
1275 status = dcerpc_spoolss_RouterReplyPrinterEx(
1276 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277 mem_ctx,
1278 &prn_hnd->notify.cli_hnd,
1279 prn_hnd->notify.change, /* color */
1280 prn_hnd->notify.flags,
1281 &reply_result,
1282 0, /* reply_type, must be 0 */
1283 info, &werr);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286 "failed: %s\n",
1287 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288 nt_errstr(status)));
1289 werr = ntstatus_to_werror(status);
1290 } else if (!W_ERROR_IS_OK(werr)) {
1291 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292 "failed: %s\n",
1293 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294 win_errstr(werr)));
1296 switch (reply_result) {
1297 case 0:
1298 break;
1299 case PRINTER_NOTIFY_INFO_DISCARDED:
1300 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302 break;
1303 default:
1304 break;
1307 return 0;
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1312 struct printer_handle *p;
1313 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1314 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315 int ret;
1317 if ( !msg_group ) {
1318 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319 return;
1322 if (!msg_group->msgs) {
1323 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324 return;
1327 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1329 /* loop over all printers */
1331 for (p = printers_list; p; p = p->next) {
1332 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333 if (ret) {
1334 goto done;
1338 done:
1339 DEBUG(8,("send_notify2_changes: Exit...\n"));
1340 return;
1343 /***********************************************************************
1344 **********************************************************************/
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1349 uint32_t tv_sec, tv_usec;
1350 size_t offset = 0;
1352 /* Unpack message */
1354 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355 msg->printer);
1357 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358 &tv_sec, &tv_usec,
1359 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1361 if (msg->len == 0)
1362 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363 &msg->notify.value[0], &msg->notify.value[1]);
1364 else
1365 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366 &msg->len, &msg->notify.data);
1368 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1371 tv->tv_sec = tv_sec;
1372 tv->tv_usec = tv_usec;
1374 if (msg->len == 0)
1375 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376 msg->notify.value[1]));
1377 else
1378 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1380 return true;
1383 /********************************************************************
1384 Receive a notify2 message list
1385 ********************************************************************/
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388 void *private_data,
1389 uint32_t msg_type,
1390 struct server_id server_id,
1391 DATA_BLOB *data)
1393 size_t msg_count, i;
1394 char *buf = (char *)data->data;
1395 char *msg_ptr;
1396 size_t msg_len;
1397 SPOOLSS_NOTIFY_MSG notify;
1398 SPOOLSS_NOTIFY_MSG_CTR messages;
1399 int num_groups;
1401 if (data->length < 4) {
1402 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403 return;
1406 msg_count = IVAL(buf, 0);
1407 msg_ptr = buf + 4;
1409 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1411 if (msg_count == 0) {
1412 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413 return;
1416 /* initialize the container */
1418 ZERO_STRUCT( messages );
1419 notify_msg_ctr_init( &messages );
1422 * build message groups for each printer identified
1423 * in a change_notify msg. Remember that a PCN message
1424 * includes the handle returned for the srv_spoolss_replyopenprinter()
1425 * call. Therefore messages are grouped according to printer handle.
1428 for ( i=0; i<msg_count; i++ ) {
1429 struct timeval msg_tv;
1431 if (msg_ptr + 4 - buf > data->length) {
1432 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433 return;
1436 msg_len = IVAL(msg_ptr,0);
1437 msg_ptr += 4;
1439 if (msg_ptr + msg_len - buf > data->length) {
1440 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441 return;
1444 /* unpack messages */
1446 ZERO_STRUCT( notify );
1447 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448 msg_ptr += msg_len;
1450 /* add to correct list in container */
1452 notify_msg_ctr_addmsg( &messages, &notify );
1454 /* free memory that might have been allocated by notify2_unpack_msg() */
1456 if ( notify.len != 0 )
1457 SAFE_FREE( notify.notify.data );
1460 /* process each group of messages */
1462 num_groups = notify_msg_ctr_numgroups( &messages );
1463 for ( i=0; i<num_groups; i++ )
1464 send_notify2_changes( &messages, i );
1467 /* cleanup */
1469 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470 (uint32_t)msg_count ));
1472 notify_msg_ctr_destroy( &messages );
1474 return;
1477 /********************************************************************
1478 Send a message to ourself about new driver being installed
1479 so we can upgrade the information for each printer bound to this
1480 driver
1481 ********************************************************************/
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484 struct messaging_context *msg_ctx)
1486 int len = strlen(drivername);
1488 if (!len)
1489 return false;
1491 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492 drivername));
1494 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495 MSG_PRINTER_DRVUPGRADE,
1496 (const uint8_t *)drivername, len+1);
1498 return true;
1501 void srv_spoolss_cleanup(void)
1503 struct printer_session_counter *session_counter;
1505 for (session_counter = counter_list;
1506 session_counter != NULL;
1507 session_counter = counter_list) {
1508 DLIST_REMOVE(counter_list, session_counter);
1509 TALLOC_FREE(session_counter);
1513 /**********************************************************************
1514 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515 over all printers, upgrading ones as necessary
1516 This is now *ONLY* called inside the background lpq updater. JRA.
1517 **********************************************************************/
1519 void do_drv_upgrade_printer(struct messaging_context *msg,
1520 void *private_data,
1521 uint32_t msg_type,
1522 struct server_id server_id,
1523 DATA_BLOB *data)
1525 TALLOC_CTX *tmp_ctx;
1526 const struct auth_session_info *session_info = get_session_info_system();
1527 struct spoolss_PrinterInfo2 *pinfo2;
1528 WERROR result;
1529 const char *drivername;
1530 int snum;
1531 int n_services = lp_numservices();
1532 struct dcerpc_binding_handle *b = NULL;
1534 tmp_ctx = talloc_new(NULL);
1535 if (!tmp_ctx) return;
1537 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1538 if (!drivername) {
1539 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1540 goto done;
1543 DEBUG(10, ("do_drv_upgrade_printer: "
1544 "Got message for new driver [%s]\n", drivername));
1546 /* Iterate the printer list */
1548 for (snum = 0; snum < n_services; snum++) {
1549 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1550 continue;
1553 /* ignore [printers] share */
1554 if (strequal(lp_const_servicename(snum), "printers")) {
1555 continue;
1558 if (b == NULL) {
1559 result = winreg_printer_binding_handle(tmp_ctx,
1560 session_info,
1561 msg,
1562 &b);
1563 if (!W_ERROR_IS_OK(result)) {
1564 break;
1568 result = winreg_get_printer(tmp_ctx, b,
1569 lp_const_servicename(snum),
1570 &pinfo2);
1572 if (!W_ERROR_IS_OK(result)) {
1573 continue;
1576 if (!pinfo2->drivername) {
1577 continue;
1580 if (strcmp(drivername, pinfo2->drivername) != 0) {
1581 continue;
1584 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1586 /* all we care about currently is the change_id */
1587 result = winreg_printer_update_changeid(tmp_ctx, b,
1588 pinfo2->printername);
1590 if (!W_ERROR_IS_OK(result)) {
1591 DEBUG(3, ("do_drv_upgrade_printer: "
1592 "Failed to update changeid [%s]\n",
1593 win_errstr(result)));
1597 /* all done */
1598 done:
1599 talloc_free(tmp_ctx);
1602 /********************************************************************
1603 Update the cache for all printq's with a registered client
1604 connection
1605 ********************************************************************/
1607 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1609 struct printer_handle *printer = printers_list;
1610 int snum;
1612 /* loop through all printers and update the cache where
1613 a client is connected */
1614 while (printer) {
1615 if ((printer->printer_type == SPLHND_PRINTER) &&
1616 ((printer->notify.cli_chan != NULL) &&
1617 (printer->notify.cli_chan->active_connections > 0))) {
1618 snum = print_queue_snum(printer->sharename);
1619 print_queue_status(msg_ctx, snum, NULL, NULL);
1622 printer = printer->next;
1625 return;
1628 /****************************************************************
1629 _spoolss_OpenPrinter
1630 ****************************************************************/
1632 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1633 struct spoolss_OpenPrinter *r)
1635 struct spoolss_OpenPrinterEx e;
1636 struct spoolss_UserLevel1 level1;
1637 WERROR werr;
1639 ZERO_STRUCT(level1);
1641 e.in.printername = r->in.printername;
1642 e.in.datatype = r->in.datatype;
1643 e.in.devmode_ctr = r->in.devmode_ctr;
1644 e.in.access_mask = r->in.access_mask;
1645 e.in.userlevel_ctr.level = 1;
1646 e.in.userlevel_ctr.user_info.level1 = &level1;
1648 e.out.handle = r->out.handle;
1650 werr = _spoolss_OpenPrinterEx(p, &e);
1652 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1653 /* OpenPrinterEx returns this for a bad
1654 * printer name. We must return WERR_INVALID_PRINTER_NAME
1655 * instead.
1657 werr = WERR_INVALID_PRINTER_NAME;
1660 return werr;
1663 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1664 struct spoolss_DeviceMode *orig,
1665 struct spoolss_DeviceMode **dest)
1667 struct spoolss_DeviceMode *dm;
1669 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1670 if (!dm) {
1671 return WERR_NOMEM;
1674 /* copy all values, then duplicate strings and structs */
1675 *dm = *orig;
1677 dm->devicename = talloc_strdup(dm, orig->devicename);
1678 if (!dm->devicename) {
1679 return WERR_NOMEM;
1681 dm->formname = talloc_strdup(dm, orig->formname);
1682 if (!dm->formname) {
1683 return WERR_NOMEM;
1685 if (orig->driverextra_data.data) {
1686 dm->driverextra_data.data =
1687 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1688 orig->driverextra_data.length);
1689 if (!dm->driverextra_data.data) {
1690 return WERR_NOMEM;
1694 *dest = dm;
1695 return WERR_OK;
1698 /****************************************************************
1699 _spoolss_OpenPrinterEx
1700 ****************************************************************/
1702 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1703 struct spoolss_OpenPrinterEx *r)
1705 int snum;
1706 char *raddr;
1707 char *rhost;
1708 struct printer_handle *Printer=NULL;
1709 WERROR result;
1710 int rc;
1712 if (!r->in.printername) {
1713 return WERR_INVALID_PARAM;
1716 if (!*r->in.printername) {
1717 return WERR_INVALID_PARAM;
1720 if (r->in.userlevel_ctr.level > 3) {
1721 return WERR_INVALID_PARAM;
1723 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1724 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1725 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1726 return WERR_INVALID_PARAM;
1730 * The printcap printer share inventory is updated on client
1731 * enumeration. For clients that do not perform enumeration prior to
1732 * access, such as cupssmbadd, we reinitialise the printer share
1733 * inventory on open as well.
1735 become_root();
1736 delete_and_reload_printers(server_event_context(), p->msg_ctx);
1737 unbecome_root();
1739 /* some sanity check because you can open a printer or a print server */
1740 /* aka: \\server\printer or \\server */
1742 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1744 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1745 if (!W_ERROR_IS_OK(result)) {
1746 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1747 "for printer %s\n", r->in.printername));
1748 ZERO_STRUCTP(r->out.handle);
1749 return result;
1752 Printer = find_printer_index_by_hnd(p, r->out.handle);
1753 if ( !Printer ) {
1754 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1755 "handle we created for printer %s\n", r->in.printername));
1756 close_printer_handle(p, r->out.handle);
1757 ZERO_STRUCTP(r->out.handle);
1758 return WERR_INVALID_PARAM;
1762 * First case: the user is opening the print server:
1764 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1765 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1767 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1768 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1769 * or if the user is listed in the smb.conf printer admin parameter.
1771 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1772 * client view printer folder, but does not show the MSAPW.
1774 * Note: this test needs code to check access rights here too. Jeremy
1775 * could you look at this?
1777 * Second case: the user is opening a printer:
1778 * NT doesn't let us connect to a printer if the connecting user
1779 * doesn't have print permission.
1781 * Third case: user is opening a Port Monitor
1782 * access checks same as opening a handle to the print server.
1785 switch (Printer->printer_type )
1787 case SPLHND_SERVER:
1788 case SPLHND_PORTMON_TCP:
1789 case SPLHND_PORTMON_LOCAL:
1790 /* Printserver handles use global struct... */
1792 snum = -1;
1794 /* Map standard access rights to object specific access rights */
1796 se_map_standard(&r->in.access_mask,
1797 &printserver_std_mapping);
1799 /* Deny any object specific bits that don't apply to print
1800 servers (i.e printer and job specific bits) */
1802 r->in.access_mask &= SEC_MASK_SPECIFIC;
1804 if (r->in.access_mask &
1805 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1806 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1807 close_printer_handle(p, r->out.handle);
1808 ZERO_STRUCTP(r->out.handle);
1809 return WERR_ACCESS_DENIED;
1812 /* Allow admin access */
1814 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1816 if (!lp_ms_add_printer_wizard()) {
1817 close_printer_handle(p, r->out.handle);
1818 ZERO_STRUCTP(r->out.handle);
1819 return WERR_ACCESS_DENIED;
1822 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1823 and not a printer admin, then fail */
1825 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1826 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1827 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1828 p->session_info->security_token)) {
1829 close_printer_handle(p, r->out.handle);
1830 ZERO_STRUCTP(r->out.handle);
1831 DEBUG(3,("access DENIED as user is not root, "
1832 "has no printoperator privilege, "
1833 "not a member of the printoperator builtin group and "
1834 "is not in printer admin list"));
1835 return WERR_ACCESS_DENIED;
1838 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1840 else
1842 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1845 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1846 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1848 /* We fall through to return WERR_OK */
1849 break;
1851 case SPLHND_PRINTER:
1852 /* NT doesn't let us connect to a printer if the connecting user
1853 doesn't have print permission. */
1855 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1856 close_printer_handle(p, r->out.handle);
1857 ZERO_STRUCTP(r->out.handle);
1858 return WERR_BADFID;
1861 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1862 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1865 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1867 /* map an empty access mask to the minimum access mask */
1868 if (r->in.access_mask == 0x0)
1869 r->in.access_mask = PRINTER_ACCESS_USE;
1872 * If we are not serving the printer driver for this printer,
1873 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1874 * will keep NT clients happy --jerry
1877 if (lp_use_client_driver(snum)
1878 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1880 r->in.access_mask = PRINTER_ACCESS_USE;
1883 /* check smb.conf parameters and the the sec_desc */
1884 raddr = tsocket_address_inet_addr_string(p->remote_address,
1885 p->mem_ctx);
1886 if (raddr == NULL) {
1887 return WERR_NOMEM;
1890 rc = get_remote_hostname(p->remote_address,
1891 &rhost,
1892 p->mem_ctx);
1893 if (rc < 0) {
1894 return WERR_NOMEM;
1896 if (strequal(rhost, "UNKNOWN")) {
1897 rhost = raddr;
1900 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1901 rhost, raddr)) {
1902 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1903 ZERO_STRUCTP(r->out.handle);
1904 return WERR_ACCESS_DENIED;
1907 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1908 p->session_info->security_token, snum) ||
1909 !print_access_check(p->session_info,
1910 p->msg_ctx,
1911 snum,
1912 r->in.access_mask)) {
1913 DEBUG(3, ("access DENIED for printer open\n"));
1914 close_printer_handle(p, r->out.handle);
1915 ZERO_STRUCTP(r->out.handle);
1916 return WERR_ACCESS_DENIED;
1919 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1920 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1921 close_printer_handle(p, r->out.handle);
1922 ZERO_STRUCTP(r->out.handle);
1923 return WERR_ACCESS_DENIED;
1926 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1927 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1928 else
1929 r->in.access_mask = PRINTER_ACCESS_USE;
1931 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1932 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1934 winreg_create_printer_internal(p->mem_ctx,
1935 get_session_info_system(),
1936 p->msg_ctx,
1937 lp_const_servicename(snum));
1939 break;
1941 default:
1942 /* sanity check to prevent programmer error */
1943 ZERO_STRUCTP(r->out.handle);
1944 return WERR_BADFID;
1947 Printer->access_granted = r->in.access_mask;
1950 * If the client sent a devmode in the OpenPrinter() call, then
1951 * save it here in case we get a job submission on this handle
1954 if ((Printer->printer_type != SPLHND_SERVER)
1955 && (r->in.devmode_ctr.devmode != NULL)) {
1956 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1957 &Printer->devmode);
1960 return WERR_OK;
1963 /****************************************************************
1964 _spoolss_ClosePrinter
1965 ****************************************************************/
1967 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1968 struct spoolss_ClosePrinter *r)
1970 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1972 if (Printer && Printer->document_started) {
1973 struct spoolss_EndDocPrinter e;
1975 e.in.handle = r->in.handle;
1977 _spoolss_EndDocPrinter(p, &e);
1980 if (!close_printer_handle(p, r->in.handle))
1981 return WERR_BADFID;
1983 /* clear the returned printer handle. Observed behavior
1984 from Win2k server. Don't think this really matters.
1985 Previous code just copied the value of the closed
1986 handle. --jerry */
1988 ZERO_STRUCTP(r->out.handle);
1990 return WERR_OK;
1993 /****************************************************************
1994 _spoolss_DeletePrinter
1995 ****************************************************************/
1997 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1998 struct spoolss_DeletePrinter *r)
2000 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2001 WERROR result;
2002 int snum;
2004 if (Printer && Printer->document_started) {
2005 struct spoolss_EndDocPrinter e;
2007 e.in.handle = r->in.handle;
2009 _spoolss_EndDocPrinter(p, &e);
2012 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2013 winreg_delete_printer_key_internal(p->mem_ctx,
2014 get_session_info_system(),
2015 p->msg_ctx,
2016 lp_const_servicename(snum),
2017 "");
2020 result = delete_printer_handle(p, r->in.handle);
2022 return result;
2025 /*******************************************************************
2026 * static function to lookup the version id corresponding to an
2027 * long architecture string
2028 ******************************************************************/
2030 static const struct print_architecture_table_node archi_table[]= {
2032 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2033 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2034 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2035 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2036 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2037 {"Windows IA64", SPL_ARCH_IA64, 3 },
2038 {"Windows x64", SPL_ARCH_X64, 3 },
2039 {NULL, "", -1 }
2042 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2043 SPOOLSS_DRIVER_VERSION_NT35,
2044 SPOOLSS_DRIVER_VERSION_NT4,
2045 SPOOLSS_DRIVER_VERSION_200X,
2046 -1};
2048 static int get_version_id(const char *arch)
2050 int i;
2052 for (i=0; archi_table[i].long_archi != NULL; i++)
2054 if (strcmp(arch, archi_table[i].long_archi) == 0)
2055 return (archi_table[i].version);
2058 return -1;
2061 /****************************************************************
2062 _spoolss_DeletePrinterDriver
2063 ****************************************************************/
2065 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2066 struct spoolss_DeletePrinterDriver *r)
2069 struct spoolss_DriverInfo8 *info = NULL;
2070 int version;
2071 WERROR status;
2072 struct dcerpc_binding_handle *b;
2073 TALLOC_CTX *tmp_ctx = NULL;
2074 int i;
2075 bool found;
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2081 !security_token_has_privilege(p->session_info->security_token,
2082 SEC_PRIV_PRINT_OPERATOR)) {
2083 return WERR_ACCESS_DENIED;
2086 /* check that we have a valid driver name first */
2088 if ((version = get_version_id(r->in.architecture)) == -1) {
2089 return WERR_INVALID_ENVIRONMENT;
2092 tmp_ctx = talloc_new(p->mem_ctx);
2093 if (!tmp_ctx) {
2094 return WERR_NOMEM;
2097 status = winreg_printer_binding_handle(tmp_ctx,
2098 get_session_info_system(),
2099 p->msg_ctx,
2100 &b);
2101 if (!W_ERROR_IS_OK(status)) {
2102 goto done;
2105 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2106 status = winreg_get_driver(tmp_ctx, b,
2107 r->in.architecture, r->in.driver,
2108 drv_cversion[i], &info);
2109 if (!W_ERROR_IS_OK(status)) {
2110 DEBUG(5, ("skipping del of driver with version %d\n",
2111 drv_cversion[i]));
2112 continue;
2114 found = true;
2116 if (printer_driver_in_use(tmp_ctx, b, info)) {
2117 status = WERR_PRINTER_DRIVER_IN_USE;
2118 goto done;
2121 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2122 if (!W_ERROR_IS_OK(status)) {
2123 DEBUG(0, ("failed del of driver with version %d\n",
2124 drv_cversion[i]));
2125 goto done;
2128 if (found == false) {
2129 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2130 status = WERR_UNKNOWN_PRINTER_DRIVER;
2131 } else {
2132 status = WERR_OK;
2135 done:
2136 talloc_free(tmp_ctx);
2138 return status;
2141 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2142 struct pipes_struct *p,
2143 struct spoolss_DeletePrinterDriverEx *r,
2144 struct dcerpc_binding_handle *b,
2145 struct spoolss_DriverInfo8 *info)
2147 WERROR status;
2148 bool delete_files;
2150 if (printer_driver_in_use(mem_ctx, b, info)) {
2151 status = WERR_PRINTER_DRIVER_IN_USE;
2152 goto done;
2156 * we have a couple of cases to consider.
2157 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2158 * then the delete should fail if **any** files overlap with
2159 * other drivers
2160 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2161 * non-overlapping files
2162 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2163 * are set, then do not delete any files
2164 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2167 delete_files = r->in.delete_flags
2168 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2171 if (delete_files) {
2172 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2173 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2174 status = WERR_PRINTER_DRIVER_IN_USE;
2175 goto done;
2178 * printer_driver_files_in_use() has trimmed overlapping files
2179 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2184 status = winreg_del_driver(mem_ctx, b, info, info->version);
2185 if (!W_ERROR_IS_OK(status)) {
2186 goto done;
2190 * now delete any associated files if delete_files is
2191 * true. Even if this part failes, we return succes
2192 * because the driver doesn not exist any more
2194 if (delete_files) {
2195 delete_driver_files(p->session_info, info);
2198 done:
2199 return status;
2202 /****************************************************************
2203 _spoolss_DeletePrinterDriverEx
2204 ****************************************************************/
2206 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2207 struct spoolss_DeletePrinterDriverEx *r)
2209 struct spoolss_DriverInfo8 *info = NULL;
2210 WERROR status;
2211 struct dcerpc_binding_handle *b;
2212 TALLOC_CTX *tmp_ctx = NULL;
2213 int i;
2214 bool found;
2216 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2217 and not a printer admin, then fail */
2219 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2220 !security_token_has_privilege(p->session_info->security_token,
2221 SEC_PRIV_PRINT_OPERATOR)) {
2222 return WERR_ACCESS_DENIED;
2225 /* check that we have a valid driver name first */
2226 if (get_version_id(r->in.architecture) == -1) {
2227 /* this is what NT returns */
2228 return WERR_INVALID_ENVIRONMENT;
2231 tmp_ctx = talloc_new(p->mem_ctx);
2232 if (!tmp_ctx) {
2233 return WERR_NOMEM;
2236 status = winreg_printer_binding_handle(tmp_ctx,
2237 get_session_info_system(),
2238 p->msg_ctx,
2239 &b);
2240 if (!W_ERROR_IS_OK(status)) {
2241 goto done;
2244 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2245 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2246 && (drv_cversion[i] != r->in.version)) {
2247 continue;
2250 /* check if a driver with this version exists before delete */
2251 status = winreg_get_driver(tmp_ctx, b,
2252 r->in.architecture, r->in.driver,
2253 drv_cversion[i], &info);
2254 if (!W_ERROR_IS_OK(status)) {
2255 DEBUG(5, ("skipping del of driver with version %d\n",
2256 drv_cversion[i]));
2257 continue;
2259 found = true;
2261 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2262 if (!W_ERROR_IS_OK(status)) {
2263 DEBUG(0, ("failed to delete driver with version %d\n",
2264 drv_cversion[i]));
2265 goto done;
2268 if (found == false) {
2269 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2270 status = WERR_UNKNOWN_PRINTER_DRIVER;
2271 } else {
2272 status = WERR_OK;
2275 done:
2276 talloc_free(tmp_ctx);
2277 return status;
2281 /********************************************************************
2282 GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2285 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2286 const char *value,
2287 enum winreg_Type *type,
2288 union spoolss_PrinterData *data)
2290 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2292 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2293 *type = REG_DWORD;
2294 SIVAL(&data->value, 0, 0x00);
2295 return WERR_OK;
2298 if (!strcasecmp_m(value, "BeepEnabled")) {
2299 *type = REG_DWORD;
2300 SIVAL(&data->value, 0, 0x00);
2301 return WERR_OK;
2304 if (!strcasecmp_m(value, "EventLog")) {
2305 *type = REG_DWORD;
2306 /* formally was 0x1b */
2307 SIVAL(&data->value, 0, 0x00);
2308 return WERR_OK;
2311 if (!strcasecmp_m(value, "NetPopup")) {
2312 *type = REG_DWORD;
2313 SIVAL(&data->value, 0, 0x00);
2314 return WERR_OK;
2317 if (!strcasecmp_m(value, "MajorVersion")) {
2318 *type = REG_DWORD;
2320 /* Windows NT 4.0 seems to not allow uploading of drivers
2321 to a server that reports 0x3 as the MajorVersion.
2322 need to investigate more how Win2k gets around this .
2323 -- jerry */
2325 if (RA_WINNT == get_remote_arch()) {
2326 SIVAL(&data->value, 0, 0x02);
2327 } else {
2328 SIVAL(&data->value, 0, 0x03);
2331 return WERR_OK;
2334 if (!strcasecmp_m(value, "MinorVersion")) {
2335 *type = REG_DWORD;
2336 SIVAL(&data->value, 0, 0x00);
2337 return WERR_OK;
2340 /* REG_BINARY
2341 * uint32_t size = 0x114
2342 * uint32_t major = 5
2343 * uint32_t minor = [0|1]
2344 * uint32_t build = [2195|2600]
2345 * extra unicode string = e.g. "Service Pack 3"
2347 if (!strcasecmp_m(value, "OSVersion")) {
2348 DATA_BLOB blob;
2349 enum ndr_err_code ndr_err;
2350 struct spoolss_OSVersion os;
2352 os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2353 "spoolss", "os_major", 5);
2354 /* Windows 2000 == 5.0 */
2355 os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2356 "spoolss", "os_minor", 0);
2357 os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2358 "spoolss", "os_build", 2195);
2359 os.extra_string = ""; /* leave extra string empty */
2361 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2362 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2363 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2364 return WERR_GENERAL_FAILURE;
2367 if (DEBUGLEVEL >= 10) {
2368 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2371 *type = REG_BINARY;
2372 data->binary = blob;
2374 return WERR_OK;
2378 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2379 *type = REG_SZ;
2381 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2382 W_ERROR_HAVE_NO_MEMORY(data->string);
2384 return WERR_OK;
2387 if (!strcasecmp_m(value, "Architecture")) {
2388 *type = REG_SZ;
2389 data->string = talloc_strdup(mem_ctx,
2390 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2391 W_ERROR_HAVE_NO_MEMORY(data->string);
2393 return WERR_OK;
2396 if (!strcasecmp_m(value, "DsPresent")) {
2397 *type = REG_DWORD;
2399 /* only show the publish check box if we are a
2400 member of a AD domain */
2402 if (lp_security() == SEC_ADS) {
2403 SIVAL(&data->value, 0, 0x01);
2404 } else {
2405 SIVAL(&data->value, 0, 0x00);
2407 return WERR_OK;
2410 if (!strcasecmp_m(value, "DNSMachineName")) {
2411 const char *hostname = get_mydnsfullname();
2413 if (!hostname) {
2414 return WERR_BADFILE;
2417 *type = REG_SZ;
2418 data->string = talloc_strdup(mem_ctx, hostname);
2419 W_ERROR_HAVE_NO_MEMORY(data->string);
2421 return WERR_OK;
2424 *type = REG_NONE;
2426 return WERR_INVALID_PARAM;
2429 /****************************************************************
2430 _spoolss_GetPrinterData
2431 ****************************************************************/
2433 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2434 struct spoolss_GetPrinterData *r)
2436 struct spoolss_GetPrinterDataEx r2;
2438 r2.in.handle = r->in.handle;
2439 r2.in.key_name = "PrinterDriverData";
2440 r2.in.value_name = r->in.value_name;
2441 r2.in.offered = r->in.offered;
2442 r2.out.type = r->out.type;
2443 r2.out.data = r->out.data;
2444 r2.out.needed = r->out.needed;
2446 return _spoolss_GetPrinterDataEx(p, &r2);
2449 /*********************************************************
2450 Connect to the client machine.
2451 **********************************************************/
2453 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2454 struct sockaddr_storage *client_ss, const char *remote_machine)
2456 NTSTATUS ret;
2457 struct cli_state *the_cli;
2458 struct sockaddr_storage rm_addr;
2459 char addr[INET6_ADDRSTRLEN];
2461 if ( is_zero_addr(client_ss) ) {
2462 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2463 remote_machine));
2464 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2465 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2466 return false;
2468 print_sockaddr(addr, sizeof(addr), &rm_addr);
2469 } else {
2470 rm_addr = *client_ss;
2471 print_sockaddr(addr, sizeof(addr), &rm_addr);
2472 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2473 addr));
2476 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2477 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2478 addr));
2479 return false;
2482 /* setup the connection */
2483 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2484 &rm_addr, 0, "IPC$", "IPC",
2485 "", /* username */
2486 "", /* domain */
2487 "", /* password */
2488 0, lp_client_signing());
2490 if ( !NT_STATUS_IS_OK( ret ) ) {
2491 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2492 remote_machine ));
2493 return false;
2496 if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2497 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2498 cli_shutdown(the_cli);
2499 return false;
2503 * Ok - we have an anonymous connection to the IPC$ share.
2504 * Now start the NT Domain stuff :-).
2507 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2508 if (!NT_STATUS_IS_OK(ret)) {
2509 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2510 remote_machine, nt_errstr(ret)));
2511 cli_shutdown(the_cli);
2512 return false;
2515 return true;
2518 /***************************************************************************
2519 Connect to the client.
2520 ****************************************************************************/
2522 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2523 uint32_t localprinter,
2524 enum winreg_Type type,
2525 struct policy_handle *handle,
2526 struct notify_back_channel **_chan,
2527 struct sockaddr_storage *client_ss,
2528 struct messaging_context *msg_ctx)
2530 WERROR result;
2531 NTSTATUS status;
2532 struct notify_back_channel *chan;
2534 for (chan = back_channels; chan; chan = chan->next) {
2535 if (memcmp(&chan->client_address, client_ss,
2536 sizeof(struct sockaddr_storage)) == 0) {
2537 break;
2542 * If it's the first connection, contact the client
2543 * and connect to the IPC$ share anonymously
2545 if (!chan) {
2546 fstring unix_printer;
2548 /* the +2 is to strip the leading 2 backslashs */
2549 fstrcpy(unix_printer, printer + 2);
2551 chan = talloc_zero(NULL, struct notify_back_channel);
2552 if (!chan) {
2553 return false;
2555 chan->client_address = *client_ss;
2557 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2558 TALLOC_FREE(chan);
2559 return false;
2562 DLIST_ADD(back_channels, chan);
2564 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2565 receive_notify2_message_list);
2568 if (chan->cli_pipe == NULL ||
2569 chan->cli_pipe->binding_handle == NULL) {
2570 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2571 "NULL %s for printer %s\n",
2572 chan->cli_pipe == NULL ?
2573 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2574 printer));
2575 return false;
2579 * Tell the specific printing tdb we want messages for this printer
2580 * by registering our PID.
2583 if (!print_notify_register_pid(snum)) {
2584 DEBUG(0, ("Failed to register our pid for printer %s\n",
2585 printer));
2588 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2589 talloc_tos(),
2590 printer,
2591 localprinter,
2592 type,
2594 NULL,
2595 handle,
2596 &result);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2599 result = ntstatus_to_werror(status);
2600 } else if (!W_ERROR_IS_OK(result)) {
2601 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2604 chan->active_connections++;
2605 *_chan = chan;
2607 return (W_ERROR_IS_OK(result));
2610 /****************************************************************
2611 ****************************************************************/
2613 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2614 const struct spoolss_NotifyOption *r)
2616 struct spoolss_NotifyOption *option;
2617 uint32_t i,k;
2619 if (!r) {
2620 return NULL;
2623 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2624 if (!option) {
2625 return NULL;
2628 *option = *r;
2630 if (!option->count) {
2631 return option;
2634 option->types = talloc_zero_array(option,
2635 struct spoolss_NotifyOptionType, option->count);
2636 if (!option->types) {
2637 talloc_free(option);
2638 return NULL;
2641 for (i=0; i < option->count; i++) {
2642 option->types[i] = r->types[i];
2644 if (option->types[i].count) {
2645 option->types[i].fields = talloc_zero_array(option,
2646 union spoolss_Field, option->types[i].count);
2647 if (!option->types[i].fields) {
2648 talloc_free(option);
2649 return NULL;
2651 for (k=0; k<option->types[i].count; k++) {
2652 option->types[i].fields[k] =
2653 r->types[i].fields[k];
2658 return option;
2661 /****************************************************************
2662 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2664 * before replying OK: status=0 a rpc call is made to the workstation
2665 * asking ReplyOpenPrinter
2667 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2668 * called from api_spoolss_rffpcnex
2669 ****************************************************************/
2671 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2672 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2674 int snum = -1;
2675 struct spoolss_NotifyOption *option = r->in.notify_options;
2676 struct sockaddr_storage client_ss;
2677 ssize_t client_len;
2679 /* store the notify value in the printer struct */
2681 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2683 if (!Printer) {
2684 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2685 "Invalid handle (%s:%u:%u).\n",
2686 OUR_HANDLE(r->in.handle)));
2687 return WERR_BADFID;
2690 Printer->notify.flags = r->in.flags;
2691 Printer->notify.options = r->in.options;
2692 Printer->notify.printerlocal = r->in.printer_local;
2693 Printer->notify.msg_ctx = p->msg_ctx;
2695 TALLOC_FREE(Printer->notify.option);
2696 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2698 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2700 /* Connect to the client machine and send a ReplyOpenPrinter */
2702 if ( Printer->printer_type == SPLHND_SERVER)
2703 snum = -1;
2704 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2705 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2706 return WERR_BADFID;
2708 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2709 "remote_address is %s\n",
2710 tsocket_address_string(p->remote_address, p->mem_ctx)));
2712 if (!lp_print_notify_backchannel(snum)) {
2713 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2714 "backchannel disabled\n"));
2715 return WERR_SERVER_UNAVAILABLE;
2718 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2719 (struct sockaddr *) &client_ss,
2720 sizeof(struct sockaddr_storage));
2721 if (client_len < 0) {
2722 return WERR_NOMEM;
2725 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2726 Printer->notify.printerlocal, REG_SZ,
2727 &Printer->notify.cli_hnd,
2728 &Printer->notify.cli_chan,
2729 &client_ss, p->msg_ctx)) {
2730 return WERR_SERVER_UNAVAILABLE;
2733 return WERR_OK;
2736 /*******************************************************************
2737 * fill a notify_info_data with the servername
2738 ********************************************************************/
2740 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2741 int snum,
2742 struct spoolss_Notify *data,
2743 print_queue_struct *queue,
2744 struct spoolss_PrinterInfo2 *pinfo2,
2745 TALLOC_CTX *mem_ctx)
2747 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2750 /*******************************************************************
2751 * fill a notify_info_data with the printername (not including the servername).
2752 ********************************************************************/
2754 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2755 int snum,
2756 struct spoolss_Notify *data,
2757 print_queue_struct *queue,
2758 struct spoolss_PrinterInfo2 *pinfo2,
2759 TALLOC_CTX *mem_ctx)
2761 /* the notify name should not contain the \\server\ part */
2762 const char *p = strrchr(pinfo2->printername, '\\');
2764 if (!p) {
2765 p = pinfo2->printername;
2766 } else {
2767 p++;
2770 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2773 /*******************************************************************
2774 * fill a notify_info_data with the servicename
2775 ********************************************************************/
2777 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2778 int snum,
2779 struct spoolss_Notify *data,
2780 print_queue_struct *queue,
2781 struct spoolss_PrinterInfo2 *pinfo2,
2782 TALLOC_CTX *mem_ctx)
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2787 /*******************************************************************
2788 * fill a notify_info_data with the port name
2789 ********************************************************************/
2791 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2792 int snum,
2793 struct spoolss_Notify *data,
2794 print_queue_struct *queue,
2795 struct spoolss_PrinterInfo2 *pinfo2,
2796 TALLOC_CTX *mem_ctx)
2798 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2801 /*******************************************************************
2802 * fill a notify_info_data with the printername
2803 * but it doesn't exist, have to see what to do
2804 ********************************************************************/
2806 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2807 int snum,
2808 struct spoolss_Notify *data,
2809 print_queue_struct *queue,
2810 struct spoolss_PrinterInfo2 *pinfo2,
2811 TALLOC_CTX *mem_ctx)
2813 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2816 /*******************************************************************
2817 * fill a notify_info_data with the comment
2818 ********************************************************************/
2820 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2821 int snum,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 struct spoolss_PrinterInfo2 *pinfo2,
2825 TALLOC_CTX *mem_ctx)
2827 const char *p;
2829 if (*pinfo2->comment == '\0') {
2830 p = lp_comment(talloc_tos(), snum);
2831 } else {
2832 p = pinfo2->comment;
2835 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2838 /*******************************************************************
2839 * fill a notify_info_data with the comment
2840 * location = "Room 1, floor 2, building 3"
2841 ********************************************************************/
2843 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2844 int snum,
2845 struct spoolss_Notify *data,
2846 print_queue_struct *queue,
2847 struct spoolss_PrinterInfo2 *pinfo2,
2848 TALLOC_CTX *mem_ctx)
2850 const char *loc = pinfo2->location;
2851 NTSTATUS status;
2853 status = printer_list_get_printer(mem_ctx,
2854 pinfo2->sharename,
2855 NULL,
2856 &loc,
2857 NULL);
2858 if (NT_STATUS_IS_OK(status)) {
2859 if (loc == NULL) {
2860 loc = pinfo2->location;
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2867 /*******************************************************************
2868 * fill a notify_info_data with the device mode
2869 * jfm:xxxx don't to it for know but that's a real problem !!!
2870 ********************************************************************/
2872 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2873 int snum,
2874 struct spoolss_Notify *data,
2875 print_queue_struct *queue,
2876 struct spoolss_PrinterInfo2 *pinfo2,
2877 TALLOC_CTX *mem_ctx)
2879 /* for a dummy implementation we have to zero the fields */
2880 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2883 /*******************************************************************
2884 * fill a notify_info_data with the separator file name
2885 ********************************************************************/
2887 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2888 int snum,
2889 struct spoolss_Notify *data,
2890 print_queue_struct *queue,
2891 struct spoolss_PrinterInfo2 *pinfo2,
2892 TALLOC_CTX *mem_ctx)
2894 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2897 /*******************************************************************
2898 * fill a notify_info_data with the print processor
2899 * jfm:xxxx return always winprint to indicate we don't do anything to it
2900 ********************************************************************/
2902 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2903 int snum,
2904 struct spoolss_Notify *data,
2905 print_queue_struct *queue,
2906 struct spoolss_PrinterInfo2 *pinfo2,
2907 TALLOC_CTX *mem_ctx)
2909 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2912 /*******************************************************************
2913 * fill a notify_info_data with the print processor options
2914 * jfm:xxxx send an empty string
2915 ********************************************************************/
2917 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2918 int snum,
2919 struct spoolss_Notify *data,
2920 print_queue_struct *queue,
2921 struct spoolss_PrinterInfo2 *pinfo2,
2922 TALLOC_CTX *mem_ctx)
2924 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2927 /*******************************************************************
2928 * fill a notify_info_data with the data type
2929 * jfm:xxxx always send RAW as data type
2930 ********************************************************************/
2932 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2933 int snum,
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 struct spoolss_PrinterInfo2 *pinfo2,
2937 TALLOC_CTX *mem_ctx)
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2942 /*******************************************************************
2943 * fill a notify_info_data with the security descriptor
2944 * jfm:xxxx send an null pointer to say no security desc
2945 * have to implement security before !
2946 ********************************************************************/
2948 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2949 int snum,
2950 struct spoolss_Notify *data,
2951 print_queue_struct *queue,
2952 struct spoolss_PrinterInfo2 *pinfo2,
2953 TALLOC_CTX *mem_ctx)
2955 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2958 /*******************************************************************
2959 * fill a notify_info_data with the attributes
2960 * jfm:xxxx a samba printer is always shared
2961 ********************************************************************/
2963 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2964 int snum,
2965 struct spoolss_Notify *data,
2966 print_queue_struct *queue,
2967 struct spoolss_PrinterInfo2 *pinfo2,
2968 TALLOC_CTX *mem_ctx)
2970 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2973 /*******************************************************************
2974 * fill a notify_info_data with the priority
2975 ********************************************************************/
2977 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2978 int snum,
2979 struct spoolss_Notify *data,
2980 print_queue_struct *queue,
2981 struct spoolss_PrinterInfo2 *pinfo2,
2982 TALLOC_CTX *mem_ctx)
2984 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2987 /*******************************************************************
2988 * fill a notify_info_data with the default priority
2989 ********************************************************************/
2991 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2992 int snum,
2993 struct spoolss_Notify *data,
2994 print_queue_struct *queue,
2995 struct spoolss_PrinterInfo2 *pinfo2,
2996 TALLOC_CTX *mem_ctx)
2998 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3001 /*******************************************************************
3002 * fill a notify_info_data with the start time
3003 ********************************************************************/
3005 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3006 int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 struct spoolss_PrinterInfo2 *pinfo2,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3015 /*******************************************************************
3016 * fill a notify_info_data with the until time
3017 ********************************************************************/
3019 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3020 int snum,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 struct spoolss_PrinterInfo2 *pinfo2,
3024 TALLOC_CTX *mem_ctx)
3026 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3029 /*******************************************************************
3030 * fill a notify_info_data with the status
3031 ********************************************************************/
3033 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3034 int snum,
3035 struct spoolss_Notify *data,
3036 print_queue_struct *queue,
3037 struct spoolss_PrinterInfo2 *pinfo2,
3038 TALLOC_CTX *mem_ctx)
3040 print_status_struct status;
3042 print_queue_length(msg_ctx, snum, &status);
3043 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3046 /*******************************************************************
3047 * fill a notify_info_data with the number of jobs queued
3048 ********************************************************************/
3050 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3051 int snum,
3052 struct spoolss_Notify *data,
3053 print_queue_struct *queue,
3054 struct spoolss_PrinterInfo2 *pinfo2,
3055 TALLOC_CTX *mem_ctx)
3057 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3058 data, print_queue_length(msg_ctx, snum, NULL));
3061 /*******************************************************************
3062 * fill a notify_info_data with the average ppm
3063 ********************************************************************/
3065 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3066 int snum,
3067 struct spoolss_Notify *data,
3068 print_queue_struct *queue,
3069 struct spoolss_PrinterInfo2 *pinfo2,
3070 TALLOC_CTX *mem_ctx)
3072 /* always respond 8 pages per minutes */
3073 /* a little hard ! */
3074 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3077 /*******************************************************************
3078 * fill a notify_info_data with username
3079 ********************************************************************/
3081 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3082 int snum,
3083 struct spoolss_Notify *data,
3084 print_queue_struct *queue,
3085 struct spoolss_PrinterInfo2 *pinfo2,
3086 TALLOC_CTX *mem_ctx)
3088 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3091 /*******************************************************************
3092 * fill a notify_info_data with job status
3093 ********************************************************************/
3095 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3096 int snum,
3097 struct spoolss_Notify *data,
3098 print_queue_struct *queue,
3099 struct spoolss_PrinterInfo2 *pinfo2,
3100 TALLOC_CTX *mem_ctx)
3102 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3105 /*******************************************************************
3106 * fill a notify_info_data with job name
3107 ********************************************************************/
3109 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3110 int snum,
3111 struct spoolss_Notify *data,
3112 print_queue_struct *queue,
3113 struct spoolss_PrinterInfo2 *pinfo2,
3114 TALLOC_CTX *mem_ctx)
3116 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3119 /*******************************************************************
3120 * fill a notify_info_data with job status
3121 ********************************************************************/
3123 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3124 int snum,
3125 struct spoolss_Notify *data,
3126 print_queue_struct *queue,
3127 struct spoolss_PrinterInfo2 *pinfo2,
3128 TALLOC_CTX *mem_ctx)
3131 * Now we're returning job status codes we just return a "" here. JRA.
3134 const char *p = "";
3136 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3137 p = "unknown";
3139 switch (queue->status) {
3140 case LPQ_QUEUED:
3141 p = "Queued";
3142 break;
3143 case LPQ_PAUSED:
3144 p = ""; /* NT provides the paused string */
3145 break;
3146 case LPQ_SPOOLING:
3147 p = "Spooling";
3148 break;
3149 case LPQ_PRINTING:
3150 p = "Printing";
3151 break;
3153 #endif /* NO LONGER NEEDED. */
3155 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3158 /*******************************************************************
3159 * fill a notify_info_data with job time
3160 ********************************************************************/
3162 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3163 int snum,
3164 struct spoolss_Notify *data,
3165 print_queue_struct *queue,
3166 struct spoolss_PrinterInfo2 *pinfo2,
3167 TALLOC_CTX *mem_ctx)
3169 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3172 /*******************************************************************
3173 * fill a notify_info_data with job size
3174 ********************************************************************/
3176 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3177 int snum,
3178 struct spoolss_Notify *data,
3179 print_queue_struct *queue,
3180 struct spoolss_PrinterInfo2 *pinfo2,
3181 TALLOC_CTX *mem_ctx)
3183 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3186 /*******************************************************************
3187 * fill a notify_info_data with page info
3188 ********************************************************************/
3189 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3190 int snum,
3191 struct spoolss_Notify *data,
3192 print_queue_struct *queue,
3193 struct spoolss_PrinterInfo2 *pinfo2,
3194 TALLOC_CTX *mem_ctx)
3196 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3199 /*******************************************************************
3200 * fill a notify_info_data with pages printed info.
3201 ********************************************************************/
3202 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3203 int snum,
3204 struct spoolss_Notify *data,
3205 print_queue_struct *queue,
3206 struct spoolss_PrinterInfo2 *pinfo2,
3207 TALLOC_CTX *mem_ctx)
3209 /* Add code when back-end tracks this */
3210 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3213 /*******************************************************************
3214 Fill a notify_info_data with job position.
3215 ********************************************************************/
3217 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3218 int snum,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 struct spoolss_PrinterInfo2 *pinfo2,
3222 TALLOC_CTX *mem_ctx)
3224 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3227 /*******************************************************************
3228 Fill a notify_info_data with submitted time.
3229 ********************************************************************/
3231 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3232 int snum,
3233 struct spoolss_Notify *data,
3234 print_queue_struct *queue,
3235 struct spoolss_PrinterInfo2 *pinfo2,
3236 TALLOC_CTX *mem_ctx)
3238 data->data.string.string = NULL;
3239 data->data.string.size = 0;
3241 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3242 &data->data.string.string,
3243 &data->data.string.size);
3247 struct s_notify_info_data_table
3249 enum spoolss_NotifyType type;
3250 uint16_t field;
3251 const char *name;
3252 enum spoolss_NotifyTable variable_type;
3253 void (*fn) (struct messaging_context *msg_ctx,
3254 int snum, struct spoolss_Notify *data,
3255 print_queue_struct *queue,
3256 struct spoolss_PrinterInfo2 *pinfo2,
3257 TALLOC_CTX *mem_ctx);
3260 /* A table describing the various print notification constants and
3261 whether the notification data is a pointer to a variable sized
3262 buffer, a one value uint32_t or a two value uint32_t. */
3264 static const struct s_notify_info_data_table notify_info_data_table[] =
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3317 /*******************************************************************
3318 Return the variable_type of info_data structure.
3319 ********************************************************************/
3321 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3322 uint16_t field)
3324 int i=0;
3326 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3327 if ( (notify_info_data_table[i].type == type) &&
3328 (notify_info_data_table[i].field == field) ) {
3329 return notify_info_data_table[i].variable_type;
3333 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3335 return (enum spoolss_NotifyTable) 0;
3338 /****************************************************************************
3339 ****************************************************************************/
3341 static bool search_notify(enum spoolss_NotifyType type,
3342 uint16_t field,
3343 int *value)
3345 int i;
3347 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3348 if (notify_info_data_table[i].type == type &&
3349 notify_info_data_table[i].field == field &&
3350 notify_info_data_table[i].fn != NULL) {
3351 *value = i;
3352 return true;
3356 return false;
3359 /****************************************************************************
3360 ****************************************************************************/
3362 static void construct_info_data(struct spoolss_Notify *info_data,
3363 enum spoolss_NotifyType type,
3364 uint16_t field, int id)
3366 info_data->type = type;
3367 info_data->field.field = field;
3368 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3369 info_data->job_id = id;
3372 /*******************************************************************
3374 * fill a notify_info struct with info asked
3376 ********************************************************************/
3378 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3379 struct printer_handle *print_hnd,
3380 struct spoolss_NotifyInfo *info,
3381 struct spoolss_PrinterInfo2 *pinfo2,
3382 int snum,
3383 const struct spoolss_NotifyOptionType *option_type,
3384 uint32_t id,
3385 TALLOC_CTX *mem_ctx)
3387 int field_num,j;
3388 enum spoolss_NotifyType type;
3389 uint16_t field;
3391 struct spoolss_Notify *current_data;
3393 type = option_type->type;
3395 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3396 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3397 option_type->count, lp_servicename(talloc_tos(), snum)));
3399 for(field_num=0; field_num < option_type->count; field_num++) {
3400 field = option_type->fields[field_num].field;
3402 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3404 if (!search_notify(type, field, &j) )
3405 continue;
3407 info->notifies = talloc_realloc(info, info->notifies,
3408 struct spoolss_Notify,
3409 info->count + 1);
3410 if (info->notifies == NULL) {
3411 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3412 return false;
3415 current_data = &info->notifies[info->count];
3417 construct_info_data(current_data, type, field, id);
3419 DEBUG(10, ("construct_notify_printer_info: "
3420 "calling [%s] snum=%d printername=[%s])\n",
3421 notify_info_data_table[j].name, snum,
3422 pinfo2->printername));
3424 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3425 NULL, pinfo2, mem_ctx);
3427 info->count++;
3430 return true;
3433 /*******************************************************************
3435 * fill a notify_info struct with info asked
3437 ********************************************************************/
3439 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3440 print_queue_struct *queue,
3441 struct spoolss_NotifyInfo *info,
3442 struct spoolss_PrinterInfo2 *pinfo2,
3443 int snum,
3444 const struct spoolss_NotifyOptionType *option_type,
3445 uint32_t id,
3446 TALLOC_CTX *mem_ctx)
3448 int field_num,j;
3449 enum spoolss_NotifyType type;
3450 uint16_t field;
3451 struct spoolss_Notify *current_data;
3453 DEBUG(4,("construct_notify_jobs_info\n"));
3455 type = option_type->type;
3457 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3458 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3459 option_type->count));
3461 for(field_num=0; field_num<option_type->count; field_num++) {
3462 field = option_type->fields[field_num].field;
3464 if (!search_notify(type, field, &j) )
3465 continue;
3467 info->notifies = talloc_realloc(info, info->notifies,
3468 struct spoolss_Notify,
3469 info->count + 1);
3470 if (info->notifies == NULL) {
3471 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3472 return false;
3475 current_data=&(info->notifies[info->count]);
3477 construct_info_data(current_data, type, field, id);
3478 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3479 queue, pinfo2, mem_ctx);
3480 info->count++;
3483 return true;
3487 * JFM: The enumeration is not that simple, it's even non obvious.
3489 * let's take an example: I want to monitor the PRINTER SERVER for
3490 * the printer's name and the number of jobs currently queued.
3491 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3492 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3494 * I have 3 printers on the back of my server.
3496 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3497 * structures.
3498 * Number Data Id
3499 * 1 printer 1 name 1
3500 * 2 printer 1 cjob 1
3501 * 3 printer 2 name 2
3502 * 4 printer 2 cjob 2
3503 * 5 printer 3 name 3
3504 * 6 printer 3 name 3
3506 * that's the print server case, the printer case is even worse.
3509 /*******************************************************************
3511 * enumerate all printers on the printserver
3512 * fill a notify_info struct with info asked
3514 ********************************************************************/
3516 static WERROR printserver_notify_info(struct pipes_struct *p,
3517 struct policy_handle *hnd,
3518 struct spoolss_NotifyInfo *info,
3519 TALLOC_CTX *mem_ctx)
3521 int snum;
3522 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3523 int n_services=lp_numservices();
3524 int i;
3525 struct spoolss_NotifyOption *option;
3526 struct spoolss_NotifyOptionType option_type;
3527 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3528 WERROR result;
3530 DEBUG(4,("printserver_notify_info\n"));
3532 if (!Printer)
3533 return WERR_BADFID;
3535 option = Printer->notify.option;
3537 info->version = 2;
3538 info->notifies = NULL;
3539 info->count = 0;
3541 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3542 sending a ffpcn() request first */
3544 if ( !option )
3545 return WERR_BADFID;
3547 for (i=0; i<option->count; i++) {
3548 option_type = option->types[i];
3550 if (option_type.type != PRINTER_NOTIFY_TYPE)
3551 continue;
3553 for (snum = 0; snum < n_services; snum++) {
3554 if (!lp_browseable(snum) ||
3555 !lp_snum_ok(snum) ||
3556 !lp_print_ok(snum)) {
3557 continue; /* skip */
3560 /* Maybe we should use the SYSTEM session_info here... */
3561 result = winreg_get_printer_internal(mem_ctx,
3562 get_session_info_system(),
3563 p->msg_ctx,
3564 lp_servicename(talloc_tos(), snum),
3565 &pinfo2);
3566 if (!W_ERROR_IS_OK(result)) {
3567 DEBUG(4, ("printserver_notify_info: "
3568 "Failed to get printer [%s]\n",
3569 lp_servicename(talloc_tos(), snum)));
3570 continue;
3574 construct_notify_printer_info(p->msg_ctx,
3575 Printer, info,
3576 pinfo2, snum,
3577 &option_type, snum,
3578 mem_ctx);
3580 TALLOC_FREE(pinfo2);
3584 #if 0
3586 * Debugging information, don't delete.
3589 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3590 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3591 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3593 for (i=0; i<info->count; i++) {
3594 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3595 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3596 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3598 #endif
3600 return WERR_OK;
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static WERROR printer_notify_info(struct pipes_struct *p,
3610 struct policy_handle *hnd,
3611 struct spoolss_NotifyInfo *info,
3612 TALLOC_CTX *mem_ctx)
3614 int snum;
3615 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3616 int i;
3617 uint32_t id;
3618 struct spoolss_NotifyOption *option;
3619 struct spoolss_NotifyOptionType option_type;
3620 int count,j;
3621 print_queue_struct *queue=NULL;
3622 print_status_struct status;
3623 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3624 WERROR result;
3625 struct tdb_print_db *pdb;
3627 DEBUG(4,("printer_notify_info\n"));
3629 if (!Printer)
3630 return WERR_BADFID;
3632 option = Printer->notify.option;
3633 id = 0x0;
3635 info->version = 2;
3636 info->notifies = NULL;
3637 info->count = 0;
3639 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3640 sending a ffpcn() request first */
3642 if ( !option )
3643 return WERR_BADFID;
3645 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3646 return WERR_BADFID;
3649 pdb = get_print_db_byname(Printer->sharename);
3650 if (pdb == NULL) {
3651 return WERR_BADFID;
3654 /* Maybe we should use the SYSTEM session_info here... */
3655 result = winreg_get_printer_internal(mem_ctx,
3656 get_session_info_system(),
3657 p->msg_ctx,
3658 lp_servicename(talloc_tos(), snum), &pinfo2);
3659 if (!W_ERROR_IS_OK(result)) {
3660 result = WERR_BADFID;
3661 goto err_pdb_drop;
3665 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3666 * correct servername.
3668 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3669 if (pinfo2->servername == NULL) {
3670 result = WERR_NOMEM;
3671 goto err_pdb_drop;
3674 for (i = 0; i < option->count; i++) {
3675 option_type = option->types[i];
3677 switch (option_type.type) {
3678 case PRINTER_NOTIFY_TYPE:
3679 if (construct_notify_printer_info(p->msg_ctx,
3680 Printer, info,
3681 pinfo2, snum,
3682 &option_type, id,
3683 mem_ctx)) {
3684 id--;
3686 break;
3688 case JOB_NOTIFY_TYPE:
3690 count = print_queue_status(p->msg_ctx, snum, &queue,
3691 &status);
3693 for (j = 0; j < count; j++) {
3694 uint32_t jobid;
3695 jobid = sysjob_to_jobid_pdb(pdb,
3696 queue[j].sysjob);
3697 if (jobid == (uint32_t)-1) {
3698 DEBUG(2, ("ignoring untracked job %d\n",
3699 queue[j].sysjob));
3700 continue;
3702 /* FIXME check return value */
3703 construct_notify_jobs_info(p->msg_ctx,
3704 &queue[j], info,
3705 pinfo2, snum,
3706 &option_type,
3707 jobid,
3708 mem_ctx);
3711 SAFE_FREE(queue);
3712 break;
3717 * Debugging information, don't delete.
3720 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3721 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3722 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3724 for (i=0; i<info->count; i++) {
3725 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3726 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3727 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3731 talloc_free(pinfo2);
3732 result = WERR_OK;
3733 err_pdb_drop:
3734 release_print_db(pdb);
3735 return result;
3738 /****************************************************************
3739 _spoolss_RouterRefreshPrinterChangeNotify
3740 ****************************************************************/
3742 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3743 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3745 struct spoolss_NotifyInfo *info;
3747 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3748 WERROR result = WERR_BADFID;
3750 /* we always have a spoolss_NotifyInfo struct */
3751 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3752 if (!info) {
3753 result = WERR_NOMEM;
3754 goto done;
3757 *r->out.info = info;
3759 if (!Printer) {
3760 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3761 "Invalid handle (%s:%u:%u).\n",
3762 OUR_HANDLE(r->in.handle)));
3763 goto done;
3766 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3769 * We are now using the change value, and
3770 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3771 * I don't have a global notification system, I'm sending back all the
3772 * information even when _NOTHING_ has changed.
3775 /* We need to keep track of the change value to send back in
3776 RRPCN replies otherwise our updates are ignored. */
3778 Printer->notify.fnpcn = true;
3780 if (Printer->notify.cli_chan != NULL &&
3781 Printer->notify.cli_chan->active_connections > 0) {
3782 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3783 "Saving change value in request [%x]\n",
3784 r->in.change_low));
3785 Printer->notify.change = r->in.change_low;
3788 /* just ignore the spoolss_NotifyOption */
3790 switch (Printer->printer_type) {
3791 case SPLHND_SERVER:
3792 result = printserver_notify_info(p, r->in.handle,
3793 info, p->mem_ctx);
3794 break;
3796 case SPLHND_PRINTER:
3797 result = printer_notify_info(p, r->in.handle,
3798 info, p->mem_ctx);
3799 break;
3802 Printer->notify.fnpcn = false;
3804 done:
3805 return result;
3808 /********************************************************************
3809 ********************************************************************/
3811 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3812 const char *servername,
3813 const char *printername,
3814 const char **printername_p)
3816 /* FIXME: add lp_force_printername() */
3818 if (servername == NULL) {
3819 *printername_p = talloc_strdup(mem_ctx, printername);
3820 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3821 return WERR_OK;
3824 if (servername[0] == '\\' && servername[1] == '\\') {
3825 servername += 2;
3828 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3829 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3831 return WERR_OK;
3834 /********************************************************************
3835 ********************************************************************/
3837 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3838 const char *printername)
3840 if (dm == NULL) {
3841 return;
3844 dm->devicename = talloc_strndup(dm, printername,
3845 MIN(strlen(printername), 31));
3848 /********************************************************************
3849 * construct_printer_info_0
3850 * fill a printer_info_0 struct
3851 ********************************************************************/
3853 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3854 const struct auth_session_info *session_info,
3855 struct messaging_context *msg_ctx,
3856 struct spoolss_PrinterInfo2 *info2,
3857 const char *servername,
3858 struct spoolss_PrinterInfo0 *r,
3859 int snum)
3861 int count;
3862 struct printer_session_counter *session_counter;
3863 struct timeval setuptime;
3864 print_status_struct status;
3865 WERROR result;
3867 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3868 if (!W_ERROR_IS_OK(result)) {
3869 return result;
3872 if (servername) {
3873 r->servername = talloc_strdup(mem_ctx, servername);
3874 W_ERROR_HAVE_NO_MEMORY(r->servername);
3875 } else {
3876 r->servername = NULL;
3879 count = print_queue_length(msg_ctx, snum, &status);
3881 /* check if we already have a counter for this printer */
3882 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3883 if (session_counter->snum == snum)
3884 break;
3887 /* it's the first time, add it to the list */
3888 if (session_counter == NULL) {
3889 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3890 W_ERROR_HAVE_NO_MEMORY(session_counter);
3891 session_counter->snum = snum;
3892 session_counter->counter = 0;
3893 DLIST_ADD(counter_list, session_counter);
3896 /* increment it */
3897 session_counter->counter++;
3899 r->cjobs = count;
3900 r->total_jobs = 0;
3901 r->total_bytes = 0;
3903 get_startup_time(&setuptime);
3904 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3906 /* JFM:
3907 * the global_counter should be stored in a TDB as it's common to all the clients
3908 * and should be zeroed on samba startup
3910 r->global_counter = session_counter->counter;
3911 r->total_pages = 0;
3912 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3913 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3914 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3915 r->free_build = SPOOLSS_RELEASE_BUILD;
3916 r->spooling = 0;
3917 r->max_spooling = 0;
3918 r->session_counter = session_counter->counter;
3919 r->num_error_out_of_paper = 0x0;
3920 r->num_error_not_ready = 0x0; /* number of print failure */
3921 r->job_error = 0x0;
3922 r->number_of_processors = 0x1;
3923 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3924 r->high_part_total_bytes = 0x0;
3926 /* ChangeID in milliseconds*/
3927 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3928 info2->sharename, &r->change_id);
3930 r->last_error = WERR_OK;
3931 r->status = nt_printq_status(status.status);
3932 r->enumerate_network_printers = 0x0;
3933 r->c_setprinter = 0x0;
3934 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3935 r->processor_level = 0x6; /* 6 ???*/
3936 r->ref_ic = 0;
3937 r->reserved2 = 0;
3938 r->reserved3 = 0;
3940 return WERR_OK;
3944 /********************************************************************
3945 * construct_printer_info1
3946 * fill a spoolss_PrinterInfo1 struct
3947 ********************************************************************/
3949 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3950 const struct spoolss_PrinterInfo2 *info2,
3951 uint32_t flags,
3952 const char *servername,
3953 struct spoolss_PrinterInfo1 *r,
3954 int snum)
3956 WERROR result;
3958 r->flags = flags;
3960 if (info2->comment == NULL || info2->comment[0] == '\0') {
3961 r->comment = lp_comment(mem_ctx, snum);
3962 } else {
3963 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3965 W_ERROR_HAVE_NO_MEMORY(r->comment);
3967 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3968 if (!W_ERROR_IS_OK(result)) {
3969 return result;
3972 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3973 r->name,
3974 info2->drivername,
3975 r->comment);
3976 W_ERROR_HAVE_NO_MEMORY(r->description);
3978 return WERR_OK;
3981 /********************************************************************
3982 * construct_printer_info2
3983 * fill a spoolss_PrinterInfo2 struct
3984 ********************************************************************/
3986 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3987 struct messaging_context *msg_ctx,
3988 const struct spoolss_PrinterInfo2 *info2,
3989 const char *servername,
3990 struct spoolss_PrinterInfo2 *r,
3991 int snum)
3993 int count;
3994 print_status_struct status;
3995 WERROR result;
3997 count = print_queue_length(msg_ctx, snum, &status);
3999 if (servername) {
4000 r->servername = talloc_strdup(mem_ctx, servername);
4001 W_ERROR_HAVE_NO_MEMORY(r->servername);
4002 } else {
4003 r->servername = NULL;
4006 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4007 if (!W_ERROR_IS_OK(result)) {
4008 return result;
4011 r->sharename = lp_servicename(mem_ctx, snum);
4012 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4013 r->portname = talloc_strdup(mem_ctx, info2->portname);
4014 W_ERROR_HAVE_NO_MEMORY(r->portname);
4015 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4016 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4018 if (info2->comment[0] == '\0') {
4019 r->comment = lp_comment(mem_ctx, snum);
4020 } else {
4021 r->comment = talloc_strdup(mem_ctx, info2->comment);
4023 W_ERROR_HAVE_NO_MEMORY(r->comment);
4025 r->location = talloc_strdup(mem_ctx, info2->location);
4026 if (info2->location[0] == '\0') {
4027 const char *loc = NULL;
4028 NTSTATUS nt_status;
4030 nt_status = printer_list_get_printer(mem_ctx,
4031 info2->sharename,
4032 NULL,
4033 &loc,
4034 NULL);
4035 if (NT_STATUS_IS_OK(nt_status)) {
4036 if (loc != NULL) {
4037 r->location = talloc_strdup(mem_ctx, loc);
4041 W_ERROR_HAVE_NO_MEMORY(r->location);
4043 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4044 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4045 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4046 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4047 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4048 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4049 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4050 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4052 r->attributes = info2->attributes;
4054 r->priority = info2->priority;
4055 r->defaultpriority = info2->defaultpriority;
4056 r->starttime = info2->starttime;
4057 r->untiltime = info2->untiltime;
4058 r->status = nt_printq_status(status.status);
4059 r->cjobs = count;
4060 r->averageppm = info2->averageppm;
4062 if (info2->devmode != NULL) {
4063 result = copy_devicemode(mem_ctx,
4064 info2->devmode,
4065 &r->devmode);
4066 if (!W_ERROR_IS_OK(result)) {
4067 return result;
4069 } else if (lp_default_devmode(snum)) {
4070 result = spoolss_create_default_devmode(mem_ctx,
4071 info2->printername,
4072 &r->devmode);
4073 if (!W_ERROR_IS_OK(result)) {
4074 return result;
4076 } else {
4077 r->devmode = NULL;
4078 DEBUG(8,("Returning NULL Devicemode!\n"));
4081 compose_devicemode_devicename(r->devmode, r->printername);
4083 r->secdesc = NULL;
4085 if (info2->secdesc != NULL) {
4086 /* don't use talloc_steal() here unless you do a deep steal of all
4087 the SEC_DESC members */
4089 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4092 return WERR_OK;
4095 /********************************************************************
4096 * construct_printer_info3
4097 * fill a spoolss_PrinterInfo3 struct
4098 ********************************************************************/
4100 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4101 const struct spoolss_PrinterInfo2 *info2,
4102 const char *servername,
4103 struct spoolss_PrinterInfo3 *r,
4104 int snum)
4106 /* These are the components of the SD we are returning. */
4108 if (info2->secdesc != NULL) {
4109 /* don't use talloc_steal() here unless you do a deep steal of all
4110 the SEC_DESC members */
4112 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4113 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4116 return WERR_OK;
4119 /********************************************************************
4120 * construct_printer_info4
4121 * fill a spoolss_PrinterInfo4 struct
4122 ********************************************************************/
4124 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4125 const struct spoolss_PrinterInfo2 *info2,
4126 const char *servername,
4127 struct spoolss_PrinterInfo4 *r,
4128 int snum)
4130 WERROR result;
4132 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4133 if (!W_ERROR_IS_OK(result)) {
4134 return result;
4137 if (servername) {
4138 r->servername = talloc_strdup(mem_ctx, servername);
4139 W_ERROR_HAVE_NO_MEMORY(r->servername);
4140 } else {
4141 r->servername = NULL;
4144 r->attributes = info2->attributes;
4146 return WERR_OK;
4149 /********************************************************************
4150 * construct_printer_info5
4151 * fill a spoolss_PrinterInfo5 struct
4152 ********************************************************************/
4154 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4155 const struct spoolss_PrinterInfo2 *info2,
4156 const char *servername,
4157 struct spoolss_PrinterInfo5 *r,
4158 int snum)
4160 WERROR result;
4162 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4163 if (!W_ERROR_IS_OK(result)) {
4164 return result;
4167 r->portname = talloc_strdup(mem_ctx, info2->portname);
4168 W_ERROR_HAVE_NO_MEMORY(r->portname);
4170 r->attributes = info2->attributes;
4172 /* these two are not used by NT+ according to MSDN */
4173 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4174 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4176 return WERR_OK;
4179 /********************************************************************
4180 * construct_printer_info_6
4181 * fill a spoolss_PrinterInfo6 struct
4182 ********************************************************************/
4184 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4185 struct messaging_context *msg_ctx,
4186 const struct spoolss_PrinterInfo2 *info2,
4187 const char *servername,
4188 struct spoolss_PrinterInfo6 *r,
4189 int snum)
4191 print_status_struct status;
4193 print_queue_length(msg_ctx, snum, &status);
4195 r->status = nt_printq_status(status.status);
4197 return WERR_OK;
4200 /********************************************************************
4201 * construct_printer_info7
4202 * fill a spoolss_PrinterInfo7 struct
4203 ********************************************************************/
4205 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4206 struct messaging_context *msg_ctx,
4207 const char *servername,
4208 struct spoolss_PrinterInfo7 *r,
4209 int snum)
4211 const struct auth_session_info *session_info;
4212 char *printer;
4213 WERROR werr;
4214 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4215 if (tmp_ctx == NULL) {
4216 return WERR_NOMEM;
4219 session_info = get_session_info_system();
4220 SMB_ASSERT(session_info != NULL);
4222 printer = lp_servicename(tmp_ctx, snum);
4223 if (printer == NULL) {
4224 DEBUG(0, ("invalid printer snum %d\n", snum));
4225 werr = WERR_INVALID_PARAM;
4226 goto out_tmp_free;
4229 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4230 servername, printer, NULL)) {
4231 struct GUID guid;
4232 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4233 printer, &guid);
4234 if (!W_ERROR_IS_OK(werr)) {
4236 * If we do not have a GUID entry in the registry, then
4237 * try to retrieve it from AD and store it now.
4239 werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4240 &guid);
4241 if (!W_ERROR_IS_OK(werr)) {
4242 DEBUG(1, ("Failed to retrieve GUID for "
4243 "printer [%s] from AD - "
4244 "Is the the printer still "
4245 "published ?\n", printer));
4246 goto out_tmp_free;
4249 werr = nt_printer_guid_store(msg_ctx, printer, guid);
4250 if (!W_ERROR_IS_OK(werr)) {
4251 DEBUG(3, ("failed to store printer %s guid\n",
4252 printer));
4255 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4256 r->action = DSPRINT_PUBLISH;
4257 } else {
4258 r->guid = talloc_strdup(mem_ctx, "");
4259 r->action = DSPRINT_UNPUBLISH;
4261 if (r->guid == NULL) {
4262 werr = WERR_NOMEM;
4263 goto out_tmp_free;
4266 werr = WERR_OK;
4267 out_tmp_free:
4268 talloc_free(tmp_ctx);
4269 return werr;
4272 /********************************************************************
4273 * construct_printer_info8
4274 * fill a spoolss_PrinterInfo8 struct
4275 ********************************************************************/
4277 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4278 const struct spoolss_PrinterInfo2 *info2,
4279 const char *servername,
4280 struct spoolss_DeviceModeInfo *r,
4281 int snum)
4283 WERROR result;
4284 const char *printername;
4286 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4287 if (!W_ERROR_IS_OK(result)) {
4288 return result;
4291 if (info2->devmode != NULL) {
4292 result = copy_devicemode(mem_ctx,
4293 info2->devmode,
4294 &r->devmode);
4295 if (!W_ERROR_IS_OK(result)) {
4296 return result;
4298 } else if (lp_default_devmode(snum)) {
4299 result = spoolss_create_default_devmode(mem_ctx,
4300 info2->printername,
4301 &r->devmode);
4302 if (!W_ERROR_IS_OK(result)) {
4303 return result;
4305 } else {
4306 r->devmode = NULL;
4307 DEBUG(8,("Returning NULL Devicemode!\n"));
4310 compose_devicemode_devicename(r->devmode, printername);
4312 return WERR_OK;
4315 /********************************************************************
4316 Spoolss_enumprinters.
4317 ********************************************************************/
4319 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4320 const struct auth_session_info *session_info,
4321 struct messaging_context *msg_ctx,
4322 const char *servername,
4323 uint32_t level,
4324 uint32_t flags,
4325 union spoolss_PrinterInfo **info_p,
4326 uint32_t *count_p)
4328 int snum;
4329 int n_services;
4330 union spoolss_PrinterInfo *info = NULL;
4331 uint32_t count = 0;
4332 WERROR result = WERR_OK;
4333 struct dcerpc_binding_handle *b = NULL;
4334 TALLOC_CTX *tmp_ctx = NULL;
4336 tmp_ctx = talloc_new(mem_ctx);
4337 if (!tmp_ctx) {
4338 return WERR_NOMEM;
4342 * printer shares are updated on client enumeration. The background
4343 * printer process updates printer_list.tdb at regular intervals.
4345 become_root();
4346 delete_and_reload_printers(server_event_context(), msg_ctx);
4347 unbecome_root();
4349 n_services = lp_numservices();
4350 *count_p = 0;
4351 *info_p = NULL;
4353 for (snum = 0; snum < n_services; snum++) {
4355 const char *printer;
4356 struct spoolss_PrinterInfo2 *info2;
4358 if (!snum_is_shared_printer(snum)) {
4359 continue;
4362 printer = lp_const_servicename(snum);
4364 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4365 printer, snum));
4367 if (b == NULL) {
4368 result = winreg_printer_binding_handle(tmp_ctx,
4369 session_info,
4370 msg_ctx,
4371 &b);
4372 if (!W_ERROR_IS_OK(result)) {
4373 goto out;
4377 result = winreg_create_printer(tmp_ctx, b,
4378 printer);
4379 if (!W_ERROR_IS_OK(result)) {
4380 goto out;
4383 info = talloc_realloc(tmp_ctx, info,
4384 union spoolss_PrinterInfo,
4385 count + 1);
4386 if (!info) {
4387 result = WERR_NOMEM;
4388 goto out;
4391 result = winreg_get_printer(tmp_ctx, b,
4392 printer, &info2);
4393 if (!W_ERROR_IS_OK(result)) {
4394 goto out;
4397 switch (level) {
4398 case 0:
4399 result = construct_printer_info0(info, session_info,
4400 msg_ctx, info2,
4401 servername,
4402 &info[count].info0, snum);
4403 break;
4404 case 1:
4405 result = construct_printer_info1(info, info2, flags,
4406 servername,
4407 &info[count].info1, snum);
4408 break;
4409 case 2:
4410 result = construct_printer_info2(info, msg_ctx, info2,
4411 servername,
4412 &info[count].info2, snum);
4413 break;
4414 case 4:
4415 result = construct_printer_info4(info, info2,
4416 servername,
4417 &info[count].info4, snum);
4418 break;
4419 case 5:
4420 result = construct_printer_info5(info, info2,
4421 servername,
4422 &info[count].info5, snum);
4423 break;
4425 default:
4426 result = WERR_UNKNOWN_LEVEL;
4427 goto out;
4430 if (!W_ERROR_IS_OK(result)) {
4431 goto out;
4434 count++;
4437 out:
4438 if (W_ERROR_IS_OK(result)) {
4439 *info_p = talloc_move(mem_ctx, &info);
4440 *count_p = count;
4443 talloc_free(tmp_ctx);
4445 return result;
4448 /********************************************************************
4449 * handle enumeration of printers at level 0
4450 ********************************************************************/
4452 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4453 const struct auth_session_info *session_info,
4454 struct messaging_context *msg_ctx,
4455 uint32_t flags,
4456 const char *servername,
4457 union spoolss_PrinterInfo **info,
4458 uint32_t *count)
4460 DEBUG(4,("enum_all_printers_info_0\n"));
4462 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4463 servername, 0, flags, info, count);
4467 /********************************************************************
4468 ********************************************************************/
4470 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4471 const struct auth_session_info *session_info,
4472 struct messaging_context *msg_ctx,
4473 const char *servername,
4474 uint32_t flags,
4475 union spoolss_PrinterInfo **info,
4476 uint32_t *count)
4478 DEBUG(4,("enum_all_printers_info_1\n"));
4480 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4481 servername, 1, flags, info, count);
4484 /********************************************************************
4485 enum_all_printers_info_1_local.
4486 *********************************************************************/
4488 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4489 const struct auth_session_info *session_info,
4490 struct messaging_context *msg_ctx,
4491 const char *servername,
4492 union spoolss_PrinterInfo **info,
4493 uint32_t *count)
4495 DEBUG(4,("enum_all_printers_info_1_local\n"));
4497 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4498 servername, PRINTER_ENUM_ICON8, info, count);
4501 /********************************************************************
4502 enum_all_printers_info_1_name.
4503 *********************************************************************/
4505 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4506 const struct auth_session_info *session_info,
4507 struct messaging_context *msg_ctx,
4508 const char *servername,
4509 union spoolss_PrinterInfo **info,
4510 uint32_t *count)
4512 const char *s = servername;
4514 DEBUG(4,("enum_all_printers_info_1_name\n"));
4516 if (servername != NULL &&
4517 (servername[0] == '\\') && (servername[1] == '\\')) {
4518 s = servername + 2;
4521 if (!is_myname_or_ipaddr(s)) {
4522 return WERR_INVALID_NAME;
4525 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4526 servername, PRINTER_ENUM_ICON8, info, count);
4529 /********************************************************************
4530 enum_all_printers_info_1_network.
4531 *********************************************************************/
4533 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4534 const struct auth_session_info *session_info,
4535 struct messaging_context *msg_ctx,
4536 const char *servername,
4537 union spoolss_PrinterInfo **info,
4538 uint32_t *count)
4540 const char *s = servername;
4542 DEBUG(4,("enum_all_printers_info_1_network\n"));
4544 /* If we respond to a enum_printers level 1 on our name with flags
4545 set to PRINTER_ENUM_REMOTE with a list of printers then these
4546 printers incorrectly appear in the APW browse list.
4547 Specifically the printers for the server appear at the workgroup
4548 level where all the other servers in the domain are
4549 listed. Windows responds to this call with a
4550 WERR_CAN_NOT_COMPLETE so we should do the same. */
4552 if (servername != NULL &&
4553 (servername[0] == '\\') && (servername[1] == '\\')) {
4554 s = servername + 2;
4557 if (is_myname_or_ipaddr(s)) {
4558 return WERR_CAN_NOT_COMPLETE;
4561 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4562 servername, PRINTER_ENUM_NAME, info, count);
4565 /********************************************************************
4566 * api_spoolss_enumprinters
4568 * called from api_spoolss_enumprinters (see this to understand)
4569 ********************************************************************/
4571 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4572 const struct auth_session_info *session_info,
4573 struct messaging_context *msg_ctx,
4574 const char *servername,
4575 union spoolss_PrinterInfo **info,
4576 uint32_t *count)
4578 DEBUG(4,("enum_all_printers_info_2\n"));
4580 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4581 servername, 2, 0, info, count);
4584 /********************************************************************
4585 * handle enumeration of printers at level 1
4586 ********************************************************************/
4588 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4589 const struct auth_session_info *session_info,
4590 struct messaging_context *msg_ctx,
4591 uint32_t flags,
4592 const char *servername,
4593 union spoolss_PrinterInfo **info,
4594 uint32_t *count)
4596 /* Not all the flags are equals */
4598 if (flags & PRINTER_ENUM_LOCAL) {
4599 return enum_all_printers_info_1_local(mem_ctx, session_info,
4600 msg_ctx, servername, info, count);
4603 if (flags & PRINTER_ENUM_NAME) {
4604 return enum_all_printers_info_1_name(mem_ctx, session_info,
4605 msg_ctx, servername, info,
4606 count);
4609 if (flags & PRINTER_ENUM_NETWORK) {
4610 return enum_all_printers_info_1_network(mem_ctx, session_info,
4611 msg_ctx, servername, info,
4612 count);
4615 return WERR_OK; /* NT4sp5 does that */
4618 /********************************************************************
4619 * handle enumeration of printers at level 2
4620 ********************************************************************/
4622 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4623 const struct auth_session_info *session_info,
4624 struct messaging_context *msg_ctx,
4625 uint32_t flags,
4626 const char *servername,
4627 union spoolss_PrinterInfo **info,
4628 uint32_t *count)
4630 if (flags & PRINTER_ENUM_LOCAL) {
4632 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4633 servername,
4634 info, count);
4637 if (flags & PRINTER_ENUM_NAME) {
4638 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4639 return WERR_INVALID_NAME;
4642 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4643 servername,
4644 info, count);
4647 if (flags & PRINTER_ENUM_REMOTE) {
4648 return WERR_UNKNOWN_LEVEL;
4651 return WERR_OK;
4654 /********************************************************************
4655 * handle enumeration of printers at level 4
4656 ********************************************************************/
4658 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4659 const struct auth_session_info *session_info,
4660 struct messaging_context *msg_ctx,
4661 uint32_t flags,
4662 const char *servername,
4663 union spoolss_PrinterInfo **info,
4664 uint32_t *count)
4666 DEBUG(4,("enum_all_printers_info_4\n"));
4668 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4669 servername, 4, flags, info, count);
4673 /********************************************************************
4674 * handle enumeration of printers at level 5
4675 ********************************************************************/
4677 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4678 const struct auth_session_info *session_info,
4679 struct messaging_context *msg_ctx,
4680 uint32_t flags,
4681 const char *servername,
4682 union spoolss_PrinterInfo **info,
4683 uint32_t *count)
4685 DEBUG(4,("enum_all_printers_info_5\n"));
4687 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4688 servername, 5, flags, info, count);
4691 /****************************************************************
4692 _spoolss_EnumPrinters
4693 ****************************************************************/
4695 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4696 struct spoolss_EnumPrinters *r)
4698 const struct auth_session_info *session_info = get_session_info_system();
4699 WERROR result;
4701 /* that's an [in out] buffer */
4703 if (!r->in.buffer && (r->in.offered != 0)) {
4704 return WERR_INVALID_PARAM;
4707 DEBUG(4,("_spoolss_EnumPrinters\n"));
4709 *r->out.needed = 0;
4710 *r->out.count = 0;
4711 *r->out.info = NULL;
4714 * Level 1:
4715 * flags==PRINTER_ENUM_NAME
4716 * if name=="" then enumerates all printers
4717 * if name!="" then enumerate the printer
4718 * flags==PRINTER_ENUM_REMOTE
4719 * name is NULL, enumerate printers
4720 * Level 2: name!="" enumerates printers, name can't be NULL
4721 * Level 3: doesn't exist
4722 * Level 4: does a local registry lookup
4723 * Level 5: same as Level 2
4726 if (r->in.server && r->in.server[0] == '\0') {
4727 r->in.server = NULL;
4730 switch (r->in.level) {
4731 case 0:
4732 result = enumprinters_level0(p->mem_ctx, session_info,
4733 p->msg_ctx, r->in.flags,
4734 r->in.server,
4735 r->out.info, r->out.count);
4736 break;
4737 case 1:
4738 result = enumprinters_level1(p->mem_ctx, session_info,
4739 p->msg_ctx, r->in.flags,
4740 r->in.server,
4741 r->out.info, r->out.count);
4742 break;
4743 case 2:
4744 result = enumprinters_level2(p->mem_ctx, session_info,
4745 p->msg_ctx, r->in.flags,
4746 r->in.server,
4747 r->out.info, r->out.count);
4748 break;
4749 case 4:
4750 result = enumprinters_level4(p->mem_ctx, session_info,
4751 p->msg_ctx, r->in.flags,
4752 r->in.server,
4753 r->out.info, r->out.count);
4754 break;
4755 case 5:
4756 result = enumprinters_level5(p->mem_ctx, session_info,
4757 p->msg_ctx, r->in.flags,
4758 r->in.server,
4759 r->out.info, r->out.count);
4760 break;
4761 default:
4762 return WERR_UNKNOWN_LEVEL;
4765 if (!W_ERROR_IS_OK(result)) {
4766 return result;
4769 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4770 spoolss_EnumPrinters,
4771 *r->out.info, r->in.level,
4772 *r->out.count);
4773 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4774 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4776 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4779 /****************************************************************
4780 _spoolss_GetPrinter
4781 ****************************************************************/
4783 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4784 struct spoolss_GetPrinter *r)
4786 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4787 struct spoolss_PrinterInfo2 *info2 = NULL;
4788 WERROR result = WERR_OK;
4789 int snum;
4791 /* that's an [in out] buffer */
4793 if (!r->in.buffer && (r->in.offered != 0)) {
4794 result = WERR_INVALID_PARAM;
4795 goto err_info_free;
4798 *r->out.needed = 0;
4800 if (Printer == NULL) {
4801 result = WERR_BADFID;
4802 goto err_info_free;
4805 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4806 result = WERR_BADFID;
4807 goto err_info_free;
4810 result = winreg_get_printer_internal(p->mem_ctx,
4811 get_session_info_system(),
4812 p->msg_ctx,
4813 lp_const_servicename(snum),
4814 &info2);
4815 if (!W_ERROR_IS_OK(result)) {
4816 goto err_info_free;
4819 switch (r->in.level) {
4820 case 0:
4821 result = construct_printer_info0(p->mem_ctx,
4822 get_session_info_system(),
4823 p->msg_ctx,
4824 info2,
4825 Printer->servername,
4826 &r->out.info->info0,
4827 snum);
4828 break;
4829 case 1:
4830 result = construct_printer_info1(p->mem_ctx, info2,
4831 PRINTER_ENUM_ICON8,
4832 Printer->servername,
4833 &r->out.info->info1, snum);
4834 break;
4835 case 2:
4836 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4837 Printer->servername,
4838 &r->out.info->info2, snum);
4839 break;
4840 case 3:
4841 result = construct_printer_info3(p->mem_ctx, info2,
4842 Printer->servername,
4843 &r->out.info->info3, snum);
4844 break;
4845 case 4:
4846 result = construct_printer_info4(p->mem_ctx, info2,
4847 Printer->servername,
4848 &r->out.info->info4, snum);
4849 break;
4850 case 5:
4851 result = construct_printer_info5(p->mem_ctx, info2,
4852 Printer->servername,
4853 &r->out.info->info5, snum);
4854 break;
4855 case 6:
4856 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4857 Printer->servername,
4858 &r->out.info->info6, snum);
4859 break;
4860 case 7:
4861 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4862 Printer->servername,
4863 &r->out.info->info7, snum);
4864 break;
4865 case 8:
4866 result = construct_printer_info8(p->mem_ctx, info2,
4867 Printer->servername,
4868 &r->out.info->info8, snum);
4869 break;
4870 default:
4871 result = WERR_UNKNOWN_LEVEL;
4872 break;
4874 TALLOC_FREE(info2);
4876 if (!W_ERROR_IS_OK(result)) {
4877 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4878 r->in.level, win_errstr(result)));
4879 goto err_info_free;
4882 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4883 r->out.info, r->in.level);
4884 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4886 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4888 err_info_free:
4889 TALLOC_FREE(r->out.info);
4890 return result;
4893 /********************************************************************
4894 ********************************************************************/
4896 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4897 do { \
4898 if (in && strlen(in)) { \
4899 out = talloc_strdup(mem_ctx, in); \
4900 } else { \
4901 out = talloc_strdup(mem_ctx, ""); \
4903 W_ERROR_HAVE_NO_MEMORY(out); \
4904 } while (0);
4906 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4907 do { \
4908 if (in && strlen(in)) { \
4909 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4910 } else { \
4911 out = talloc_strdup(mem_ctx, ""); \
4913 W_ERROR_HAVE_NO_MEMORY(out); \
4914 } while (0);
4916 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4917 const char **string_array,
4918 const char ***presult,
4919 const char *cservername,
4920 const char *arch,
4921 int version)
4923 int i;
4924 size_t num_strings = 0;
4925 const char **array = NULL;
4927 if (string_array == NULL) {
4928 return WERR_INVALID_PARAMETER;
4931 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4932 const char *str = NULL;
4934 if (cservername == NULL || arch == NULL) {
4935 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4936 } else {
4937 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4940 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4941 TALLOC_FREE(array);
4942 return WERR_NOMEM;
4946 if (i > 0) {
4947 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4948 &array, &num_strings);
4951 if (presult != NULL) {
4952 *presult = array;
4953 } else {
4954 talloc_free(array);
4957 return WERR_OK;
4960 /********************************************************************
4961 * fill a spoolss_DriverInfo1 struct
4962 ********************************************************************/
4964 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4965 struct spoolss_DriverInfo1 *r,
4966 const struct spoolss_DriverInfo8 *driver,
4967 const char *servername)
4969 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4970 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4972 return WERR_OK;
4975 /********************************************************************
4976 * fill a spoolss_DriverInfo2 struct
4977 ********************************************************************/
4979 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4980 struct spoolss_DriverInfo2 *r,
4981 const struct spoolss_DriverInfo8 *driver,
4982 const char *servername)
4985 const char *cservername = canon_servername(servername);
4987 r->version = driver->version;
4989 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4990 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4991 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4992 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4994 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995 driver->architecture,
4996 driver->version,
4997 driver->driver_path,
4998 r->driver_path);
5000 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001 driver->architecture,
5002 driver->version,
5003 driver->data_file,
5004 r->data_file);
5006 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5007 driver->architecture,
5008 driver->version,
5009 driver->config_file,
5010 r->config_file);
5012 return WERR_OK;
5015 /********************************************************************
5016 * fill a spoolss_DriverInfo3 struct
5017 ********************************************************************/
5019 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5020 struct spoolss_DriverInfo3 *r,
5021 const struct spoolss_DriverInfo8 *driver,
5022 const char *servername)
5024 const char *cservername = canon_servername(servername);
5026 r->version = driver->version;
5028 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5029 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5030 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5031 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5033 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5034 driver->architecture,
5035 driver->version,
5036 driver->driver_path,
5037 r->driver_path);
5039 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5040 driver->architecture,
5041 driver->version,
5042 driver->data_file,
5043 r->data_file);
5045 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5046 driver->architecture,
5047 driver->version,
5048 driver->config_file,
5049 r->config_file);
5051 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5052 driver->architecture,
5053 driver->version,
5054 driver->help_file,
5055 r->help_file);
5057 FILL_DRIVER_STRING(mem_ctx,
5058 driver->monitor_name,
5059 r->monitor_name);
5061 FILL_DRIVER_STRING(mem_ctx,
5062 driver->default_datatype,
5063 r->default_datatype);
5065 return string_array_from_driver_info(mem_ctx,
5066 driver->dependent_files,
5067 &r->dependent_files,
5068 cservername,
5069 driver->architecture,
5070 driver->version);
5073 /********************************************************************
5074 * fill a spoolss_DriverInfo4 struct
5075 ********************************************************************/
5077 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5078 struct spoolss_DriverInfo4 *r,
5079 const struct spoolss_DriverInfo8 *driver,
5080 const char *servername)
5082 const char *cservername = canon_servername(servername);
5083 WERROR result;
5085 r->version = driver->version;
5087 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5088 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5089 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5090 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5092 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093 driver->architecture,
5094 driver->version,
5095 driver->driver_path,
5096 r->driver_path);
5098 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5099 driver->architecture,
5100 driver->version,
5101 driver->data_file,
5102 r->data_file);
5104 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105 driver->architecture,
5106 driver->version,
5107 driver->config_file,
5108 r->config_file);
5110 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5111 driver->architecture,
5112 driver->version,
5113 driver->help_file,
5114 r->help_file);
5116 result = string_array_from_driver_info(mem_ctx,
5117 driver->dependent_files,
5118 &r->dependent_files,
5119 cservername,
5120 driver->architecture,
5121 driver->version);
5122 if (!W_ERROR_IS_OK(result)) {
5123 return result;
5126 FILL_DRIVER_STRING(mem_ctx,
5127 driver->monitor_name,
5128 r->monitor_name);
5130 FILL_DRIVER_STRING(mem_ctx,
5131 driver->default_datatype,
5132 r->default_datatype);
5135 result = string_array_from_driver_info(mem_ctx,
5136 driver->previous_names,
5137 &r->previous_names,
5138 NULL, NULL, 0);
5140 return result;
5143 /********************************************************************
5144 * fill a spoolss_DriverInfo5 struct
5145 ********************************************************************/
5147 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5148 struct spoolss_DriverInfo5 *r,
5149 const struct spoolss_DriverInfo8 *driver,
5150 const char *servername)
5152 const char *cservername = canon_servername(servername);
5154 r->version = driver->version;
5156 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5157 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5158 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5159 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5161 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5162 driver->architecture,
5163 driver->version,
5164 driver->driver_path,
5165 r->driver_path);
5167 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5168 driver->architecture,
5169 driver->version,
5170 driver->data_file,
5171 r->data_file);
5173 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5174 driver->architecture,
5175 driver->version,
5176 driver->config_file,
5177 r->config_file);
5179 r->driver_attributes = 0;
5180 r->config_version = 0;
5181 r->driver_version = 0;
5183 return WERR_OK;
5185 /********************************************************************
5186 * fill a spoolss_DriverInfo6 struct
5187 ********************************************************************/
5189 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5190 struct spoolss_DriverInfo6 *r,
5191 const struct spoolss_DriverInfo8 *driver,
5192 const char *servername)
5194 const char *cservername = canon_servername(servername);
5195 WERROR result;
5197 r->version = driver->version;
5199 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5200 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5201 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5202 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5204 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5205 driver->architecture,
5206 driver->version,
5207 driver->driver_path,
5208 r->driver_path);
5210 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5211 driver->architecture,
5212 driver->version,
5213 driver->data_file,
5214 r->data_file);
5216 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5217 driver->architecture,
5218 driver->version,
5219 driver->config_file,
5220 r->config_file);
5222 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5223 driver->architecture,
5224 driver->version,
5225 driver->help_file,
5226 r->help_file);
5228 FILL_DRIVER_STRING(mem_ctx,
5229 driver->monitor_name,
5230 r->monitor_name);
5232 FILL_DRIVER_STRING(mem_ctx,
5233 driver->default_datatype,
5234 r->default_datatype);
5236 result = string_array_from_driver_info(mem_ctx,
5237 driver->dependent_files,
5238 &r->dependent_files,
5239 cservername,
5240 driver->architecture,
5241 driver->version);
5242 if (!W_ERROR_IS_OK(result)) {
5243 return result;
5246 result = string_array_from_driver_info(mem_ctx,
5247 driver->previous_names,
5248 &r->previous_names,
5249 NULL, NULL, 0);
5250 if (!W_ERROR_IS_OK(result)) {
5251 return result;
5254 r->driver_date = driver->driver_date;
5255 r->driver_version = driver->driver_version;
5257 FILL_DRIVER_STRING(mem_ctx,
5258 driver->manufacturer_name,
5259 r->manufacturer_name);
5260 FILL_DRIVER_STRING(mem_ctx,
5261 driver->manufacturer_url,
5262 r->manufacturer_url);
5263 FILL_DRIVER_STRING(mem_ctx,
5264 driver->hardware_id,
5265 r->hardware_id);
5266 FILL_DRIVER_STRING(mem_ctx,
5267 driver->provider,
5268 r->provider);
5270 return WERR_OK;
5273 /********************************************************************
5274 * fill a spoolss_DriverInfo8 struct
5275 ********************************************************************/
5277 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5278 struct spoolss_DriverInfo8 *r,
5279 const struct spoolss_DriverInfo8 *driver,
5280 const char *servername)
5282 const char *cservername = canon_servername(servername);
5283 WERROR result;
5285 r->version = driver->version;
5287 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5288 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5289 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5290 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5292 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5293 driver->architecture,
5294 driver->version,
5295 driver->driver_path,
5296 r->driver_path);
5298 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5299 driver->architecture,
5300 driver->version,
5301 driver->data_file,
5302 r->data_file);
5304 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5305 driver->architecture,
5306 driver->version,
5307 driver->config_file,
5308 r->config_file);
5310 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5311 driver->architecture,
5312 driver->version,
5313 driver->help_file,
5314 r->help_file);
5316 FILL_DRIVER_STRING(mem_ctx,
5317 driver->monitor_name,
5318 r->monitor_name);
5320 FILL_DRIVER_STRING(mem_ctx,
5321 driver->default_datatype,
5322 r->default_datatype);
5324 result = string_array_from_driver_info(mem_ctx,
5325 driver->dependent_files,
5326 &r->dependent_files,
5327 cservername,
5328 driver->architecture,
5329 driver->version);
5330 if (!W_ERROR_IS_OK(result)) {
5331 return result;
5334 result = string_array_from_driver_info(mem_ctx,
5335 driver->previous_names,
5336 &r->previous_names,
5337 NULL, NULL, 0);
5338 if (!W_ERROR_IS_OK(result)) {
5339 return result;
5342 r->driver_date = driver->driver_date;
5343 r->driver_version = driver->driver_version;
5345 FILL_DRIVER_STRING(mem_ctx,
5346 driver->manufacturer_name,
5347 r->manufacturer_name);
5348 FILL_DRIVER_STRING(mem_ctx,
5349 driver->manufacturer_url,
5350 r->manufacturer_url);
5351 FILL_DRIVER_STRING(mem_ctx,
5352 driver->hardware_id,
5353 r->hardware_id);
5354 FILL_DRIVER_STRING(mem_ctx,
5355 driver->provider,
5356 r->provider);
5358 FILL_DRIVER_STRING(mem_ctx,
5359 driver->print_processor,
5360 r->print_processor);
5361 FILL_DRIVER_STRING(mem_ctx,
5362 driver->vendor_setup,
5363 r->vendor_setup);
5365 result = string_array_from_driver_info(mem_ctx,
5366 driver->color_profiles,
5367 &r->color_profiles,
5368 NULL, NULL, 0);
5369 if (!W_ERROR_IS_OK(result)) {
5370 return result;
5373 FILL_DRIVER_STRING(mem_ctx,
5374 driver->inf_path,
5375 r->inf_path);
5377 r->printer_driver_attributes = driver->printer_driver_attributes;
5379 result = string_array_from_driver_info(mem_ctx,
5380 driver->core_driver_dependencies,
5381 &r->core_driver_dependencies,
5382 NULL, NULL, 0);
5383 if (!W_ERROR_IS_OK(result)) {
5384 return result;
5387 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5388 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5390 return WERR_OK;
5393 #if 0 /* disabled until marshalling issues are resolved - gd */
5394 /********************************************************************
5395 ********************************************************************/
5397 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5398 struct spoolss_DriverFileInfo *r,
5399 const char *cservername,
5400 const char *file_name,
5401 enum spoolss_DriverFileType file_type,
5402 uint32_t file_version)
5404 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5405 cservername, file_name);
5406 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5407 r->file_type = file_type;
5408 r->file_version = file_version;
5410 return WERR_OK;
5413 /********************************************************************
5414 ********************************************************************/
5416 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5417 const struct spoolss_DriverInfo8 *driver,
5418 const char *cservername,
5419 struct spoolss_DriverFileInfo **info_p,
5420 uint32_t *count_p)
5422 struct spoolss_DriverFileInfo *info = NULL;
5423 uint32_t count = 0;
5424 WERROR result;
5425 uint32_t i;
5427 *info_p = NULL;
5428 *count_p = 0;
5430 if (strlen(driver->driver_path)) {
5431 info = talloc_realloc(mem_ctx, info,
5432 struct spoolss_DriverFileInfo,
5433 count + 1);
5434 W_ERROR_HAVE_NO_MEMORY(info);
5435 result = fill_spoolss_DriverFileInfo(info,
5436 &info[count],
5437 cservername,
5438 driver->driver_path,
5439 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5441 W_ERROR_NOT_OK_RETURN(result);
5442 count++;
5445 if (strlen(driver->config_file)) {
5446 info = talloc_realloc(mem_ctx, info,
5447 struct spoolss_DriverFileInfo,
5448 count + 1);
5449 W_ERROR_HAVE_NO_MEMORY(info);
5450 result = fill_spoolss_DriverFileInfo(info,
5451 &info[count],
5452 cservername,
5453 driver->config_file,
5454 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5456 W_ERROR_NOT_OK_RETURN(result);
5457 count++;
5460 if (strlen(driver->data_file)) {
5461 info = talloc_realloc(mem_ctx, info,
5462 struct spoolss_DriverFileInfo,
5463 count + 1);
5464 W_ERROR_HAVE_NO_MEMORY(info);
5465 result = fill_spoolss_DriverFileInfo(info,
5466 &info[count],
5467 cservername,
5468 driver->data_file,
5469 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5471 W_ERROR_NOT_OK_RETURN(result);
5472 count++;
5475 if (strlen(driver->help_file)) {
5476 info = talloc_realloc(mem_ctx, info,
5477 struct spoolss_DriverFileInfo,
5478 count + 1);
5479 W_ERROR_HAVE_NO_MEMORY(info);
5480 result = fill_spoolss_DriverFileInfo(info,
5481 &info[count],
5482 cservername,
5483 driver->help_file,
5484 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5486 W_ERROR_NOT_OK_RETURN(result);
5487 count++;
5490 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5491 info = talloc_realloc(mem_ctx, info,
5492 struct spoolss_DriverFileInfo,
5493 count + 1);
5494 W_ERROR_HAVE_NO_MEMORY(info);
5495 result = fill_spoolss_DriverFileInfo(info,
5496 &info[count],
5497 cservername,
5498 driver->dependent_files[i],
5499 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5501 W_ERROR_NOT_OK_RETURN(result);
5502 count++;
5505 *info_p = info;
5506 *count_p = count;
5508 return WERR_OK;
5511 /********************************************************************
5512 * fill a spoolss_DriverInfo101 struct
5513 ********************************************************************/
5515 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5516 struct spoolss_DriverInfo101 *r,
5517 const struct spoolss_DriverInfo8 *driver,
5518 const char *servername)
5520 const char *cservername = canon_servername(servername);
5521 WERROR result;
5523 r->version = driver->version;
5525 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5526 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5527 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5528 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5530 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5531 cservername,
5532 &r->file_info,
5533 &r->file_count);
5534 if (!W_ERROR_IS_OK(result)) {
5535 return result;
5538 FILL_DRIVER_STRING(mem_ctx,
5539 driver->monitor_name,
5540 r->monitor_name);
5542 FILL_DRIVER_STRING(mem_ctx,
5543 driver->default_datatype,
5544 r->default_datatype);
5546 result = string_array_from_driver_info(mem_ctx,
5547 driver->previous_names,
5548 &r->previous_names,
5549 NULL, NULL, 0);
5550 if (!W_ERROR_IS_OK(result)) {
5551 return result;
5554 r->driver_date = driver->driver_date;
5555 r->driver_version = driver->driver_version;
5557 FILL_DRIVER_STRING(mem_ctx,
5558 driver->manufacturer_name,
5559 r->manufacturer_name);
5560 FILL_DRIVER_STRING(mem_ctx,
5561 driver->manufacturer_url,
5562 r->manufacturer_url);
5563 FILL_DRIVER_STRING(mem_ctx,
5564 driver->hardware_id,
5565 r->hardware_id);
5566 FILL_DRIVER_STRING(mem_ctx,
5567 driver->provider,
5568 r->provider);
5570 return WERR_OK;
5572 #endif
5573 /********************************************************************
5574 ********************************************************************/
5576 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5577 const struct auth_session_info *session_info,
5578 struct messaging_context *msg_ctx,
5579 uint32_t level,
5580 union spoolss_DriverInfo *r,
5581 int snum,
5582 const char *servername,
5583 const char *architecture,
5584 uint32_t version)
5586 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5587 struct spoolss_DriverInfo8 *driver;
5588 WERROR result;
5589 struct dcerpc_binding_handle *b;
5590 TALLOC_CTX *tmp_ctx = NULL;
5592 if (level == 101) {
5593 return WERR_UNKNOWN_LEVEL;
5596 tmp_ctx = talloc_new(mem_ctx);
5597 if (!tmp_ctx) {
5598 return WERR_NOMEM;
5601 result = winreg_printer_binding_handle(tmp_ctx,
5602 session_info,
5603 msg_ctx,
5604 &b);
5605 if (!W_ERROR_IS_OK(result)) {
5606 goto done;
5609 result = winreg_get_printer(tmp_ctx, b,
5610 lp_const_servicename(snum),
5611 &pinfo2);
5613 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5614 win_errstr(result)));
5616 if (!W_ERROR_IS_OK(result)) {
5617 result = WERR_INVALID_PRINTER_NAME;
5618 goto done;
5621 result = winreg_get_driver(tmp_ctx, b,
5622 architecture,
5623 pinfo2->drivername, version, &driver);
5625 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5626 win_errstr(result)));
5628 if (!W_ERROR_IS_OK(result)) {
5630 * Is this a W2k client ?
5633 if (version < 3) {
5634 result = WERR_UNKNOWN_PRINTER_DRIVER;
5635 goto done;
5638 /* Yes - try again with a WinNT driver. */
5639 version = 2;
5640 result = winreg_get_driver(tmp_ctx, b,
5641 architecture,
5642 pinfo2->drivername,
5643 version, &driver);
5644 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5645 win_errstr(result)));
5646 if (!W_ERROR_IS_OK(result)) {
5647 result = WERR_UNKNOWN_PRINTER_DRIVER;
5648 goto done;
5652 /* these are allocated on mem_ctx and not tmp_ctx because they are
5653 * the 'return value' and need to utlive this call */
5654 switch (level) {
5655 case 1:
5656 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5657 break;
5658 case 2:
5659 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5660 break;
5661 case 3:
5662 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5663 break;
5664 case 4:
5665 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5666 break;
5667 case 5:
5668 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5669 break;
5670 case 6:
5671 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5672 break;
5673 case 8:
5674 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5675 break;
5676 #if 0 /* disabled until marshalling issues are resolved - gd */
5677 case 101:
5678 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5679 break;
5680 #endif
5681 default:
5682 result = WERR_UNKNOWN_LEVEL;
5683 break;
5686 done:
5687 talloc_free(tmp_ctx);
5688 return result;
5691 /****************************************************************
5692 _spoolss_GetPrinterDriver2
5693 ****************************************************************/
5695 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5696 struct spoolss_GetPrinterDriver2 *r)
5698 struct printer_handle *printer;
5699 WERROR result;
5700 uint32_t version = r->in.client_major_version;
5702 int snum;
5704 /* that's an [in out] buffer */
5706 if (!r->in.buffer && (r->in.offered != 0)) {
5707 result = WERR_INVALID_PARAM;
5708 goto err_info_free;
5711 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5713 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5714 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5715 result = WERR_INVALID_PRINTER_NAME;
5716 goto err_info_free;
5719 *r->out.needed = 0;
5720 *r->out.server_major_version = 0;
5721 *r->out.server_minor_version = 0;
5723 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5724 result = WERR_BADFID;
5725 goto err_info_free;
5728 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5729 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5730 "downgrading to v3\n"));
5731 version = SPOOLSS_DRIVER_VERSION_200X;
5734 result = construct_printer_driver_info_level(p->mem_ctx,
5735 get_session_info_system(),
5736 p->msg_ctx,
5737 r->in.level, r->out.info,
5738 snum, printer->servername,
5739 r->in.architecture,
5740 version);
5741 if (!W_ERROR_IS_OK(result)) {
5742 goto err_info_free;
5745 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5746 r->out.info, r->in.level);
5747 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5749 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5751 err_info_free:
5752 TALLOC_FREE(r->out.info);
5753 return result;
5757 /****************************************************************
5758 _spoolss_StartPagePrinter
5759 ****************************************************************/
5761 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5762 struct spoolss_StartPagePrinter *r)
5764 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5766 if (!Printer) {
5767 DEBUG(3,("_spoolss_StartPagePrinter: "
5768 "Error in startpageprinter printer handle\n"));
5769 return WERR_BADFID;
5772 Printer->page_started = true;
5773 return WERR_OK;
5776 /****************************************************************
5777 _spoolss_EndPagePrinter
5778 ****************************************************************/
5780 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5781 struct spoolss_EndPagePrinter *r)
5783 int snum;
5785 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5787 if (!Printer) {
5788 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5789 OUR_HANDLE(r->in.handle)));
5790 return WERR_BADFID;
5793 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5794 return WERR_BADFID;
5796 Printer->page_started = false;
5797 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5799 return WERR_OK;
5802 /****************************************************************
5803 _spoolss_StartDocPrinter
5804 ****************************************************************/
5806 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5807 struct spoolss_StartDocPrinter *r)
5809 struct spoolss_DocumentInfo1 *info_1;
5810 int snum;
5811 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5812 WERROR werr;
5813 char *rhost;
5814 int rc;
5816 if (!Printer) {
5817 DEBUG(2,("_spoolss_StartDocPrinter: "
5818 "Invalid handle (%s:%u:%u)\n",
5819 OUR_HANDLE(r->in.handle)));
5820 return WERR_BADFID;
5823 if (Printer->jobid) {
5824 DEBUG(2, ("_spoolss_StartDocPrinter: "
5825 "StartDocPrinter called twice! "
5826 "(existing jobid = %d)\n", Printer->jobid));
5827 return WERR_INVALID_HANDLE;
5830 if (r->in.info_ctr->level != 1) {
5831 return WERR_UNKNOWN_LEVEL;
5834 info_1 = r->in.info_ctr->info.info1;
5837 * a nice thing with NT is it doesn't listen to what you tell it.
5838 * when asked to send _only_ RAW datas, it tries to send datas
5839 * in EMF format.
5841 * So I add checks like in NT Server ...
5844 if (info_1->datatype) {
5846 * The v4 driver model used in Windows 8 declares print jobs
5847 * intended to bypass the XPS processing layer by setting
5848 * datatype to "XPS_PASS" instead of "RAW".
5850 if ((strcmp(info_1->datatype, "RAW") != 0)
5851 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5852 *r->out.job_id = 0;
5853 return WERR_INVALID_DATATYPE;
5857 /* get the share number of the printer */
5858 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5859 return WERR_BADFID;
5862 rc = get_remote_hostname(p->remote_address,
5863 &rhost,
5864 p->mem_ctx);
5865 if (rc < 0) {
5866 return WERR_NOMEM;
5868 if (strequal(rhost,"UNKNOWN")) {
5869 rhost = tsocket_address_inet_addr_string(p->remote_address,
5870 p->mem_ctx);
5871 if (rhost == NULL) {
5872 return WERR_NOMEM;
5876 werr = print_job_start(p->session_info,
5877 p->msg_ctx,
5878 rhost,
5879 snum,
5880 info_1->document_name,
5881 info_1->output_file,
5882 Printer->devmode,
5883 &Printer->jobid);
5885 /* An error occured in print_job_start() so return an appropriate
5886 NT error code. */
5888 if (!W_ERROR_IS_OK(werr)) {
5889 return werr;
5892 Printer->document_started = true;
5893 *r->out.job_id = Printer->jobid;
5895 return WERR_OK;
5898 /****************************************************************
5899 _spoolss_EndDocPrinter
5900 ****************************************************************/
5902 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5903 struct spoolss_EndDocPrinter *r)
5905 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5906 NTSTATUS status;
5907 int snum;
5909 if (!Printer) {
5910 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5911 OUR_HANDLE(r->in.handle)));
5912 return WERR_BADFID;
5915 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5916 return WERR_BADFID;
5919 Printer->document_started = false;
5920 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5921 if (!NT_STATUS_IS_OK(status)) {
5922 DEBUG(2, ("_spoolss_EndDocPrinter: "
5923 "print_job_end failed [%s]\n",
5924 nt_errstr(status)));
5927 Printer->jobid = 0;
5928 return ntstatus_to_werror(status);
5931 /****************************************************************
5932 _spoolss_WritePrinter
5933 ****************************************************************/
5935 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5936 struct spoolss_WritePrinter *r)
5938 ssize_t buffer_written;
5939 int snum;
5940 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5942 if (!Printer) {
5943 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5944 OUR_HANDLE(r->in.handle)));
5945 *r->out.num_written = r->in._data_size;
5946 return WERR_BADFID;
5949 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5950 return WERR_BADFID;
5952 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5953 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5954 snum, Printer->jobid,
5955 (const char *)r->in.data.data,
5956 (size_t)r->in._data_size);
5957 if (buffer_written == (ssize_t)-1) {
5958 *r->out.num_written = 0;
5959 if (errno == ENOSPC)
5960 return WERR_NO_SPOOL_SPACE;
5961 else
5962 return WERR_ACCESS_DENIED;
5965 *r->out.num_written = r->in._data_size;
5967 return WERR_OK;
5970 /********************************************************************
5971 * api_spoolss_getprinter
5972 * called from the spoolss dispatcher
5974 ********************************************************************/
5976 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5977 struct pipes_struct *p)
5979 const struct auth_session_info *session_info = p->session_info;
5980 int snum;
5981 WERROR errcode = WERR_BADFUNC;
5982 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5984 if (!Printer) {
5985 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5986 OUR_HANDLE(handle)));
5987 return WERR_BADFID;
5990 if (!get_printer_snum(p, handle, &snum, NULL))
5991 return WERR_BADFID;
5993 switch (command) {
5994 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5995 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5996 break;
5997 case SPOOLSS_PRINTER_CONTROL_RESUME:
5998 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5999 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6000 break;
6001 case SPOOLSS_PRINTER_CONTROL_PURGE:
6002 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6003 break;
6004 default:
6005 return WERR_UNKNOWN_LEVEL;
6008 return errcode;
6012 /****************************************************************
6013 _spoolss_AbortPrinter
6014 * From MSDN: "Deletes printer's spool file if printer is configured
6015 * for spooling"
6016 ****************************************************************/
6018 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6019 struct spoolss_AbortPrinter *r)
6021 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6022 int snum;
6023 WERROR errcode = WERR_OK;
6025 if (!Printer) {
6026 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6027 OUR_HANDLE(r->in.handle)));
6028 return WERR_BADFID;
6031 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6032 return WERR_BADFID;
6034 if (!Printer->document_started) {
6035 return WERR_SPL_NO_STARTDOC;
6038 errcode = print_job_delete(p->session_info,
6039 p->msg_ctx,
6040 snum,
6041 Printer->jobid);
6043 return errcode;
6046 /********************************************************************
6047 * called by spoolss_api_setprinter
6048 * when updating a printer description
6049 ********************************************************************/
6051 static WERROR update_printer_sec(struct policy_handle *handle,
6052 struct pipes_struct *p,
6053 struct sec_desc_buf *secdesc_ctr)
6055 struct spoolss_security_descriptor *new_secdesc = NULL;
6056 struct spoolss_security_descriptor *old_secdesc = NULL;
6057 const char *printer;
6058 WERROR result;
6059 int snum;
6060 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6061 struct dcerpc_binding_handle *b;
6062 TALLOC_CTX *tmp_ctx = NULL;
6064 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6065 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6066 OUR_HANDLE(handle)));
6068 result = WERR_BADFID;
6069 goto done;
6072 if (secdesc_ctr == NULL) {
6073 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6074 result = WERR_INVALID_PARAM;
6075 goto done;
6077 printer = lp_const_servicename(snum);
6079 /* Check the user has permissions to change the security
6080 descriptor. By experimentation with two NT machines, the user
6081 requires Full Access to the printer to change security
6082 information. */
6084 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6085 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6086 result = WERR_ACCESS_DENIED;
6087 goto done;
6090 tmp_ctx = talloc_new(p->mem_ctx);
6091 if (!tmp_ctx) {
6092 return WERR_NOMEM;
6095 result = winreg_printer_binding_handle(tmp_ctx,
6096 get_session_info_system(),
6097 p->msg_ctx,
6098 &b);
6099 if (!W_ERROR_IS_OK(result)) {
6100 goto done;
6103 /* NT seems to like setting the security descriptor even though
6104 nothing may have actually changed. */
6105 result = winreg_get_printer_secdesc(tmp_ctx, b,
6106 printer,
6107 &old_secdesc);
6108 if (!W_ERROR_IS_OK(result)) {
6109 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6110 result = WERR_BADFID;
6111 goto done;
6114 if (DEBUGLEVEL >= 10) {
6115 struct security_acl *the_acl;
6116 int i;
6118 the_acl = old_secdesc->dacl;
6119 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6120 printer, the_acl->num_aces));
6122 for (i = 0; i < the_acl->num_aces; i++) {
6123 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6124 &the_acl->aces[i].trustee),
6125 the_acl->aces[i].access_mask));
6128 the_acl = secdesc_ctr->sd->dacl;
6130 if (the_acl) {
6131 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6132 printer, the_acl->num_aces));
6134 for (i = 0; i < the_acl->num_aces; i++) {
6135 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6136 &the_acl->aces[i].trustee),
6137 the_acl->aces[i].access_mask));
6139 } else {
6140 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6144 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6145 if (new_secdesc == NULL) {
6146 result = WERR_NOMEM;
6147 goto done;
6150 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6151 result = WERR_OK;
6152 goto done;
6155 result = winreg_set_printer_secdesc(tmp_ctx, b,
6156 printer,
6157 new_secdesc);
6159 done:
6160 talloc_free(tmp_ctx);
6161 return result;
6164 /********************************************************************
6165 Canonicalize printer info from a client
6166 ********************************************************************/
6168 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6169 struct spoolss_SetPrinterInfo2 *info2,
6170 int snum)
6172 fstring printername;
6173 const char *p;
6175 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6176 "portname=%s drivername=%s comment=%s location=%s\n",
6177 info2->servername, info2->printername, info2->sharename,
6178 info2->portname, info2->drivername, info2->comment,
6179 info2->location));
6181 /* we force some elements to "correct" values */
6182 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6183 if (info2->servername == NULL) {
6184 return false;
6186 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6187 if (info2->sharename == NULL) {
6188 return false;
6191 /* check to see if we allow printername != sharename */
6192 if (lp_force_printername(snum)) {
6193 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6194 lp_netbios_name(), info2->sharename);
6195 } else {
6196 /* make sure printername is in \\server\printername format */
6197 fstrcpy(printername, info2->printername);
6198 p = printername;
6199 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6200 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6201 p++;
6204 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6205 lp_netbios_name(), p);
6207 if (info2->printername == NULL) {
6208 return false;
6211 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6212 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6214 return true;
6217 /****************************************************************************
6218 ****************************************************************************/
6220 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6222 char *cmd = lp_addport_cmd(talloc_tos());
6223 char *command = NULL;
6224 int ret;
6225 bool is_print_op = false;
6227 if ( !*cmd ) {
6228 return WERR_ACCESS_DENIED;
6231 command = talloc_asprintf(ctx,
6232 "%s \"%s\" \"%s\"", cmd, portname, uri );
6233 if (!command) {
6234 return WERR_NOMEM;
6237 if ( token )
6238 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6240 DEBUG(10,("Running [%s]\n", command));
6242 /********* BEGIN SePrintOperatorPrivilege **********/
6244 if ( is_print_op )
6245 become_root();
6247 ret = smbrun(command, NULL);
6249 if ( is_print_op )
6250 unbecome_root();
6252 /********* END SePrintOperatorPrivilege **********/
6254 DEBUGADD(10,("returned [%d]\n", ret));
6256 TALLOC_FREE(command);
6258 if ( ret != 0 ) {
6259 return WERR_ACCESS_DENIED;
6262 return WERR_OK;
6265 /****************************************************************************
6266 ****************************************************************************/
6268 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6269 int snum)
6272 * As we do not know if we are embedded in the file server process
6273 * or not, we have to pretend that all shares are in use.
6275 return true;
6278 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6279 struct spoolss_SetPrinterInfo2 *info2,
6280 const char *remote_machine,
6281 struct messaging_context *msg_ctx)
6283 char *cmd = lp_addprinter_cmd(talloc_tos());
6284 char **qlines;
6285 char *command = NULL;
6286 int numlines;
6287 int ret;
6288 int fd;
6289 bool is_print_op = false;
6291 if (!remote_machine) {
6292 return false;
6295 command = talloc_asprintf(ctx,
6296 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6297 cmd, info2->printername, info2->sharename,
6298 info2->portname, info2->drivername,
6299 info2->location, info2->comment, remote_machine);
6300 if (!command) {
6301 return false;
6304 if ( token )
6305 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6307 DEBUG(10,("Running [%s]\n", command));
6309 /********* BEGIN SePrintOperatorPrivilege **********/
6311 if ( is_print_op )
6312 become_root();
6314 if ( (ret = smbrun(command, &fd)) == 0 ) {
6315 /* Tell everyone we updated smb.conf. */
6316 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6319 if ( is_print_op )
6320 unbecome_root();
6322 /********* END SePrintOperatorPrivilege **********/
6324 DEBUGADD(10,("returned [%d]\n", ret));
6326 TALLOC_FREE(command);
6328 if ( ret != 0 ) {
6329 if (fd != -1)
6330 close(fd);
6331 return false;
6334 /* reload our services immediately */
6335 become_root();
6336 reload_services(NULL, spoolss_conn_snum_used, false);
6337 unbecome_root();
6339 numlines = 0;
6340 /* Get lines and convert them back to dos-codepage */
6341 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6342 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6343 close(fd);
6345 /* Set the portname to what the script says the portname should be. */
6346 /* but don't require anything to be return from the script exit a good error code */
6348 if (numlines) {
6349 /* Set the portname to what the script says the portname should be. */
6350 info2->portname = talloc_strdup(ctx, qlines[0]);
6351 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6354 TALLOC_FREE(qlines);
6355 return true;
6358 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6359 const struct auth_session_info *session_info,
6360 struct messaging_context *msg_ctx,
6361 int snum,
6362 struct spoolss_SetPrinterInfo2 *printer,
6363 struct spoolss_PrinterInfo2 *old_printer)
6365 bool force_update = (old_printer == NULL);
6366 const char *dnsdomname;
6367 const char *longname;
6368 const char *uncname;
6369 const char *spooling;
6370 DATA_BLOB buffer;
6371 WERROR result = WERR_OK;
6372 struct dcerpc_binding_handle *b;
6373 TALLOC_CTX *tmp_ctx;
6374 bool ok;
6376 tmp_ctx = talloc_new(mem_ctx);
6377 if (!tmp_ctx) {
6378 return WERR_NOMEM;
6381 result = winreg_printer_binding_handle(tmp_ctx,
6382 session_info,
6383 msg_ctx,
6384 &b);
6385 if (!W_ERROR_IS_OK(result)) {
6386 goto done;
6389 if (printer->drivername != NULL &&
6390 (force_update ||
6391 !strequal(printer->drivername, old_printer->drivername))) {
6392 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6393 if (!ok) {
6394 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6395 result = WERR_INVALID_DATA;
6396 goto done;
6398 result = winreg_set_printer_dataex(tmp_ctx, b,
6399 printer->sharename,
6400 SPOOL_DSSPOOLER_KEY,
6401 SPOOL_REG_DRIVERNAME,
6402 REG_SZ,
6403 buffer.data,
6404 buffer.length);
6405 if (!W_ERROR_IS_OK(result)) {
6406 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6407 goto done;
6410 if (!force_update) {
6411 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6412 printer->drivername));
6414 notify_printer_driver(server_event_context(), msg_ctx,
6415 snum, printer->drivername ?
6416 printer->drivername : "");
6420 if (printer->comment != NULL &&
6421 (force_update ||
6422 !strequal(printer->comment, old_printer->comment))) {
6423 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6424 if (!ok) {
6425 DEBUG(0, ("comment data corrupted\n"));
6426 result = WERR_INVALID_DATA;
6427 goto done;
6429 result = winreg_set_printer_dataex(tmp_ctx, b,
6430 printer->sharename,
6431 SPOOL_DSSPOOLER_KEY,
6432 SPOOL_REG_DESCRIPTION,
6433 REG_SZ,
6434 buffer.data,
6435 buffer.length);
6436 if (!W_ERROR_IS_OK(result)) {
6437 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6438 goto done;
6441 if (!force_update) {
6442 notify_printer_comment(server_event_context(), msg_ctx,
6443 snum, printer->comment ?
6444 printer->comment : "");
6448 if (printer->sharename != NULL &&
6449 (force_update ||
6450 !strequal(printer->sharename, old_printer->sharename))) {
6451 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6452 if (!ok) {
6453 DEBUG(0, ("sharename data corrupted\n"));
6454 result = WERR_INVALID_DATA;
6455 goto done;
6457 result = winreg_set_printer_dataex(tmp_ctx, b,
6458 printer->sharename,
6459 SPOOL_DSSPOOLER_KEY,
6460 SPOOL_REG_PRINTSHARENAME,
6461 REG_SZ,
6462 buffer.data,
6463 buffer.length);
6464 if (!W_ERROR_IS_OK(result)) {
6465 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6466 goto done;
6469 if (!force_update) {
6470 notify_printer_sharename(server_event_context(),
6471 msg_ctx,
6472 snum, printer->sharename ?
6473 printer->sharename : "");
6476 /* name change, purge any cache entries for the old */
6477 prune_printername_cache();
6480 if (printer->printername != NULL &&
6481 (force_update ||
6482 !strequal(printer->printername, old_printer->printername))) {
6483 const char *p;
6485 p = strrchr(printer->printername, '\\' );
6486 if (p != NULL) {
6487 p++;
6488 } else {
6489 p = printer->printername;
6492 ok = push_reg_sz(tmp_ctx, &buffer, p);
6493 if (!ok) {
6494 DEBUG(0, ("printername data corrupted\n"));
6495 result = WERR_INVALID_DATA;
6496 goto done;
6498 result = winreg_set_printer_dataex(tmp_ctx, b,
6499 printer->sharename,
6500 SPOOL_DSSPOOLER_KEY,
6501 SPOOL_REG_PRINTERNAME,
6502 REG_SZ,
6503 buffer.data,
6504 buffer.length);
6505 if (!W_ERROR_IS_OK(result)) {
6506 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6507 goto done;
6510 if (!force_update) {
6511 notify_printer_printername(server_event_context(),
6512 msg_ctx, snum, p ? p : "");
6515 /* name change, purge any cache entries for the old */
6516 prune_printername_cache();
6519 if (printer->portname != NULL &&
6520 (force_update ||
6521 !strequal(printer->portname, old_printer->portname))) {
6522 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6523 if (!ok) {
6524 DEBUG(0, ("portname data corrupted\n"));
6525 result = WERR_INVALID_DATA;
6526 goto done;
6528 result = winreg_set_printer_dataex(tmp_ctx, b,
6529 printer->sharename,
6530 SPOOL_DSSPOOLER_KEY,
6531 SPOOL_REG_PORTNAME,
6532 REG_SZ,
6533 buffer.data,
6534 buffer.length);
6535 if (!W_ERROR_IS_OK(result)) {
6536 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6537 goto done;
6540 if (!force_update) {
6541 notify_printer_port(server_event_context(),
6542 msg_ctx, snum, printer->portname ?
6543 printer->portname : "");
6547 if (printer->location != NULL &&
6548 (force_update ||
6549 !strequal(printer->location, old_printer->location))) {
6550 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6551 if (!ok) {
6552 DEBUG(0, ("location data corrupted\n"));
6553 result = WERR_INVALID_DATA;
6554 goto done;
6556 result = winreg_set_printer_dataex(tmp_ctx, b,
6557 printer->sharename,
6558 SPOOL_DSSPOOLER_KEY,
6559 SPOOL_REG_LOCATION,
6560 REG_SZ,
6561 buffer.data,
6562 buffer.length);
6563 if (!W_ERROR_IS_OK(result)) {
6564 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6565 goto done;
6568 if (!force_update) {
6569 notify_printer_location(server_event_context(),
6570 msg_ctx, snum,
6571 printer->location ?
6572 printer->location : "");
6576 if (printer->sepfile != NULL &&
6577 (force_update ||
6578 !strequal(printer->sepfile, old_printer->sepfile))) {
6579 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6580 if (!ok) {
6581 DEBUG(0, ("sepfile data corrupted\n"));
6582 result = WERR_INVALID_DATA;
6583 goto done;
6585 result = winreg_set_printer_dataex(tmp_ctx, b,
6586 printer->sharename,
6587 SPOOL_DSSPOOLER_KEY,
6588 SPOOL_REG_PRINTSEPARATORFILE,
6589 REG_SZ,
6590 buffer.data,
6591 buffer.length);
6592 if (!W_ERROR_IS_OK(result)) {
6593 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6594 goto done;
6597 if (!force_update) {
6598 notify_printer_sepfile(server_event_context(),
6599 msg_ctx, snum,
6600 printer->sepfile ?
6601 printer->sepfile : "");
6605 if (printer->starttime != 0 &&
6606 (force_update ||
6607 printer->starttime != old_printer->starttime)) {
6608 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6609 SIVAL(buffer.data, 0, printer->starttime);
6610 result = winreg_set_printer_dataex(tmp_ctx, b,
6611 printer->sharename,
6612 SPOOL_DSSPOOLER_KEY,
6613 SPOOL_REG_PRINTSTARTTIME,
6614 REG_DWORD,
6615 buffer.data,
6616 buffer.length);
6617 if (!W_ERROR_IS_OK(result)) {
6618 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6619 goto done;
6623 if (printer->untiltime != 0 &&
6624 (force_update ||
6625 printer->untiltime != old_printer->untiltime)) {
6626 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6627 SIVAL(buffer.data, 0, printer->untiltime);
6628 result = winreg_set_printer_dataex(tmp_ctx, b,
6629 printer->sharename,
6630 SPOOL_DSSPOOLER_KEY,
6631 SPOOL_REG_PRINTENDTIME,
6632 REG_DWORD,
6633 buffer.data,
6634 buffer.length);
6635 if (!W_ERROR_IS_OK(result)) {
6636 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6637 goto done;
6641 if (force_update || printer->priority != old_printer->priority) {
6642 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6643 SIVAL(buffer.data, 0, printer->priority);
6644 result = winreg_set_printer_dataex(tmp_ctx, b,
6645 printer->sharename,
6646 SPOOL_DSSPOOLER_KEY,
6647 SPOOL_REG_PRIORITY,
6648 REG_DWORD,
6649 buffer.data,
6650 buffer.length);
6651 if (!W_ERROR_IS_OK(result)) {
6652 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6653 goto done;
6657 if (force_update || printer->attributes != old_printer->attributes) {
6658 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6659 SIVAL(buffer.data, 0, (printer->attributes &
6660 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6661 result = winreg_set_printer_dataex(tmp_ctx, b,
6662 printer->sharename,
6663 SPOOL_DSSPOOLER_KEY,
6664 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6665 REG_DWORD,
6666 buffer.data,
6667 buffer.length);
6668 if (!W_ERROR_IS_OK(result)) {
6669 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6670 goto done;
6673 switch (printer->attributes & 0x3) {
6674 case 0:
6675 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6676 break;
6677 case 1:
6678 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6679 break;
6680 case 2:
6681 spooling = SPOOL_REGVAL_PRINTDIRECT;
6682 break;
6683 default:
6684 spooling = "unknown";
6686 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6687 if (!ok) {
6688 DEBUG(0, ("printSpooling data corrupted\n"));
6689 result = WERR_INVALID_DATA;
6690 goto done;
6692 winreg_set_printer_dataex(tmp_ctx, b,
6693 printer->sharename,
6694 SPOOL_DSSPOOLER_KEY,
6695 SPOOL_REG_PRINTSPOOLING,
6696 REG_SZ,
6697 buffer.data,
6698 buffer.length);
6701 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6702 if (!ok) {
6703 DEBUG(0, ("shortServerName data corrupted\n"));
6704 result = WERR_INVALID_DATA;
6705 goto done;
6707 result = winreg_set_printer_dataex(tmp_ctx, b,
6708 printer->sharename,
6709 SPOOL_DSSPOOLER_KEY,
6710 SPOOL_REG_SHORTSERVERNAME,
6711 REG_SZ,
6712 buffer.data,
6713 buffer.length);
6714 if (!W_ERROR_IS_OK(result)) {
6715 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6716 goto done;
6719 dnsdomname = get_mydnsfullname();
6720 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6721 longname = talloc_strdup(tmp_ctx, dnsdomname);
6722 } else {
6723 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6725 if (longname == NULL) {
6726 result = WERR_NOMEM;
6727 goto done;
6730 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6731 if (!ok) {
6732 DEBUG(0, ("longname data corrupted\n"));
6733 result = WERR_INVALID_DATA;
6734 goto done;
6736 result = winreg_set_printer_dataex(tmp_ctx, b,
6737 printer->sharename,
6738 SPOOL_DSSPOOLER_KEY,
6739 SPOOL_REG_SERVERNAME,
6740 REG_SZ,
6741 buffer.data,
6742 buffer.length);
6743 if (!W_ERROR_IS_OK(result)) {
6744 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6745 goto done;
6748 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6749 lp_netbios_name(), printer->sharename);
6750 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6751 if (!ok) {
6752 DEBUG(0, ("uncName data corrupted\n"));
6753 result = WERR_INVALID_DATA;
6754 goto done;
6756 result = winreg_set_printer_dataex(tmp_ctx, b,
6757 printer->sharename,
6758 SPOOL_DSSPOOLER_KEY,
6759 SPOOL_REG_UNCNAME,
6760 REG_SZ,
6761 buffer.data,
6762 buffer.length);
6763 if (!W_ERROR_IS_OK(result)) {
6764 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6765 goto done;
6768 done:
6769 talloc_free(tmp_ctx);
6770 return result;
6773 /********************************************************************
6774 * Called by spoolss_api_setprinter
6775 * when updating a printer description.
6776 ********************************************************************/
6778 static WERROR update_printer(struct pipes_struct *p,
6779 struct policy_handle *handle,
6780 struct spoolss_SetPrinterInfoCtr *info_ctr,
6781 struct spoolss_DeviceMode *devmode)
6783 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6784 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6785 struct spoolss_PrinterInfo2 *old_printer;
6786 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6787 int snum;
6788 WERROR result = WERR_OK;
6789 TALLOC_CTX *tmp_ctx;
6790 struct dcerpc_binding_handle *b;
6792 DEBUG(8,("update_printer\n"));
6794 tmp_ctx = talloc_new(p->mem_ctx);
6795 if (tmp_ctx == NULL) {
6796 return WERR_NOMEM;
6799 if (!Printer) {
6800 result = WERR_BADFID;
6801 goto done;
6804 if (!get_printer_snum(p, handle, &snum, NULL)) {
6805 result = WERR_BADFID;
6806 goto done;
6809 result = winreg_printer_binding_handle(tmp_ctx,
6810 get_session_info_system(),
6811 p->msg_ctx,
6812 &b);
6813 if (!W_ERROR_IS_OK(result)) {
6814 goto done;
6817 result = winreg_get_printer(tmp_ctx, b,
6818 lp_const_servicename(snum),
6819 &old_printer);
6820 if (!W_ERROR_IS_OK(result)) {
6821 result = WERR_BADFID;
6822 goto done;
6825 /* Do sanity check on the requested changes for Samba */
6826 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6827 result = WERR_INVALID_PARAM;
6828 goto done;
6831 /* FIXME!!! If the driver has changed we really should verify that
6832 it is installed before doing much else --jerry */
6834 /* Check calling user has permission to update printer description */
6835 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6836 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6837 result = WERR_ACCESS_DENIED;
6838 goto done;
6841 /* Call addprinter hook */
6842 /* Check changes to see if this is really needed */
6844 if (*lp_addprinter_cmd(talloc_tos()) &&
6845 (!strequal(printer->drivername, old_printer->drivername) ||
6846 !strequal(printer->comment, old_printer->comment) ||
6847 !strequal(printer->portname, old_printer->portname) ||
6848 !strequal(printer->location, old_printer->location)) )
6850 char *raddr;
6852 raddr = tsocket_address_inet_addr_string(p->remote_address,
6853 p->mem_ctx);
6854 if (raddr == NULL) {
6855 return WERR_NOMEM;
6858 /* add_printer_hook() will call reload_services() */
6859 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6860 printer, raddr,
6861 p->msg_ctx)) {
6862 result = WERR_ACCESS_DENIED;
6863 goto done;
6867 result = update_dsspooler(tmp_ctx,
6868 get_session_info_system(),
6869 p->msg_ctx,
6870 snum,
6871 printer,
6872 old_printer);
6873 if (!W_ERROR_IS_OK(result)) {
6874 goto done;
6877 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6879 if (devmode == NULL) {
6880 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6882 result = winreg_update_printer(tmp_ctx, b,
6883 printer->sharename,
6884 printer_mask,
6885 printer,
6886 devmode,
6887 NULL);
6889 done:
6890 talloc_free(tmp_ctx);
6892 return result;
6895 /****************************************************************************
6896 ****************************************************************************/
6897 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6898 struct policy_handle *handle,
6899 struct spoolss_SetPrinterInfo7 *info7)
6901 #ifdef HAVE_ADS
6902 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6903 WERROR result;
6904 int snum;
6905 struct printer_handle *Printer;
6907 if ( lp_security() != SEC_ADS ) {
6908 return WERR_UNKNOWN_LEVEL;
6911 Printer = find_printer_index_by_hnd(p, handle);
6913 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6915 if (!Printer)
6916 return WERR_BADFID;
6918 if (!get_printer_snum(p, handle, &snum, NULL))
6919 return WERR_BADFID;
6921 result = winreg_get_printer_internal(p->mem_ctx,
6922 get_session_info_system(),
6923 p->msg_ctx,
6924 lp_servicename(talloc_tos(), snum),
6925 &pinfo2);
6926 if (!W_ERROR_IS_OK(result)) {
6927 return WERR_BADFID;
6930 nt_printer_publish(pinfo2,
6931 get_session_info_system(),
6932 p->msg_ctx,
6933 pinfo2,
6934 info7->action);
6936 TALLOC_FREE(pinfo2);
6937 return WERR_OK;
6938 #else
6939 return WERR_UNKNOWN_LEVEL;
6940 #endif
6943 /********************************************************************
6944 ********************************************************************/
6946 static WERROR update_printer_devmode(struct pipes_struct *p,
6947 struct policy_handle *handle,
6948 struct spoolss_DeviceMode *devmode)
6950 int snum;
6951 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6952 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6954 DEBUG(8,("update_printer_devmode\n"));
6956 if (!Printer) {
6957 return WERR_BADFID;
6960 if (!get_printer_snum(p, handle, &snum, NULL)) {
6961 return WERR_BADFID;
6964 /* Check calling user has permission to update printer description */
6965 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6966 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6967 return WERR_ACCESS_DENIED;
6970 return winreg_update_printer_internal(p->mem_ctx,
6971 get_session_info_system(),
6972 p->msg_ctx,
6973 lp_const_servicename(snum),
6974 info2_mask,
6975 NULL,
6976 devmode,
6977 NULL);
6981 /****************************************************************
6982 _spoolss_SetPrinter
6983 ****************************************************************/
6985 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6986 struct spoolss_SetPrinter *r)
6988 WERROR result;
6990 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6992 if (!Printer) {
6993 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6994 OUR_HANDLE(r->in.handle)));
6995 return WERR_BADFID;
6998 /* check the level */
6999 switch (r->in.info_ctr->level) {
7000 case 0:
7001 return control_printer(r->in.handle, r->in.command, p);
7002 case 2:
7003 result = update_printer(p, r->in.handle,
7004 r->in.info_ctr,
7005 r->in.devmode_ctr->devmode);
7006 if (!W_ERROR_IS_OK(result))
7007 return result;
7008 if (r->in.secdesc_ctr->sd)
7009 result = update_printer_sec(r->in.handle, p,
7010 r->in.secdesc_ctr);
7011 return result;
7012 case 3:
7013 return update_printer_sec(r->in.handle, p,
7014 r->in.secdesc_ctr);
7015 case 7:
7016 return publish_or_unpublish_printer(p, r->in.handle,
7017 r->in.info_ctr->info.info7);
7018 case 8:
7019 return update_printer_devmode(p, r->in.handle,
7020 r->in.devmode_ctr->devmode);
7021 default:
7022 return WERR_UNKNOWN_LEVEL;
7026 /****************************************************************
7027 _spoolss_FindClosePrinterNotify
7028 ****************************************************************/
7030 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7031 struct spoolss_FindClosePrinterNotify *r)
7033 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7035 if (!Printer) {
7036 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7037 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7038 return WERR_BADFID;
7041 if (Printer->notify.cli_chan != NULL &&
7042 Printer->notify.cli_chan->active_connections > 0) {
7043 int snum = -1;
7045 if (Printer->printer_type == SPLHND_PRINTER) {
7046 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7047 return WERR_BADFID;
7051 srv_spoolss_replycloseprinter(snum, Printer);
7054 Printer->notify.flags=0;
7055 Printer->notify.options=0;
7056 Printer->notify.localmachine[0]='\0';
7057 Printer->notify.printerlocal=0;
7058 TALLOC_FREE(Printer->notify.option);
7060 return WERR_OK;
7063 /****************************************************************
7064 _spoolss_AddJob
7065 ****************************************************************/
7067 WERROR _spoolss_AddJob(struct pipes_struct *p,
7068 struct spoolss_AddJob *r)
7070 if (!r->in.buffer && (r->in.offered != 0)) {
7071 return WERR_INVALID_PARAM;
7074 /* this is what a NT server returns for AddJob. AddJob must fail on
7075 * non-local printers */
7077 if (r->in.level != 1) {
7078 return WERR_UNKNOWN_LEVEL;
7081 return WERR_INVALID_PARAM;
7084 /****************************************************************************
7085 fill_job_info1
7086 ****************************************************************************/
7088 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7089 struct spoolss_JobInfo1 *r,
7090 const print_queue_struct *queue,
7091 uint32_t jobid,
7092 int position, int snum,
7093 struct spoolss_PrinterInfo2 *pinfo2)
7095 struct tm *t;
7097 t = gmtime(&queue->time);
7099 r->job_id = jobid;
7101 r->printer_name = lp_servicename(mem_ctx, snum);
7102 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7103 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7104 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7105 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7106 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7107 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7108 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7109 r->data_type = talloc_strdup(mem_ctx, "RAW");
7110 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7111 r->text_status = talloc_strdup(mem_ctx, "");
7112 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7114 r->status = nt_printj_status(queue->status);
7115 r->priority = queue->priority;
7116 r->position = position;
7117 r->total_pages = queue->page_count;
7118 r->pages_printed = 0; /* ??? */
7120 init_systemtime(&r->submitted, t);
7122 return WERR_OK;
7125 /****************************************************************************
7126 fill_job_info2
7127 ****************************************************************************/
7129 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7130 struct spoolss_JobInfo2 *r,
7131 const print_queue_struct *queue,
7132 uint32_t jobid,
7133 int position, int snum,
7134 struct spoolss_PrinterInfo2 *pinfo2,
7135 struct spoolss_DeviceMode *devmode)
7137 struct tm *t;
7139 t = gmtime(&queue->time);
7141 r->job_id = jobid;
7143 r->printer_name = lp_servicename(mem_ctx, snum);
7144 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7145 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7146 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7147 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7148 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7149 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7150 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7151 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7152 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7153 r->data_type = talloc_strdup(mem_ctx, "RAW");
7154 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7155 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7156 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7157 r->parameters = talloc_strdup(mem_ctx, "");
7158 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7159 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7160 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7162 r->devmode = devmode;
7164 r->text_status = talloc_strdup(mem_ctx, "");
7165 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7167 r->secdesc = NULL;
7169 r->status = nt_printj_status(queue->status);
7170 r->priority = queue->priority;
7171 r->position = position;
7172 r->start_time = 0;
7173 r->until_time = 0;
7174 r->total_pages = queue->page_count;
7175 r->size = queue->size;
7176 init_systemtime(&r->submitted, t);
7177 r->time = 0;
7178 r->pages_printed = 0; /* ??? */
7180 return WERR_OK;
7183 /****************************************************************************
7184 Enumjobs at level 1.
7185 ****************************************************************************/
7187 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7188 const print_queue_struct *queue,
7189 uint32_t num_queues, int snum,
7190 struct spoolss_PrinterInfo2 *pinfo2,
7191 union spoolss_JobInfo **info_p,
7192 uint32_t *count)
7194 union spoolss_JobInfo *info;
7195 int i;
7196 WERROR result = WERR_OK;
7197 uint32_t num_filled;
7198 struct tdb_print_db *pdb;
7200 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7201 if (info == NULL) {
7202 result = WERR_NOMEM;
7203 goto err_out;
7206 pdb = get_print_db_byname(pinfo2->sharename);
7207 if (pdb == NULL) {
7208 result = WERR_INVALID_PARAM;
7209 goto err_info_free;
7212 num_filled = 0;
7213 for (i = 0; i < num_queues; i++) {
7214 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7215 if (jobid == (uint32_t)-1) {
7216 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7217 continue;
7220 result = fill_job_info1(info,
7221 &info[num_filled].info1,
7222 &queue[i],
7223 jobid,
7225 snum,
7226 pinfo2);
7227 if (!W_ERROR_IS_OK(result)) {
7228 goto err_pdb_drop;
7231 num_filled++;
7234 release_print_db(pdb);
7235 *info_p = info;
7236 *count = num_filled;
7238 return WERR_OK;
7240 err_pdb_drop:
7241 release_print_db(pdb);
7242 err_info_free:
7243 TALLOC_FREE(info);
7244 err_out:
7245 *count = 0;
7246 return result;
7249 /****************************************************************************
7250 Enumjobs at level 2.
7251 ****************************************************************************/
7253 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7254 const print_queue_struct *queue,
7255 uint32_t num_queues, int snum,
7256 struct spoolss_PrinterInfo2 *pinfo2,
7257 union spoolss_JobInfo **info_p,
7258 uint32_t *count)
7260 union spoolss_JobInfo *info;
7261 int i;
7262 WERROR result = WERR_OK;
7263 uint32_t num_filled;
7264 struct tdb_print_db *pdb;
7266 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7267 if (info == NULL) {
7268 result = WERR_NOMEM;
7269 goto err_out;
7272 pdb = get_print_db_byname(pinfo2->sharename);
7273 if (pdb == NULL) {
7274 result = WERR_INVALID_PARAM;
7275 goto err_info_free;
7278 num_filled = 0;
7279 for (i = 0; i< num_queues; i++) {
7280 struct spoolss_DeviceMode *devmode;
7281 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7282 if (jobid == (uint32_t)-1) {
7283 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7284 continue;
7287 result = spoolss_create_default_devmode(info,
7288 pinfo2->printername,
7289 &devmode);
7290 if (!W_ERROR_IS_OK(result)) {
7291 DEBUG(3, ("Can't proceed w/o a devmode!"));
7292 goto err_pdb_drop;
7295 result = fill_job_info2(info,
7296 &info[num_filled].info2,
7297 &queue[i],
7298 jobid,
7300 snum,
7301 pinfo2,
7302 devmode);
7303 if (!W_ERROR_IS_OK(result)) {
7304 goto err_pdb_drop;
7306 num_filled++;
7309 release_print_db(pdb);
7310 *info_p = info;
7311 *count = num_filled;
7313 return WERR_OK;
7315 err_pdb_drop:
7316 release_print_db(pdb);
7317 err_info_free:
7318 TALLOC_FREE(info);
7319 err_out:
7320 *count = 0;
7321 return result;
7324 /****************************************************************************
7325 Enumjobs at level 3.
7326 ****************************************************************************/
7328 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7329 const print_queue_struct *queue,
7330 uint32_t num_queues, int snum,
7331 struct spoolss_PrinterInfo2 *pinfo2,
7332 union spoolss_JobInfo **info_p,
7333 uint32_t *count)
7335 union spoolss_JobInfo *info;
7336 int i;
7337 WERROR result = WERR_OK;
7338 uint32_t num_filled;
7339 struct tdb_print_db *pdb;
7341 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7342 if (info == NULL) {
7343 result = WERR_NOMEM;
7344 goto err_out;
7347 pdb = get_print_db_byname(pinfo2->sharename);
7348 if (pdb == NULL) {
7349 result = WERR_INVALID_PARAM;
7350 goto err_info_free;
7353 num_filled = 0;
7354 for (i = 0; i < num_queues; i++) {
7355 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7356 if (jobid == (uint32_t)-1) {
7357 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7358 continue;
7361 info[num_filled].info3.job_id = jobid;
7362 /* next_job_id is overwritten on next iteration */
7363 info[num_filled].info3.next_job_id = 0;
7364 info[num_filled].info3.reserved = 0;
7366 if (num_filled > 0) {
7367 info[num_filled - 1].info3.next_job_id = jobid;
7369 num_filled++;
7372 release_print_db(pdb);
7373 *info_p = info;
7374 *count = num_filled;
7376 return WERR_OK;
7378 err_info_free:
7379 TALLOC_FREE(info);
7380 err_out:
7381 *count = 0;
7382 return result;
7385 /****************************************************************
7386 _spoolss_EnumJobs
7387 ****************************************************************/
7389 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7390 struct spoolss_EnumJobs *r)
7392 WERROR result;
7393 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7394 int snum;
7395 print_status_struct prt_status;
7396 print_queue_struct *queue = NULL;
7397 uint32_t count;
7399 /* that's an [in out] buffer */
7401 if (!r->in.buffer && (r->in.offered != 0)) {
7402 return WERR_INVALID_PARAM;
7405 if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7406 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7407 return WERR_UNKNOWN_LEVEL;
7410 DEBUG(4,("_spoolss_EnumJobs\n"));
7412 *r->out.needed = 0;
7413 *r->out.count = 0;
7414 *r->out.info = NULL;
7416 /* lookup the printer snum and tdb entry */
7418 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7419 return WERR_BADFID;
7422 result = winreg_get_printer_internal(p->mem_ctx,
7423 get_session_info_system(),
7424 p->msg_ctx,
7425 lp_const_servicename(snum),
7426 &pinfo2);
7427 if (!W_ERROR_IS_OK(result)) {
7428 return result;
7431 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7432 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7433 count, prt_status.status, prt_status.message));
7435 if (count == 0) {
7436 SAFE_FREE(queue);
7437 TALLOC_FREE(pinfo2);
7438 return WERR_OK;
7441 switch (r->in.level) {
7442 case 1:
7443 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7444 pinfo2, r->out.info, r->out.count);
7445 break;
7446 case 2:
7447 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7448 pinfo2, r->out.info, r->out.count);
7449 break;
7450 case 3:
7451 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7452 pinfo2, r->out.info, r->out.count);
7453 break;
7454 default:
7455 SMB_ASSERT(false); /* level checked on entry */
7456 break;
7459 SAFE_FREE(queue);
7460 TALLOC_FREE(pinfo2);
7462 if (!W_ERROR_IS_OK(result)) {
7463 return result;
7466 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7467 spoolss_EnumJobs,
7468 *r->out.info, r->in.level,
7469 *r->out.count);
7470 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7471 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7473 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7476 /****************************************************************
7477 _spoolss_ScheduleJob
7478 ****************************************************************/
7480 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7481 struct spoolss_ScheduleJob *r)
7483 return WERR_OK;
7486 /****************************************************************
7487 ****************************************************************/
7489 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7490 struct messaging_context *msg_ctx,
7491 const char *printer_name,
7492 uint32_t job_id,
7493 struct spoolss_SetJobInfo1 *r)
7495 char *old_doc_name;
7497 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7498 return WERR_BADFID;
7501 if (strequal(old_doc_name, r->document_name)) {
7502 return WERR_OK;
7505 if (!print_job_set_name(server_event_context(), msg_ctx,
7506 printer_name, job_id, r->document_name)) {
7507 return WERR_BADFID;
7510 return WERR_OK;
7513 /****************************************************************
7514 _spoolss_SetJob
7515 ****************************************************************/
7517 WERROR _spoolss_SetJob(struct pipes_struct *p,
7518 struct spoolss_SetJob *r)
7520 const struct auth_session_info *session_info = p->session_info;
7521 int snum;
7522 WERROR errcode = WERR_BADFUNC;
7524 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7525 return WERR_BADFID;
7528 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7529 return WERR_INVALID_PRINTER_NAME;
7532 switch (r->in.command) {
7533 case SPOOLSS_JOB_CONTROL_CANCEL:
7534 case SPOOLSS_JOB_CONTROL_DELETE:
7535 errcode = print_job_delete(session_info, p->msg_ctx,
7536 snum, r->in.job_id);
7537 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7538 errcode = WERR_OK;
7540 break;
7541 case SPOOLSS_JOB_CONTROL_PAUSE:
7542 errcode = print_job_pause(session_info, p->msg_ctx,
7543 snum, r->in.job_id);
7544 break;
7545 case SPOOLSS_JOB_CONTROL_RESTART:
7546 case SPOOLSS_JOB_CONTROL_RESUME:
7547 errcode = print_job_resume(session_info, p->msg_ctx,
7548 snum, r->in.job_id);
7549 break;
7550 case 0:
7551 errcode = WERR_OK;
7552 break;
7553 default:
7554 return WERR_UNKNOWN_LEVEL;
7557 if (!W_ERROR_IS_OK(errcode)) {
7558 return errcode;
7561 if (r->in.ctr == NULL) {
7562 return errcode;
7565 switch (r->in.ctr->level) {
7566 case 1:
7567 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7568 lp_const_servicename(snum),
7569 r->in.job_id,
7570 r->in.ctr->info.info1);
7571 break;
7572 case 2:
7573 case 3:
7574 case 4:
7575 default:
7576 return WERR_UNKNOWN_LEVEL;
7579 return errcode;
7582 /****************************************************************************
7583 Enumerates all printer drivers by level and architecture.
7584 ****************************************************************************/
7586 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7587 const struct auth_session_info *session_info,
7588 struct messaging_context *msg_ctx,
7589 const char *servername,
7590 const char *architecture,
7591 uint32_t level,
7592 union spoolss_DriverInfo **info_p,
7593 uint32_t *count_p)
7595 int i;
7596 uint32_t version;
7597 struct spoolss_DriverInfo8 *driver;
7598 union spoolss_DriverInfo *info = NULL;
7599 uint32_t count = 0;
7600 WERROR result = WERR_OK;
7601 uint32_t num_drivers;
7602 const char **drivers;
7603 struct dcerpc_binding_handle *b;
7604 TALLOC_CTX *tmp_ctx = NULL;
7606 *count_p = 0;
7607 *info_p = NULL;
7609 tmp_ctx = talloc_new(mem_ctx);
7610 if (!tmp_ctx) {
7611 return WERR_NOMEM;
7614 result = winreg_printer_binding_handle(tmp_ctx,
7615 session_info,
7616 msg_ctx,
7617 &b);
7618 if (!W_ERROR_IS_OK(result)) {
7619 goto out;
7622 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7623 result = winreg_get_driver_list(tmp_ctx, b,
7624 architecture, version,
7625 &num_drivers, &drivers);
7626 if (!W_ERROR_IS_OK(result)) {
7627 goto out;
7629 DEBUG(4, ("we have:[%d] drivers in environment"
7630 " [%s] and version [%d]\n",
7631 num_drivers, architecture, version));
7633 if (num_drivers != 0) {
7634 info = talloc_realloc(tmp_ctx, info,
7635 union spoolss_DriverInfo,
7636 count + num_drivers);
7637 if (!info) {
7638 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7639 "failed to enlarge driver info buffer!\n"));
7640 result = WERR_NOMEM;
7641 goto out;
7645 for (i = 0; i < num_drivers; i++) {
7646 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7648 result = winreg_get_driver(tmp_ctx, b,
7649 architecture, drivers[i],
7650 version, &driver);
7651 if (!W_ERROR_IS_OK(result)) {
7652 goto out;
7655 switch (level) {
7656 case 1:
7657 result = fill_printer_driver_info1(info, &info[count+i].info1,
7658 driver, servername);
7659 break;
7660 case 2:
7661 result = fill_printer_driver_info2(info, &info[count+i].info2,
7662 driver, servername);
7663 break;
7664 case 3:
7665 result = fill_printer_driver_info3(info, &info[count+i].info3,
7666 driver, servername);
7667 break;
7668 case 4:
7669 result = fill_printer_driver_info4(info, &info[count+i].info4,
7670 driver, servername);
7671 break;
7672 case 5:
7673 result = fill_printer_driver_info5(info, &info[count+i].info5,
7674 driver, servername);
7675 break;
7676 case 6:
7677 result = fill_printer_driver_info6(info, &info[count+i].info6,
7678 driver, servername);
7679 break;
7680 case 8:
7681 result = fill_printer_driver_info8(info, &info[count+i].info8,
7682 driver, servername);
7683 break;
7684 default:
7685 result = WERR_UNKNOWN_LEVEL;
7686 break;
7689 TALLOC_FREE(driver);
7691 if (!W_ERROR_IS_OK(result)) {
7692 goto out;
7696 count += num_drivers;
7697 TALLOC_FREE(drivers);
7700 out:
7701 if (W_ERROR_IS_OK(result)) {
7702 *info_p = talloc_move(mem_ctx, &info);
7703 *count_p = count;
7706 talloc_free(tmp_ctx);
7707 return result;
7710 /****************************************************************************
7711 Enumerates all printer drivers by level.
7712 ****************************************************************************/
7714 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7715 const struct auth_session_info *session_info,
7716 struct messaging_context *msg_ctx,
7717 const char *servername,
7718 const char *architecture,
7719 uint32_t level,
7720 union spoolss_DriverInfo **info_p,
7721 uint32_t *count_p)
7723 uint32_t a,i;
7724 WERROR result = WERR_OK;
7726 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7728 for (a=0; archi_table[a].long_archi != NULL; a++) {
7730 union spoolss_DriverInfo *info = NULL;
7731 uint32_t count = 0;
7733 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7734 session_info,
7735 msg_ctx,
7736 servername,
7737 archi_table[a].long_archi,
7738 level,
7739 &info,
7740 &count);
7741 if (!W_ERROR_IS_OK(result)) {
7742 continue;
7745 for (i=0; i < count; i++) {
7746 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7747 info[i], info_p, count_p);
7751 return result;
7754 return enumprinterdrivers_level_by_architecture(mem_ctx,
7755 session_info,
7756 msg_ctx,
7757 servername,
7758 architecture,
7759 level,
7760 info_p,
7761 count_p);
7764 /****************************************************************
7765 _spoolss_EnumPrinterDrivers
7766 ****************************************************************/
7768 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7769 struct spoolss_EnumPrinterDrivers *r)
7771 const char *cservername;
7772 WERROR result;
7774 /* that's an [in out] buffer */
7776 if (!r->in.buffer && (r->in.offered != 0)) {
7777 return WERR_INVALID_PARAM;
7780 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7782 *r->out.needed = 0;
7783 *r->out.count = 0;
7784 *r->out.info = NULL;
7786 cservername = canon_servername(r->in.server);
7788 if (!is_myname_or_ipaddr(cservername)) {
7789 return WERR_UNKNOWN_PRINTER_DRIVER;
7792 result = enumprinterdrivers_level(p->mem_ctx,
7793 get_session_info_system(),
7794 p->msg_ctx,
7795 cservername,
7796 r->in.environment,
7797 r->in.level,
7798 r->out.info,
7799 r->out.count);
7800 if (!W_ERROR_IS_OK(result)) {
7801 return result;
7804 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7805 spoolss_EnumPrinterDrivers,
7806 *r->out.info, r->in.level,
7807 *r->out.count);
7808 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7809 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7811 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7814 /****************************************************************
7815 _spoolss_EnumForms
7816 ****************************************************************/
7818 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7819 struct spoolss_EnumForms *r)
7821 WERROR result;
7823 *r->out.count = 0;
7824 *r->out.needed = 0;
7825 *r->out.info = NULL;
7827 /* that's an [in out] buffer */
7829 if (!r->in.buffer && (r->in.offered != 0) ) {
7830 return WERR_INVALID_PARAM;
7833 DEBUG(4,("_spoolss_EnumForms\n"));
7834 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7835 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7837 switch (r->in.level) {
7838 case 1:
7839 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7840 get_session_info_system(),
7841 p->msg_ctx,
7842 r->out.count,
7843 r->out.info);
7844 break;
7845 default:
7846 result = WERR_UNKNOWN_LEVEL;
7847 break;
7850 if (!W_ERROR_IS_OK(result)) {
7851 return result;
7854 if (*r->out.count == 0) {
7855 return WERR_NO_MORE_ITEMS;
7858 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7859 spoolss_EnumForms,
7860 *r->out.info, r->in.level,
7861 *r->out.count);
7862 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7863 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7865 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7868 /****************************************************************
7869 _spoolss_GetForm
7870 ****************************************************************/
7872 WERROR _spoolss_GetForm(struct pipes_struct *p,
7873 struct spoolss_GetForm *r)
7875 WERROR result;
7877 /* that's an [in out] buffer */
7879 if (!r->in.buffer && (r->in.offered != 0)) {
7880 TALLOC_FREE(r->out.info);
7881 return WERR_INVALID_PARAM;
7884 DEBUG(4,("_spoolss_GetForm\n"));
7885 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7886 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7888 switch (r->in.level) {
7889 case 1:
7890 result = winreg_printer_getform1_internal(p->mem_ctx,
7891 get_session_info_system(),
7892 p->msg_ctx,
7893 r->in.form_name,
7894 &r->out.info->info1);
7895 break;
7896 default:
7897 result = WERR_UNKNOWN_LEVEL;
7898 break;
7901 if (!W_ERROR_IS_OK(result)) {
7902 TALLOC_FREE(r->out.info);
7903 return result;
7906 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7907 r->out.info, r->in.level);
7908 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7910 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7913 /****************************************************************************
7914 ****************************************************************************/
7916 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7917 struct spoolss_PortInfo1 *r,
7918 const char *name)
7920 r->port_name = talloc_strdup(mem_ctx, name);
7921 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7923 return WERR_OK;
7926 /****************************************************************************
7927 TODO: This probably needs distinguish between TCP/IP and Local ports
7928 somehow.
7929 ****************************************************************************/
7931 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7932 struct spoolss_PortInfo2 *r,
7933 const char *name)
7935 r->port_name = talloc_strdup(mem_ctx, name);
7936 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7938 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7939 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7941 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7942 W_ERROR_HAVE_NO_MEMORY(r->description);
7944 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7945 r->reserved = 0;
7947 return WERR_OK;
7951 /****************************************************************************
7952 wrapper around the enumer ports command
7953 ****************************************************************************/
7955 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7957 char *cmd = lp_enumports_cmd(talloc_tos());
7958 char **qlines = NULL;
7959 char *command = NULL;
7960 int numlines;
7961 int ret;
7962 int fd;
7964 *count = 0;
7965 *lines = NULL;
7967 /* if no hook then just fill in the default port */
7969 if ( !*cmd ) {
7970 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7971 return WERR_NOMEM;
7973 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7974 TALLOC_FREE(qlines);
7975 return WERR_NOMEM;
7977 qlines[1] = NULL;
7978 numlines = 1;
7980 else {
7981 /* we have a valid enumport command */
7983 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7984 if (!command) {
7985 return WERR_NOMEM;
7988 DEBUG(10,("Running [%s]\n", command));
7989 ret = smbrun(command, &fd);
7990 DEBUG(10,("Returned [%d]\n", ret));
7991 TALLOC_FREE(command);
7992 if (ret != 0) {
7993 if (fd != -1) {
7994 close(fd);
7996 return WERR_ACCESS_DENIED;
7999 numlines = 0;
8000 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8001 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8002 close(fd);
8005 *count = numlines;
8006 *lines = qlines;
8008 return WERR_OK;
8011 /****************************************************************************
8012 enumports level 1.
8013 ****************************************************************************/
8015 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8016 union spoolss_PortInfo **info_p,
8017 uint32_t *count)
8019 union spoolss_PortInfo *info = NULL;
8020 int i=0;
8021 WERROR result = WERR_OK;
8022 char **qlines = NULL;
8023 int numlines = 0;
8025 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8026 if (!W_ERROR_IS_OK(result)) {
8027 goto out;
8030 if (numlines) {
8031 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8032 if (!info) {
8033 DEBUG(10,("Returning WERR_NOMEM\n"));
8034 result = WERR_NOMEM;
8035 goto out;
8038 for (i=0; i<numlines; i++) {
8039 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8040 result = fill_port_1(info, &info[i].info1, qlines[i]);
8041 if (!W_ERROR_IS_OK(result)) {
8042 goto out;
8046 TALLOC_FREE(qlines);
8048 out:
8049 if (!W_ERROR_IS_OK(result)) {
8050 TALLOC_FREE(info);
8051 TALLOC_FREE(qlines);
8052 *count = 0;
8053 *info_p = NULL;
8054 return result;
8057 *info_p = info;
8058 *count = numlines;
8060 return WERR_OK;
8063 /****************************************************************************
8064 enumports level 2.
8065 ****************************************************************************/
8067 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8068 union spoolss_PortInfo **info_p,
8069 uint32_t *count)
8071 union spoolss_PortInfo *info = NULL;
8072 int i=0;
8073 WERROR result = WERR_OK;
8074 char **qlines = NULL;
8075 int numlines = 0;
8077 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8078 if (!W_ERROR_IS_OK(result)) {
8079 goto out;
8082 if (numlines) {
8083 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8084 if (!info) {
8085 DEBUG(10,("Returning WERR_NOMEM\n"));
8086 result = WERR_NOMEM;
8087 goto out;
8090 for (i=0; i<numlines; i++) {
8091 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8092 result = fill_port_2(info, &info[i].info2, qlines[i]);
8093 if (!W_ERROR_IS_OK(result)) {
8094 goto out;
8098 TALLOC_FREE(qlines);
8100 out:
8101 if (!W_ERROR_IS_OK(result)) {
8102 TALLOC_FREE(info);
8103 TALLOC_FREE(qlines);
8104 *count = 0;
8105 *info_p = NULL;
8106 return result;
8109 *info_p = info;
8110 *count = numlines;
8112 return WERR_OK;
8115 /****************************************************************
8116 _spoolss_EnumPorts
8117 ****************************************************************/
8119 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8120 struct spoolss_EnumPorts *r)
8122 WERROR result;
8124 /* that's an [in out] buffer */
8126 if (!r->in.buffer && (r->in.offered != 0)) {
8127 return WERR_INVALID_PARAM;
8130 DEBUG(4,("_spoolss_EnumPorts\n"));
8132 *r->out.count = 0;
8133 *r->out.needed = 0;
8134 *r->out.info = NULL;
8136 switch (r->in.level) {
8137 case 1:
8138 result = enumports_level_1(p->mem_ctx, r->out.info,
8139 r->out.count);
8140 break;
8141 case 2:
8142 result = enumports_level_2(p->mem_ctx, r->out.info,
8143 r->out.count);
8144 break;
8145 default:
8146 return WERR_UNKNOWN_LEVEL;
8149 if (!W_ERROR_IS_OK(result)) {
8150 return result;
8153 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8154 spoolss_EnumPorts,
8155 *r->out.info, r->in.level,
8156 *r->out.count);
8157 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8158 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8160 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8163 /****************************************************************************
8164 ****************************************************************************/
8166 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8167 const char *server,
8168 struct spoolss_SetPrinterInfoCtr *info_ctr,
8169 struct spoolss_DeviceMode *devmode,
8170 struct security_descriptor *secdesc,
8171 struct spoolss_UserLevelCtr *user_ctr,
8172 struct policy_handle *handle)
8174 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8175 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8176 int snum;
8177 WERROR err = WERR_OK;
8179 /* samba does not have a concept of local, non-shared printers yet, so
8180 * make sure we always setup sharename - gd */
8181 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8182 (info2->printername != NULL && info2->printername[0] != '\0')) {
8183 DEBUG(5, ("spoolss_addprinterex_level_2: "
8184 "no sharename has been set, setting printername %s as sharename\n",
8185 info2->printername));
8186 info2->sharename = info2->printername;
8189 /* check to see if the printer already exists */
8190 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8191 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8192 info2->sharename));
8193 return WERR_PRINTER_ALREADY_EXISTS;
8196 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8197 if ((snum = print_queue_snum(info2->printername)) != -1) {
8198 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8199 info2->printername));
8200 return WERR_PRINTER_ALREADY_EXISTS;
8204 /* validate printer info struct */
8205 if (!info2->printername || strlen(info2->printername) == 0) {
8206 return WERR_INVALID_PRINTER_NAME;
8208 if (!info2->portname || strlen(info2->portname) == 0) {
8209 return WERR_UNKNOWN_PORT;
8211 if (!info2->drivername || strlen(info2->drivername) == 0) {
8212 return WERR_UNKNOWN_PRINTER_DRIVER;
8214 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8215 return WERR_UNKNOWN_PRINTPROCESSOR;
8218 /* FIXME!!! smbd should check to see if the driver is installed before
8219 trying to add a printer like this --jerry */
8221 if (*lp_addprinter_cmd(talloc_tos()) ) {
8222 char *raddr;
8224 raddr = tsocket_address_inet_addr_string(p->remote_address,
8225 p->mem_ctx);
8226 if (raddr == NULL) {
8227 return WERR_NOMEM;
8230 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8231 info2, raddr,
8232 p->msg_ctx) ) {
8233 return WERR_ACCESS_DENIED;
8235 } else {
8236 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8237 "smb.conf parameter \"addprinter command\" is defined. This "
8238 "parameter must exist for this call to succeed\n",
8239 info2->sharename ));
8242 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8243 return WERR_ACCESS_DENIED;
8246 /* you must be a printer admin to add a new printer */
8247 if (!print_access_check(p->session_info,
8248 p->msg_ctx,
8249 snum,
8250 PRINTER_ACCESS_ADMINISTER)) {
8251 return WERR_ACCESS_DENIED;
8255 * Do sanity check on the requested changes for Samba.
8258 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8259 return WERR_INVALID_PARAM;
8262 if (devmode == NULL) {
8263 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8266 err = update_dsspooler(p->mem_ctx,
8267 get_session_info_system(),
8268 p->msg_ctx,
8270 info2,
8271 NULL);
8272 if (!W_ERROR_IS_OK(err)) {
8273 return err;
8276 err = winreg_update_printer_internal(p->mem_ctx,
8277 get_session_info_system(),
8278 p->msg_ctx,
8279 info2->sharename,
8280 info2_mask,
8281 info2,
8282 devmode,
8283 secdesc);
8284 if (!W_ERROR_IS_OK(err)) {
8285 return err;
8288 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8289 if (!W_ERROR_IS_OK(err)) {
8290 /* Handle open failed - remove addition. */
8291 ZERO_STRUCTP(handle);
8292 return err;
8295 return WERR_OK;
8298 /****************************************************************
8299 _spoolss_AddPrinterEx
8300 ****************************************************************/
8302 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8303 struct spoolss_AddPrinterEx *r)
8305 switch (r->in.info_ctr->level) {
8306 case 1:
8307 /* we don't handle yet */
8308 /* but I know what to do ... */
8309 return WERR_UNKNOWN_LEVEL;
8310 case 2:
8311 return spoolss_addprinterex_level_2(p, r->in.server,
8312 r->in.info_ctr,
8313 r->in.devmode_ctr->devmode,
8314 r->in.secdesc_ctr->sd,
8315 r->in.userlevel_ctr,
8316 r->out.handle);
8317 default:
8318 return WERR_UNKNOWN_LEVEL;
8322 /****************************************************************
8323 _spoolss_AddPrinter
8324 ****************************************************************/
8326 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8327 struct spoolss_AddPrinter *r)
8329 struct spoolss_AddPrinterEx a;
8330 struct spoolss_UserLevelCtr userlevel_ctr;
8332 ZERO_STRUCT(userlevel_ctr);
8334 userlevel_ctr.level = 1;
8336 a.in.server = r->in.server;
8337 a.in.info_ctr = r->in.info_ctr;
8338 a.in.devmode_ctr = r->in.devmode_ctr;
8339 a.in.secdesc_ctr = r->in.secdesc_ctr;
8340 a.in.userlevel_ctr = &userlevel_ctr;
8341 a.out.handle = r->out.handle;
8343 return _spoolss_AddPrinterEx(p, &a);
8346 /****************************************************************
8347 _spoolss_AddPrinterDriverEx
8348 ****************************************************************/
8350 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8351 struct spoolss_AddPrinterDriverEx *r)
8353 WERROR err = WERR_OK;
8354 const char *driver_name = NULL;
8355 uint32_t version;
8356 const char *fn;
8358 switch (p->opnum) {
8359 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8360 fn = "_spoolss_AddPrinterDriver";
8361 break;
8362 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8363 fn = "_spoolss_AddPrinterDriverEx";
8364 break;
8365 default:
8366 return WERR_INVALID_PARAM;
8370 * we only support the semantics of AddPrinterDriver()
8371 * i.e. only copy files that are newer than existing ones
8374 if (r->in.flags == 0) {
8375 return WERR_INVALID_PARAM;
8378 if (r->in.flags != APD_COPY_NEW_FILES) {
8379 return WERR_ACCESS_DENIED;
8382 /* FIXME */
8383 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8384 /* Clever hack from Martin Zielinski <mz@seh.de>
8385 * to allow downgrade from level 8 (Vista).
8387 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8388 r->in.info_ctr->level));
8389 return WERR_UNKNOWN_LEVEL;
8392 DEBUG(5,("Cleaning driver's information\n"));
8393 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8394 if (!W_ERROR_IS_OK(err))
8395 goto done;
8397 DEBUG(5,("Moving driver to final destination\n"));
8398 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8399 if (!W_ERROR_IS_OK(err)) {
8400 goto done;
8403 err = winreg_add_driver_internal(p->mem_ctx,
8404 get_session_info_system(),
8405 p->msg_ctx,
8406 r->in.info_ctr,
8407 &driver_name,
8408 &version);
8409 if (!W_ERROR_IS_OK(err)) {
8410 goto done;
8414 * I think this is where he DrvUpgradePrinter() hook would be
8415 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8416 * server. Right now, we just need to send ourselves a message
8417 * to update each printer bound to this driver. --jerry
8420 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8421 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8422 fn, driver_name));
8425 done:
8426 return err;
8429 /****************************************************************
8430 _spoolss_AddPrinterDriver
8431 ****************************************************************/
8433 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8434 struct spoolss_AddPrinterDriver *r)
8436 struct spoolss_AddPrinterDriverEx a;
8438 switch (r->in.info_ctr->level) {
8439 case 2:
8440 case 3:
8441 case 4:
8442 case 5:
8443 break;
8444 default:
8445 return WERR_UNKNOWN_LEVEL;
8448 a.in.servername = r->in.servername;
8449 a.in.info_ctr = r->in.info_ctr;
8450 a.in.flags = APD_COPY_NEW_FILES;
8452 return _spoolss_AddPrinterDriverEx(p, &a);
8455 /****************************************************************************
8456 ****************************************************************************/
8458 struct _spoolss_paths {
8459 int type;
8460 const char *share;
8461 const char *dir;
8464 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8466 static const struct _spoolss_paths spoolss_paths[]= {
8467 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8468 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8471 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8472 const char *servername,
8473 const char *environment,
8474 int component,
8475 char **path)
8477 const char *pservername = NULL;
8478 const char *long_archi;
8479 const char *short_archi;
8481 *path = NULL;
8483 /* environment may be empty */
8484 if (environment && strlen(environment)) {
8485 long_archi = environment;
8486 } else {
8487 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8488 "spoolss", "architecture",
8489 SPOOLSS_ARCHITECTURE_NT_X86);
8492 /* servername may be empty */
8493 if (servername && strlen(servername)) {
8494 pservername = canon_servername(servername);
8496 if (!is_myname_or_ipaddr(pservername)) {
8497 return WERR_INVALID_PARAM;
8501 if (!(short_archi = get_short_archi(long_archi))) {
8502 return WERR_INVALID_ENVIRONMENT;
8505 switch (component) {
8506 case SPOOLSS_PRTPROCS_PATH:
8507 case SPOOLSS_DRIVER_PATH:
8508 if (pservername) {
8509 *path = talloc_asprintf(mem_ctx,
8510 "\\\\%s\\%s\\%s",
8511 pservername,
8512 spoolss_paths[component].share,
8513 short_archi);
8514 } else {
8515 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8516 SPOOLSS_DEFAULT_SERVER_PATH,
8517 spoolss_paths[component].dir,
8518 short_archi);
8520 break;
8521 default:
8522 return WERR_INVALID_PARAM;
8525 if (!*path) {
8526 return WERR_NOMEM;
8529 return WERR_OK;
8532 /****************************************************************************
8533 ****************************************************************************/
8535 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8536 const char *servername,
8537 const char *environment,
8538 struct spoolss_DriverDirectoryInfo1 *r)
8540 WERROR werr;
8541 char *path = NULL;
8543 werr = compose_spoolss_server_path(mem_ctx,
8544 servername,
8545 environment,
8546 SPOOLSS_DRIVER_PATH,
8547 &path);
8548 if (!W_ERROR_IS_OK(werr)) {
8549 return werr;
8552 DEBUG(4,("printer driver directory: [%s]\n", path));
8554 r->directory_name = path;
8556 return WERR_OK;
8559 /****************************************************************
8560 _spoolss_GetPrinterDriverDirectory
8561 ****************************************************************/
8563 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8564 struct spoolss_GetPrinterDriverDirectory *r)
8566 WERROR werror;
8568 /* that's an [in out] buffer */
8570 if (!r->in.buffer && (r->in.offered != 0)) {
8571 TALLOC_FREE(r->out.info);
8572 return WERR_INVALID_PARAM;
8575 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8576 r->in.level));
8578 *r->out.needed = 0;
8580 /* r->in.level is ignored */
8582 werror = getprinterdriverdir_level_1(p->mem_ctx,
8583 r->in.server,
8584 r->in.environment,
8585 &r->out.info->info1);
8586 if (!W_ERROR_IS_OK(werror)) {
8587 TALLOC_FREE(r->out.info);
8588 return werror;
8591 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8592 r->out.info, r->in.level);
8593 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8595 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8598 /****************************************************************
8599 _spoolss_EnumPrinterData
8600 ****************************************************************/
8602 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8603 struct spoolss_EnumPrinterData *r)
8605 WERROR result;
8606 struct spoolss_EnumPrinterDataEx r2;
8607 uint32_t count;
8608 struct spoolss_PrinterEnumValues *info, *val = NULL;
8609 uint32_t needed;
8611 r2.in.handle = r->in.handle;
8612 r2.in.key_name = "PrinterDriverData";
8613 r2.in.offered = 0;
8614 r2.out.count = &count;
8615 r2.out.info = &info;
8616 r2.out.needed = &needed;
8618 result = _spoolss_EnumPrinterDataEx(p, &r2);
8619 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8620 r2.in.offered = needed;
8621 result = _spoolss_EnumPrinterDataEx(p, &r2);
8623 if (!W_ERROR_IS_OK(result)) {
8624 return result;
8628 * The NT machine wants to know the biggest size of value and data
8630 * cf: MSDN EnumPrinterData remark section
8633 if (!r->in.value_offered && !r->in.data_offered) {
8634 uint32_t biggest_valuesize = 0;
8635 uint32_t biggest_datasize = 0;
8636 int i, name_length;
8638 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8640 for (i=0; i<count; i++) {
8642 name_length = strlen(info[i].value_name);
8643 if (strlen(info[i].value_name) > biggest_valuesize) {
8644 biggest_valuesize = name_length;
8647 if (info[i].data_length > biggest_datasize) {
8648 biggest_datasize = info[i].data_length;
8651 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8652 biggest_datasize));
8655 /* the value is an UNICODE string but real_value_size is the length
8656 in bytes including the trailing 0 */
8658 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8659 *r->out.data_needed = biggest_datasize;
8661 DEBUG(6,("final values: [%d], [%d]\n",
8662 *r->out.value_needed, *r->out.data_needed));
8664 return WERR_OK;
8667 if (r->in.enum_index < count) {
8668 val = &info[r->in.enum_index];
8671 if (val == NULL) {
8672 /* out_value should default to "" or else NT4 has
8673 problems unmarshalling the response */
8675 if (r->in.value_offered) {
8676 *r->out.value_needed = 1;
8677 r->out.value_name = talloc_strdup(r, "");
8678 if (!r->out.value_name) {
8679 return WERR_NOMEM;
8681 } else {
8682 r->out.value_name = NULL;
8683 *r->out.value_needed = 0;
8686 /* the data is counted in bytes */
8688 *r->out.data_needed = r->in.data_offered;
8690 result = WERR_NO_MORE_ITEMS;
8691 } else {
8693 * the value is:
8694 * - counted in bytes in the request
8695 * - counted in UNICODE chars in the max reply
8696 * - counted in bytes in the real size
8698 * take a pause *before* coding not *during* coding
8701 /* name */
8702 if (r->in.value_offered) {
8703 r->out.value_name = talloc_strdup(r, val->value_name);
8704 if (!r->out.value_name) {
8705 return WERR_NOMEM;
8707 *r->out.value_needed = val->value_name_len;
8708 } else {
8709 r->out.value_name = NULL;
8710 *r->out.value_needed = 0;
8713 /* type */
8715 *r->out.type = val->type;
8717 /* data - counted in bytes */
8720 * See the section "Dynamically Typed Query Parameters"
8721 * in MS-RPRN.
8724 if (r->out.data && val->data && val->data->data &&
8725 val->data_length && r->in.data_offered) {
8726 memcpy(r->out.data, val->data->data,
8727 MIN(val->data_length,r->in.data_offered));
8730 *r->out.data_needed = val->data_length;
8732 result = WERR_OK;
8735 return result;
8738 /****************************************************************
8739 _spoolss_SetPrinterData
8740 ****************************************************************/
8742 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8743 struct spoolss_SetPrinterData *r)
8745 struct spoolss_SetPrinterDataEx r2;
8747 r2.in.handle = r->in.handle;
8748 r2.in.key_name = "PrinterDriverData";
8749 r2.in.value_name = r->in.value_name;
8750 r2.in.type = r->in.type;
8751 r2.in.data = r->in.data;
8752 r2.in.offered = r->in.offered;
8754 return _spoolss_SetPrinterDataEx(p, &r2);
8757 /****************************************************************
8758 _spoolss_ResetPrinter
8759 ****************************************************************/
8761 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8762 struct spoolss_ResetPrinter *r)
8764 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8765 int snum;
8767 DEBUG(5,("_spoolss_ResetPrinter\n"));
8770 * All we do is to check to see if the handle and queue is valid.
8771 * This call really doesn't mean anything to us because we only
8772 * support RAW printing. --jerry
8775 if (!Printer) {
8776 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8777 OUR_HANDLE(r->in.handle)));
8778 return WERR_BADFID;
8781 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8782 return WERR_BADFID;
8785 /* blindly return success */
8786 return WERR_OK;
8789 /****************************************************************
8790 _spoolss_DeletePrinterData
8791 ****************************************************************/
8793 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8794 struct spoolss_DeletePrinterData *r)
8796 struct spoolss_DeletePrinterDataEx r2;
8798 r2.in.handle = r->in.handle;
8799 r2.in.key_name = "PrinterDriverData";
8800 r2.in.value_name = r->in.value_name;
8802 return _spoolss_DeletePrinterDataEx(p, &r2);
8805 /****************************************************************
8806 _spoolss_AddForm
8807 ****************************************************************/
8809 WERROR _spoolss_AddForm(struct pipes_struct *p,
8810 struct spoolss_AddForm *r)
8812 struct spoolss_AddFormInfo1 *form;
8813 int snum = -1;
8814 WERROR status = WERR_OK;
8815 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8816 struct dcerpc_binding_handle *b;
8817 TALLOC_CTX *tmp_ctx = NULL;
8819 DEBUG(5,("_spoolss_AddForm\n"));
8821 if (!Printer) {
8822 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8823 OUR_HANDLE(r->in.handle)));
8824 return WERR_BADFID;
8827 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8828 and not a printer admin, then fail */
8830 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8831 !security_token_has_privilege(p->session_info->security_token,
8832 SEC_PRIV_PRINT_OPERATOR)) {
8833 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8834 return WERR_ACCESS_DENIED;
8837 if (r->in.info_ctr->level != 1) {
8838 return WERR_INVALID_LEVEL;
8841 form = r->in.info_ctr->info.info1;
8842 if (!form) {
8843 return WERR_INVALID_PARAM;
8846 switch (form->flags) {
8847 case SPOOLSS_FORM_USER:
8848 case SPOOLSS_FORM_BUILTIN:
8849 case SPOOLSS_FORM_PRINTER:
8850 break;
8851 default:
8852 return WERR_INVALID_PARAM;
8855 tmp_ctx = talloc_new(p->mem_ctx);
8856 if (!tmp_ctx) {
8857 return WERR_NOMEM;
8860 status = winreg_printer_binding_handle(tmp_ctx,
8861 get_session_info_system(),
8862 p->msg_ctx,
8863 &b);
8864 if (!W_ERROR_IS_OK(status)) {
8865 goto done;
8868 status = winreg_printer_addform1(tmp_ctx, b, form);
8869 if (!W_ERROR_IS_OK(status)) {
8870 goto done;
8874 * ChangeID must always be set if this is a printer
8876 if (Printer->printer_type == SPLHND_PRINTER) {
8877 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8878 status = WERR_BADFID;
8879 goto done;
8882 status = winreg_printer_update_changeid(tmp_ctx, b,
8883 lp_const_servicename(snum));
8886 done:
8887 talloc_free(tmp_ctx);
8888 return status;
8891 /****************************************************************
8892 _spoolss_DeleteForm
8893 ****************************************************************/
8895 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8896 struct spoolss_DeleteForm *r)
8898 const char *form_name = r->in.form_name;
8899 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8900 int snum = -1;
8901 WERROR status = WERR_OK;
8902 struct dcerpc_binding_handle *b;
8903 TALLOC_CTX *tmp_ctx = NULL;
8905 DEBUG(5,("_spoolss_DeleteForm\n"));
8907 if (!Printer) {
8908 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8909 OUR_HANDLE(r->in.handle)));
8910 return WERR_BADFID;
8913 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8914 !security_token_has_privilege(p->session_info->security_token,
8915 SEC_PRIV_PRINT_OPERATOR)) {
8916 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8917 return WERR_ACCESS_DENIED;
8920 tmp_ctx = talloc_new(p->mem_ctx);
8921 if (!tmp_ctx) {
8922 return WERR_NOMEM;
8925 status = winreg_printer_binding_handle(tmp_ctx,
8926 get_session_info_system(),
8927 p->msg_ctx,
8928 &b);
8929 if (!W_ERROR_IS_OK(status)) {
8930 goto done;
8933 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8934 if (!W_ERROR_IS_OK(status)) {
8935 goto done;
8939 * ChangeID must always be set if this is a printer
8941 if (Printer->printer_type == SPLHND_PRINTER) {
8942 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8943 status = WERR_BADFID;
8944 goto done;
8947 status = winreg_printer_update_changeid(tmp_ctx, b,
8948 lp_const_servicename(snum));
8951 done:
8952 talloc_free(tmp_ctx);
8953 return status;
8956 /****************************************************************
8957 _spoolss_SetForm
8958 ****************************************************************/
8960 WERROR _spoolss_SetForm(struct pipes_struct *p,
8961 struct spoolss_SetForm *r)
8963 struct spoolss_AddFormInfo1 *form;
8964 const char *form_name = r->in.form_name;
8965 int snum = -1;
8966 WERROR status = WERR_OK;
8967 struct dcerpc_binding_handle *b;
8968 TALLOC_CTX *tmp_ctx = NULL;
8970 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8972 DEBUG(5,("_spoolss_SetForm\n"));
8974 if (!Printer) {
8975 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8976 OUR_HANDLE(r->in.handle)));
8977 return WERR_BADFID;
8980 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8981 and not a printer admin, then fail */
8983 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8984 !security_token_has_privilege(p->session_info->security_token,
8985 SEC_PRIV_PRINT_OPERATOR)) {
8986 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8987 return WERR_ACCESS_DENIED;
8990 if (r->in.info_ctr->level != 1) {
8991 return WERR_INVALID_LEVEL;
8994 form = r->in.info_ctr->info.info1;
8995 if (!form) {
8996 return WERR_INVALID_PARAM;
8999 tmp_ctx = talloc_new(p->mem_ctx);
9000 if (!tmp_ctx) {
9001 return WERR_NOMEM;
9004 status = winreg_printer_binding_handle(tmp_ctx,
9005 get_session_info_system(),
9006 p->msg_ctx,
9007 &b);
9008 if (!W_ERROR_IS_OK(status)) {
9009 goto done;
9012 status = winreg_printer_setform1(tmp_ctx, b,
9013 form_name,
9014 form);
9015 if (!W_ERROR_IS_OK(status)) {
9016 goto done;
9020 * ChangeID must always be set if this is a printer
9022 if (Printer->printer_type == SPLHND_PRINTER) {
9023 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9024 status = WERR_BADFID;
9025 goto done;
9028 status = winreg_printer_update_changeid(tmp_ctx, b,
9029 lp_const_servicename(snum));
9032 done:
9033 talloc_free(tmp_ctx);
9034 return status;
9037 /****************************************************************************
9038 fill_print_processor1
9039 ****************************************************************************/
9041 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9042 struct spoolss_PrintProcessorInfo1 *r,
9043 const char *print_processor_name)
9045 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9046 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9048 return WERR_OK;
9051 /****************************************************************************
9052 enumprintprocessors level 1.
9053 ****************************************************************************/
9055 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9056 union spoolss_PrintProcessorInfo **info_p,
9057 uint32_t *count)
9059 union spoolss_PrintProcessorInfo *info;
9060 WERROR result;
9062 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9063 W_ERROR_HAVE_NO_MEMORY(info);
9065 *count = 1;
9067 result = fill_print_processor1(info, &info[0].info1, "winprint");
9068 if (!W_ERROR_IS_OK(result)) {
9069 goto out;
9072 out:
9073 if (!W_ERROR_IS_OK(result)) {
9074 TALLOC_FREE(info);
9075 *count = 0;
9076 return result;
9079 *info_p = info;
9081 return WERR_OK;
9084 /****************************************************************
9085 _spoolss_EnumPrintProcessors
9086 ****************************************************************/
9088 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9089 struct spoolss_EnumPrintProcessors *r)
9091 WERROR result;
9093 /* that's an [in out] buffer */
9095 if (!r->in.buffer && (r->in.offered != 0)) {
9096 return WERR_INVALID_PARAM;
9099 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9102 * Enumerate the print processors ...
9104 * Just reply with "winprint", to keep NT happy
9105 * and I can use my nice printer checker.
9108 *r->out.count = 0;
9109 *r->out.needed = 0;
9110 *r->out.info = NULL;
9112 if (!get_short_archi(r->in.environment)) {
9113 return WERR_INVALID_ENVIRONMENT;
9116 switch (r->in.level) {
9117 case 1:
9118 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9119 r->out.count);
9120 break;
9121 default:
9122 return WERR_UNKNOWN_LEVEL;
9125 if (!W_ERROR_IS_OK(result)) {
9126 return result;
9129 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9130 spoolss_EnumPrintProcessors,
9131 *r->out.info, r->in.level,
9132 *r->out.count);
9133 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9134 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9136 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9139 /****************************************************************************
9140 fill_printprocdatatype1
9141 ****************************************************************************/
9143 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9144 struct spoolss_PrintProcDataTypesInfo1 *r,
9145 const char *name_array)
9147 r->name_array = talloc_strdup(mem_ctx, name_array);
9148 W_ERROR_HAVE_NO_MEMORY(r->name_array);
9150 return WERR_OK;
9153 /****************************************************************************
9154 enumprintprocdatatypes level 1.
9155 ****************************************************************************/
9157 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9158 union spoolss_PrintProcDataTypesInfo **info_p,
9159 uint32_t *count)
9161 WERROR result;
9162 union spoolss_PrintProcDataTypesInfo *info;
9164 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9165 W_ERROR_HAVE_NO_MEMORY(info);
9167 *count = 1;
9169 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9170 if (!W_ERROR_IS_OK(result)) {
9171 goto out;
9174 out:
9175 if (!W_ERROR_IS_OK(result)) {
9176 TALLOC_FREE(info);
9177 *count = 0;
9178 return result;
9181 *info_p = info;
9183 return WERR_OK;
9186 /****************************************************************
9187 _spoolss_EnumPrintProcDataTypes
9188 ****************************************************************/
9190 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9191 struct spoolss_EnumPrintProcDataTypes *r)
9193 WERROR result;
9195 /* that's an [in out] buffer */
9197 if (!r->in.buffer && (r->in.offered != 0)) {
9198 return WERR_INVALID_PARAM;
9201 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9203 *r->out.count = 0;
9204 *r->out.needed = 0;
9205 *r->out.info = NULL;
9207 if (r->in.print_processor_name == NULL ||
9208 !strequal(r->in.print_processor_name, "winprint")) {
9209 return WERR_UNKNOWN_PRINTPROCESSOR;
9212 switch (r->in.level) {
9213 case 1:
9214 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9215 r->out.count);
9216 break;
9217 default:
9218 return WERR_UNKNOWN_LEVEL;
9221 if (!W_ERROR_IS_OK(result)) {
9222 return result;
9225 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9226 spoolss_EnumPrintProcDataTypes,
9227 *r->out.info, r->in.level,
9228 *r->out.count);
9229 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9230 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9232 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9235 /****************************************************************************
9236 fill_monitor_1
9237 ****************************************************************************/
9239 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9240 struct spoolss_MonitorInfo1 *r,
9241 const char *monitor_name)
9243 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9244 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9246 return WERR_OK;
9249 /****************************************************************************
9250 fill_monitor_2
9251 ****************************************************************************/
9253 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9254 struct spoolss_MonitorInfo2 *r,
9255 const char *monitor_name,
9256 const char *environment,
9257 const char *dll_name)
9259 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9260 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9261 r->environment = talloc_strdup(mem_ctx, environment);
9262 W_ERROR_HAVE_NO_MEMORY(r->environment);
9263 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9264 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9266 return WERR_OK;
9269 /****************************************************************************
9270 enumprintmonitors level 1.
9271 ****************************************************************************/
9273 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9274 union spoolss_MonitorInfo **info_p,
9275 uint32_t *count)
9277 union spoolss_MonitorInfo *info;
9278 WERROR result = WERR_OK;
9280 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9281 W_ERROR_HAVE_NO_MEMORY(info);
9283 *count = 2;
9285 result = fill_monitor_1(info, &info[0].info1,
9286 SPL_LOCAL_PORT);
9287 if (!W_ERROR_IS_OK(result)) {
9288 goto out;
9291 result = fill_monitor_1(info, &info[1].info1,
9292 SPL_TCPIP_PORT);
9293 if (!W_ERROR_IS_OK(result)) {
9294 goto out;
9297 out:
9298 if (!W_ERROR_IS_OK(result)) {
9299 TALLOC_FREE(info);
9300 *count = 0;
9301 return result;
9304 *info_p = info;
9306 return WERR_OK;
9309 /****************************************************************************
9310 enumprintmonitors level 2.
9311 ****************************************************************************/
9313 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9314 union spoolss_MonitorInfo **info_p,
9315 uint32_t *count)
9317 union spoolss_MonitorInfo *info;
9318 WERROR result = WERR_OK;
9320 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9321 W_ERROR_HAVE_NO_MEMORY(info);
9323 *count = 2;
9325 result = fill_monitor_2(info, &info[0].info2,
9326 SPL_LOCAL_PORT,
9327 "Windows NT X86", /* FIXME */
9328 "localmon.dll");
9329 if (!W_ERROR_IS_OK(result)) {
9330 goto out;
9333 result = fill_monitor_2(info, &info[1].info2,
9334 SPL_TCPIP_PORT,
9335 "Windows NT X86", /* FIXME */
9336 "tcpmon.dll");
9337 if (!W_ERROR_IS_OK(result)) {
9338 goto out;
9341 out:
9342 if (!W_ERROR_IS_OK(result)) {
9343 TALLOC_FREE(info);
9344 *count = 0;
9345 return result;
9348 *info_p = info;
9350 return WERR_OK;
9353 /****************************************************************
9354 _spoolss_EnumMonitors
9355 ****************************************************************/
9357 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9358 struct spoolss_EnumMonitors *r)
9360 WERROR result;
9362 /* that's an [in out] buffer */
9364 if (!r->in.buffer && (r->in.offered != 0)) {
9365 return WERR_INVALID_PARAM;
9368 DEBUG(5,("_spoolss_EnumMonitors\n"));
9371 * Enumerate the print monitors ...
9373 * Just reply with "Local Port", to keep NT happy
9374 * and I can use my nice printer checker.
9377 *r->out.count = 0;
9378 *r->out.needed = 0;
9379 *r->out.info = NULL;
9381 switch (r->in.level) {
9382 case 1:
9383 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9384 r->out.count);
9385 break;
9386 case 2:
9387 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9388 r->out.count);
9389 break;
9390 default:
9391 return WERR_UNKNOWN_LEVEL;
9394 if (!W_ERROR_IS_OK(result)) {
9395 return result;
9398 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9399 spoolss_EnumMonitors,
9400 *r->out.info, r->in.level,
9401 *r->out.count);
9402 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9403 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9405 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9408 /****************************************************************************
9409 ****************************************************************************/
9411 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9412 const print_queue_struct *queue,
9413 int count, int snum,
9414 struct spoolss_PrinterInfo2 *pinfo2,
9415 uint32_t jobid,
9416 int sysjob,
9417 struct spoolss_JobInfo1 *r)
9419 int i = 0;
9420 bool found = false;
9422 for (i=0; i<count; i++) {
9423 if (queue[i].sysjob == sysjob) {
9424 found = true;
9425 break;
9429 if (found == false) {
9430 /* NT treats not found as bad param... yet another bad choice */
9431 return WERR_INVALID_PARAM;
9434 return fill_job_info1(mem_ctx,
9436 &queue[i],
9437 jobid,
9439 snum,
9440 pinfo2);
9443 /****************************************************************************
9444 ****************************************************************************/
9446 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9447 const print_queue_struct *queue,
9448 int count, int snum,
9449 struct spoolss_PrinterInfo2 *pinfo2,
9450 uint32_t jobid,
9451 int sysjob,
9452 struct spoolss_JobInfo2 *r)
9454 int i = 0;
9455 bool found = false;
9456 struct spoolss_DeviceMode *devmode;
9457 WERROR result;
9459 for (i=0; i<count; i++) {
9460 if (queue[i].sysjob == sysjob) {
9461 found = true;
9462 break;
9466 if (found == false) {
9467 /* NT treats not found as bad param... yet another bad
9468 choice */
9469 return WERR_INVALID_PARAM;
9473 * if the print job does not have a DEVMODE associated with it,
9474 * just use the one for the printer. A NULL devicemode is not
9475 * a failure condition
9478 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9479 if (!devmode) {
9480 result = spoolss_create_default_devmode(mem_ctx,
9481 pinfo2->printername,
9482 &devmode);
9483 if (!W_ERROR_IS_OK(result)) {
9484 DEBUG(3, ("Can't proceed w/o a devmode!"));
9485 return result;
9489 return fill_job_info2(mem_ctx,
9491 &queue[i],
9492 jobid,
9494 snum,
9495 pinfo2,
9496 devmode);
9499 /****************************************************************
9500 _spoolss_GetJob
9501 ****************************************************************/
9503 WERROR _spoolss_GetJob(struct pipes_struct *p,
9504 struct spoolss_GetJob *r)
9506 WERROR result = WERR_OK;
9507 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9508 const char *svc_name;
9509 int sysjob;
9510 int snum;
9511 int count;
9512 struct tdb_print_db *pdb;
9513 print_queue_struct *queue = NULL;
9514 print_status_struct prt_status;
9516 /* that's an [in out] buffer */
9518 if (!r->in.buffer && (r->in.offered != 0)) {
9519 result = WERR_INVALID_PARAM;
9520 goto err_jinfo_free;
9523 DEBUG(5,("_spoolss_GetJob\n"));
9525 *r->out.needed = 0;
9527 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9528 result = WERR_BADFID;
9529 goto err_jinfo_free;
9532 svc_name = lp_const_servicename(snum);
9533 if (svc_name == NULL) {
9534 result = WERR_INVALID_PARAM;
9535 goto err_jinfo_free;
9538 result = winreg_get_printer_internal(p->mem_ctx,
9539 get_session_info_system(),
9540 p->msg_ctx,
9541 svc_name,
9542 &pinfo2);
9543 if (!W_ERROR_IS_OK(result)) {
9544 goto err_jinfo_free;
9547 pdb = get_print_db_byname(svc_name);
9548 if (pdb == NULL) {
9549 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9550 result = WERR_INVALID_PARAM;
9551 goto err_pinfo_free;
9554 sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9555 release_print_db(pdb);
9556 if (sysjob == -1) {
9557 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9558 result = WERR_INVALID_PARAM;
9559 goto err_pinfo_free;
9562 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9564 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9565 count, prt_status.status, prt_status.message));
9567 switch (r->in.level) {
9568 case 1:
9569 result = getjob_level_1(p->mem_ctx,
9570 queue, count, snum, pinfo2,
9571 r->in.job_id, sysjob,
9572 &r->out.info->info1);
9573 break;
9574 case 2:
9575 result = getjob_level_2(p->mem_ctx,
9576 queue, count, snum, pinfo2,
9577 r->in.job_id, sysjob,
9578 &r->out.info->info2);
9579 break;
9580 default:
9581 result = WERR_UNKNOWN_LEVEL;
9582 break;
9585 SAFE_FREE(queue);
9586 TALLOC_FREE(pinfo2);
9588 if (!W_ERROR_IS_OK(result)) {
9589 goto err_jinfo_free;
9592 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9593 r->in.level);
9594 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9596 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9598 err_pinfo_free:
9599 TALLOC_FREE(pinfo2);
9600 err_jinfo_free:
9601 TALLOC_FREE(r->out.info);
9602 return result;
9605 /****************************************************************
9606 _spoolss_GetPrinterDataEx
9607 ****************************************************************/
9609 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9610 struct spoolss_GetPrinterDataEx *r)
9613 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9614 const char *printer;
9615 int snum = 0;
9616 WERROR result = WERR_OK;
9617 DATA_BLOB blob;
9618 enum winreg_Type val_type = REG_NONE;
9619 uint8_t *val_data = NULL;
9620 uint32_t val_size = 0;
9621 struct dcerpc_binding_handle *b;
9622 TALLOC_CTX *tmp_ctx;
9624 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9626 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9627 r->in.key_name, r->in.value_name));
9629 /* in case of problem, return some default values */
9631 *r->out.needed = 0;
9632 *r->out.type = REG_NONE;
9634 tmp_ctx = talloc_new(p->mem_ctx);
9635 if (!tmp_ctx) {
9636 return WERR_NOMEM;
9639 if (!Printer) {
9640 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9641 OUR_HANDLE(r->in.handle)));
9642 result = WERR_BADFID;
9643 goto done;
9646 /* check to see if the keyname is valid */
9647 if (!strlen(r->in.key_name)) {
9648 result = WERR_INVALID_PARAM;
9649 goto done;
9652 /* Is the handle to a printer or to the server? */
9654 if (Printer->printer_type == SPLHND_SERVER) {
9656 union spoolss_PrinterData data;
9658 result = getprinterdata_printer_server(tmp_ctx,
9659 r->in.value_name,
9660 r->out.type,
9661 &data);
9662 if (!W_ERROR_IS_OK(result)) {
9663 goto done;
9666 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9667 *r->out.type, &data);
9668 if (!W_ERROR_IS_OK(result)) {
9669 goto done;
9672 *r->out.needed = blob.length;
9674 if (r->in.offered >= *r->out.needed) {
9675 memcpy(r->out.data, blob.data, blob.length);
9678 result = WERR_OK;
9679 goto done;
9682 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9683 result = WERR_BADFID;
9684 goto done;
9686 printer = lp_const_servicename(snum);
9688 result = winreg_printer_binding_handle(tmp_ctx,
9689 get_session_info_system(),
9690 p->msg_ctx,
9691 &b);
9692 if (!W_ERROR_IS_OK(result)) {
9693 goto done;
9696 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9697 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9698 strequal(r->in.value_name, "ChangeId")) {
9699 *r->out.type = REG_DWORD;
9700 *r->out.needed = 4;
9701 if (r->in.offered >= *r->out.needed) {
9702 uint32_t changeid = 0;
9704 result = winreg_printer_get_changeid(tmp_ctx, b,
9705 printer,
9706 &changeid);
9707 if (!W_ERROR_IS_OK(result)) {
9708 goto done;
9711 SIVAL(r->out.data, 0, changeid);
9712 result = WERR_OK;
9714 goto done;
9717 result = winreg_get_printer_dataex(tmp_ctx, b,
9718 printer,
9719 r->in.key_name,
9720 r->in.value_name,
9721 &val_type,
9722 &val_data,
9723 &val_size);
9724 if (!W_ERROR_IS_OK(result)) {
9725 goto done;
9728 *r->out.needed = val_size;
9729 *r->out.type = val_type;
9731 if (r->in.offered >= *r->out.needed) {
9732 memcpy(r->out.data, val_data, val_size);
9735 done:
9736 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9738 if (W_ERROR_IS_OK(result)) {
9739 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9742 talloc_free(tmp_ctx);
9743 return result;
9746 /****************************************************************
9747 _spoolss_SetPrinterDataEx
9748 ****************************************************************/
9750 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9751 struct spoolss_SetPrinterDataEx *r)
9753 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9754 int snum = 0;
9755 WERROR result = WERR_OK;
9756 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9757 char *oid_string;
9758 struct dcerpc_binding_handle *b;
9759 TALLOC_CTX *tmp_ctx;
9761 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9763 /* From MSDN documentation of SetPrinterDataEx: pass request to
9764 SetPrinterData if key is "PrinterDriverData" */
9766 if (!Printer) {
9767 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9768 OUR_HANDLE(r->in.handle)));
9769 return WERR_BADFID;
9772 if (Printer->printer_type == SPLHND_SERVER) {
9773 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9774 "Not implemented for server handles yet\n"));
9775 return WERR_INVALID_PARAM;
9778 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9779 return WERR_BADFID;
9783 * Access check : NT returns "access denied" if you make a
9784 * SetPrinterData call without the necessary privildge.
9785 * we were originally returning OK if nothing changed
9786 * which made Win2k issue **a lot** of SetPrinterData
9787 * when connecting to a printer --jerry
9790 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9791 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9792 "change denied by handle access permissions\n"));
9793 return WERR_ACCESS_DENIED;
9796 tmp_ctx = talloc_new(p->mem_ctx);
9797 if (!tmp_ctx) {
9798 return WERR_NOMEM;
9801 result = winreg_printer_binding_handle(tmp_ctx,
9802 get_session_info_system(),
9803 p->msg_ctx,
9804 &b);
9805 if (!W_ERROR_IS_OK(result)) {
9806 goto done;
9809 result = winreg_get_printer(tmp_ctx, b,
9810 lp_servicename(talloc_tos(), snum),
9811 &pinfo2);
9812 if (!W_ERROR_IS_OK(result)) {
9813 goto done;
9816 /* check for OID in valuename */
9818 oid_string = strchr(r->in.value_name, ',');
9819 if (oid_string) {
9820 *oid_string = '\0';
9821 oid_string++;
9824 /* save the registry data */
9826 result = winreg_set_printer_dataex(tmp_ctx, b,
9827 pinfo2->sharename,
9828 r->in.key_name,
9829 r->in.value_name,
9830 r->in.type,
9831 r->in.data,
9832 r->in.offered);
9834 if (W_ERROR_IS_OK(result)) {
9835 /* save the OID if one was specified */
9836 if (oid_string) {
9837 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9838 r->in.key_name, SPOOL_OID_KEY);
9839 if (!str) {
9840 result = WERR_NOMEM;
9841 goto done;
9845 * I'm not checking the status here on purpose. Don't know
9846 * if this is right, but I'm returning the status from the
9847 * previous set_printer_dataex() call. I have no idea if
9848 * this is right. --jerry
9850 winreg_set_printer_dataex(tmp_ctx, b,
9851 pinfo2->sharename,
9852 str,
9853 r->in.value_name,
9854 REG_SZ,
9855 (uint8_t *) oid_string,
9856 strlen(oid_string) + 1);
9859 result = winreg_printer_update_changeid(tmp_ctx, b,
9860 lp_const_servicename(snum));
9864 done:
9865 talloc_free(tmp_ctx);
9866 return result;
9869 /****************************************************************
9870 _spoolss_DeletePrinterDataEx
9871 ****************************************************************/
9873 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9874 struct spoolss_DeletePrinterDataEx *r)
9876 const char *printer;
9877 int snum=0;
9878 WERROR status = WERR_OK;
9879 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9881 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9883 if (!Printer) {
9884 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9885 "Invalid handle (%s:%u:%u).\n",
9886 OUR_HANDLE(r->in.handle)));
9887 return WERR_BADFID;
9890 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9891 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9892 "printer properties change denied by handle\n"));
9893 return WERR_ACCESS_DENIED;
9896 if (!r->in.value_name || !r->in.key_name) {
9897 return WERR_NOMEM;
9900 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9901 return WERR_BADFID;
9903 printer = lp_const_servicename(snum);
9905 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9906 get_session_info_system(),
9907 p->msg_ctx,
9908 printer,
9909 r->in.key_name,
9910 r->in.value_name);
9911 if (W_ERROR_IS_OK(status)) {
9912 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9913 get_session_info_system(),
9914 p->msg_ctx,
9915 printer);
9918 return status;
9921 /****************************************************************
9922 _spoolss_EnumPrinterKey
9923 ****************************************************************/
9925 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9926 struct spoolss_EnumPrinterKey *r)
9928 uint32_t num_keys;
9929 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9930 int snum = 0;
9931 WERROR result = WERR_BADFILE;
9932 const char **array = NULL;
9933 DATA_BLOB blob;
9935 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9937 if (!Printer) {
9938 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9939 OUR_HANDLE(r->in.handle)));
9940 return WERR_BADFID;
9943 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9944 return WERR_BADFID;
9947 result = winreg_enum_printer_key_internal(p->mem_ctx,
9948 get_session_info_system(),
9949 p->msg_ctx,
9950 lp_const_servicename(snum),
9951 r->in.key_name,
9952 &num_keys,
9953 &array);
9954 if (!W_ERROR_IS_OK(result)) {
9955 goto done;
9958 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9959 result = WERR_NOMEM;
9960 goto done;
9963 *r->out._ndr_size = r->in.offered / 2;
9964 *r->out.needed = blob.length;
9966 if (r->in.offered < *r->out.needed) {
9967 result = WERR_MORE_DATA;
9968 } else {
9969 result = WERR_OK;
9970 r->out.key_buffer->string_array = array;
9973 done:
9974 if (!W_ERROR_IS_OK(result)) {
9975 TALLOC_FREE(array);
9976 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9977 *r->out.needed = 0;
9981 return result;
9984 /****************************************************************
9985 _spoolss_DeletePrinterKey
9986 ****************************************************************/
9988 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9989 struct spoolss_DeletePrinterKey *r)
9991 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9992 int snum=0;
9993 WERROR status;
9994 const char *printer;
9995 struct dcerpc_binding_handle *b;
9996 TALLOC_CTX *tmp_ctx;
9998 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10000 if (!Printer) {
10001 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10002 OUR_HANDLE(r->in.handle)));
10003 return WERR_BADFID;
10006 /* if keyname == NULL, return error */
10007 if ( !r->in.key_name )
10008 return WERR_INVALID_PARAM;
10010 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10011 return WERR_BADFID;
10014 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10015 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10016 "printer properties change denied by handle\n"));
10017 return WERR_ACCESS_DENIED;
10020 printer = lp_const_servicename(snum);
10022 tmp_ctx = talloc_new(p->mem_ctx);
10023 if (!tmp_ctx) {
10024 return WERR_NOMEM;
10027 status = winreg_printer_binding_handle(tmp_ctx,
10028 get_session_info_system(),
10029 p->msg_ctx,
10030 &b);
10031 if (!W_ERROR_IS_OK(status)) {
10032 goto done;
10035 /* delete the key and all subkeys */
10036 status = winreg_delete_printer_key(tmp_ctx, b,
10037 printer,
10038 r->in.key_name);
10039 if (W_ERROR_IS_OK(status)) {
10040 status = winreg_printer_update_changeid(tmp_ctx, b,
10041 printer);
10044 done:
10045 talloc_free(tmp_ctx);
10046 return status;
10049 /****************************************************************
10050 _spoolss_EnumPrinterDataEx
10051 ****************************************************************/
10053 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10054 struct spoolss_EnumPrinterDataEx *r)
10056 uint32_t count = 0;
10057 struct spoolss_PrinterEnumValues *info = NULL;
10058 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10059 int snum;
10060 WERROR result;
10062 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10064 *r->out.count = 0;
10065 *r->out.needed = 0;
10066 *r->out.info = NULL;
10068 if (!Printer) {
10069 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10070 OUR_HANDLE(r->in.handle)));
10071 return WERR_BADFID;
10075 * first check for a keyname of NULL or "". Win2k seems to send
10076 * this a lot and we should send back WERR_INVALID_PARAM
10077 * no need to spend time looking up the printer in this case.
10078 * --jerry
10081 if (!strlen(r->in.key_name)) {
10082 result = WERR_INVALID_PARAM;
10083 goto done;
10086 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10087 return WERR_BADFID;
10090 /* now look for a match on the key name */
10091 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10092 get_session_info_system(),
10093 p->msg_ctx,
10094 lp_const_servicename(snum),
10095 r->in.key_name,
10096 &count,
10097 &info);
10098 if (!W_ERROR_IS_OK(result)) {
10099 goto done;
10102 #if 0 /* FIXME - gd */
10103 /* housekeeping information in the reply */
10105 /* Fix from Martin Zielinski <mz@seh.de> - ensure
10106 * the hand marshalled container size is a multiple
10107 * of 4 bytes for RPC alignment.
10110 if (needed % 4) {
10111 needed += 4-(needed % 4);
10113 #endif
10114 *r->out.count = count;
10115 *r->out.info = info;
10117 done:
10118 if (!W_ERROR_IS_OK(result)) {
10119 return result;
10122 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10123 spoolss_EnumPrinterDataEx,
10124 *r->out.info,
10125 *r->out.count);
10126 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10127 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10129 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10132 /****************************************************************************
10133 ****************************************************************************/
10135 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10136 const char *servername,
10137 const char *environment,
10138 struct spoolss_PrintProcessorDirectoryInfo1 *r)
10140 WERROR werr;
10141 char *path = NULL;
10143 werr = compose_spoolss_server_path(mem_ctx,
10144 servername,
10145 environment,
10146 SPOOLSS_PRTPROCS_PATH,
10147 &path);
10148 if (!W_ERROR_IS_OK(werr)) {
10149 return werr;
10152 DEBUG(4,("print processor directory: [%s]\n", path));
10154 r->directory_name = path;
10156 return WERR_OK;
10159 /****************************************************************
10160 _spoolss_GetPrintProcessorDirectory
10161 ****************************************************************/
10163 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10164 struct spoolss_GetPrintProcessorDirectory *r)
10166 WERROR result;
10167 char *prnproc_share = NULL;
10168 bool prnproc_share_exists = false;
10169 int snum;
10171 /* that's an [in out] buffer */
10173 if (!r->in.buffer && (r->in.offered != 0)) {
10174 result = WERR_INVALID_PARAM;
10175 goto err_info_free;
10178 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10179 r->in.level));
10181 *r->out.needed = 0;
10183 /* r->in.level is ignored */
10185 /* We always should reply with a local print processor directory so that
10186 * users are not forced to have a [prnproc$] share on the Samba spoolss
10187 * server, if users decide to do so, lets announce it though - Guenther */
10189 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10190 if (!prnproc_share) {
10191 result = WERR_NOMEM;
10192 goto err_info_free;
10194 if (snum != -1) {
10195 prnproc_share_exists = true;
10198 result = getprintprocessordirectory_level_1(p->mem_ctx,
10199 prnproc_share_exists ? r->in.server : NULL,
10200 r->in.environment,
10201 &r->out.info->info1);
10202 if (!W_ERROR_IS_OK(result)) {
10203 goto err_info_free;
10206 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10207 r->out.info, r->in.level);
10208 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10210 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10212 err_info_free:
10213 TALLOC_FREE(r->out.info);
10214 return result;
10217 /*******************************************************************
10218 ********************************************************************/
10220 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10221 const char *dllname)
10223 enum ndr_err_code ndr_err;
10224 struct spoolss_MonitorUi ui;
10226 ui.dll_name = dllname;
10228 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10229 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10230 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10231 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10233 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10236 /*******************************************************************
10237 Streams the monitor UI DLL name in UNICODE
10238 *******************************************************************/
10240 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10241 struct security_token *token, DATA_BLOB *in,
10242 DATA_BLOB *out, uint32_t *needed)
10244 const char *dllname = "tcpmonui.dll";
10246 *needed = (strlen(dllname)+1) * 2;
10248 if (out->length < *needed) {
10249 return WERR_INSUFFICIENT_BUFFER;
10252 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10253 return WERR_NOMEM;
10256 return WERR_OK;
10259 /*******************************************************************
10260 ********************************************************************/
10262 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10263 struct spoolss_PortData1 *port1,
10264 const DATA_BLOB *buf)
10266 enum ndr_err_code ndr_err;
10267 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10268 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10269 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10270 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10272 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10275 /*******************************************************************
10276 ********************************************************************/
10278 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10279 struct spoolss_PortData2 *port2,
10280 const DATA_BLOB *buf)
10282 enum ndr_err_code ndr_err;
10283 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10284 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10285 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10286 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10288 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10291 /*******************************************************************
10292 Create a new TCP/IP port
10293 *******************************************************************/
10295 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10296 struct security_token *token, DATA_BLOB *in,
10297 DATA_BLOB *out, uint32_t *needed)
10299 struct spoolss_PortData1 port1;
10300 struct spoolss_PortData2 port2;
10301 char *device_uri = NULL;
10302 uint32_t version;
10304 const char *portname;
10305 const char *hostaddress;
10306 const char *queue;
10307 uint32_t port_number;
10308 uint32_t protocol;
10310 /* peek for spoolss_PortData version */
10312 if (!in || (in->length < (128 + 4))) {
10313 return WERR_GENERAL_FAILURE;
10316 version = IVAL(in->data, 128);
10318 switch (version) {
10319 case 1:
10320 ZERO_STRUCT(port1);
10322 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10323 return WERR_NOMEM;
10326 portname = port1.portname;
10327 hostaddress = port1.hostaddress;
10328 queue = port1.queue;
10329 protocol = port1.protocol;
10330 port_number = port1.port_number;
10332 break;
10333 case 2:
10334 ZERO_STRUCT(port2);
10336 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10337 return WERR_NOMEM;
10340 portname = port2.portname;
10341 hostaddress = port2.hostaddress;
10342 queue = port2.queue;
10343 protocol = port2.protocol;
10344 port_number = port2.port_number;
10346 break;
10347 default:
10348 DEBUG(1,("xcvtcp_addport: "
10349 "unknown version of port_data: %d\n", version));
10350 return WERR_UNKNOWN_PORT;
10353 /* create the device URI and call the add_port_hook() */
10355 switch (protocol) {
10356 case PROTOCOL_RAWTCP_TYPE:
10357 device_uri = talloc_asprintf(mem_ctx,
10358 "socket://%s:%d/", hostaddress,
10359 port_number);
10360 break;
10362 case PROTOCOL_LPR_TYPE:
10363 device_uri = talloc_asprintf(mem_ctx,
10364 "lpr://%s/%s", hostaddress, queue );
10365 break;
10367 default:
10368 return WERR_UNKNOWN_PORT;
10371 if (!device_uri) {
10372 return WERR_NOMEM;
10375 return add_port_hook(mem_ctx, token, portname, device_uri);
10378 /*******************************************************************
10379 *******************************************************************/
10381 struct xcv_api_table xcvtcp_cmds[] = {
10382 { "MonitorUI", xcvtcp_monitorui },
10383 { "AddPort", xcvtcp_addport},
10384 { NULL, NULL }
10387 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10388 struct security_token *token, const char *command,
10389 DATA_BLOB *inbuf,
10390 DATA_BLOB *outbuf,
10391 uint32_t *needed )
10393 int i;
10395 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10397 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10398 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10399 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10402 return WERR_BADFUNC;
10405 /*******************************************************************
10406 *******************************************************************/
10407 #if 0 /* don't support management using the "Local Port" monitor */
10409 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10410 struct security_token *token, DATA_BLOB *in,
10411 DATA_BLOB *out, uint32_t *needed)
10413 const char *dllname = "localui.dll";
10415 *needed = (strlen(dllname)+1) * 2;
10417 if (out->length < *needed) {
10418 return WERR_INSUFFICIENT_BUFFER;
10421 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10422 return WERR_NOMEM;
10425 return WERR_OK;
10428 /*******************************************************************
10429 *******************************************************************/
10431 struct xcv_api_table xcvlocal_cmds[] = {
10432 { "MonitorUI", xcvlocal_monitorui },
10433 { NULL, NULL }
10435 #else
10436 struct xcv_api_table xcvlocal_cmds[] = {
10437 { NULL, NULL }
10439 #endif
10443 /*******************************************************************
10444 *******************************************************************/
10446 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10447 struct security_token *token, const char *command,
10448 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10449 uint32_t *needed)
10451 int i;
10453 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10455 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10456 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10457 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10459 return WERR_BADFUNC;
10462 /****************************************************************
10463 _spoolss_XcvData
10464 ****************************************************************/
10466 WERROR _spoolss_XcvData(struct pipes_struct *p,
10467 struct spoolss_XcvData *r)
10469 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10470 DATA_BLOB out_data = data_blob_null;
10471 WERROR werror;
10473 if (!Printer) {
10474 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10475 OUR_HANDLE(r->in.handle)));
10476 return WERR_BADFID;
10479 /* Has to be a handle to the TCP/IP port monitor */
10481 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10482 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10483 return WERR_BADFID;
10486 /* requires administrative access to the server */
10488 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10489 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10490 return WERR_ACCESS_DENIED;
10493 /* Allocate the outgoing buffer */
10495 if (r->in.out_data_size) {
10496 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10497 if (out_data.data == NULL) {
10498 return WERR_NOMEM;
10502 switch ( Printer->printer_type ) {
10503 case SPLHND_PORTMON_TCP:
10504 werror = process_xcvtcp_command(p->mem_ctx,
10505 p->session_info->security_token,
10506 r->in.function_name,
10507 &r->in.in_data, &out_data,
10508 r->out.needed);
10509 break;
10510 case SPLHND_PORTMON_LOCAL:
10511 werror = process_xcvlocal_command(p->mem_ctx,
10512 p->session_info->security_token,
10513 r->in.function_name,
10514 &r->in.in_data, &out_data,
10515 r->out.needed);
10516 break;
10517 default:
10518 werror = WERR_INVALID_PRINT_MONITOR;
10521 if (!W_ERROR_IS_OK(werror)) {
10522 return werror;
10525 *r->out.status_code = 0;
10527 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10528 memcpy(r->out.out_data, out_data.data,
10529 MIN(r->in.out_data_size, out_data.length));
10532 return WERR_OK;
10535 /****************************************************************
10536 _spoolss_AddPrintProcessor
10537 ****************************************************************/
10539 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10540 struct spoolss_AddPrintProcessor *r)
10542 /* for now, just indicate success and ignore the add. We'll
10543 automatically set the winprint processor for printer
10544 entries later. Used to debug the LexMark Optra S 1855 PCL
10545 driver --jerry */
10547 return WERR_OK;
10550 /****************************************************************
10551 _spoolss_AddPort
10552 ****************************************************************/
10554 WERROR _spoolss_AddPort(struct pipes_struct *p,
10555 struct spoolss_AddPort *r)
10557 /* do what w2k3 does */
10559 return WERR_NOT_SUPPORTED;
10562 /****************************************************************
10563 _spoolss_GetPrinterDriver
10564 ****************************************************************/
10566 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10567 struct spoolss_GetPrinterDriver *r)
10569 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10570 return WERR_NOT_SUPPORTED;
10573 /****************************************************************
10574 _spoolss_ReadPrinter
10575 ****************************************************************/
10577 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10578 struct spoolss_ReadPrinter *r)
10580 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10581 return WERR_NOT_SUPPORTED;
10584 /****************************************************************
10585 _spoolss_WaitForPrinterChange
10586 ****************************************************************/
10588 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10589 struct spoolss_WaitForPrinterChange *r)
10591 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10592 return WERR_NOT_SUPPORTED;
10595 /****************************************************************
10596 _spoolss_ConfigurePort
10597 ****************************************************************/
10599 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10600 struct spoolss_ConfigurePort *r)
10602 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10603 return WERR_NOT_SUPPORTED;
10606 /****************************************************************
10607 _spoolss_DeletePort
10608 ****************************************************************/
10610 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10611 struct spoolss_DeletePort *r)
10613 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10614 return WERR_NOT_SUPPORTED;
10617 /****************************************************************
10618 _spoolss_CreatePrinterIC
10619 ****************************************************************/
10621 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10622 struct spoolss_CreatePrinterIC *r)
10624 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10625 return WERR_NOT_SUPPORTED;
10628 /****************************************************************
10629 _spoolss_PlayGDIScriptOnPrinterIC
10630 ****************************************************************/
10632 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10633 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10635 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10636 return WERR_NOT_SUPPORTED;
10639 /****************************************************************
10640 _spoolss_DeletePrinterIC
10641 ****************************************************************/
10643 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10644 struct spoolss_DeletePrinterIC *r)
10646 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10647 return WERR_NOT_SUPPORTED;
10650 /****************************************************************
10651 _spoolss_AddPrinterConnection
10652 ****************************************************************/
10654 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10655 struct spoolss_AddPrinterConnection *r)
10657 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10658 return WERR_NOT_SUPPORTED;
10661 /****************************************************************
10662 _spoolss_DeletePrinterConnection
10663 ****************************************************************/
10665 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10666 struct spoolss_DeletePrinterConnection *r)
10668 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10669 return WERR_NOT_SUPPORTED;
10672 /****************************************************************
10673 _spoolss_PrinterMessageBox
10674 ****************************************************************/
10676 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10677 struct spoolss_PrinterMessageBox *r)
10679 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10680 return WERR_NOT_SUPPORTED;
10683 /****************************************************************
10684 _spoolss_AddMonitor
10685 ****************************************************************/
10687 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10688 struct spoolss_AddMonitor *r)
10690 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10691 return WERR_NOT_SUPPORTED;
10694 /****************************************************************
10695 _spoolss_DeleteMonitor
10696 ****************************************************************/
10698 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10699 struct spoolss_DeleteMonitor *r)
10701 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10702 return WERR_NOT_SUPPORTED;
10705 /****************************************************************
10706 _spoolss_DeletePrintProcessor
10707 ****************************************************************/
10709 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10710 struct spoolss_DeletePrintProcessor *r)
10712 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10713 return WERR_NOT_SUPPORTED;
10716 /****************************************************************
10717 _spoolss_AddPrintProvidor
10718 ****************************************************************/
10720 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10721 struct spoolss_AddPrintProvidor *r)
10723 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10724 return WERR_NOT_SUPPORTED;
10727 /****************************************************************
10728 _spoolss_DeletePrintProvidor
10729 ****************************************************************/
10731 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10732 struct spoolss_DeletePrintProvidor *r)
10734 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10735 return WERR_NOT_SUPPORTED;
10738 /****************************************************************
10739 _spoolss_FindFirstPrinterChangeNotification
10740 ****************************************************************/
10742 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10743 struct spoolss_FindFirstPrinterChangeNotification *r)
10745 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10746 return WERR_NOT_SUPPORTED;
10749 /****************************************************************
10750 _spoolss_FindNextPrinterChangeNotification
10751 ****************************************************************/
10753 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10754 struct spoolss_FindNextPrinterChangeNotification *r)
10756 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10757 return WERR_NOT_SUPPORTED;
10760 /****************************************************************
10761 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10762 ****************************************************************/
10764 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10765 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10767 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10768 return WERR_NOT_SUPPORTED;
10771 /****************************************************************
10772 _spoolss_ReplyOpenPrinter
10773 ****************************************************************/
10775 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10776 struct spoolss_ReplyOpenPrinter *r)
10778 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10779 return WERR_NOT_SUPPORTED;
10782 /****************************************************************
10783 _spoolss_RouterReplyPrinter
10784 ****************************************************************/
10786 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10787 struct spoolss_RouterReplyPrinter *r)
10789 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10790 return WERR_NOT_SUPPORTED;
10793 /****************************************************************
10794 _spoolss_ReplyClosePrinter
10795 ****************************************************************/
10797 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10798 struct spoolss_ReplyClosePrinter *r)
10800 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10801 return WERR_NOT_SUPPORTED;
10804 /****************************************************************
10805 _spoolss_AddPortEx
10806 ****************************************************************/
10808 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10809 struct spoolss_AddPortEx *r)
10811 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10812 return WERR_NOT_SUPPORTED;
10815 /****************************************************************
10816 _spoolss_RouterFindFirstPrinterChangeNotification
10817 ****************************************************************/
10819 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10820 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10822 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10823 return WERR_NOT_SUPPORTED;
10826 /****************************************************************
10827 _spoolss_SpoolerInit
10828 ****************************************************************/
10830 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10831 struct spoolss_SpoolerInit *r)
10833 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10834 return WERR_NOT_SUPPORTED;
10837 /****************************************************************
10838 _spoolss_ResetPrinterEx
10839 ****************************************************************/
10841 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10842 struct spoolss_ResetPrinterEx *r)
10844 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10845 return WERR_NOT_SUPPORTED;
10848 /****************************************************************
10849 _spoolss_RouterReplyPrinterEx
10850 ****************************************************************/
10852 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10853 struct spoolss_RouterReplyPrinterEx *r)
10855 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10856 return WERR_NOT_SUPPORTED;
10859 /****************************************************************
10860 _spoolss_44
10861 ****************************************************************/
10863 WERROR _spoolss_44(struct pipes_struct *p,
10864 struct spoolss_44 *r)
10866 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10867 return WERR_NOT_SUPPORTED;
10870 /****************************************************************
10871 _spoolss_SetPort
10872 ****************************************************************/
10874 WERROR _spoolss_SetPort(struct pipes_struct *p,
10875 struct spoolss_SetPort *r)
10877 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10878 return WERR_NOT_SUPPORTED;
10881 /****************************************************************
10882 _spoolss_4a
10883 ****************************************************************/
10885 WERROR _spoolss_4a(struct pipes_struct *p,
10886 struct spoolss_4a *r)
10888 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10889 return WERR_NOT_SUPPORTED;
10892 /****************************************************************
10893 _spoolss_4b
10894 ****************************************************************/
10896 WERROR _spoolss_4b(struct pipes_struct *p,
10897 struct spoolss_4b *r)
10899 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10900 return WERR_NOT_SUPPORTED;
10903 /****************************************************************
10904 _spoolss_4c
10905 ****************************************************************/
10907 WERROR _spoolss_4c(struct pipes_struct *p,
10908 struct spoolss_4c *r)
10910 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10911 return WERR_NOT_SUPPORTED;
10914 /****************************************************************
10915 _spoolss_53
10916 ****************************************************************/
10918 WERROR _spoolss_53(struct pipes_struct *p,
10919 struct spoolss_53 *r)
10921 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10922 return WERR_NOT_SUPPORTED;
10925 /****************************************************************
10926 _spoolss_AddPerMachineConnection
10927 ****************************************************************/
10929 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10930 struct spoolss_AddPerMachineConnection *r)
10932 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10933 return WERR_NOT_SUPPORTED;
10936 /****************************************************************
10937 _spoolss_DeletePerMachineConnection
10938 ****************************************************************/
10940 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10941 struct spoolss_DeletePerMachineConnection *r)
10943 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10944 return WERR_NOT_SUPPORTED;
10947 /****************************************************************
10948 _spoolss_EnumPerMachineConnections
10949 ****************************************************************/
10951 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10952 struct spoolss_EnumPerMachineConnections *r)
10954 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10955 return WERR_NOT_SUPPORTED;
10958 /****************************************************************
10959 _spoolss_5a
10960 ****************************************************************/
10962 WERROR _spoolss_5a(struct pipes_struct *p,
10963 struct spoolss_5a *r)
10965 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10966 return WERR_NOT_SUPPORTED;
10969 /****************************************************************
10970 _spoolss_5b
10971 ****************************************************************/
10973 WERROR _spoolss_5b(struct pipes_struct *p,
10974 struct spoolss_5b *r)
10976 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10977 return WERR_NOT_SUPPORTED;
10980 /****************************************************************
10981 _spoolss_5c
10982 ****************************************************************/
10984 WERROR _spoolss_5c(struct pipes_struct *p,
10985 struct spoolss_5c *r)
10987 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10988 return WERR_NOT_SUPPORTED;
10991 /****************************************************************
10992 _spoolss_5d
10993 ****************************************************************/
10995 WERROR _spoolss_5d(struct pipes_struct *p,
10996 struct spoolss_5d *r)
10998 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10999 return WERR_NOT_SUPPORTED;
11002 /****************************************************************
11003 _spoolss_5e
11004 ****************************************************************/
11006 WERROR _spoolss_5e(struct pipes_struct *p,
11007 struct spoolss_5e *r)
11009 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11010 return WERR_NOT_SUPPORTED;
11013 /****************************************************************
11014 _spoolss_5f
11015 ****************************************************************/
11017 WERROR _spoolss_5f(struct pipes_struct *p,
11018 struct spoolss_5f *r)
11020 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11021 return WERR_NOT_SUPPORTED;
11024 /****************************************************************
11025 _spoolss_60
11026 ****************************************************************/
11028 WERROR _spoolss_60(struct pipes_struct *p,
11029 struct spoolss_60 *r)
11031 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11032 return WERR_NOT_SUPPORTED;
11035 /****************************************************************
11036 _spoolss_RpcSendRecvBidiData
11037 ****************************************************************/
11039 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
11040 struct spoolss_RpcSendRecvBidiData *r)
11042 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11043 return WERR_NOT_SUPPORTED;
11046 /****************************************************************
11047 _spoolss_62
11048 ****************************************************************/
11050 WERROR _spoolss_62(struct pipes_struct *p,
11051 struct spoolss_62 *r)
11053 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11054 return WERR_NOT_SUPPORTED;
11057 /****************************************************************
11058 _spoolss_63
11059 ****************************************************************/
11061 WERROR _spoolss_63(struct pipes_struct *p,
11062 struct spoolss_63 *r)
11064 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11065 return WERR_NOT_SUPPORTED;
11068 /****************************************************************
11069 _spoolss_64
11070 ****************************************************************/
11072 WERROR _spoolss_64(struct pipes_struct *p,
11073 struct spoolss_64 *r)
11075 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11076 return WERR_NOT_SUPPORTED;
11079 /****************************************************************
11080 _spoolss_65
11081 ****************************************************************/
11083 WERROR _spoolss_65(struct pipes_struct *p,
11084 struct spoolss_65 *r)
11086 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11087 return WERR_NOT_SUPPORTED;
11090 /****************************************************************
11091 _spoolss_GetCorePrinterDrivers
11092 ****************************************************************/
11094 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11095 struct spoolss_GetCorePrinterDrivers *r)
11097 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11098 return WERR_NOT_SUPPORTED;
11101 /****************************************************************
11102 _spoolss_67
11103 ****************************************************************/
11105 WERROR _spoolss_67(struct pipes_struct *p,
11106 struct spoolss_67 *r)
11108 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11109 return WERR_NOT_SUPPORTED;
11112 /****************************************************************
11113 _spoolss_GetPrinterDriverPackagePath
11114 ****************************************************************/
11116 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11117 struct spoolss_GetPrinterDriverPackagePath *r)
11119 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11120 return WERR_NOT_SUPPORTED;
11123 /****************************************************************
11124 _spoolss_69
11125 ****************************************************************/
11127 WERROR _spoolss_69(struct pipes_struct *p,
11128 struct spoolss_69 *r)
11130 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11131 return WERR_NOT_SUPPORTED;
11134 /****************************************************************
11135 _spoolss_6a
11136 ****************************************************************/
11138 WERROR _spoolss_6a(struct pipes_struct *p,
11139 struct spoolss_6a *r)
11141 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11142 return WERR_NOT_SUPPORTED;
11145 /****************************************************************
11146 _spoolss_6b
11147 ****************************************************************/
11149 WERROR _spoolss_6b(struct pipes_struct *p,
11150 struct spoolss_6b *r)
11152 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11153 return WERR_NOT_SUPPORTED;
11156 /****************************************************************
11157 _spoolss_6c
11158 ****************************************************************/
11160 WERROR _spoolss_6c(struct pipes_struct *p,
11161 struct spoolss_6c *r)
11163 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11164 return WERR_NOT_SUPPORTED;
11167 /****************************************************************
11168 _spoolss_6d
11169 ****************************************************************/
11171 WERROR _spoolss_6d(struct pipes_struct *p,
11172 struct spoolss_6d *r)
11174 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11175 return WERR_NOT_SUPPORTED;
11178 /****************************************************************
11179 _spoolss_RpcGetJobNamedPropertyValue
11180 ****************************************************************/
11182 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11183 struct spoolss_RpcGetJobNamedPropertyValue *r)
11185 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11186 return WERR_NOT_SUPPORTED;
11189 /****************************************************************
11190 _spoolss_RpcSetJobNamedProperty
11191 ****************************************************************/
11193 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11194 struct spoolss_RpcSetJobNamedProperty *r)
11196 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11197 return WERR_NOT_SUPPORTED;
11200 /****************************************************************
11201 _spoolss_RpcDeleteJobNamedProperty
11202 ****************************************************************/
11204 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11205 struct spoolss_RpcDeleteJobNamedProperty *r)
11207 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11208 return WERR_NOT_SUPPORTED;
11211 /****************************************************************
11212 _spoolss_RpcEnumJobNamedProperties
11213 ****************************************************************/
11215 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11216 struct spoolss_RpcEnumJobNamedProperties *r)
11218 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11219 return WERR_NOT_SUPPORTED;