WHATSNEW: list SMB3 as max protocol and durable handles as changes since 4.0 beta8
[Samba/gebeck_regimport.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blobff342dea920665ae9c0af61e0570377d1a70e58a
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 **********************************************************************/
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519 void *private_data,
1520 uint32_t msg_type,
1521 struct server_id server_id,
1522 DATA_BLOB *data)
1524 TALLOC_CTX *tmp_ctx;
1525 const struct auth_session_info *session_info = get_session_info_system();
1526 struct spoolss_PrinterInfo2 *pinfo2;
1527 WERROR result;
1528 const char *drivername;
1529 int snum;
1530 int n_services = lp_numservices();
1531 struct dcerpc_binding_handle *b = NULL;
1533 tmp_ctx = talloc_new(NULL);
1534 if (!tmp_ctx) return;
1536 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537 if (!drivername) {
1538 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539 goto done;
1542 DEBUG(10, ("do_drv_upgrade_printer: "
1543 "Got message for new driver [%s]\n", drivername));
1545 /* Iterate the printer list */
1547 for (snum = 0; snum < n_services; snum++) {
1548 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549 continue;
1552 /* ignore [printers] share */
1553 if (strequal(lp_const_servicename(snum), "printers")) {
1554 continue;
1557 if (b == NULL) {
1558 result = winreg_printer_binding_handle(tmp_ctx,
1559 session_info,
1560 msg,
1561 &b);
1562 if (!W_ERROR_IS_OK(result)) {
1563 break;
1567 result = winreg_get_printer(tmp_ctx, b,
1568 lp_const_servicename(snum),
1569 &pinfo2);
1571 if (!W_ERROR_IS_OK(result)) {
1572 continue;
1575 if (!pinfo2->drivername) {
1576 continue;
1579 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580 continue;
1583 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1585 /* all we care about currently is the change_id */
1586 result = winreg_printer_update_changeid(tmp_ctx, b,
1587 pinfo2->printername);
1589 if (!W_ERROR_IS_OK(result)) {
1590 DEBUG(3, ("do_drv_upgrade_printer: "
1591 "Failed to update changeid [%s]\n",
1592 win_errstr(result)));
1596 /* all done */
1597 done:
1598 talloc_free(tmp_ctx);
1601 /********************************************************************
1602 Update the cache for all printq's with a registered client
1603 connection
1604 ********************************************************************/
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1608 struct printer_handle *printer = printers_list;
1609 int snum;
1611 /* loop through all printers and update the cache where
1612 a client is connected */
1613 while (printer) {
1614 if ((printer->printer_type == SPLHND_PRINTER) &&
1615 ((printer->notify.cli_chan != NULL) &&
1616 (printer->notify.cli_chan->active_connections > 0))) {
1617 snum = print_queue_snum(printer->sharename);
1618 print_queue_status(msg_ctx, snum, NULL, NULL);
1621 printer = printer->next;
1624 return;
1627 /****************************************************************
1628 _spoolss_OpenPrinter
1629 ****************************************************************/
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632 struct spoolss_OpenPrinter *r)
1634 struct spoolss_OpenPrinterEx e;
1635 WERROR werr;
1637 ZERO_STRUCT(e.in.userlevel);
1639 e.in.printername = r->in.printername;
1640 e.in.datatype = r->in.datatype;
1641 e.in.devmode_ctr = r->in.devmode_ctr;
1642 e.in.access_mask = r->in.access_mask;
1643 e.in.level = 0;
1645 e.out.handle = r->out.handle;
1647 werr = _spoolss_OpenPrinterEx(p, &e);
1649 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1650 /* OpenPrinterEx returns this for a bad
1651 * printer name. We must return WERR_INVALID_PRINTER_NAME
1652 * instead.
1654 werr = WERR_INVALID_PRINTER_NAME;
1657 return werr;
1660 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1661 struct spoolss_DeviceMode *orig,
1662 struct spoolss_DeviceMode **dest)
1664 struct spoolss_DeviceMode *dm;
1666 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1667 if (!dm) {
1668 return WERR_NOMEM;
1671 /* copy all values, then duplicate strings and structs */
1672 *dm = *orig;
1674 dm->devicename = talloc_strdup(dm, orig->devicename);
1675 if (!dm->devicename) {
1676 return WERR_NOMEM;
1678 dm->formname = talloc_strdup(dm, orig->formname);
1679 if (!dm->formname) {
1680 return WERR_NOMEM;
1682 if (orig->driverextra_data.data) {
1683 dm->driverextra_data.data =
1684 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1685 orig->driverextra_data.length);
1686 if (!dm->driverextra_data.data) {
1687 return WERR_NOMEM;
1691 *dest = dm;
1692 return WERR_OK;
1695 /****************************************************************
1696 _spoolss_OpenPrinterEx
1697 ****************************************************************/
1699 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1700 struct spoolss_OpenPrinterEx *r)
1702 int snum;
1703 char *raddr;
1704 char *rhost;
1705 struct printer_handle *Printer=NULL;
1706 WERROR result;
1707 int rc;
1709 if (!r->in.printername) {
1710 return WERR_INVALID_PARAM;
1713 if (!*r->in.printername) {
1714 return WERR_INVALID_PARAM;
1717 if (r->in.level > 3) {
1718 return WERR_INVALID_PARAM;
1720 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1721 (r->in.level == 2 && !r->in.userlevel.level2) ||
1722 (r->in.level == 3 && !r->in.userlevel.level3)) {
1723 return WERR_INVALID_PARAM;
1726 /* some sanity check because you can open a printer or a print server */
1727 /* aka: \\server\printer or \\server */
1729 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1731 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1732 if (!W_ERROR_IS_OK(result)) {
1733 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1734 "for printer %s\n", r->in.printername));
1735 ZERO_STRUCTP(r->out.handle);
1736 return result;
1739 Printer = find_printer_index_by_hnd(p, r->out.handle);
1740 if ( !Printer ) {
1741 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1742 "handle we created for printer %s\n", r->in.printername));
1743 close_printer_handle(p, r->out.handle);
1744 ZERO_STRUCTP(r->out.handle);
1745 return WERR_INVALID_PARAM;
1749 * First case: the user is opening the print server:
1751 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1752 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1754 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1755 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1756 * or if the user is listed in the smb.conf printer admin parameter.
1758 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1759 * client view printer folder, but does not show the MSAPW.
1761 * Note: this test needs code to check access rights here too. Jeremy
1762 * could you look at this?
1764 * Second case: the user is opening a printer:
1765 * NT doesn't let us connect to a printer if the connecting user
1766 * doesn't have print permission.
1768 * Third case: user is opening a Port Monitor
1769 * access checks same as opening a handle to the print server.
1772 switch (Printer->printer_type )
1774 case SPLHND_SERVER:
1775 case SPLHND_PORTMON_TCP:
1776 case SPLHND_PORTMON_LOCAL:
1777 /* Printserver handles use global struct... */
1779 snum = -1;
1781 /* Map standard access rights to object specific access rights */
1783 se_map_standard(&r->in.access_mask,
1784 &printserver_std_mapping);
1786 /* Deny any object specific bits that don't apply to print
1787 servers (i.e printer and job specific bits) */
1789 r->in.access_mask &= SEC_MASK_SPECIFIC;
1791 if (r->in.access_mask &
1792 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1793 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1794 close_printer_handle(p, r->out.handle);
1795 ZERO_STRUCTP(r->out.handle);
1796 return WERR_ACCESS_DENIED;
1799 /* Allow admin access */
1801 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1803 if (!lp_ms_add_printer_wizard()) {
1804 close_printer_handle(p, r->out.handle);
1805 ZERO_STRUCTP(r->out.handle);
1806 return WERR_ACCESS_DENIED;
1809 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1810 and not a printer admin, then fail */
1812 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1813 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1814 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1815 p->session_info->security_token)) {
1816 close_printer_handle(p, r->out.handle);
1817 ZERO_STRUCTP(r->out.handle);
1818 DEBUG(3,("access DENIED as user is not root, "
1819 "has no printoperator privilege, "
1820 "not a member of the printoperator builtin group and "
1821 "is not in printer admin list"));
1822 return WERR_ACCESS_DENIED;
1825 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1827 else
1829 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1832 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1835 /* We fall through to return WERR_OK */
1836 break;
1838 case SPLHND_PRINTER:
1839 /* NT doesn't let us connect to a printer if the connecting user
1840 doesn't have print permission. */
1842 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843 close_printer_handle(p, r->out.handle);
1844 ZERO_STRUCTP(r->out.handle);
1845 return WERR_BADFID;
1848 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1852 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1854 /* map an empty access mask to the minimum access mask */
1855 if (r->in.access_mask == 0x0)
1856 r->in.access_mask = PRINTER_ACCESS_USE;
1859 * If we are not serving the printer driver for this printer,
1860 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1861 * will keep NT clients happy --jerry
1864 if (lp_use_client_driver(snum)
1865 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1867 r->in.access_mask = PRINTER_ACCESS_USE;
1870 /* check smb.conf parameters and the the sec_desc */
1871 raddr = tsocket_address_inet_addr_string(p->remote_address,
1872 p->mem_ctx);
1873 if (raddr == NULL) {
1874 return WERR_NOMEM;
1877 rc = get_remote_hostname(p->remote_address,
1878 &rhost,
1879 p->mem_ctx);
1880 if (rc < 0) {
1881 return WERR_NOMEM;
1883 if (strequal(rhost, "UNKNOWN")) {
1884 rhost = raddr;
1887 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1888 rhost, raddr)) {
1889 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1890 ZERO_STRUCTP(r->out.handle);
1891 return WERR_ACCESS_DENIED;
1894 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1895 p->session_info->security_token, snum) ||
1896 !print_access_check(p->session_info,
1897 p->msg_ctx,
1898 snum,
1899 r->in.access_mask)) {
1900 DEBUG(3, ("access DENIED for printer open\n"));
1901 close_printer_handle(p, r->out.handle);
1902 ZERO_STRUCTP(r->out.handle);
1903 return WERR_ACCESS_DENIED;
1906 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1907 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1908 close_printer_handle(p, r->out.handle);
1909 ZERO_STRUCTP(r->out.handle);
1910 return WERR_ACCESS_DENIED;
1913 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1914 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1915 else
1916 r->in.access_mask = PRINTER_ACCESS_USE;
1918 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1919 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1921 winreg_create_printer_internal(p->mem_ctx,
1922 get_session_info_system(),
1923 p->msg_ctx,
1924 lp_const_servicename(snum));
1926 break;
1928 default:
1929 /* sanity check to prevent programmer error */
1930 ZERO_STRUCTP(r->out.handle);
1931 return WERR_BADFID;
1934 Printer->access_granted = r->in.access_mask;
1937 * If the client sent a devmode in the OpenPrinter() call, then
1938 * save it here in case we get a job submission on this handle
1941 if ((Printer->printer_type != SPLHND_SERVER) &&
1942 r->in.devmode_ctr.devmode) {
1943 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1944 &Printer->devmode);
1947 #if 0 /* JERRY -- I'm doubtful this is really effective */
1948 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1949 optimization in Windows 2000 clients --jerry */
1951 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1952 && (RA_WIN2K == get_remote_arch()) )
1954 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1955 usleep( 500000 );
1957 #endif
1959 return WERR_OK;
1962 /****************************************************************
1963 _spoolss_ClosePrinter
1964 ****************************************************************/
1966 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1967 struct spoolss_ClosePrinter *r)
1969 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1971 if (Printer && Printer->document_started) {
1972 struct spoolss_EndDocPrinter e;
1974 e.in.handle = r->in.handle;
1976 _spoolss_EndDocPrinter(p, &e);
1979 if (!close_printer_handle(p, r->in.handle))
1980 return WERR_BADFID;
1982 /* clear the returned printer handle. Observed behavior
1983 from Win2k server. Don't think this really matters.
1984 Previous code just copied the value of the closed
1985 handle. --jerry */
1987 ZERO_STRUCTP(r->out.handle);
1989 return WERR_OK;
1992 /****************************************************************
1993 _spoolss_DeletePrinter
1994 ****************************************************************/
1996 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1997 struct spoolss_DeletePrinter *r)
1999 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2000 WERROR result;
2001 int snum;
2003 if (Printer && Printer->document_started) {
2004 struct spoolss_EndDocPrinter e;
2006 e.in.handle = r->in.handle;
2008 _spoolss_EndDocPrinter(p, &e);
2011 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2012 winreg_delete_printer_key_internal(p->mem_ctx,
2013 get_session_info_system(),
2014 p->msg_ctx,
2015 lp_const_servicename(snum),
2016 "");
2019 result = delete_printer_handle(p, r->in.handle);
2021 return result;
2024 /*******************************************************************
2025 * static function to lookup the version id corresponding to an
2026 * long architecture string
2027 ******************************************************************/
2029 static const struct print_architecture_table_node archi_table[]= {
2031 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2032 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2033 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2034 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2035 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2036 {"Windows IA64", SPL_ARCH_IA64, 3 },
2037 {"Windows x64", SPL_ARCH_X64, 3 },
2038 {NULL, "", -1 }
2041 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2042 SPOOLSS_DRIVER_VERSION_NT35,
2043 SPOOLSS_DRIVER_VERSION_NT4,
2044 SPOOLSS_DRIVER_VERSION_200X,
2045 -1};
2047 static int get_version_id(const char *arch)
2049 int i;
2051 for (i=0; archi_table[i].long_archi != NULL; i++)
2053 if (strcmp(arch, archi_table[i].long_archi) == 0)
2054 return (archi_table[i].version);
2057 return -1;
2060 /****************************************************************
2061 _spoolss_DeletePrinterDriver
2062 ****************************************************************/
2064 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2065 struct spoolss_DeletePrinterDriver *r)
2068 struct spoolss_DriverInfo8 *info = NULL;
2069 int version;
2070 WERROR status;
2071 struct dcerpc_binding_handle *b;
2072 TALLOC_CTX *tmp_ctx = NULL;
2073 int i;
2074 bool found;
2076 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2077 and not a printer admin, then fail */
2079 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2080 !security_token_has_privilege(p->session_info->security_token,
2081 SEC_PRIV_PRINT_OPERATOR)) {
2082 return WERR_ACCESS_DENIED;
2085 /* check that we have a valid driver name first */
2087 if ((version = get_version_id(r->in.architecture)) == -1) {
2088 return WERR_INVALID_ENVIRONMENT;
2091 tmp_ctx = talloc_new(p->mem_ctx);
2092 if (!tmp_ctx) {
2093 return WERR_NOMEM;
2096 status = winreg_printer_binding_handle(tmp_ctx,
2097 get_session_info_system(),
2098 p->msg_ctx,
2099 &b);
2100 if (!W_ERROR_IS_OK(status)) {
2101 goto done;
2104 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2105 status = winreg_get_driver(tmp_ctx, b,
2106 r->in.architecture, r->in.driver,
2107 drv_cversion[i], &info);
2108 if (!W_ERROR_IS_OK(status)) {
2109 DEBUG(5, ("skipping del of driver with version %d\n",
2110 drv_cversion[i]));
2111 continue;
2113 found = true;
2115 if (printer_driver_in_use(tmp_ctx, b, info)) {
2116 status = WERR_PRINTER_DRIVER_IN_USE;
2117 goto done;
2120 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2121 if (!W_ERROR_IS_OK(status)) {
2122 DEBUG(0, ("failed del of driver with version %d\n",
2123 drv_cversion[i]));
2124 goto done;
2127 if (found == false) {
2128 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2129 status = WERR_UNKNOWN_PRINTER_DRIVER;
2130 } else {
2131 status = WERR_OK;
2134 done:
2135 talloc_free(tmp_ctx);
2137 return status;
2140 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2141 struct pipes_struct *p,
2142 struct spoolss_DeletePrinterDriverEx *r,
2143 struct dcerpc_binding_handle *b,
2144 struct spoolss_DriverInfo8 *info)
2146 WERROR status;
2147 bool delete_files;
2149 if (printer_driver_in_use(mem_ctx, b, info)) {
2150 status = WERR_PRINTER_DRIVER_IN_USE;
2151 goto done;
2155 * we have a couple of cases to consider.
2156 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2157 * then the delete should fail if **any** files overlap with
2158 * other drivers
2159 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2160 * non-overlapping files
2161 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2162 * are set, then do not delete any files
2163 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2166 delete_files = r->in.delete_flags
2167 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2170 if (delete_files) {
2171 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2172 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2173 status = WERR_PRINTER_DRIVER_IN_USE;
2174 goto done;
2177 * printer_driver_files_in_use() has trimmed overlapping files
2178 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2183 status = winreg_del_driver(mem_ctx, b, info, info->version);
2184 if (!W_ERROR_IS_OK(status)) {
2185 goto done;
2189 * now delete any associated files if delete_files is
2190 * true. Even if this part failes, we return succes
2191 * because the driver doesn not exist any more
2193 if (delete_files) {
2194 delete_driver_files(p->session_info, info);
2197 done:
2198 return status;
2201 /****************************************************************
2202 _spoolss_DeletePrinterDriverEx
2203 ****************************************************************/
2205 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2206 struct spoolss_DeletePrinterDriverEx *r)
2208 struct spoolss_DriverInfo8 *info = NULL;
2209 WERROR status;
2210 struct dcerpc_binding_handle *b;
2211 TALLOC_CTX *tmp_ctx = NULL;
2212 int i;
2213 bool found;
2215 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2216 and not a printer admin, then fail */
2218 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2219 !security_token_has_privilege(p->session_info->security_token,
2220 SEC_PRIV_PRINT_OPERATOR)) {
2221 return WERR_ACCESS_DENIED;
2224 /* check that we have a valid driver name first */
2225 if (get_version_id(r->in.architecture) == -1) {
2226 /* this is what NT returns */
2227 return WERR_INVALID_ENVIRONMENT;
2230 tmp_ctx = talloc_new(p->mem_ctx);
2231 if (!tmp_ctx) {
2232 return WERR_NOMEM;
2235 status = winreg_printer_binding_handle(tmp_ctx,
2236 get_session_info_system(),
2237 p->msg_ctx,
2238 &b);
2239 if (!W_ERROR_IS_OK(status)) {
2240 goto done;
2243 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2244 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2245 && (drv_cversion[i] != r->in.version)) {
2246 continue;
2249 /* check if a driver with this version exists before delete */
2250 status = winreg_get_driver(tmp_ctx, b,
2251 r->in.architecture, r->in.driver,
2252 drv_cversion[i], &info);
2253 if (!W_ERROR_IS_OK(status)) {
2254 DEBUG(5, ("skipping del of driver with version %d\n",
2255 drv_cversion[i]));
2256 continue;
2258 found = true;
2260 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2261 if (!W_ERROR_IS_OK(status)) {
2262 DEBUG(0, ("failed to delete driver with version %d\n",
2263 drv_cversion[i]));
2264 goto done;
2267 if (found == false) {
2268 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2269 status = WERR_UNKNOWN_PRINTER_DRIVER;
2270 } else {
2271 status = WERR_OK;
2274 done:
2275 talloc_free(tmp_ctx);
2276 return status;
2280 /********************************************************************
2281 GetPrinterData on a printer server Handle.
2282 ********************************************************************/
2284 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2285 const char *value,
2286 enum winreg_Type *type,
2287 union spoolss_PrinterData *data)
2289 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2292 *type = REG_DWORD;
2293 SIVAL(&data->value, 0, 0x00);
2294 return WERR_OK;
2297 if (!strcasecmp_m(value, "BeepEnabled")) {
2298 *type = REG_DWORD;
2299 SIVAL(&data->value, 0, 0x00);
2300 return WERR_OK;
2303 if (!strcasecmp_m(value, "EventLog")) {
2304 *type = REG_DWORD;
2305 /* formally was 0x1b */
2306 SIVAL(&data->value, 0, 0x00);
2307 return WERR_OK;
2310 if (!strcasecmp_m(value, "NetPopup")) {
2311 *type = REG_DWORD;
2312 SIVAL(&data->value, 0, 0x00);
2313 return WERR_OK;
2316 if (!strcasecmp_m(value, "MajorVersion")) {
2317 *type = REG_DWORD;
2319 /* Windows NT 4.0 seems to not allow uploading of drivers
2320 to a server that reports 0x3 as the MajorVersion.
2321 need to investigate more how Win2k gets around this .
2322 -- jerry */
2324 if (RA_WINNT == get_remote_arch()) {
2325 SIVAL(&data->value, 0, 0x02);
2326 } else {
2327 SIVAL(&data->value, 0, 0x03);
2330 return WERR_OK;
2333 if (!strcasecmp_m(value, "MinorVersion")) {
2334 *type = REG_DWORD;
2335 SIVAL(&data->value, 0, 0x00);
2336 return WERR_OK;
2339 /* REG_BINARY
2340 * uint32_t size = 0x114
2341 * uint32_t major = 5
2342 * uint32_t minor = [0|1]
2343 * uint32_t build = [2195|2600]
2344 * extra unicode string = e.g. "Service Pack 3"
2346 if (!strcasecmp_m(value, "OSVersion")) {
2347 DATA_BLOB blob;
2348 enum ndr_err_code ndr_err;
2349 struct spoolss_OSVersion os;
2351 os.major = 5; /* Windows 2000 == 5.0 */
2352 os.minor = 0;
2353 os.build = 2195; /* build */
2354 os.extra_string = ""; /* leave extra string empty */
2356 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2357 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2358 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2359 return WERR_GENERAL_FAILURE;
2362 *type = REG_BINARY;
2363 data->binary = blob;
2365 return WERR_OK;
2369 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2370 *type = REG_SZ;
2372 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2373 W_ERROR_HAVE_NO_MEMORY(data->string);
2375 return WERR_OK;
2378 if (!strcasecmp_m(value, "Architecture")) {
2379 *type = REG_SZ;
2380 data->string = talloc_strdup(mem_ctx,
2381 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2382 W_ERROR_HAVE_NO_MEMORY(data->string);
2384 return WERR_OK;
2387 if (!strcasecmp_m(value, "DsPresent")) {
2388 *type = REG_DWORD;
2390 /* only show the publish check box if we are a
2391 member of a AD domain */
2393 if (lp_security() == SEC_ADS) {
2394 SIVAL(&data->value, 0, 0x01);
2395 } else {
2396 SIVAL(&data->value, 0, 0x00);
2398 return WERR_OK;
2401 if (!strcasecmp_m(value, "DNSMachineName")) {
2402 const char *hostname = get_mydnsfullname();
2404 if (!hostname) {
2405 return WERR_BADFILE;
2408 *type = REG_SZ;
2409 data->string = talloc_strdup(mem_ctx, hostname);
2410 W_ERROR_HAVE_NO_MEMORY(data->string);
2412 return WERR_OK;
2415 *type = REG_NONE;
2417 return WERR_INVALID_PARAM;
2420 /****************************************************************
2421 _spoolss_GetPrinterData
2422 ****************************************************************/
2424 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2425 struct spoolss_GetPrinterData *r)
2427 struct spoolss_GetPrinterDataEx r2;
2429 r2.in.handle = r->in.handle;
2430 r2.in.key_name = "PrinterDriverData";
2431 r2.in.value_name = r->in.value_name;
2432 r2.in.offered = r->in.offered;
2433 r2.out.type = r->out.type;
2434 r2.out.data = r->out.data;
2435 r2.out.needed = r->out.needed;
2437 return _spoolss_GetPrinterDataEx(p, &r2);
2440 /*********************************************************
2441 Connect to the client machine.
2442 **********************************************************/
2444 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2445 struct sockaddr_storage *client_ss, const char *remote_machine)
2447 NTSTATUS ret;
2448 struct cli_state *the_cli;
2449 struct sockaddr_storage rm_addr;
2450 char addr[INET6_ADDRSTRLEN];
2452 if ( is_zero_addr(client_ss) ) {
2453 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2454 remote_machine));
2455 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2456 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2457 return false;
2459 print_sockaddr(addr, sizeof(addr), &rm_addr);
2460 } else {
2461 rm_addr = *client_ss;
2462 print_sockaddr(addr, sizeof(addr), &rm_addr);
2463 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2464 addr));
2467 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2468 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2469 addr));
2470 return false;
2473 /* setup the connection */
2474 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2475 &rm_addr, 0, "IPC$", "IPC",
2476 "", /* username */
2477 "", /* domain */
2478 "", /* password */
2479 0, lp_client_signing());
2481 if ( !NT_STATUS_IS_OK( ret ) ) {
2482 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2483 remote_machine ));
2484 return false;
2487 if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2488 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2489 cli_shutdown(the_cli);
2490 return false;
2494 * Ok - we have an anonymous connection to the IPC$ share.
2495 * Now start the NT Domain stuff :-).
2498 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2499 if (!NT_STATUS_IS_OK(ret)) {
2500 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2501 remote_machine, nt_errstr(ret)));
2502 cli_shutdown(the_cli);
2503 return false;
2506 return true;
2509 /***************************************************************************
2510 Connect to the client.
2511 ****************************************************************************/
2513 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2514 uint32_t localprinter,
2515 enum winreg_Type type,
2516 struct policy_handle *handle,
2517 struct notify_back_channel **_chan,
2518 struct sockaddr_storage *client_ss,
2519 struct messaging_context *msg_ctx)
2521 WERROR result;
2522 NTSTATUS status;
2523 struct notify_back_channel *chan;
2525 for (chan = back_channels; chan; chan = chan->next) {
2526 if (memcmp(&chan->client_address, client_ss,
2527 sizeof(struct sockaddr_storage)) == 0) {
2528 break;
2533 * If it's the first connection, contact the client
2534 * and connect to the IPC$ share anonymously
2536 if (!chan) {
2537 fstring unix_printer;
2539 /* the +2 is to strip the leading 2 backslashs */
2540 fstrcpy(unix_printer, printer + 2);
2542 chan = talloc_zero(NULL, struct notify_back_channel);
2543 if (!chan) {
2544 return false;
2546 chan->client_address = *client_ss;
2548 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2549 TALLOC_FREE(chan);
2550 return false;
2553 DLIST_ADD(back_channels, chan);
2555 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2556 receive_notify2_message_list);
2559 if (chan->cli_pipe == NULL ||
2560 chan->cli_pipe->binding_handle == NULL) {
2561 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2562 "NULL %s for printer %s\n",
2563 chan->cli_pipe == NULL ?
2564 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2565 printer));
2566 return false;
2570 * Tell the specific printing tdb we want messages for this printer
2571 * by registering our PID.
2574 if (!print_notify_register_pid(snum)) {
2575 DEBUG(0, ("Failed to register our pid for printer %s\n",
2576 printer));
2579 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2580 talloc_tos(),
2581 printer,
2582 localprinter,
2583 type,
2585 NULL,
2586 handle,
2587 &result);
2588 if (!NT_STATUS_IS_OK(status)) {
2589 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2590 result = ntstatus_to_werror(status);
2591 } else if (!W_ERROR_IS_OK(result)) {
2592 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2595 chan->active_connections++;
2596 *_chan = chan;
2598 return (W_ERROR_IS_OK(result));
2601 /****************************************************************
2602 ****************************************************************/
2604 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2605 const struct spoolss_NotifyOption *r)
2607 struct spoolss_NotifyOption *option;
2608 uint32_t i,k;
2610 if (!r) {
2611 return NULL;
2614 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2615 if (!option) {
2616 return NULL;
2619 *option = *r;
2621 if (!option->count) {
2622 return option;
2625 option->types = talloc_zero_array(option,
2626 struct spoolss_NotifyOptionType, option->count);
2627 if (!option->types) {
2628 talloc_free(option);
2629 return NULL;
2632 for (i=0; i < option->count; i++) {
2633 option->types[i] = r->types[i];
2635 if (option->types[i].count) {
2636 option->types[i].fields = talloc_zero_array(option,
2637 union spoolss_Field, option->types[i].count);
2638 if (!option->types[i].fields) {
2639 talloc_free(option);
2640 return NULL;
2642 for (k=0; k<option->types[i].count; k++) {
2643 option->types[i].fields[k] =
2644 r->types[i].fields[k];
2649 return option;
2652 /****************************************************************
2653 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2655 * before replying OK: status=0 a rpc call is made to the workstation
2656 * asking ReplyOpenPrinter
2658 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2659 * called from api_spoolss_rffpcnex
2660 ****************************************************************/
2662 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2663 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2665 int snum = -1;
2666 struct spoolss_NotifyOption *option = r->in.notify_options;
2667 struct sockaddr_storage client_ss;
2668 ssize_t client_len;
2670 /* store the notify value in the printer struct */
2672 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2674 if (!Printer) {
2675 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2676 "Invalid handle (%s:%u:%u).\n",
2677 OUR_HANDLE(r->in.handle)));
2678 return WERR_BADFID;
2681 Printer->notify.flags = r->in.flags;
2682 Printer->notify.options = r->in.options;
2683 Printer->notify.printerlocal = r->in.printer_local;
2684 Printer->notify.msg_ctx = p->msg_ctx;
2686 TALLOC_FREE(Printer->notify.option);
2687 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2689 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2691 /* Connect to the client machine and send a ReplyOpenPrinter */
2693 if ( Printer->printer_type == SPLHND_SERVER)
2694 snum = -1;
2695 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2696 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2697 return WERR_BADFID;
2699 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2700 "remote_address is %s\n",
2701 tsocket_address_string(p->remote_address, p->mem_ctx)));
2703 if (!lp_print_notify_backchannel(snum)) {
2704 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2705 "backchannel disabled\n"));
2706 return WERR_SERVER_UNAVAILABLE;
2709 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2710 (struct sockaddr *) &client_ss,
2711 sizeof(struct sockaddr_storage));
2712 if (client_len < 0) {
2713 return WERR_NOMEM;
2716 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2717 Printer->notify.printerlocal, REG_SZ,
2718 &Printer->notify.cli_hnd,
2719 &Printer->notify.cli_chan,
2720 &client_ss, p->msg_ctx)) {
2721 return WERR_SERVER_UNAVAILABLE;
2724 return WERR_OK;
2727 /*******************************************************************
2728 * fill a notify_info_data with the servername
2729 ********************************************************************/
2731 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2732 int snum,
2733 struct spoolss_Notify *data,
2734 print_queue_struct *queue,
2735 struct spoolss_PrinterInfo2 *pinfo2,
2736 TALLOC_CTX *mem_ctx)
2738 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2741 /*******************************************************************
2742 * fill a notify_info_data with the printername (not including the servername).
2743 ********************************************************************/
2745 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2746 int snum,
2747 struct spoolss_Notify *data,
2748 print_queue_struct *queue,
2749 struct spoolss_PrinterInfo2 *pinfo2,
2750 TALLOC_CTX *mem_ctx)
2752 /* the notify name should not contain the \\server\ part */
2753 const char *p = strrchr(pinfo2->printername, '\\');
2755 if (!p) {
2756 p = pinfo2->printername;
2757 } else {
2758 p++;
2761 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2764 /*******************************************************************
2765 * fill a notify_info_data with the servicename
2766 ********************************************************************/
2768 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2769 int snum,
2770 struct spoolss_Notify *data,
2771 print_queue_struct *queue,
2772 struct spoolss_PrinterInfo2 *pinfo2,
2773 TALLOC_CTX *mem_ctx)
2775 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2778 /*******************************************************************
2779 * fill a notify_info_data with the port name
2780 ********************************************************************/
2782 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2783 int snum,
2784 struct spoolss_Notify *data,
2785 print_queue_struct *queue,
2786 struct spoolss_PrinterInfo2 *pinfo2,
2787 TALLOC_CTX *mem_ctx)
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2792 /*******************************************************************
2793 * fill a notify_info_data with the printername
2794 * but it doesn't exist, have to see what to do
2795 ********************************************************************/
2797 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2798 int snum,
2799 struct spoolss_Notify *data,
2800 print_queue_struct *queue,
2801 struct spoolss_PrinterInfo2 *pinfo2,
2802 TALLOC_CTX *mem_ctx)
2804 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2807 /*******************************************************************
2808 * fill a notify_info_data with the comment
2809 ********************************************************************/
2811 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2812 int snum,
2813 struct spoolss_Notify *data,
2814 print_queue_struct *queue,
2815 struct spoolss_PrinterInfo2 *pinfo2,
2816 TALLOC_CTX *mem_ctx)
2818 const char *p;
2820 if (*pinfo2->comment == '\0') {
2821 p = lp_comment(talloc_tos(), snum);
2822 } else {
2823 p = pinfo2->comment;
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2829 /*******************************************************************
2830 * fill a notify_info_data with the comment
2831 * location = "Room 1, floor 2, building 3"
2832 ********************************************************************/
2834 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2835 int snum,
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 struct spoolss_PrinterInfo2 *pinfo2,
2839 TALLOC_CTX *mem_ctx)
2841 const char *loc = pinfo2->location;
2842 NTSTATUS status;
2844 status = printer_list_get_printer(mem_ctx,
2845 pinfo2->sharename,
2846 NULL,
2847 &loc,
2848 NULL);
2849 if (NT_STATUS_IS_OK(status)) {
2850 if (loc == NULL) {
2851 loc = pinfo2->location;
2855 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2858 /*******************************************************************
2859 * fill a notify_info_data with the device mode
2860 * jfm:xxxx don't to it for know but that's a real problem !!!
2861 ********************************************************************/
2863 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2864 int snum,
2865 struct spoolss_Notify *data,
2866 print_queue_struct *queue,
2867 struct spoolss_PrinterInfo2 *pinfo2,
2868 TALLOC_CTX *mem_ctx)
2870 /* for a dummy implementation we have to zero the fields */
2871 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2874 /*******************************************************************
2875 * fill a notify_info_data with the separator file name
2876 ********************************************************************/
2878 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2879 int snum,
2880 struct spoolss_Notify *data,
2881 print_queue_struct *queue,
2882 struct spoolss_PrinterInfo2 *pinfo2,
2883 TALLOC_CTX *mem_ctx)
2885 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2888 /*******************************************************************
2889 * fill a notify_info_data with the print processor
2890 * jfm:xxxx return always winprint to indicate we don't do anything to it
2891 ********************************************************************/
2893 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2894 int snum,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 struct spoolss_PrinterInfo2 *pinfo2,
2898 TALLOC_CTX *mem_ctx)
2900 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2903 /*******************************************************************
2904 * fill a notify_info_data with the print processor options
2905 * jfm:xxxx send an empty string
2906 ********************************************************************/
2908 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2909 int snum,
2910 struct spoolss_Notify *data,
2911 print_queue_struct *queue,
2912 struct spoolss_PrinterInfo2 *pinfo2,
2913 TALLOC_CTX *mem_ctx)
2915 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2918 /*******************************************************************
2919 * fill a notify_info_data with the data type
2920 * jfm:xxxx always send RAW as data type
2921 ********************************************************************/
2923 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2924 int snum,
2925 struct spoolss_Notify *data,
2926 print_queue_struct *queue,
2927 struct spoolss_PrinterInfo2 *pinfo2,
2928 TALLOC_CTX *mem_ctx)
2930 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2933 /*******************************************************************
2934 * fill a notify_info_data with the security descriptor
2935 * jfm:xxxx send an null pointer to say no security desc
2936 * have to implement security before !
2937 ********************************************************************/
2939 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2940 int snum,
2941 struct spoolss_Notify *data,
2942 print_queue_struct *queue,
2943 struct spoolss_PrinterInfo2 *pinfo2,
2944 TALLOC_CTX *mem_ctx)
2946 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2949 /*******************************************************************
2950 * fill a notify_info_data with the attributes
2951 * jfm:xxxx a samba printer is always shared
2952 ********************************************************************/
2954 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2955 int snum,
2956 struct spoolss_Notify *data,
2957 print_queue_struct *queue,
2958 struct spoolss_PrinterInfo2 *pinfo2,
2959 TALLOC_CTX *mem_ctx)
2961 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2964 /*******************************************************************
2965 * fill a notify_info_data with the priority
2966 ********************************************************************/
2968 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2969 int snum,
2970 struct spoolss_Notify *data,
2971 print_queue_struct *queue,
2972 struct spoolss_PrinterInfo2 *pinfo2,
2973 TALLOC_CTX *mem_ctx)
2975 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2978 /*******************************************************************
2979 * fill a notify_info_data with the default priority
2980 ********************************************************************/
2982 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2983 int snum,
2984 struct spoolss_Notify *data,
2985 print_queue_struct *queue,
2986 struct spoolss_PrinterInfo2 *pinfo2,
2987 TALLOC_CTX *mem_ctx)
2989 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2992 /*******************************************************************
2993 * fill a notify_info_data with the start time
2994 ********************************************************************/
2996 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2997 int snum,
2998 struct spoolss_Notify *data,
2999 print_queue_struct *queue,
3000 struct spoolss_PrinterInfo2 *pinfo2,
3001 TALLOC_CTX *mem_ctx)
3003 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3006 /*******************************************************************
3007 * fill a notify_info_data with the until time
3008 ********************************************************************/
3010 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3011 int snum,
3012 struct spoolss_Notify *data,
3013 print_queue_struct *queue,
3014 struct spoolss_PrinterInfo2 *pinfo2,
3015 TALLOC_CTX *mem_ctx)
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3020 /*******************************************************************
3021 * fill a notify_info_data with the status
3022 ********************************************************************/
3024 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3025 int snum,
3026 struct spoolss_Notify *data,
3027 print_queue_struct *queue,
3028 struct spoolss_PrinterInfo2 *pinfo2,
3029 TALLOC_CTX *mem_ctx)
3031 print_status_struct status;
3033 print_queue_length(msg_ctx, snum, &status);
3034 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3037 /*******************************************************************
3038 * fill a notify_info_data with the number of jobs queued
3039 ********************************************************************/
3041 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3042 int snum,
3043 struct spoolss_Notify *data,
3044 print_queue_struct *queue,
3045 struct spoolss_PrinterInfo2 *pinfo2,
3046 TALLOC_CTX *mem_ctx)
3048 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3049 data, print_queue_length(msg_ctx, snum, NULL));
3052 /*******************************************************************
3053 * fill a notify_info_data with the average ppm
3054 ********************************************************************/
3056 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3057 int snum,
3058 struct spoolss_Notify *data,
3059 print_queue_struct *queue,
3060 struct spoolss_PrinterInfo2 *pinfo2,
3061 TALLOC_CTX *mem_ctx)
3063 /* always respond 8 pages per minutes */
3064 /* a little hard ! */
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3068 /*******************************************************************
3069 * fill a notify_info_data with username
3070 ********************************************************************/
3072 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3073 int snum,
3074 struct spoolss_Notify *data,
3075 print_queue_struct *queue,
3076 struct spoolss_PrinterInfo2 *pinfo2,
3077 TALLOC_CTX *mem_ctx)
3079 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3082 /*******************************************************************
3083 * fill a notify_info_data with job status
3084 ********************************************************************/
3086 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3087 int snum,
3088 struct spoolss_Notify *data,
3089 print_queue_struct *queue,
3090 struct spoolss_PrinterInfo2 *pinfo2,
3091 TALLOC_CTX *mem_ctx)
3093 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3096 /*******************************************************************
3097 * fill a notify_info_data with job name
3098 ********************************************************************/
3100 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3101 int snum,
3102 struct spoolss_Notify *data,
3103 print_queue_struct *queue,
3104 struct spoolss_PrinterInfo2 *pinfo2,
3105 TALLOC_CTX *mem_ctx)
3107 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3110 /*******************************************************************
3111 * fill a notify_info_data with job status
3112 ********************************************************************/
3114 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3115 int snum,
3116 struct spoolss_Notify *data,
3117 print_queue_struct *queue,
3118 struct spoolss_PrinterInfo2 *pinfo2,
3119 TALLOC_CTX *mem_ctx)
3122 * Now we're returning job status codes we just return a "" here. JRA.
3125 const char *p = "";
3127 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3128 p = "unknown";
3130 switch (queue->status) {
3131 case LPQ_QUEUED:
3132 p = "Queued";
3133 break;
3134 case LPQ_PAUSED:
3135 p = ""; /* NT provides the paused string */
3136 break;
3137 case LPQ_SPOOLING:
3138 p = "Spooling";
3139 break;
3140 case LPQ_PRINTING:
3141 p = "Printing";
3142 break;
3144 #endif /* NO LONGER NEEDED. */
3146 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3149 /*******************************************************************
3150 * fill a notify_info_data with job time
3151 ********************************************************************/
3153 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3154 int snum,
3155 struct spoolss_Notify *data,
3156 print_queue_struct *queue,
3157 struct spoolss_PrinterInfo2 *pinfo2,
3158 TALLOC_CTX *mem_ctx)
3160 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3163 /*******************************************************************
3164 * fill a notify_info_data with job size
3165 ********************************************************************/
3167 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3168 int snum,
3169 struct spoolss_Notify *data,
3170 print_queue_struct *queue,
3171 struct spoolss_PrinterInfo2 *pinfo2,
3172 TALLOC_CTX *mem_ctx)
3174 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3177 /*******************************************************************
3178 * fill a notify_info_data with page info
3179 ********************************************************************/
3180 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3181 int snum,
3182 struct spoolss_Notify *data,
3183 print_queue_struct *queue,
3184 struct spoolss_PrinterInfo2 *pinfo2,
3185 TALLOC_CTX *mem_ctx)
3187 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3190 /*******************************************************************
3191 * fill a notify_info_data with pages printed info.
3192 ********************************************************************/
3193 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3194 int snum,
3195 struct spoolss_Notify *data,
3196 print_queue_struct *queue,
3197 struct spoolss_PrinterInfo2 *pinfo2,
3198 TALLOC_CTX *mem_ctx)
3200 /* Add code when back-end tracks this */
3201 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3204 /*******************************************************************
3205 Fill a notify_info_data with job position.
3206 ********************************************************************/
3208 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3209 int snum,
3210 struct spoolss_Notify *data,
3211 print_queue_struct *queue,
3212 struct spoolss_PrinterInfo2 *pinfo2,
3213 TALLOC_CTX *mem_ctx)
3215 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3218 /*******************************************************************
3219 Fill a notify_info_data with submitted time.
3220 ********************************************************************/
3222 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3223 int snum,
3224 struct spoolss_Notify *data,
3225 print_queue_struct *queue,
3226 struct spoolss_PrinterInfo2 *pinfo2,
3227 TALLOC_CTX *mem_ctx)
3229 data->data.string.string = NULL;
3230 data->data.string.size = 0;
3232 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3233 &data->data.string.string,
3234 &data->data.string.size);
3238 struct s_notify_info_data_table
3240 enum spoolss_NotifyType type;
3241 uint16_t field;
3242 const char *name;
3243 enum spoolss_NotifyTable variable_type;
3244 void (*fn) (struct messaging_context *msg_ctx,
3245 int snum, struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 struct spoolss_PrinterInfo2 *pinfo2,
3248 TALLOC_CTX *mem_ctx);
3251 /* A table describing the various print notification constants and
3252 whether the notification data is a pointer to a variable sized
3253 buffer, a one value uint32_t or a two value uint32_t. */
3255 static const struct s_notify_info_data_table notify_info_data_table[] =
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3308 /*******************************************************************
3309 Return the variable_type of info_data structure.
3310 ********************************************************************/
3312 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3313 uint16_t field)
3315 int i=0;
3317 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3318 if ( (notify_info_data_table[i].type == type) &&
3319 (notify_info_data_table[i].field == field) ) {
3320 return notify_info_data_table[i].variable_type;
3324 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3326 return (enum spoolss_NotifyTable) 0;
3329 /****************************************************************************
3330 ****************************************************************************/
3332 static bool search_notify(enum spoolss_NotifyType type,
3333 uint16_t field,
3334 int *value)
3336 int i;
3338 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3339 if (notify_info_data_table[i].type == type &&
3340 notify_info_data_table[i].field == field &&
3341 notify_info_data_table[i].fn != NULL) {
3342 *value = i;
3343 return true;
3347 return false;
3350 /****************************************************************************
3351 ****************************************************************************/
3353 static void construct_info_data(struct spoolss_Notify *info_data,
3354 enum spoolss_NotifyType type,
3355 uint16_t field, int id)
3357 info_data->type = type;
3358 info_data->field.field = field;
3359 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3360 info_data->job_id = id;
3363 /*******************************************************************
3365 * fill a notify_info struct with info asked
3367 ********************************************************************/
3369 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3370 struct printer_handle *print_hnd,
3371 struct spoolss_NotifyInfo *info,
3372 struct spoolss_PrinterInfo2 *pinfo2,
3373 int snum,
3374 const struct spoolss_NotifyOptionType *option_type,
3375 uint32_t id,
3376 TALLOC_CTX *mem_ctx)
3378 int field_num,j;
3379 enum spoolss_NotifyType type;
3380 uint16_t field;
3382 struct spoolss_Notify *current_data;
3384 type = option_type->type;
3386 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3387 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3388 option_type->count, lp_servicename(talloc_tos(), snum)));
3390 for(field_num=0; field_num < option_type->count; field_num++) {
3391 field = option_type->fields[field_num].field;
3393 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3395 if (!search_notify(type, field, &j) )
3396 continue;
3398 info->notifies = talloc_realloc(info, info->notifies,
3399 struct spoolss_Notify,
3400 info->count + 1);
3401 if (info->notifies == NULL) {
3402 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3403 return false;
3406 current_data = &info->notifies[info->count];
3408 construct_info_data(current_data, type, field, id);
3410 DEBUG(10, ("construct_notify_printer_info: "
3411 "calling [%s] snum=%d printername=[%s])\n",
3412 notify_info_data_table[j].name, snum,
3413 pinfo2->printername));
3415 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3416 NULL, pinfo2, mem_ctx);
3418 info->count++;
3421 return true;
3424 /*******************************************************************
3426 * fill a notify_info struct with info asked
3428 ********************************************************************/
3430 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3431 print_queue_struct *queue,
3432 struct spoolss_NotifyInfo *info,
3433 struct spoolss_PrinterInfo2 *pinfo2,
3434 int snum,
3435 const struct spoolss_NotifyOptionType *option_type,
3436 uint32_t id,
3437 TALLOC_CTX *mem_ctx)
3439 int field_num,j;
3440 enum spoolss_NotifyType type;
3441 uint16_t field;
3442 struct spoolss_Notify *current_data;
3444 DEBUG(4,("construct_notify_jobs_info\n"));
3446 type = option_type->type;
3448 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3449 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3450 option_type->count));
3452 for(field_num=0; field_num<option_type->count; field_num++) {
3453 field = option_type->fields[field_num].field;
3455 if (!search_notify(type, field, &j) )
3456 continue;
3458 info->notifies = talloc_realloc(info, info->notifies,
3459 struct spoolss_Notify,
3460 info->count + 1);
3461 if (info->notifies == NULL) {
3462 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3463 return false;
3466 current_data=&(info->notifies[info->count]);
3468 construct_info_data(current_data, type, field, id);
3469 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3470 queue, pinfo2, mem_ctx);
3471 info->count++;
3474 return true;
3478 * JFM: The enumeration is not that simple, it's even non obvious.
3480 * let's take an example: I want to monitor the PRINTER SERVER for
3481 * the printer's name and the number of jobs currently queued.
3482 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3483 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3485 * I have 3 printers on the back of my server.
3487 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3488 * structures.
3489 * Number Data Id
3490 * 1 printer 1 name 1
3491 * 2 printer 1 cjob 1
3492 * 3 printer 2 name 2
3493 * 4 printer 2 cjob 2
3494 * 5 printer 3 name 3
3495 * 6 printer 3 name 3
3497 * that's the print server case, the printer case is even worse.
3500 /*******************************************************************
3502 * enumerate all printers on the printserver
3503 * fill a notify_info struct with info asked
3505 ********************************************************************/
3507 static WERROR printserver_notify_info(struct pipes_struct *p,
3508 struct policy_handle *hnd,
3509 struct spoolss_NotifyInfo *info,
3510 TALLOC_CTX *mem_ctx)
3512 int snum;
3513 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3514 int n_services=lp_numservices();
3515 int i;
3516 struct spoolss_NotifyOption *option;
3517 struct spoolss_NotifyOptionType option_type;
3518 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3519 WERROR result;
3521 DEBUG(4,("printserver_notify_info\n"));
3523 if (!Printer)
3524 return WERR_BADFID;
3526 option = Printer->notify.option;
3528 info->version = 2;
3529 info->notifies = NULL;
3530 info->count = 0;
3532 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3533 sending a ffpcn() request first */
3535 if ( !option )
3536 return WERR_BADFID;
3538 for (i=0; i<option->count; i++) {
3539 option_type = option->types[i];
3541 if (option_type.type != PRINTER_NOTIFY_TYPE)
3542 continue;
3544 for (snum = 0; snum < n_services; snum++) {
3545 if (!lp_browseable(snum) ||
3546 !lp_snum_ok(snum) ||
3547 !lp_print_ok(snum)) {
3548 continue; /* skip */
3551 /* Maybe we should use the SYSTEM session_info here... */
3552 result = winreg_get_printer_internal(mem_ctx,
3553 get_session_info_system(),
3554 p->msg_ctx,
3555 lp_servicename(talloc_tos(), snum),
3556 &pinfo2);
3557 if (!W_ERROR_IS_OK(result)) {
3558 DEBUG(4, ("printserver_notify_info: "
3559 "Failed to get printer [%s]\n",
3560 lp_servicename(talloc_tos(), snum)));
3561 continue;
3565 construct_notify_printer_info(p->msg_ctx,
3566 Printer, info,
3567 pinfo2, snum,
3568 &option_type, snum,
3569 mem_ctx);
3571 TALLOC_FREE(pinfo2);
3575 #if 0
3577 * Debugging information, don't delete.
3580 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3581 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3582 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3584 for (i=0; i<info->count; i++) {
3585 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3586 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3587 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3589 #endif
3591 return WERR_OK;
3594 /*******************************************************************
3596 * fill a notify_info struct with info asked
3598 ********************************************************************/
3600 static WERROR printer_notify_info(struct pipes_struct *p,
3601 struct policy_handle *hnd,
3602 struct spoolss_NotifyInfo *info,
3603 TALLOC_CTX *mem_ctx)
3605 int snum;
3606 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3607 int i;
3608 uint32_t id;
3609 struct spoolss_NotifyOption *option;
3610 struct spoolss_NotifyOptionType option_type;
3611 int count,j;
3612 print_queue_struct *queue=NULL;
3613 print_status_struct status;
3614 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3615 WERROR result;
3617 DEBUG(4,("printer_notify_info\n"));
3619 if (!Printer)
3620 return WERR_BADFID;
3622 option = Printer->notify.option;
3623 id = 0x0;
3625 info->version = 2;
3626 info->notifies = NULL;
3627 info->count = 0;
3629 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3630 sending a ffpcn() request first */
3632 if ( !option )
3633 return WERR_BADFID;
3635 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3636 return WERR_BADFID;
3639 /* Maybe we should use the SYSTEM session_info here... */
3640 result = winreg_get_printer_internal(mem_ctx,
3641 get_session_info_system(),
3642 p->msg_ctx,
3643 lp_servicename(talloc_tos(), snum), &pinfo2);
3644 if (!W_ERROR_IS_OK(result)) {
3645 return WERR_BADFID;
3649 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3650 * correct servername.
3652 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3653 if (pinfo2->servername == NULL) {
3654 return WERR_NOMEM;
3657 for (i=0; i<option->count; i++) {
3658 option_type = option->types[i];
3660 switch (option_type.type) {
3661 case PRINTER_NOTIFY_TYPE:
3662 if (construct_notify_printer_info(p->msg_ctx,
3663 Printer, info,
3664 pinfo2, snum,
3665 &option_type, id,
3666 mem_ctx)) {
3667 id--;
3669 break;
3671 case JOB_NOTIFY_TYPE:
3673 count = print_queue_status(p->msg_ctx, snum, &queue,
3674 &status);
3676 for (j=0; j<count; j++) {
3677 construct_notify_jobs_info(p->msg_ctx,
3678 &queue[j], info,
3679 pinfo2, snum,
3680 &option_type,
3681 queue[j].sysjob,
3682 mem_ctx);
3685 SAFE_FREE(queue);
3686 break;
3691 * Debugging information, don't delete.
3694 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3695 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3696 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3698 for (i=0; i<info->count; i++) {
3699 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3700 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3701 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3705 talloc_free(pinfo2);
3706 return WERR_OK;
3709 /****************************************************************
3710 _spoolss_RouterRefreshPrinterChangeNotify
3711 ****************************************************************/
3713 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3714 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3716 struct spoolss_NotifyInfo *info;
3718 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3719 WERROR result = WERR_BADFID;
3721 /* we always have a spoolss_NotifyInfo struct */
3722 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3723 if (!info) {
3724 result = WERR_NOMEM;
3725 goto done;
3728 *r->out.info = info;
3730 if (!Printer) {
3731 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3732 "Invalid handle (%s:%u:%u).\n",
3733 OUR_HANDLE(r->in.handle)));
3734 goto done;
3737 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3740 * We are now using the change value, and
3741 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3742 * I don't have a global notification system, I'm sending back all the
3743 * information even when _NOTHING_ has changed.
3746 /* We need to keep track of the change value to send back in
3747 RRPCN replies otherwise our updates are ignored. */
3749 Printer->notify.fnpcn = true;
3751 if (Printer->notify.cli_chan != NULL &&
3752 Printer->notify.cli_chan->active_connections > 0) {
3753 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3754 "Saving change value in request [%x]\n",
3755 r->in.change_low));
3756 Printer->notify.change = r->in.change_low;
3759 /* just ignore the spoolss_NotifyOption */
3761 switch (Printer->printer_type) {
3762 case SPLHND_SERVER:
3763 result = printserver_notify_info(p, r->in.handle,
3764 info, p->mem_ctx);
3765 break;
3767 case SPLHND_PRINTER:
3768 result = printer_notify_info(p, r->in.handle,
3769 info, p->mem_ctx);
3770 break;
3773 Printer->notify.fnpcn = false;
3775 done:
3776 return result;
3779 /********************************************************************
3780 ********************************************************************/
3782 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3783 const char *servername,
3784 const char *printername,
3785 const char **printername_p)
3787 /* FIXME: add lp_force_printername() */
3789 if (servername == NULL) {
3790 *printername_p = talloc_strdup(mem_ctx, printername);
3791 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3792 return WERR_OK;
3795 if (servername[0] == '\\' && servername[1] == '\\') {
3796 servername += 2;
3799 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3800 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3802 return WERR_OK;
3805 /********************************************************************
3806 ********************************************************************/
3808 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3809 const char *printername)
3811 if (dm == NULL) {
3812 return;
3815 dm->devicename = talloc_strndup(dm, printername,
3816 MIN(strlen(printername), 31));
3819 /********************************************************************
3820 * construct_printer_info_0
3821 * fill a printer_info_0 struct
3822 ********************************************************************/
3824 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3825 const struct auth_session_info *session_info,
3826 struct messaging_context *msg_ctx,
3827 struct spoolss_PrinterInfo2 *info2,
3828 const char *servername,
3829 struct spoolss_PrinterInfo0 *r,
3830 int snum)
3832 int count;
3833 struct printer_session_counter *session_counter;
3834 struct timeval setuptime;
3835 print_status_struct status;
3836 WERROR result;
3838 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3839 if (!W_ERROR_IS_OK(result)) {
3840 return result;
3843 if (servername) {
3844 r->servername = talloc_strdup(mem_ctx, servername);
3845 W_ERROR_HAVE_NO_MEMORY(r->servername);
3846 } else {
3847 r->servername = NULL;
3850 count = print_queue_length(msg_ctx, snum, &status);
3852 /* check if we already have a counter for this printer */
3853 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3854 if (session_counter->snum == snum)
3855 break;
3858 /* it's the first time, add it to the list */
3859 if (session_counter == NULL) {
3860 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3861 W_ERROR_HAVE_NO_MEMORY(session_counter);
3862 session_counter->snum = snum;
3863 session_counter->counter = 0;
3864 DLIST_ADD(counter_list, session_counter);
3867 /* increment it */
3868 session_counter->counter++;
3870 r->cjobs = count;
3871 r->total_jobs = 0;
3872 r->total_bytes = 0;
3874 get_startup_time(&setuptime);
3875 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3877 /* JFM:
3878 * the global_counter should be stored in a TDB as it's common to all the clients
3879 * and should be zeroed on samba startup
3881 r->global_counter = session_counter->counter;
3882 r->total_pages = 0;
3883 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3884 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3885 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3886 r->free_build = SPOOLSS_RELEASE_BUILD;
3887 r->spooling = 0;
3888 r->max_spooling = 0;
3889 r->session_counter = session_counter->counter;
3890 r->num_error_out_of_paper = 0x0;
3891 r->num_error_not_ready = 0x0; /* number of print failure */
3892 r->job_error = 0x0;
3893 r->number_of_processors = 0x1;
3894 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3895 r->high_part_total_bytes = 0x0;
3897 /* ChangeID in milliseconds*/
3898 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3899 info2->sharename, &r->change_id);
3901 r->last_error = WERR_OK;
3902 r->status = nt_printq_status(status.status);
3903 r->enumerate_network_printers = 0x0;
3904 r->c_setprinter = 0x0;
3905 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3906 r->processor_level = 0x6; /* 6 ???*/
3907 r->ref_ic = 0;
3908 r->reserved2 = 0;
3909 r->reserved3 = 0;
3911 return WERR_OK;
3915 /********************************************************************
3916 * construct_printer_info1
3917 * fill a spoolss_PrinterInfo1 struct
3918 ********************************************************************/
3920 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3921 const struct spoolss_PrinterInfo2 *info2,
3922 uint32_t flags,
3923 const char *servername,
3924 struct spoolss_PrinterInfo1 *r,
3925 int snum)
3927 WERROR result;
3929 r->flags = flags;
3931 if (info2->comment == NULL || info2->comment[0] == '\0') {
3932 r->comment = lp_comment(mem_ctx, snum);
3933 } else {
3934 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3936 W_ERROR_HAVE_NO_MEMORY(r->comment);
3938 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3939 if (!W_ERROR_IS_OK(result)) {
3940 return result;
3943 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3944 r->name,
3945 info2->drivername,
3946 r->comment);
3947 W_ERROR_HAVE_NO_MEMORY(r->description);
3949 return WERR_OK;
3952 /********************************************************************
3953 * construct_printer_info2
3954 * fill a spoolss_PrinterInfo2 struct
3955 ********************************************************************/
3957 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3958 struct messaging_context *msg_ctx,
3959 const struct spoolss_PrinterInfo2 *info2,
3960 const char *servername,
3961 struct spoolss_PrinterInfo2 *r,
3962 int snum)
3964 int count;
3965 print_status_struct status;
3966 WERROR result;
3968 count = print_queue_length(msg_ctx, snum, &status);
3970 if (servername) {
3971 r->servername = talloc_strdup(mem_ctx, servername);
3972 W_ERROR_HAVE_NO_MEMORY(r->servername);
3973 } else {
3974 r->servername = NULL;
3977 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3978 if (!W_ERROR_IS_OK(result)) {
3979 return result;
3982 r->sharename = lp_servicename(mem_ctx, snum);
3983 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3984 r->portname = talloc_strdup(mem_ctx, info2->portname);
3985 W_ERROR_HAVE_NO_MEMORY(r->portname);
3986 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3987 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3989 if (info2->comment[0] == '\0') {
3990 r->comment = lp_comment(mem_ctx, snum);
3991 } else {
3992 r->comment = talloc_strdup(mem_ctx, info2->comment);
3994 W_ERROR_HAVE_NO_MEMORY(r->comment);
3996 r->location = talloc_strdup(mem_ctx, info2->location);
3997 if (info2->location[0] == '\0') {
3998 const char *loc = NULL;
3999 NTSTATUS nt_status;
4001 nt_status = printer_list_get_printer(mem_ctx,
4002 info2->sharename,
4003 NULL,
4004 &loc,
4005 NULL);
4006 if (NT_STATUS_IS_OK(nt_status)) {
4007 if (loc != NULL) {
4008 r->location = talloc_strdup(mem_ctx, loc);
4012 W_ERROR_HAVE_NO_MEMORY(r->location);
4014 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4015 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4016 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4017 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4018 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4019 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4020 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4021 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4023 r->attributes = info2->attributes;
4025 r->priority = info2->priority;
4026 r->defaultpriority = info2->defaultpriority;
4027 r->starttime = info2->starttime;
4028 r->untiltime = info2->untiltime;
4029 r->status = nt_printq_status(status.status);
4030 r->cjobs = count;
4031 r->averageppm = info2->averageppm;
4033 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4034 if (!r->devmode) {
4035 DEBUG(8,("Returning NULL Devicemode!\n"));
4038 compose_devicemode_devicename(r->devmode, r->printername);
4040 r->secdesc = NULL;
4042 if (info2->secdesc != NULL) {
4043 /* don't use talloc_steal() here unless you do a deep steal of all
4044 the SEC_DESC members */
4046 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4049 return WERR_OK;
4052 /********************************************************************
4053 * construct_printer_info3
4054 * fill a spoolss_PrinterInfo3 struct
4055 ********************************************************************/
4057 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4058 const struct spoolss_PrinterInfo2 *info2,
4059 const char *servername,
4060 struct spoolss_PrinterInfo3 *r,
4061 int snum)
4063 /* These are the components of the SD we are returning. */
4065 if (info2->secdesc != NULL) {
4066 /* don't use talloc_steal() here unless you do a deep steal of all
4067 the SEC_DESC members */
4069 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4070 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4073 return WERR_OK;
4076 /********************************************************************
4077 * construct_printer_info4
4078 * fill a spoolss_PrinterInfo4 struct
4079 ********************************************************************/
4081 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4082 const struct spoolss_PrinterInfo2 *info2,
4083 const char *servername,
4084 struct spoolss_PrinterInfo4 *r,
4085 int snum)
4087 WERROR result;
4089 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4090 if (!W_ERROR_IS_OK(result)) {
4091 return result;
4094 if (servername) {
4095 r->servername = talloc_strdup(mem_ctx, servername);
4096 W_ERROR_HAVE_NO_MEMORY(r->servername);
4097 } else {
4098 r->servername = NULL;
4101 r->attributes = info2->attributes;
4103 return WERR_OK;
4106 /********************************************************************
4107 * construct_printer_info5
4108 * fill a spoolss_PrinterInfo5 struct
4109 ********************************************************************/
4111 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4112 const struct spoolss_PrinterInfo2 *info2,
4113 const char *servername,
4114 struct spoolss_PrinterInfo5 *r,
4115 int snum)
4117 WERROR result;
4119 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4120 if (!W_ERROR_IS_OK(result)) {
4121 return result;
4124 r->portname = talloc_strdup(mem_ctx, info2->portname);
4125 W_ERROR_HAVE_NO_MEMORY(r->portname);
4127 r->attributes = info2->attributes;
4129 /* these two are not used by NT+ according to MSDN */
4130 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4131 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4133 return WERR_OK;
4136 /********************************************************************
4137 * construct_printer_info_6
4138 * fill a spoolss_PrinterInfo6 struct
4139 ********************************************************************/
4141 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4142 struct messaging_context *msg_ctx,
4143 const struct spoolss_PrinterInfo2 *info2,
4144 const char *servername,
4145 struct spoolss_PrinterInfo6 *r,
4146 int snum)
4148 print_status_struct status;
4150 print_queue_length(msg_ctx, snum, &status);
4152 r->status = nt_printq_status(status.status);
4154 return WERR_OK;
4157 /********************************************************************
4158 * construct_printer_info7
4159 * fill a spoolss_PrinterInfo7 struct
4160 ********************************************************************/
4162 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4163 struct messaging_context *msg_ctx,
4164 const char *servername,
4165 struct spoolss_PrinterInfo7 *r,
4166 int snum)
4168 const struct auth_session_info *session_info = get_session_info_system();
4169 struct GUID guid;
4171 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4172 servername,
4173 lp_servicename(talloc_tos(), snum), &guid, NULL)) {
4174 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4175 r->action = DSPRINT_PUBLISH;
4176 } else {
4177 r->guid = talloc_strdup(mem_ctx, "");
4178 r->action = DSPRINT_UNPUBLISH;
4180 W_ERROR_HAVE_NO_MEMORY(r->guid);
4182 return WERR_OK;
4185 /********************************************************************
4186 * construct_printer_info8
4187 * fill a spoolss_PrinterInfo8 struct
4188 ********************************************************************/
4190 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4191 const struct spoolss_PrinterInfo2 *info2,
4192 const char *servername,
4193 struct spoolss_DeviceModeInfo *r,
4194 int snum)
4196 WERROR result;
4197 const char *printername;
4199 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4200 if (!W_ERROR_IS_OK(result)) {
4201 return result;
4204 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4205 if (!r->devmode) {
4206 DEBUG(8,("Returning NULL Devicemode!\n"));
4209 compose_devicemode_devicename(r->devmode, printername);
4211 return WERR_OK;
4215 /********************************************************************
4216 ********************************************************************/
4218 static bool snum_is_shared_printer(int snum)
4220 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4223 /********************************************************************
4224 Spoolss_enumprinters.
4225 ********************************************************************/
4227 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4228 const struct auth_session_info *session_info,
4229 struct messaging_context *msg_ctx,
4230 const char *servername,
4231 uint32_t level,
4232 uint32_t flags,
4233 union spoolss_PrinterInfo **info_p,
4234 uint32_t *count_p)
4236 int snum;
4237 int n_services = lp_numservices();
4238 union spoolss_PrinterInfo *info = NULL;
4239 uint32_t count = 0;
4240 WERROR result = WERR_OK;
4241 struct dcerpc_binding_handle *b = NULL;
4242 TALLOC_CTX *tmp_ctx = NULL;
4244 tmp_ctx = talloc_new(mem_ctx);
4245 if (!tmp_ctx) {
4246 return WERR_NOMEM;
4249 *count_p = 0;
4250 *info_p = NULL;
4252 for (snum = 0; snum < n_services; snum++) {
4254 const char *printer;
4255 struct spoolss_PrinterInfo2 *info2;
4257 if (!snum_is_shared_printer(snum)) {
4258 continue;
4261 printer = lp_const_servicename(snum);
4263 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4264 printer, snum));
4266 if (b == NULL) {
4267 result = winreg_printer_binding_handle(tmp_ctx,
4268 session_info,
4269 msg_ctx,
4270 &b);
4271 if (!W_ERROR_IS_OK(result)) {
4272 goto out;
4276 result = winreg_create_printer(tmp_ctx, b,
4277 printer);
4278 if (!W_ERROR_IS_OK(result)) {
4279 goto out;
4282 info = talloc_realloc(tmp_ctx, info,
4283 union spoolss_PrinterInfo,
4284 count + 1);
4285 if (!info) {
4286 result = WERR_NOMEM;
4287 goto out;
4290 result = winreg_get_printer(tmp_ctx, b,
4291 printer, &info2);
4292 if (!W_ERROR_IS_OK(result)) {
4293 goto out;
4296 switch (level) {
4297 case 0:
4298 result = construct_printer_info0(info, session_info,
4299 msg_ctx, info2,
4300 servername,
4301 &info[count].info0, snum);
4302 break;
4303 case 1:
4304 result = construct_printer_info1(info, info2, flags,
4305 servername,
4306 &info[count].info1, snum);
4307 break;
4308 case 2:
4309 result = construct_printer_info2(info, msg_ctx, info2,
4310 servername,
4311 &info[count].info2, snum);
4312 break;
4313 case 4:
4314 result = construct_printer_info4(info, info2,
4315 servername,
4316 &info[count].info4, snum);
4317 break;
4318 case 5:
4319 result = construct_printer_info5(info, info2,
4320 servername,
4321 &info[count].info5, snum);
4322 break;
4324 default:
4325 result = WERR_UNKNOWN_LEVEL;
4326 goto out;
4329 if (!W_ERROR_IS_OK(result)) {
4330 goto out;
4333 count++;
4336 out:
4337 if (W_ERROR_IS_OK(result)) {
4338 *info_p = talloc_move(mem_ctx, &info);
4339 *count_p = count;
4342 talloc_free(tmp_ctx);
4344 return result;
4347 /********************************************************************
4348 * handle enumeration of printers at level 0
4349 ********************************************************************/
4351 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4352 const struct auth_session_info *session_info,
4353 struct messaging_context *msg_ctx,
4354 uint32_t flags,
4355 const char *servername,
4356 union spoolss_PrinterInfo **info,
4357 uint32_t *count)
4359 DEBUG(4,("enum_all_printers_info_0\n"));
4361 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4362 servername, 0, flags, info, count);
4366 /********************************************************************
4367 ********************************************************************/
4369 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4370 const struct auth_session_info *session_info,
4371 struct messaging_context *msg_ctx,
4372 const char *servername,
4373 uint32_t flags,
4374 union spoolss_PrinterInfo **info,
4375 uint32_t *count)
4377 DEBUG(4,("enum_all_printers_info_1\n"));
4379 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380 servername, 1, flags, info, count);
4383 /********************************************************************
4384 enum_all_printers_info_1_local.
4385 *********************************************************************/
4387 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4388 const struct auth_session_info *session_info,
4389 struct messaging_context *msg_ctx,
4390 const char *servername,
4391 union spoolss_PrinterInfo **info,
4392 uint32_t *count)
4394 DEBUG(4,("enum_all_printers_info_1_local\n"));
4396 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4397 servername, PRINTER_ENUM_ICON8, info, count);
4400 /********************************************************************
4401 enum_all_printers_info_1_name.
4402 *********************************************************************/
4404 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4405 const struct auth_session_info *session_info,
4406 struct messaging_context *msg_ctx,
4407 const char *servername,
4408 union spoolss_PrinterInfo **info,
4409 uint32_t *count)
4411 const char *s = servername;
4413 DEBUG(4,("enum_all_printers_info_1_name\n"));
4415 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4416 s = servername + 2;
4419 if (!is_myname_or_ipaddr(s)) {
4420 return WERR_INVALID_NAME;
4423 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4424 servername, PRINTER_ENUM_ICON8, info, count);
4427 /********************************************************************
4428 enum_all_printers_info_1_network.
4429 *********************************************************************/
4431 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4432 const struct auth_session_info *session_info,
4433 struct messaging_context *msg_ctx,
4434 const char *servername,
4435 union spoolss_PrinterInfo **info,
4436 uint32_t *count)
4438 const char *s = servername;
4440 DEBUG(4,("enum_all_printers_info_1_network\n"));
4442 /* If we respond to a enum_printers level 1 on our name with flags
4443 set to PRINTER_ENUM_REMOTE with a list of printers then these
4444 printers incorrectly appear in the APW browse list.
4445 Specifically the printers for the server appear at the workgroup
4446 level where all the other servers in the domain are
4447 listed. Windows responds to this call with a
4448 WERR_CAN_NOT_COMPLETE so we should do the same. */
4450 if (servername[0] == '\\' && servername[1] == '\\') {
4451 s = servername + 2;
4454 if (is_myname_or_ipaddr(s)) {
4455 return WERR_CAN_NOT_COMPLETE;
4458 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4459 servername, PRINTER_ENUM_NAME, info, count);
4462 /********************************************************************
4463 * api_spoolss_enumprinters
4465 * called from api_spoolss_enumprinters (see this to understand)
4466 ********************************************************************/
4468 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4469 const struct auth_session_info *session_info,
4470 struct messaging_context *msg_ctx,
4471 const char *servername,
4472 union spoolss_PrinterInfo **info,
4473 uint32_t *count)
4475 DEBUG(4,("enum_all_printers_info_2\n"));
4477 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4478 servername, 2, 0, info, count);
4481 /********************************************************************
4482 * handle enumeration of printers at level 1
4483 ********************************************************************/
4485 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4486 const struct auth_session_info *session_info,
4487 struct messaging_context *msg_ctx,
4488 uint32_t flags,
4489 const char *servername,
4490 union spoolss_PrinterInfo **info,
4491 uint32_t *count)
4493 /* Not all the flags are equals */
4495 if (flags & PRINTER_ENUM_LOCAL) {
4496 return enum_all_printers_info_1_local(mem_ctx, session_info,
4497 msg_ctx, servername, info, count);
4500 if (flags & PRINTER_ENUM_NAME) {
4501 return enum_all_printers_info_1_name(mem_ctx, session_info,
4502 msg_ctx, servername, info,
4503 count);
4506 if (flags & PRINTER_ENUM_NETWORK) {
4507 return enum_all_printers_info_1_network(mem_ctx, session_info,
4508 msg_ctx, servername, info,
4509 count);
4512 return WERR_OK; /* NT4sp5 does that */
4515 /********************************************************************
4516 * handle enumeration of printers at level 2
4517 ********************************************************************/
4519 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4520 const struct auth_session_info *session_info,
4521 struct messaging_context *msg_ctx,
4522 uint32_t flags,
4523 const char *servername,
4524 union spoolss_PrinterInfo **info,
4525 uint32_t *count)
4527 if (flags & PRINTER_ENUM_LOCAL) {
4529 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4530 servername,
4531 info, count);
4534 if (flags & PRINTER_ENUM_NAME) {
4535 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4536 return WERR_INVALID_NAME;
4539 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4540 servername,
4541 info, count);
4544 if (flags & PRINTER_ENUM_REMOTE) {
4545 return WERR_UNKNOWN_LEVEL;
4548 return WERR_OK;
4551 /********************************************************************
4552 * handle enumeration of printers at level 4
4553 ********************************************************************/
4555 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4556 const struct auth_session_info *session_info,
4557 struct messaging_context *msg_ctx,
4558 uint32_t flags,
4559 const char *servername,
4560 union spoolss_PrinterInfo **info,
4561 uint32_t *count)
4563 DEBUG(4,("enum_all_printers_info_4\n"));
4565 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4566 servername, 4, flags, info, count);
4570 /********************************************************************
4571 * handle enumeration of printers at level 5
4572 ********************************************************************/
4574 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4575 const struct auth_session_info *session_info,
4576 struct messaging_context *msg_ctx,
4577 uint32_t flags,
4578 const char *servername,
4579 union spoolss_PrinterInfo **info,
4580 uint32_t *count)
4582 DEBUG(4,("enum_all_printers_info_5\n"));
4584 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585 servername, 5, flags, info, count);
4588 /****************************************************************
4589 _spoolss_EnumPrinters
4590 ****************************************************************/
4592 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4593 struct spoolss_EnumPrinters *r)
4595 const struct auth_session_info *session_info = get_session_info_system();
4596 WERROR result;
4598 /* that's an [in out] buffer */
4600 if (!r->in.buffer && (r->in.offered != 0)) {
4601 return WERR_INVALID_PARAM;
4604 DEBUG(4,("_spoolss_EnumPrinters\n"));
4606 *r->out.needed = 0;
4607 *r->out.count = 0;
4608 *r->out.info = NULL;
4611 * Level 1:
4612 * flags==PRINTER_ENUM_NAME
4613 * if name=="" then enumerates all printers
4614 * if name!="" then enumerate the printer
4615 * flags==PRINTER_ENUM_REMOTE
4616 * name is NULL, enumerate printers
4617 * Level 2: name!="" enumerates printers, name can't be NULL
4618 * Level 3: doesn't exist
4619 * Level 4: does a local registry lookup
4620 * Level 5: same as Level 2
4623 if (r->in.server && r->in.server[0] == '\0') {
4624 r->in.server = NULL;
4627 switch (r->in.level) {
4628 case 0:
4629 result = enumprinters_level0(p->mem_ctx, session_info,
4630 p->msg_ctx, r->in.flags,
4631 r->in.server,
4632 r->out.info, r->out.count);
4633 break;
4634 case 1:
4635 result = enumprinters_level1(p->mem_ctx, session_info,
4636 p->msg_ctx, r->in.flags,
4637 r->in.server,
4638 r->out.info, r->out.count);
4639 break;
4640 case 2:
4641 result = enumprinters_level2(p->mem_ctx, session_info,
4642 p->msg_ctx, r->in.flags,
4643 r->in.server,
4644 r->out.info, r->out.count);
4645 break;
4646 case 4:
4647 result = enumprinters_level4(p->mem_ctx, session_info,
4648 p->msg_ctx, r->in.flags,
4649 r->in.server,
4650 r->out.info, r->out.count);
4651 break;
4652 case 5:
4653 result = enumprinters_level5(p->mem_ctx, session_info,
4654 p->msg_ctx, r->in.flags,
4655 r->in.server,
4656 r->out.info, r->out.count);
4657 break;
4658 default:
4659 return WERR_UNKNOWN_LEVEL;
4662 if (!W_ERROR_IS_OK(result)) {
4663 return result;
4666 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4667 spoolss_EnumPrinters,
4668 *r->out.info, r->in.level,
4669 *r->out.count);
4670 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4671 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4673 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4676 /****************************************************************
4677 _spoolss_GetPrinter
4678 ****************************************************************/
4680 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4681 struct spoolss_GetPrinter *r)
4683 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4684 struct spoolss_PrinterInfo2 *info2 = NULL;
4685 WERROR result = WERR_OK;
4686 int snum;
4688 /* that's an [in out] buffer */
4690 if (!r->in.buffer && (r->in.offered != 0)) {
4691 return WERR_INVALID_PARAM;
4694 *r->out.needed = 0;
4696 if (Printer == NULL) {
4697 return WERR_BADFID;
4700 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4701 return WERR_BADFID;
4704 result = winreg_get_printer_internal(p->mem_ctx,
4705 get_session_info_system(),
4706 p->msg_ctx,
4707 lp_const_servicename(snum),
4708 &info2);
4709 if (!W_ERROR_IS_OK(result)) {
4710 goto out;
4713 switch (r->in.level) {
4714 case 0:
4715 result = construct_printer_info0(p->mem_ctx,
4716 get_session_info_system(),
4717 p->msg_ctx,
4718 info2,
4719 Printer->servername,
4720 &r->out.info->info0,
4721 snum);
4722 break;
4723 case 1:
4724 result = construct_printer_info1(p->mem_ctx, info2,
4725 PRINTER_ENUM_ICON8,
4726 Printer->servername,
4727 &r->out.info->info1, snum);
4728 break;
4729 case 2:
4730 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4731 Printer->servername,
4732 &r->out.info->info2, snum);
4733 break;
4734 case 3:
4735 result = construct_printer_info3(p->mem_ctx, info2,
4736 Printer->servername,
4737 &r->out.info->info3, snum);
4738 break;
4739 case 4:
4740 result = construct_printer_info4(p->mem_ctx, info2,
4741 Printer->servername,
4742 &r->out.info->info4, snum);
4743 break;
4744 case 5:
4745 result = construct_printer_info5(p->mem_ctx, info2,
4746 Printer->servername,
4747 &r->out.info->info5, snum);
4748 break;
4749 case 6:
4750 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4751 Printer->servername,
4752 &r->out.info->info6, snum);
4753 break;
4754 case 7:
4755 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4756 Printer->servername,
4757 &r->out.info->info7, snum);
4758 break;
4759 case 8:
4760 result = construct_printer_info8(p->mem_ctx, info2,
4761 Printer->servername,
4762 &r->out.info->info8, snum);
4763 break;
4764 default:
4765 result = WERR_UNKNOWN_LEVEL;
4766 break;
4768 TALLOC_FREE(info2);
4770 out:
4771 if (!W_ERROR_IS_OK(result)) {
4772 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4773 r->in.level, win_errstr(result)));
4774 TALLOC_FREE(r->out.info);
4775 return result;
4778 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4779 r->out.info, r->in.level);
4780 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4782 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4785 /********************************************************************
4786 ********************************************************************/
4788 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4789 do { \
4790 if (in && strlen(in)) { \
4791 out = talloc_strdup(mem_ctx, in); \
4792 } else { \
4793 out = talloc_strdup(mem_ctx, ""); \
4795 W_ERROR_HAVE_NO_MEMORY(out); \
4796 } while (0);
4798 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4799 do { \
4800 if (in && strlen(in)) { \
4801 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4802 } else { \
4803 out = talloc_strdup(mem_ctx, ""); \
4805 W_ERROR_HAVE_NO_MEMORY(out); \
4806 } while (0);
4808 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4809 const char **string_array,
4810 const char ***presult,
4811 const char *cservername,
4812 const char *arch,
4813 int version)
4815 int i, num_strings = 0;
4816 const char **array = NULL;
4818 if (string_array == NULL) {
4819 return WERR_INVALID_PARAMETER;
4822 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4823 const char *str = NULL;
4825 if (cservername == NULL || arch == NULL) {
4826 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4827 } else {
4828 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4831 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4832 TALLOC_FREE(array);
4833 return WERR_NOMEM;
4837 if (i > 0) {
4838 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4839 &array, &num_strings);
4842 if (presult) {
4843 *presult = array;
4846 return WERR_OK;
4849 /********************************************************************
4850 * fill a spoolss_DriverInfo1 struct
4851 ********************************************************************/
4853 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4854 struct spoolss_DriverInfo1 *r,
4855 const struct spoolss_DriverInfo8 *driver,
4856 const char *servername)
4858 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4859 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4861 return WERR_OK;
4864 /********************************************************************
4865 * fill a spoolss_DriverInfo2 struct
4866 ********************************************************************/
4868 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4869 struct spoolss_DriverInfo2 *r,
4870 const struct spoolss_DriverInfo8 *driver,
4871 const char *servername)
4874 const char *cservername = canon_servername(servername);
4876 r->version = driver->version;
4878 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4879 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4880 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4881 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4883 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4884 driver->architecture,
4885 driver->version,
4886 driver->driver_path,
4887 r->driver_path);
4889 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4890 driver->architecture,
4891 driver->version,
4892 driver->data_file,
4893 r->data_file);
4895 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4896 driver->architecture,
4897 driver->version,
4898 driver->config_file,
4899 r->config_file);
4901 return WERR_OK;
4904 /********************************************************************
4905 * fill a spoolss_DriverInfo3 struct
4906 ********************************************************************/
4908 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4909 struct spoolss_DriverInfo3 *r,
4910 const struct spoolss_DriverInfo8 *driver,
4911 const char *servername)
4913 const char *cservername = canon_servername(servername);
4915 r->version = driver->version;
4917 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4918 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4919 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4920 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4922 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923 driver->architecture,
4924 driver->version,
4925 driver->driver_path,
4926 r->driver_path);
4928 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4929 driver->architecture,
4930 driver->version,
4931 driver->data_file,
4932 r->data_file);
4934 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4935 driver->architecture,
4936 driver->version,
4937 driver->config_file,
4938 r->config_file);
4940 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4941 driver->architecture,
4942 driver->version,
4943 driver->help_file,
4944 r->help_file);
4946 FILL_DRIVER_STRING(mem_ctx,
4947 driver->monitor_name,
4948 r->monitor_name);
4950 FILL_DRIVER_STRING(mem_ctx,
4951 driver->default_datatype,
4952 r->default_datatype);
4954 return string_array_from_driver_info(mem_ctx,
4955 driver->dependent_files,
4956 &r->dependent_files,
4957 cservername,
4958 driver->architecture,
4959 driver->version);
4962 /********************************************************************
4963 * fill a spoolss_DriverInfo4 struct
4964 ********************************************************************/
4966 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4967 struct spoolss_DriverInfo4 *r,
4968 const struct spoolss_DriverInfo8 *driver,
4969 const char *servername)
4971 const char *cservername = canon_servername(servername);
4972 WERROR result;
4974 r->version = driver->version;
4976 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4977 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4978 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4979 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4981 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4982 driver->architecture,
4983 driver->version,
4984 driver->driver_path,
4985 r->driver_path);
4987 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4988 driver->architecture,
4989 driver->version,
4990 driver->data_file,
4991 r->data_file);
4993 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994 driver->architecture,
4995 driver->version,
4996 driver->config_file,
4997 r->config_file);
4999 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000 driver->architecture,
5001 driver->version,
5002 driver->help_file,
5003 r->help_file);
5005 result = string_array_from_driver_info(mem_ctx,
5006 driver->dependent_files,
5007 &r->dependent_files,
5008 cservername,
5009 driver->architecture,
5010 driver->version);
5011 if (!W_ERROR_IS_OK(result)) {
5012 return result;
5015 FILL_DRIVER_STRING(mem_ctx,
5016 driver->monitor_name,
5017 r->monitor_name);
5019 FILL_DRIVER_STRING(mem_ctx,
5020 driver->default_datatype,
5021 r->default_datatype);
5024 result = string_array_from_driver_info(mem_ctx,
5025 driver->previous_names,
5026 &r->previous_names,
5027 NULL, NULL, 0);
5029 return result;
5032 /********************************************************************
5033 * fill a spoolss_DriverInfo5 struct
5034 ********************************************************************/
5036 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5037 struct spoolss_DriverInfo5 *r,
5038 const struct spoolss_DriverInfo8 *driver,
5039 const char *servername)
5041 const char *cservername = canon_servername(servername);
5043 r->version = driver->version;
5045 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5046 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5047 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5048 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5050 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051 driver->architecture,
5052 driver->version,
5053 driver->driver_path,
5054 r->driver_path);
5056 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057 driver->architecture,
5058 driver->version,
5059 driver->data_file,
5060 r->data_file);
5062 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5063 driver->architecture,
5064 driver->version,
5065 driver->config_file,
5066 r->config_file);
5068 r->driver_attributes = 0;
5069 r->config_version = 0;
5070 r->driver_version = 0;
5072 return WERR_OK;
5074 /********************************************************************
5075 * fill a spoolss_DriverInfo6 struct
5076 ********************************************************************/
5078 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5079 struct spoolss_DriverInfo6 *r,
5080 const struct spoolss_DriverInfo8 *driver,
5081 const char *servername)
5083 const char *cservername = canon_servername(servername);
5084 WERROR result;
5086 r->version = driver->version;
5088 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5089 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5090 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5091 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5093 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094 driver->architecture,
5095 driver->version,
5096 driver->driver_path,
5097 r->driver_path);
5099 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5100 driver->architecture,
5101 driver->version,
5102 driver->data_file,
5103 r->data_file);
5105 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5106 driver->architecture,
5107 driver->version,
5108 driver->config_file,
5109 r->config_file);
5111 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5112 driver->architecture,
5113 driver->version,
5114 driver->help_file,
5115 r->help_file);
5117 FILL_DRIVER_STRING(mem_ctx,
5118 driver->monitor_name,
5119 r->monitor_name);
5121 FILL_DRIVER_STRING(mem_ctx,
5122 driver->default_datatype,
5123 r->default_datatype);
5125 result = string_array_from_driver_info(mem_ctx,
5126 driver->dependent_files,
5127 &r->dependent_files,
5128 cservername,
5129 driver->architecture,
5130 driver->version);
5131 if (!W_ERROR_IS_OK(result)) {
5132 return result;
5135 result = string_array_from_driver_info(mem_ctx,
5136 driver->previous_names,
5137 &r->previous_names,
5138 NULL, NULL, 0);
5139 if (!W_ERROR_IS_OK(result)) {
5140 return result;
5143 r->driver_date = driver->driver_date;
5144 r->driver_version = driver->driver_version;
5146 FILL_DRIVER_STRING(mem_ctx,
5147 driver->manufacturer_name,
5148 r->manufacturer_name);
5149 FILL_DRIVER_STRING(mem_ctx,
5150 driver->manufacturer_url,
5151 r->manufacturer_url);
5152 FILL_DRIVER_STRING(mem_ctx,
5153 driver->hardware_id,
5154 r->hardware_id);
5155 FILL_DRIVER_STRING(mem_ctx,
5156 driver->provider,
5157 r->provider);
5159 return WERR_OK;
5162 /********************************************************************
5163 * fill a spoolss_DriverInfo8 struct
5164 ********************************************************************/
5166 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5167 struct spoolss_DriverInfo8 *r,
5168 const struct spoolss_DriverInfo8 *driver,
5169 const char *servername)
5171 const char *cservername = canon_servername(servername);
5172 WERROR result;
5174 r->version = driver->version;
5176 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5177 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5178 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5179 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5181 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182 driver->architecture,
5183 driver->version,
5184 driver->driver_path,
5185 r->driver_path);
5187 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5188 driver->architecture,
5189 driver->version,
5190 driver->data_file,
5191 r->data_file);
5193 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5194 driver->architecture,
5195 driver->version,
5196 driver->config_file,
5197 r->config_file);
5199 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5200 driver->architecture,
5201 driver->version,
5202 driver->help_file,
5203 r->help_file);
5205 FILL_DRIVER_STRING(mem_ctx,
5206 driver->monitor_name,
5207 r->monitor_name);
5209 FILL_DRIVER_STRING(mem_ctx,
5210 driver->default_datatype,
5211 r->default_datatype);
5213 result = string_array_from_driver_info(mem_ctx,
5214 driver->dependent_files,
5215 &r->dependent_files,
5216 cservername,
5217 driver->architecture,
5218 driver->version);
5219 if (!W_ERROR_IS_OK(result)) {
5220 return result;
5223 result = string_array_from_driver_info(mem_ctx,
5224 driver->previous_names,
5225 &r->previous_names,
5226 NULL, NULL, 0);
5227 if (!W_ERROR_IS_OK(result)) {
5228 return result;
5231 r->driver_date = driver->driver_date;
5232 r->driver_version = driver->driver_version;
5234 FILL_DRIVER_STRING(mem_ctx,
5235 driver->manufacturer_name,
5236 r->manufacturer_name);
5237 FILL_DRIVER_STRING(mem_ctx,
5238 driver->manufacturer_url,
5239 r->manufacturer_url);
5240 FILL_DRIVER_STRING(mem_ctx,
5241 driver->hardware_id,
5242 r->hardware_id);
5243 FILL_DRIVER_STRING(mem_ctx,
5244 driver->provider,
5245 r->provider);
5247 FILL_DRIVER_STRING(mem_ctx,
5248 driver->print_processor,
5249 r->print_processor);
5250 FILL_DRIVER_STRING(mem_ctx,
5251 driver->vendor_setup,
5252 r->vendor_setup);
5254 result = string_array_from_driver_info(mem_ctx,
5255 driver->color_profiles,
5256 &r->color_profiles,
5257 NULL, NULL, 0);
5258 if (!W_ERROR_IS_OK(result)) {
5259 return result;
5262 FILL_DRIVER_STRING(mem_ctx,
5263 driver->inf_path,
5264 r->inf_path);
5266 r->printer_driver_attributes = driver->printer_driver_attributes;
5268 result = string_array_from_driver_info(mem_ctx,
5269 driver->core_driver_dependencies,
5270 &r->core_driver_dependencies,
5271 NULL, NULL, 0);
5272 if (!W_ERROR_IS_OK(result)) {
5273 return result;
5276 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5277 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5279 return WERR_OK;
5282 #if 0 /* disabled until marshalling issues are resolved - gd */
5283 /********************************************************************
5284 ********************************************************************/
5286 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5287 struct spoolss_DriverFileInfo *r,
5288 const char *cservername,
5289 const char *file_name,
5290 enum spoolss_DriverFileType file_type,
5291 uint32_t file_version)
5293 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5294 cservername, file_name);
5295 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5296 r->file_type = file_type;
5297 r->file_version = file_version;
5299 return WERR_OK;
5302 /********************************************************************
5303 ********************************************************************/
5305 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5306 const struct spoolss_DriverInfo8 *driver,
5307 const char *cservername,
5308 struct spoolss_DriverFileInfo **info_p,
5309 uint32_t *count_p)
5311 struct spoolss_DriverFileInfo *info = NULL;
5312 uint32_t count = 0;
5313 WERROR result;
5314 uint32_t i;
5316 *info_p = NULL;
5317 *count_p = 0;
5319 if (strlen(driver->driver_path)) {
5320 info = talloc_realloc(mem_ctx, info,
5321 struct spoolss_DriverFileInfo,
5322 count + 1);
5323 W_ERROR_HAVE_NO_MEMORY(info);
5324 result = fill_spoolss_DriverFileInfo(info,
5325 &info[count],
5326 cservername,
5327 driver->driver_path,
5328 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5330 W_ERROR_NOT_OK_RETURN(result);
5331 count++;
5334 if (strlen(driver->config_file)) {
5335 info = talloc_realloc(mem_ctx, info,
5336 struct spoolss_DriverFileInfo,
5337 count + 1);
5338 W_ERROR_HAVE_NO_MEMORY(info);
5339 result = fill_spoolss_DriverFileInfo(info,
5340 &info[count],
5341 cservername,
5342 driver->config_file,
5343 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5345 W_ERROR_NOT_OK_RETURN(result);
5346 count++;
5349 if (strlen(driver->data_file)) {
5350 info = talloc_realloc(mem_ctx, info,
5351 struct spoolss_DriverFileInfo,
5352 count + 1);
5353 W_ERROR_HAVE_NO_MEMORY(info);
5354 result = fill_spoolss_DriverFileInfo(info,
5355 &info[count],
5356 cservername,
5357 driver->data_file,
5358 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5360 W_ERROR_NOT_OK_RETURN(result);
5361 count++;
5364 if (strlen(driver->help_file)) {
5365 info = talloc_realloc(mem_ctx, info,
5366 struct spoolss_DriverFileInfo,
5367 count + 1);
5368 W_ERROR_HAVE_NO_MEMORY(info);
5369 result = fill_spoolss_DriverFileInfo(info,
5370 &info[count],
5371 cservername,
5372 driver->help_file,
5373 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5375 W_ERROR_NOT_OK_RETURN(result);
5376 count++;
5379 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5380 info = talloc_realloc(mem_ctx, info,
5381 struct spoolss_DriverFileInfo,
5382 count + 1);
5383 W_ERROR_HAVE_NO_MEMORY(info);
5384 result = fill_spoolss_DriverFileInfo(info,
5385 &info[count],
5386 cservername,
5387 driver->dependent_files[i],
5388 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5390 W_ERROR_NOT_OK_RETURN(result);
5391 count++;
5394 *info_p = info;
5395 *count_p = count;
5397 return WERR_OK;
5400 /********************************************************************
5401 * fill a spoolss_DriverInfo101 struct
5402 ********************************************************************/
5404 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5405 struct spoolss_DriverInfo101 *r,
5406 const struct spoolss_DriverInfo8 *driver,
5407 const char *servername)
5409 const char *cservername = canon_servername(servername);
5410 WERROR result;
5412 r->version = driver->version;
5414 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5415 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5416 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5417 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5419 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5420 cservername,
5421 &r->file_info,
5422 &r->file_count);
5423 if (!W_ERROR_IS_OK(result)) {
5424 return result;
5427 FILL_DRIVER_STRING(mem_ctx,
5428 driver->monitor_name,
5429 r->monitor_name);
5431 FILL_DRIVER_STRING(mem_ctx,
5432 driver->default_datatype,
5433 r->default_datatype);
5435 result = string_array_from_driver_info(mem_ctx,
5436 driver->previous_names,
5437 &r->previous_names,
5438 NULL, NULL, 0);
5439 if (!W_ERROR_IS_OK(result)) {
5440 return result;
5443 r->driver_date = driver->driver_date;
5444 r->driver_version = driver->driver_version;
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->manufacturer_name,
5448 r->manufacturer_name);
5449 FILL_DRIVER_STRING(mem_ctx,
5450 driver->manufacturer_url,
5451 r->manufacturer_url);
5452 FILL_DRIVER_STRING(mem_ctx,
5453 driver->hardware_id,
5454 r->hardware_id);
5455 FILL_DRIVER_STRING(mem_ctx,
5456 driver->provider,
5457 r->provider);
5459 return WERR_OK;
5461 #endif
5462 /********************************************************************
5463 ********************************************************************/
5465 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5466 const struct auth_session_info *session_info,
5467 struct messaging_context *msg_ctx,
5468 uint32_t level,
5469 union spoolss_DriverInfo *r,
5470 int snum,
5471 const char *servername,
5472 const char *architecture,
5473 uint32_t version)
5475 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5476 struct spoolss_DriverInfo8 *driver;
5477 WERROR result;
5478 struct dcerpc_binding_handle *b;
5479 TALLOC_CTX *tmp_ctx = NULL;
5481 if (level == 101) {
5482 return WERR_UNKNOWN_LEVEL;
5485 tmp_ctx = talloc_new(mem_ctx);
5486 if (!tmp_ctx) {
5487 return WERR_NOMEM;
5490 result = winreg_printer_binding_handle(tmp_ctx,
5491 session_info,
5492 msg_ctx,
5493 &b);
5494 if (!W_ERROR_IS_OK(result)) {
5495 goto done;
5498 result = winreg_get_printer(tmp_ctx, b,
5499 lp_const_servicename(snum),
5500 &pinfo2);
5502 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5503 win_errstr(result)));
5505 if (!W_ERROR_IS_OK(result)) {
5506 result = WERR_INVALID_PRINTER_NAME;
5507 goto done;
5510 result = winreg_get_driver(tmp_ctx, b,
5511 architecture,
5512 pinfo2->drivername, version, &driver);
5514 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5515 win_errstr(result)));
5517 if (!W_ERROR_IS_OK(result)) {
5519 * Is this a W2k client ?
5522 if (version < 3) {
5523 result = WERR_UNKNOWN_PRINTER_DRIVER;
5524 goto done;
5527 /* Yes - try again with a WinNT driver. */
5528 version = 2;
5529 result = winreg_get_driver(tmp_ctx, b,
5530 architecture,
5531 pinfo2->drivername,
5532 version, &driver);
5533 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5534 win_errstr(result)));
5535 if (!W_ERROR_IS_OK(result)) {
5536 result = WERR_UNKNOWN_PRINTER_DRIVER;
5537 goto done;
5541 /* these are allocated on mem_ctx and not tmp_ctx because they are
5542 * the 'return value' and need to utlive this call */
5543 switch (level) {
5544 case 1:
5545 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5546 break;
5547 case 2:
5548 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5549 break;
5550 case 3:
5551 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5552 break;
5553 case 4:
5554 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5555 break;
5556 case 5:
5557 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5558 break;
5559 case 6:
5560 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5561 break;
5562 case 8:
5563 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5564 break;
5565 #if 0 /* disabled until marshalling issues are resolved - gd */
5566 case 101:
5567 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5568 break;
5569 #endif
5570 default:
5571 result = WERR_UNKNOWN_LEVEL;
5572 break;
5575 done:
5576 talloc_free(tmp_ctx);
5577 return result;
5580 /****************************************************************
5581 _spoolss_GetPrinterDriver2
5582 ****************************************************************/
5584 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5585 struct spoolss_GetPrinterDriver2 *r)
5587 struct printer_handle *printer;
5588 WERROR result;
5590 int snum;
5592 /* that's an [in out] buffer */
5594 if (!r->in.buffer && (r->in.offered != 0)) {
5595 return WERR_INVALID_PARAM;
5598 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5600 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5601 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5602 return WERR_INVALID_PRINTER_NAME;
5605 *r->out.needed = 0;
5606 *r->out.server_major_version = 0;
5607 *r->out.server_minor_version = 0;
5609 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5610 return WERR_BADFID;
5613 result = construct_printer_driver_info_level(p->mem_ctx,
5614 get_session_info_system(),
5615 p->msg_ctx,
5616 r->in.level, r->out.info,
5617 snum, printer->servername,
5618 r->in.architecture,
5619 r->in.client_major_version);
5620 if (!W_ERROR_IS_OK(result)) {
5621 TALLOC_FREE(r->out.info);
5622 return result;
5625 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5626 r->out.info, r->in.level);
5627 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5629 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5633 /****************************************************************
5634 _spoolss_StartPagePrinter
5635 ****************************************************************/
5637 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5638 struct spoolss_StartPagePrinter *r)
5640 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5642 if (!Printer) {
5643 DEBUG(3,("_spoolss_StartPagePrinter: "
5644 "Error in startpageprinter printer handle\n"));
5645 return WERR_BADFID;
5648 Printer->page_started = true;
5649 return WERR_OK;
5652 /****************************************************************
5653 _spoolss_EndPagePrinter
5654 ****************************************************************/
5656 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5657 struct spoolss_EndPagePrinter *r)
5659 int snum;
5661 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5663 if (!Printer) {
5664 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5665 OUR_HANDLE(r->in.handle)));
5666 return WERR_BADFID;
5669 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5670 return WERR_BADFID;
5672 Printer->page_started = false;
5673 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5675 return WERR_OK;
5678 /****************************************************************
5679 _spoolss_StartDocPrinter
5680 ****************************************************************/
5682 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5683 struct spoolss_StartDocPrinter *r)
5685 struct spoolss_DocumentInfo1 *info_1;
5686 int snum;
5687 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5688 WERROR werr;
5689 char *rhost;
5690 int rc;
5692 if (!Printer) {
5693 DEBUG(2,("_spoolss_StartDocPrinter: "
5694 "Invalid handle (%s:%u:%u)\n",
5695 OUR_HANDLE(r->in.handle)));
5696 return WERR_BADFID;
5699 if (Printer->jobid) {
5700 DEBUG(2, ("_spoolss_StartDocPrinter: "
5701 "StartDocPrinter called twice! "
5702 "(existing jobid = %d)\n", Printer->jobid));
5703 return WERR_INVALID_HANDLE;
5706 if (r->in.level != 1) {
5707 return WERR_UNKNOWN_LEVEL;
5710 info_1 = r->in.info.info1;
5713 * a nice thing with NT is it doesn't listen to what you tell it.
5714 * when asked to send _only_ RAW datas, it tries to send datas
5715 * in EMF format.
5717 * So I add checks like in NT Server ...
5720 if (info_1->datatype) {
5721 if (strcmp(info_1->datatype, "RAW") != 0) {
5722 *r->out.job_id = 0;
5723 return WERR_INVALID_DATATYPE;
5727 /* get the share number of the printer */
5728 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5729 return WERR_BADFID;
5732 rc = get_remote_hostname(p->remote_address,
5733 &rhost,
5734 p->mem_ctx);
5735 if (rc < 0) {
5736 return WERR_NOMEM;
5738 if (strequal(rhost,"UNKNOWN")) {
5739 rhost = tsocket_address_inet_addr_string(p->remote_address,
5740 p->mem_ctx);
5741 if (rhost == NULL) {
5742 return WERR_NOMEM;
5746 werr = print_job_start(p->session_info,
5747 p->msg_ctx,
5748 rhost,
5749 snum,
5750 info_1->document_name,
5751 info_1->output_file,
5752 Printer->devmode,
5753 &Printer->jobid);
5755 /* An error occured in print_job_start() so return an appropriate
5756 NT error code. */
5758 if (!W_ERROR_IS_OK(werr)) {
5759 return werr;
5762 Printer->document_started = true;
5763 *r->out.job_id = Printer->jobid;
5765 return WERR_OK;
5768 /****************************************************************
5769 _spoolss_EndDocPrinter
5770 ****************************************************************/
5772 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5773 struct spoolss_EndDocPrinter *r)
5775 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5776 NTSTATUS status;
5777 int snum;
5779 if (!Printer) {
5780 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5781 OUR_HANDLE(r->in.handle)));
5782 return WERR_BADFID;
5785 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5786 return WERR_BADFID;
5789 Printer->document_started = false;
5790 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 DEBUG(2, ("_spoolss_EndDocPrinter: "
5793 "print_job_end failed [%s]\n",
5794 nt_errstr(status)));
5797 Printer->jobid = 0;
5798 return ntstatus_to_werror(status);
5801 /****************************************************************
5802 _spoolss_WritePrinter
5803 ****************************************************************/
5805 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5806 struct spoolss_WritePrinter *r)
5808 ssize_t buffer_written;
5809 int snum;
5810 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5812 if (!Printer) {
5813 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5814 OUR_HANDLE(r->in.handle)));
5815 *r->out.num_written = r->in._data_size;
5816 return WERR_BADFID;
5819 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5820 return WERR_BADFID;
5822 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5823 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5824 snum, Printer->jobid,
5825 (const char *)r->in.data.data,
5826 (size_t)r->in._data_size);
5827 if (buffer_written == (ssize_t)-1) {
5828 *r->out.num_written = 0;
5829 if (errno == ENOSPC)
5830 return WERR_NO_SPOOL_SPACE;
5831 else
5832 return WERR_ACCESS_DENIED;
5835 *r->out.num_written = r->in._data_size;
5837 return WERR_OK;
5840 /********************************************************************
5841 * api_spoolss_getprinter
5842 * called from the spoolss dispatcher
5844 ********************************************************************/
5846 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5847 struct pipes_struct *p)
5849 const struct auth_session_info *session_info = p->session_info;
5850 int snum;
5851 WERROR errcode = WERR_BADFUNC;
5852 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5854 if (!Printer) {
5855 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5856 OUR_HANDLE(handle)));
5857 return WERR_BADFID;
5860 if (!get_printer_snum(p, handle, &snum, NULL))
5861 return WERR_BADFID;
5863 switch (command) {
5864 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5865 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5866 break;
5867 case SPOOLSS_PRINTER_CONTROL_RESUME:
5868 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5869 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5870 break;
5871 case SPOOLSS_PRINTER_CONTROL_PURGE:
5872 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5873 break;
5874 default:
5875 return WERR_UNKNOWN_LEVEL;
5878 return errcode;
5882 /****************************************************************
5883 _spoolss_AbortPrinter
5884 * From MSDN: "Deletes printer's spool file if printer is configured
5885 * for spooling"
5886 ****************************************************************/
5888 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5889 struct spoolss_AbortPrinter *r)
5891 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5892 int snum;
5893 WERROR errcode = WERR_OK;
5895 if (!Printer) {
5896 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5897 OUR_HANDLE(r->in.handle)));
5898 return WERR_BADFID;
5901 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5902 return WERR_BADFID;
5904 if (!Printer->document_started) {
5905 return WERR_SPL_NO_STARTDOC;
5908 errcode = print_job_delete(p->session_info,
5909 p->msg_ctx,
5910 snum,
5911 Printer->jobid);
5913 return errcode;
5916 /********************************************************************
5917 * called by spoolss_api_setprinter
5918 * when updating a printer description
5919 ********************************************************************/
5921 static WERROR update_printer_sec(struct policy_handle *handle,
5922 struct pipes_struct *p,
5923 struct sec_desc_buf *secdesc_ctr)
5925 struct spoolss_security_descriptor *new_secdesc = NULL;
5926 struct spoolss_security_descriptor *old_secdesc = NULL;
5927 const char *printer;
5928 WERROR result;
5929 int snum;
5930 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5931 struct dcerpc_binding_handle *b;
5932 TALLOC_CTX *tmp_ctx = NULL;
5934 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5935 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5936 OUR_HANDLE(handle)));
5938 result = WERR_BADFID;
5939 goto done;
5942 if (secdesc_ctr == NULL) {
5943 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5944 result = WERR_INVALID_PARAM;
5945 goto done;
5947 printer = lp_const_servicename(snum);
5949 /* Check the user has permissions to change the security
5950 descriptor. By experimentation with two NT machines, the user
5951 requires Full Access to the printer to change security
5952 information. */
5954 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5955 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5956 result = WERR_ACCESS_DENIED;
5957 goto done;
5960 tmp_ctx = talloc_new(p->mem_ctx);
5961 if (!tmp_ctx) {
5962 return WERR_NOMEM;
5965 result = winreg_printer_binding_handle(tmp_ctx,
5966 get_session_info_system(),
5967 p->msg_ctx,
5968 &b);
5969 if (!W_ERROR_IS_OK(result)) {
5970 goto done;
5973 /* NT seems to like setting the security descriptor even though
5974 nothing may have actually changed. */
5975 result = winreg_get_printer_secdesc(tmp_ctx, b,
5976 printer,
5977 &old_secdesc);
5978 if (!W_ERROR_IS_OK(result)) {
5979 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5980 result = WERR_BADFID;
5981 goto done;
5984 if (DEBUGLEVEL >= 10) {
5985 struct security_acl *the_acl;
5986 int i;
5988 the_acl = old_secdesc->dacl;
5989 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5990 printer, the_acl->num_aces));
5992 for (i = 0; i < the_acl->num_aces; i++) {
5993 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5994 &the_acl->aces[i].trustee),
5995 the_acl->aces[i].access_mask));
5998 the_acl = secdesc_ctr->sd->dacl;
6000 if (the_acl) {
6001 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6002 printer, the_acl->num_aces));
6004 for (i = 0; i < the_acl->num_aces; i++) {
6005 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6006 &the_acl->aces[i].trustee),
6007 the_acl->aces[i].access_mask));
6009 } else {
6010 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6014 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6015 if (new_secdesc == NULL) {
6016 result = WERR_NOMEM;
6017 goto done;
6020 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6021 result = WERR_OK;
6022 goto done;
6025 result = winreg_set_printer_secdesc(tmp_ctx, b,
6026 printer,
6027 new_secdesc);
6029 done:
6030 talloc_free(tmp_ctx);
6031 return result;
6034 /********************************************************************
6035 Canonicalize printer info from a client
6036 ********************************************************************/
6038 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6039 struct spoolss_SetPrinterInfo2 *info2,
6040 int snum)
6042 fstring printername;
6043 const char *p;
6045 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6046 "portname=%s drivername=%s comment=%s location=%s\n",
6047 info2->servername, info2->printername, info2->sharename,
6048 info2->portname, info2->drivername, info2->comment,
6049 info2->location));
6051 /* we force some elements to "correct" values */
6052 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6053 if (info2->servername == NULL) {
6054 return false;
6056 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6057 if (info2->sharename == NULL) {
6058 return false;
6061 /* check to see if we allow printername != sharename */
6062 if (lp_force_printername(snum)) {
6063 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6064 lp_netbios_name(), info2->sharename);
6065 } else {
6066 /* make sure printername is in \\server\printername format */
6067 fstrcpy(printername, info2->printername);
6068 p = printername;
6069 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6070 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6071 p++;
6074 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6075 lp_netbios_name(), p);
6077 if (info2->printername == NULL) {
6078 return false;
6081 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6082 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6084 return true;
6087 /****************************************************************************
6088 ****************************************************************************/
6090 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6092 char *cmd = lp_addport_cmd(talloc_tos());
6093 char *command = NULL;
6094 int ret;
6095 bool is_print_op = false;
6097 if ( !*cmd ) {
6098 return WERR_ACCESS_DENIED;
6101 command = talloc_asprintf(ctx,
6102 "%s \"%s\" \"%s\"", cmd, portname, uri );
6103 if (!command) {
6104 return WERR_NOMEM;
6107 if ( token )
6108 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6110 DEBUG(10,("Running [%s]\n", command));
6112 /********* BEGIN SePrintOperatorPrivilege **********/
6114 if ( is_print_op )
6115 become_root();
6117 ret = smbrun(command, NULL);
6119 if ( is_print_op )
6120 unbecome_root();
6122 /********* END SePrintOperatorPrivilege **********/
6124 DEBUGADD(10,("returned [%d]\n", ret));
6126 TALLOC_FREE(command);
6128 if ( ret != 0 ) {
6129 return WERR_ACCESS_DENIED;
6132 return WERR_OK;
6135 /****************************************************************************
6136 ****************************************************************************/
6138 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6139 int snum)
6142 * As we do not know if we are embedded in the file server process
6143 * or not, we have to pretend that all shares are in use.
6145 return true;
6148 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6149 struct spoolss_SetPrinterInfo2 *info2,
6150 const char *remote_machine,
6151 struct messaging_context *msg_ctx)
6153 char *cmd = lp_addprinter_cmd(talloc_tos());
6154 char **qlines;
6155 char *command = NULL;
6156 int numlines;
6157 int ret;
6158 int fd;
6159 bool is_print_op = false;
6161 if (!remote_machine) {
6162 return false;
6165 command = talloc_asprintf(ctx,
6166 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6167 cmd, info2->printername, info2->sharename,
6168 info2->portname, info2->drivername,
6169 info2->location, info2->comment, remote_machine);
6170 if (!command) {
6171 return false;
6174 if ( token )
6175 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6177 DEBUG(10,("Running [%s]\n", command));
6179 /********* BEGIN SePrintOperatorPrivilege **********/
6181 if ( is_print_op )
6182 become_root();
6184 if ( (ret = smbrun(command, &fd)) == 0 ) {
6185 /* Tell everyone we updated smb.conf. */
6186 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6189 if ( is_print_op )
6190 unbecome_root();
6192 /********* END SePrintOperatorPrivilege **********/
6194 DEBUGADD(10,("returned [%d]\n", ret));
6196 TALLOC_FREE(command);
6198 if ( ret != 0 ) {
6199 if (fd != -1)
6200 close(fd);
6201 return false;
6204 /* reload our services immediately */
6205 become_root();
6206 reload_services(NULL, spoolss_conn_snum_used, false);
6207 unbecome_root();
6209 numlines = 0;
6210 /* Get lines and convert them back to dos-codepage */
6211 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6212 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6213 close(fd);
6215 /* Set the portname to what the script says the portname should be. */
6216 /* but don't require anything to be return from the script exit a good error code */
6218 if (numlines) {
6219 /* Set the portname to what the script says the portname should be. */
6220 info2->portname = talloc_strdup(ctx, qlines[0]);
6221 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6224 TALLOC_FREE(qlines);
6225 return true;
6228 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6229 const struct auth_session_info *session_info,
6230 struct messaging_context *msg_ctx,
6231 int snum,
6232 struct spoolss_SetPrinterInfo2 *printer,
6233 struct spoolss_PrinterInfo2 *old_printer)
6235 bool force_update = (old_printer == NULL);
6236 const char *dnsdomname;
6237 const char *longname;
6238 const char *uncname;
6239 const char *spooling;
6240 DATA_BLOB buffer;
6241 WERROR result = WERR_OK;
6242 struct dcerpc_binding_handle *b;
6243 TALLOC_CTX *tmp_ctx;
6244 bool ok;
6246 tmp_ctx = talloc_new(mem_ctx);
6247 if (!tmp_ctx) {
6248 return WERR_NOMEM;
6251 result = winreg_printer_binding_handle(tmp_ctx,
6252 session_info,
6253 msg_ctx,
6254 &b);
6255 if (!W_ERROR_IS_OK(result)) {
6256 goto done;
6259 if (printer->drivername != NULL &&
6260 (force_update ||
6261 !strequal(printer->drivername, old_printer->drivername))) {
6262 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6263 if (!ok) {
6264 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6265 result = WERR_INVALID_DATA;
6266 goto done;
6268 result = winreg_set_printer_dataex(tmp_ctx, b,
6269 printer->sharename,
6270 SPOOL_DSSPOOLER_KEY,
6271 SPOOL_REG_DRIVERNAME,
6272 REG_SZ,
6273 buffer.data,
6274 buffer.length);
6275 if (!W_ERROR_IS_OK(result)) {
6276 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6277 goto done;
6280 if (!force_update) {
6281 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6282 printer->drivername));
6284 notify_printer_driver(server_event_context(), msg_ctx,
6285 snum, printer->drivername ?
6286 printer->drivername : "");
6290 if (printer->comment != NULL &&
6291 (force_update ||
6292 !strequal(printer->comment, old_printer->comment))) {
6293 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6294 if (!ok) {
6295 DEBUG(0, ("comment data corrupted\n"));
6296 result = WERR_INVALID_DATA;
6297 goto done;
6299 result = winreg_set_printer_dataex(tmp_ctx, b,
6300 printer->sharename,
6301 SPOOL_DSSPOOLER_KEY,
6302 SPOOL_REG_DESCRIPTION,
6303 REG_SZ,
6304 buffer.data,
6305 buffer.length);
6306 if (!W_ERROR_IS_OK(result)) {
6307 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6308 goto done;
6311 if (!force_update) {
6312 notify_printer_comment(server_event_context(), msg_ctx,
6313 snum, printer->comment ?
6314 printer->comment : "");
6318 if (printer->sharename != NULL &&
6319 (force_update ||
6320 !strequal(printer->sharename, old_printer->sharename))) {
6321 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6322 if (!ok) {
6323 DEBUG(0, ("sharename data corrupted\n"));
6324 result = WERR_INVALID_DATA;
6325 goto done;
6327 result = winreg_set_printer_dataex(tmp_ctx, b,
6328 printer->sharename,
6329 SPOOL_DSSPOOLER_KEY,
6330 SPOOL_REG_PRINTSHARENAME,
6331 REG_SZ,
6332 buffer.data,
6333 buffer.length);
6334 if (!W_ERROR_IS_OK(result)) {
6335 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6336 goto done;
6339 if (!force_update) {
6340 notify_printer_sharename(server_event_context(),
6341 msg_ctx,
6342 snum, printer->sharename ?
6343 printer->sharename : "");
6347 if (printer->printername != NULL &&
6348 (force_update ||
6349 !strequal(printer->printername, old_printer->printername))) {
6350 const char *p;
6352 p = strrchr(printer->printername, '\\' );
6353 if (p != NULL) {
6354 p++;
6355 } else {
6356 p = printer->printername;
6359 ok = push_reg_sz(tmp_ctx, &buffer, p);
6360 if (!ok) {
6361 DEBUG(0, ("printername data corrupted\n"));
6362 result = WERR_INVALID_DATA;
6363 goto done;
6365 result = winreg_set_printer_dataex(tmp_ctx, b,
6366 printer->sharename,
6367 SPOOL_DSSPOOLER_KEY,
6368 SPOOL_REG_PRINTERNAME,
6369 REG_SZ,
6370 buffer.data,
6371 buffer.length);
6372 if (!W_ERROR_IS_OK(result)) {
6373 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6374 goto done;
6377 if (!force_update) {
6378 notify_printer_printername(server_event_context(),
6379 msg_ctx, snum, p ? p : "");
6383 if (printer->portname != NULL &&
6384 (force_update ||
6385 !strequal(printer->portname, old_printer->portname))) {
6386 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6387 if (!ok) {
6388 DEBUG(0, ("portname data corrupted\n"));
6389 result = WERR_INVALID_DATA;
6390 goto done;
6392 result = winreg_set_printer_dataex(tmp_ctx, b,
6393 printer->sharename,
6394 SPOOL_DSSPOOLER_KEY,
6395 SPOOL_REG_PORTNAME,
6396 REG_SZ,
6397 buffer.data,
6398 buffer.length);
6399 if (!W_ERROR_IS_OK(result)) {
6400 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6401 goto done;
6404 if (!force_update) {
6405 notify_printer_port(server_event_context(),
6406 msg_ctx, snum, printer->portname ?
6407 printer->portname : "");
6411 if (printer->location != NULL &&
6412 (force_update ||
6413 !strequal(printer->location, old_printer->location))) {
6414 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6415 if (!ok) {
6416 DEBUG(0, ("location data corrupted\n"));
6417 result = WERR_INVALID_DATA;
6418 goto done;
6420 result = winreg_set_printer_dataex(tmp_ctx, b,
6421 printer->sharename,
6422 SPOOL_DSSPOOLER_KEY,
6423 SPOOL_REG_LOCATION,
6424 REG_SZ,
6425 buffer.data,
6426 buffer.length);
6427 if (!W_ERROR_IS_OK(result)) {
6428 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6429 goto done;
6432 if (!force_update) {
6433 notify_printer_location(server_event_context(),
6434 msg_ctx, snum,
6435 printer->location ?
6436 printer->location : "");
6440 if (printer->sepfile != NULL &&
6441 (force_update ||
6442 !strequal(printer->sepfile, old_printer->sepfile))) {
6443 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6444 if (!ok) {
6445 DEBUG(0, ("sepfile data corrupted\n"));
6446 result = WERR_INVALID_DATA;
6447 goto done;
6449 result = winreg_set_printer_dataex(tmp_ctx, b,
6450 printer->sharename,
6451 SPOOL_DSSPOOLER_KEY,
6452 SPOOL_REG_PRINTSEPARATORFILE,
6453 REG_SZ,
6454 buffer.data,
6455 buffer.length);
6456 if (!W_ERROR_IS_OK(result)) {
6457 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6458 goto done;
6461 if (!force_update) {
6462 notify_printer_sepfile(server_event_context(),
6463 msg_ctx, snum,
6464 printer->sepfile ?
6465 printer->sepfile : "");
6469 if (printer->starttime != 0 &&
6470 (force_update ||
6471 printer->starttime != old_printer->starttime)) {
6472 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6473 SIVAL(buffer.data, 0, printer->starttime);
6474 result = winreg_set_printer_dataex(tmp_ctx, b,
6475 printer->sharename,
6476 SPOOL_DSSPOOLER_KEY,
6477 SPOOL_REG_PRINTSTARTTIME,
6478 REG_DWORD,
6479 buffer.data,
6480 buffer.length);
6481 if (!W_ERROR_IS_OK(result)) {
6482 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6483 goto done;
6487 if (printer->untiltime != 0 &&
6488 (force_update ||
6489 printer->untiltime != old_printer->untiltime)) {
6490 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6491 SIVAL(buffer.data, 0, printer->untiltime);
6492 result = winreg_set_printer_dataex(tmp_ctx, b,
6493 printer->sharename,
6494 SPOOL_DSSPOOLER_KEY,
6495 SPOOL_REG_PRINTENDTIME,
6496 REG_DWORD,
6497 buffer.data,
6498 buffer.length);
6499 if (!W_ERROR_IS_OK(result)) {
6500 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6501 goto done;
6505 if (force_update || printer->priority != old_printer->priority) {
6506 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6507 SIVAL(buffer.data, 0, printer->priority);
6508 result = winreg_set_printer_dataex(tmp_ctx, b,
6509 printer->sharename,
6510 SPOOL_DSSPOOLER_KEY,
6511 SPOOL_REG_PRIORITY,
6512 REG_DWORD,
6513 buffer.data,
6514 buffer.length);
6515 if (!W_ERROR_IS_OK(result)) {
6516 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6517 goto done;
6521 if (force_update || printer->attributes != old_printer->attributes) {
6522 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6523 SIVAL(buffer.data, 0, (printer->attributes &
6524 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6525 result = winreg_set_printer_dataex(tmp_ctx, b,
6526 printer->sharename,
6527 SPOOL_DSSPOOLER_KEY,
6528 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6529 REG_DWORD,
6530 buffer.data,
6531 buffer.length);
6532 if (!W_ERROR_IS_OK(result)) {
6533 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6534 goto done;
6537 switch (printer->attributes & 0x3) {
6538 case 0:
6539 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6540 break;
6541 case 1:
6542 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6543 break;
6544 case 2:
6545 spooling = SPOOL_REGVAL_PRINTDIRECT;
6546 break;
6547 default:
6548 spooling = "unknown";
6550 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6551 if (!ok) {
6552 DEBUG(0, ("printSpooling data corrupted\n"));
6553 result = WERR_INVALID_DATA;
6554 goto done;
6556 winreg_set_printer_dataex(tmp_ctx, b,
6557 printer->sharename,
6558 SPOOL_DSSPOOLER_KEY,
6559 SPOOL_REG_PRINTSPOOLING,
6560 REG_SZ,
6561 buffer.data,
6562 buffer.length);
6565 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6566 if (!ok) {
6567 DEBUG(0, ("shortServerName data corrupted\n"));
6568 result = WERR_INVALID_DATA;
6569 goto done;
6571 result = winreg_set_printer_dataex(tmp_ctx, b,
6572 printer->sharename,
6573 SPOOL_DSSPOOLER_KEY,
6574 SPOOL_REG_SHORTSERVERNAME,
6575 REG_SZ,
6576 buffer.data,
6577 buffer.length);
6578 if (!W_ERROR_IS_OK(result)) {
6579 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6580 goto done;
6583 dnsdomname = get_mydnsfullname();
6584 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6585 longname = talloc_strdup(tmp_ctx, dnsdomname);
6586 } else {
6587 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6589 if (longname == NULL) {
6590 result = WERR_NOMEM;
6591 goto done;
6594 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6595 if (!ok) {
6596 DEBUG(0, ("longname data corrupted\n"));
6597 result = WERR_INVALID_DATA;
6598 goto done;
6600 result = winreg_set_printer_dataex(tmp_ctx, b,
6601 printer->sharename,
6602 SPOOL_DSSPOOLER_KEY,
6603 SPOOL_REG_SERVERNAME,
6604 REG_SZ,
6605 buffer.data,
6606 buffer.length);
6607 if (!W_ERROR_IS_OK(result)) {
6608 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6609 goto done;
6612 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6613 lp_netbios_name(), printer->sharename);
6614 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6615 if (!ok) {
6616 DEBUG(0, ("uncName data corrupted\n"));
6617 result = WERR_INVALID_DATA;
6618 goto done;
6620 result = winreg_set_printer_dataex(tmp_ctx, b,
6621 printer->sharename,
6622 SPOOL_DSSPOOLER_KEY,
6623 SPOOL_REG_UNCNAME,
6624 REG_SZ,
6625 buffer.data,
6626 buffer.length);
6627 if (!W_ERROR_IS_OK(result)) {
6628 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6629 goto done;
6632 done:
6633 talloc_free(tmp_ctx);
6634 return result;
6637 /********************************************************************
6638 * Called by spoolss_api_setprinter
6639 * when updating a printer description.
6640 ********************************************************************/
6642 static WERROR update_printer(struct pipes_struct *p,
6643 struct policy_handle *handle,
6644 struct spoolss_SetPrinterInfoCtr *info_ctr,
6645 struct spoolss_DeviceMode *devmode)
6647 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6648 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6649 struct spoolss_PrinterInfo2 *old_printer;
6650 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6651 int snum;
6652 WERROR result = WERR_OK;
6653 TALLOC_CTX *tmp_ctx;
6654 struct dcerpc_binding_handle *b;
6656 DEBUG(8,("update_printer\n"));
6658 tmp_ctx = talloc_new(p->mem_ctx);
6659 if (tmp_ctx == NULL) {
6660 return WERR_NOMEM;
6663 if (!Printer) {
6664 result = WERR_BADFID;
6665 goto done;
6668 if (!get_printer_snum(p, handle, &snum, NULL)) {
6669 result = WERR_BADFID;
6670 goto done;
6673 result = winreg_printer_binding_handle(tmp_ctx,
6674 get_session_info_system(),
6675 p->msg_ctx,
6676 &b);
6677 if (!W_ERROR_IS_OK(result)) {
6678 goto done;
6681 result = winreg_get_printer(tmp_ctx, b,
6682 lp_const_servicename(snum),
6683 &old_printer);
6684 if (!W_ERROR_IS_OK(result)) {
6685 result = WERR_BADFID;
6686 goto done;
6689 /* Do sanity check on the requested changes for Samba */
6690 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6691 result = WERR_INVALID_PARAM;
6692 goto done;
6695 /* FIXME!!! If the driver has changed we really should verify that
6696 it is installed before doing much else --jerry */
6698 /* Check calling user has permission to update printer description */
6699 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6700 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6701 result = WERR_ACCESS_DENIED;
6702 goto done;
6705 /* Call addprinter hook */
6706 /* Check changes to see if this is really needed */
6708 if (*lp_addprinter_cmd(talloc_tos()) &&
6709 (!strequal(printer->drivername, old_printer->drivername) ||
6710 !strequal(printer->comment, old_printer->comment) ||
6711 !strequal(printer->portname, old_printer->portname) ||
6712 !strequal(printer->location, old_printer->location)) )
6714 char *raddr;
6716 raddr = tsocket_address_inet_addr_string(p->remote_address,
6717 p->mem_ctx);
6718 if (raddr == NULL) {
6719 return WERR_NOMEM;
6722 /* add_printer_hook() will call reload_services() */
6723 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6724 printer, raddr,
6725 p->msg_ctx)) {
6726 result = WERR_ACCESS_DENIED;
6727 goto done;
6731 result = update_dsspooler(tmp_ctx,
6732 get_session_info_system(),
6733 p->msg_ctx,
6734 snum,
6735 printer,
6736 old_printer);
6737 if (!W_ERROR_IS_OK(result)) {
6738 goto done;
6741 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6743 if (devmode == NULL) {
6744 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6746 result = winreg_update_printer(tmp_ctx, b,
6747 printer->sharename,
6748 printer_mask,
6749 printer,
6750 devmode,
6751 NULL);
6753 done:
6754 talloc_free(tmp_ctx);
6756 return result;
6759 /****************************************************************************
6760 ****************************************************************************/
6761 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6762 struct policy_handle *handle,
6763 struct spoolss_SetPrinterInfo7 *info7)
6765 #ifdef HAVE_ADS
6766 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6767 WERROR result;
6768 int snum;
6769 struct printer_handle *Printer;
6771 if ( lp_security() != SEC_ADS ) {
6772 return WERR_UNKNOWN_LEVEL;
6775 Printer = find_printer_index_by_hnd(p, handle);
6777 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6779 if (!Printer)
6780 return WERR_BADFID;
6782 if (!get_printer_snum(p, handle, &snum, NULL))
6783 return WERR_BADFID;
6785 result = winreg_get_printer_internal(p->mem_ctx,
6786 get_session_info_system(),
6787 p->msg_ctx,
6788 lp_servicename(talloc_tos(), snum),
6789 &pinfo2);
6790 if (!W_ERROR_IS_OK(result)) {
6791 return WERR_BADFID;
6794 nt_printer_publish(pinfo2,
6795 get_session_info_system(),
6796 p->msg_ctx,
6797 pinfo2,
6798 info7->action);
6800 TALLOC_FREE(pinfo2);
6801 return WERR_OK;
6802 #else
6803 return WERR_UNKNOWN_LEVEL;
6804 #endif
6807 /********************************************************************
6808 ********************************************************************/
6810 static WERROR update_printer_devmode(struct pipes_struct *p,
6811 struct policy_handle *handle,
6812 struct spoolss_DeviceMode *devmode)
6814 int snum;
6815 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6816 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6818 DEBUG(8,("update_printer_devmode\n"));
6820 if (!Printer) {
6821 return WERR_BADFID;
6824 if (!get_printer_snum(p, handle, &snum, NULL)) {
6825 return WERR_BADFID;
6828 /* Check calling user has permission to update printer description */
6829 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6830 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6831 return WERR_ACCESS_DENIED;
6834 return winreg_update_printer_internal(p->mem_ctx,
6835 get_session_info_system(),
6836 p->msg_ctx,
6837 lp_const_servicename(snum),
6838 info2_mask,
6839 NULL,
6840 devmode,
6841 NULL);
6845 /****************************************************************
6846 _spoolss_SetPrinter
6847 ****************************************************************/
6849 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6850 struct spoolss_SetPrinter *r)
6852 WERROR result;
6854 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6856 if (!Printer) {
6857 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6858 OUR_HANDLE(r->in.handle)));
6859 return WERR_BADFID;
6862 /* check the level */
6863 switch (r->in.info_ctr->level) {
6864 case 0:
6865 return control_printer(r->in.handle, r->in.command, p);
6866 case 2:
6867 result = update_printer(p, r->in.handle,
6868 r->in.info_ctr,
6869 r->in.devmode_ctr->devmode);
6870 if (!W_ERROR_IS_OK(result))
6871 return result;
6872 if (r->in.secdesc_ctr->sd)
6873 result = update_printer_sec(r->in.handle, p,
6874 r->in.secdesc_ctr);
6875 return result;
6876 case 3:
6877 return update_printer_sec(r->in.handle, p,
6878 r->in.secdesc_ctr);
6879 case 7:
6880 return publish_or_unpublish_printer(p, r->in.handle,
6881 r->in.info_ctr->info.info7);
6882 case 8:
6883 return update_printer_devmode(p, r->in.handle,
6884 r->in.devmode_ctr->devmode);
6885 default:
6886 return WERR_UNKNOWN_LEVEL;
6890 /****************************************************************
6891 _spoolss_FindClosePrinterNotify
6892 ****************************************************************/
6894 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6895 struct spoolss_FindClosePrinterNotify *r)
6897 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6899 if (!Printer) {
6900 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6901 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6902 return WERR_BADFID;
6905 if (Printer->notify.cli_chan != NULL &&
6906 Printer->notify.cli_chan->active_connections > 0) {
6907 int snum = -1;
6909 if (Printer->printer_type == SPLHND_PRINTER) {
6910 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6911 return WERR_BADFID;
6915 srv_spoolss_replycloseprinter(snum, Printer);
6918 Printer->notify.flags=0;
6919 Printer->notify.options=0;
6920 Printer->notify.localmachine[0]='\0';
6921 Printer->notify.printerlocal=0;
6922 TALLOC_FREE(Printer->notify.option);
6924 return WERR_OK;
6927 /****************************************************************
6928 _spoolss_AddJob
6929 ****************************************************************/
6931 WERROR _spoolss_AddJob(struct pipes_struct *p,
6932 struct spoolss_AddJob *r)
6934 if (!r->in.buffer && (r->in.offered != 0)) {
6935 return WERR_INVALID_PARAM;
6938 /* this is what a NT server returns for AddJob. AddJob must fail on
6939 * non-local printers */
6941 if (r->in.level != 1) {
6942 return WERR_UNKNOWN_LEVEL;
6945 return WERR_INVALID_PARAM;
6948 /****************************************************************************
6949 fill_job_info1
6950 ****************************************************************************/
6952 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6953 struct spoolss_JobInfo1 *r,
6954 const print_queue_struct *queue,
6955 int position, int snum,
6956 struct spoolss_PrinterInfo2 *pinfo2)
6958 struct tm *t;
6960 t = gmtime(&queue->time);
6962 r->job_id = queue->sysjob;
6964 r->printer_name = lp_servicename(mem_ctx, snum);
6965 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6966 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6967 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6968 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6969 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6970 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6971 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6972 r->data_type = talloc_strdup(mem_ctx, "RAW");
6973 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6974 r->text_status = talloc_strdup(mem_ctx, "");
6975 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6977 r->status = nt_printj_status(queue->status);
6978 r->priority = queue->priority;
6979 r->position = position;
6980 r->total_pages = queue->page_count;
6981 r->pages_printed = 0; /* ??? */
6983 init_systemtime(&r->submitted, t);
6985 return WERR_OK;
6988 /****************************************************************************
6989 fill_job_info2
6990 ****************************************************************************/
6992 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6993 struct spoolss_JobInfo2 *r,
6994 const print_queue_struct *queue,
6995 int position, int snum,
6996 struct spoolss_PrinterInfo2 *pinfo2,
6997 struct spoolss_DeviceMode *devmode)
6999 struct tm *t;
7001 t = gmtime(&queue->time);
7003 r->job_id = queue->sysjob;
7005 r->printer_name = lp_servicename(mem_ctx, snum);
7006 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7007 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7008 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7009 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7010 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7011 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7012 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7013 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7014 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7015 r->data_type = talloc_strdup(mem_ctx, "RAW");
7016 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7017 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7018 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7019 r->parameters = talloc_strdup(mem_ctx, "");
7020 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7021 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7022 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7024 r->devmode = devmode;
7026 r->text_status = talloc_strdup(mem_ctx, "");
7027 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7029 r->secdesc = NULL;
7031 r->status = nt_printj_status(queue->status);
7032 r->priority = queue->priority;
7033 r->position = position;
7034 r->start_time = 0;
7035 r->until_time = 0;
7036 r->total_pages = queue->page_count;
7037 r->size = queue->size;
7038 init_systemtime(&r->submitted, t);
7039 r->time = 0;
7040 r->pages_printed = 0; /* ??? */
7042 return WERR_OK;
7045 /****************************************************************************
7046 fill_job_info3
7047 ****************************************************************************/
7049 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7050 struct spoolss_JobInfo3 *r,
7051 const print_queue_struct *queue,
7052 const print_queue_struct *next_queue,
7053 int position, int snum,
7054 struct spoolss_PrinterInfo2 *pinfo2)
7056 r->job_id = queue->sysjob;
7057 r->next_job_id = 0;
7058 if (next_queue) {
7059 r->next_job_id = next_queue->sysjob;
7061 r->reserved = 0;
7063 return WERR_OK;
7066 /****************************************************************************
7067 Enumjobs at level 1.
7068 ****************************************************************************/
7070 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7071 const print_queue_struct *queue,
7072 uint32_t num_queues, int snum,
7073 struct spoolss_PrinterInfo2 *pinfo2,
7074 union spoolss_JobInfo **info_p,
7075 uint32_t *count)
7077 union spoolss_JobInfo *info;
7078 int i;
7079 WERROR result = WERR_OK;
7081 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7082 W_ERROR_HAVE_NO_MEMORY(info);
7084 *count = num_queues;
7086 for (i=0; i<*count; i++) {
7087 result = fill_job_info1(info,
7088 &info[i].info1,
7089 &queue[i],
7091 snum,
7092 pinfo2);
7093 if (!W_ERROR_IS_OK(result)) {
7094 goto out;
7098 out:
7099 if (!W_ERROR_IS_OK(result)) {
7100 TALLOC_FREE(info);
7101 *count = 0;
7102 return result;
7105 *info_p = info;
7107 return WERR_OK;
7110 /****************************************************************************
7111 Enumjobs at level 2.
7112 ****************************************************************************/
7114 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7115 const print_queue_struct *queue,
7116 uint32_t num_queues, int snum,
7117 struct spoolss_PrinterInfo2 *pinfo2,
7118 union spoolss_JobInfo **info_p,
7119 uint32_t *count)
7121 union spoolss_JobInfo *info;
7122 int i;
7123 WERROR result = WERR_OK;
7125 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7126 W_ERROR_HAVE_NO_MEMORY(info);
7128 *count = num_queues;
7130 for (i=0; i<*count; i++) {
7131 struct spoolss_DeviceMode *devmode;
7133 result = spoolss_create_default_devmode(info,
7134 pinfo2->printername,
7135 &devmode);
7136 if (!W_ERROR_IS_OK(result)) {
7137 DEBUG(3, ("Can't proceed w/o a devmode!"));
7138 goto out;
7141 result = fill_job_info2(info,
7142 &info[i].info2,
7143 &queue[i],
7145 snum,
7146 pinfo2,
7147 devmode);
7148 if (!W_ERROR_IS_OK(result)) {
7149 goto out;
7153 out:
7154 if (!W_ERROR_IS_OK(result)) {
7155 TALLOC_FREE(info);
7156 *count = 0;
7157 return result;
7160 *info_p = info;
7162 return WERR_OK;
7165 /****************************************************************************
7166 Enumjobs at level 3.
7167 ****************************************************************************/
7169 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7170 const print_queue_struct *queue,
7171 uint32_t num_queues, int snum,
7172 struct spoolss_PrinterInfo2 *pinfo2,
7173 union spoolss_JobInfo **info_p,
7174 uint32_t *count)
7176 union spoolss_JobInfo *info;
7177 int i;
7178 WERROR result = WERR_OK;
7180 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7181 W_ERROR_HAVE_NO_MEMORY(info);
7183 *count = num_queues;
7185 for (i=0; i<*count; i++) {
7186 const print_queue_struct *next_queue = NULL;
7188 if (i+1 < *count) {
7189 next_queue = &queue[i+1];
7192 result = fill_job_info3(info,
7193 &info[i].info3,
7194 &queue[i],
7195 next_queue,
7197 snum,
7198 pinfo2);
7199 if (!W_ERROR_IS_OK(result)) {
7200 goto out;
7204 out:
7205 if (!W_ERROR_IS_OK(result)) {
7206 TALLOC_FREE(info);
7207 *count = 0;
7208 return result;
7211 *info_p = info;
7213 return WERR_OK;
7216 /****************************************************************
7217 _spoolss_EnumJobs
7218 ****************************************************************/
7220 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7221 struct spoolss_EnumJobs *r)
7223 WERROR result;
7224 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7225 int snum;
7226 print_status_struct prt_status;
7227 print_queue_struct *queue = NULL;
7228 uint32_t count;
7230 /* that's an [in out] buffer */
7232 if (!r->in.buffer && (r->in.offered != 0)) {
7233 return WERR_INVALID_PARAM;
7236 DEBUG(4,("_spoolss_EnumJobs\n"));
7238 *r->out.needed = 0;
7239 *r->out.count = 0;
7240 *r->out.info = NULL;
7242 /* lookup the printer snum and tdb entry */
7244 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7245 return WERR_BADFID;
7248 result = winreg_get_printer_internal(p->mem_ctx,
7249 get_session_info_system(),
7250 p->msg_ctx,
7251 lp_const_servicename(snum),
7252 &pinfo2);
7253 if (!W_ERROR_IS_OK(result)) {
7254 return result;
7257 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7258 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7259 count, prt_status.status, prt_status.message));
7261 if (count == 0) {
7262 SAFE_FREE(queue);
7263 TALLOC_FREE(pinfo2);
7264 return WERR_OK;
7267 switch (r->in.level) {
7268 case 1:
7269 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7270 pinfo2, r->out.info, r->out.count);
7271 break;
7272 case 2:
7273 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7274 pinfo2, r->out.info, r->out.count);
7275 break;
7276 case 3:
7277 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7278 pinfo2, r->out.info, r->out.count);
7279 break;
7280 default:
7281 result = WERR_UNKNOWN_LEVEL;
7282 break;
7285 SAFE_FREE(queue);
7286 TALLOC_FREE(pinfo2);
7288 if (!W_ERROR_IS_OK(result)) {
7289 return result;
7292 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7293 spoolss_EnumJobs,
7294 *r->out.info, r->in.level,
7295 *r->out.count);
7296 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7297 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7299 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7302 /****************************************************************
7303 _spoolss_ScheduleJob
7304 ****************************************************************/
7306 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7307 struct spoolss_ScheduleJob *r)
7309 return WERR_OK;
7312 /****************************************************************
7313 ****************************************************************/
7315 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7316 struct messaging_context *msg_ctx,
7317 const char *printer_name,
7318 uint32_t job_id,
7319 struct spoolss_SetJobInfo1 *r)
7321 char *old_doc_name;
7323 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7324 return WERR_BADFID;
7327 if (strequal(old_doc_name, r->document_name)) {
7328 return WERR_OK;
7331 if (!print_job_set_name(server_event_context(), msg_ctx,
7332 printer_name, job_id, r->document_name)) {
7333 return WERR_BADFID;
7336 return WERR_OK;
7339 /****************************************************************
7340 _spoolss_SetJob
7341 ****************************************************************/
7343 WERROR _spoolss_SetJob(struct pipes_struct *p,
7344 struct spoolss_SetJob *r)
7346 const struct auth_session_info *session_info = p->session_info;
7347 int snum;
7348 WERROR errcode = WERR_BADFUNC;
7350 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7351 return WERR_BADFID;
7354 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7355 return WERR_INVALID_PRINTER_NAME;
7358 switch (r->in.command) {
7359 case SPOOLSS_JOB_CONTROL_CANCEL:
7360 case SPOOLSS_JOB_CONTROL_DELETE:
7361 errcode = print_job_delete(session_info, p->msg_ctx,
7362 snum, r->in.job_id);
7363 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7364 errcode = WERR_OK;
7366 break;
7367 case SPOOLSS_JOB_CONTROL_PAUSE:
7368 errcode = print_job_pause(session_info, p->msg_ctx,
7369 snum, r->in.job_id);
7370 break;
7371 case SPOOLSS_JOB_CONTROL_RESTART:
7372 case SPOOLSS_JOB_CONTROL_RESUME:
7373 errcode = print_job_resume(session_info, p->msg_ctx,
7374 snum, r->in.job_id);
7375 break;
7376 case 0:
7377 errcode = WERR_OK;
7378 break;
7379 default:
7380 return WERR_UNKNOWN_LEVEL;
7383 if (!W_ERROR_IS_OK(errcode)) {
7384 return errcode;
7387 if (r->in.ctr == NULL) {
7388 return errcode;
7391 switch (r->in.ctr->level) {
7392 case 1:
7393 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7394 lp_const_servicename(snum),
7395 r->in.job_id,
7396 r->in.ctr->info.info1);
7397 break;
7398 case 2:
7399 case 3:
7400 case 4:
7401 default:
7402 return WERR_UNKNOWN_LEVEL;
7405 return errcode;
7408 /****************************************************************************
7409 Enumerates all printer drivers by level and architecture.
7410 ****************************************************************************/
7412 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7413 const struct auth_session_info *session_info,
7414 struct messaging_context *msg_ctx,
7415 const char *servername,
7416 const char *architecture,
7417 uint32_t level,
7418 union spoolss_DriverInfo **info_p,
7419 uint32_t *count_p)
7421 int i;
7422 uint32_t version;
7423 struct spoolss_DriverInfo8 *driver;
7424 union spoolss_DriverInfo *info = NULL;
7425 uint32_t count = 0;
7426 WERROR result = WERR_OK;
7427 uint32_t num_drivers;
7428 const char **drivers;
7429 struct dcerpc_binding_handle *b;
7430 TALLOC_CTX *tmp_ctx = NULL;
7432 *count_p = 0;
7433 *info_p = NULL;
7435 tmp_ctx = talloc_new(mem_ctx);
7436 if (!tmp_ctx) {
7437 return WERR_NOMEM;
7440 result = winreg_printer_binding_handle(tmp_ctx,
7441 session_info,
7442 msg_ctx,
7443 &b);
7444 if (!W_ERROR_IS_OK(result)) {
7445 goto out;
7448 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7449 result = winreg_get_driver_list(tmp_ctx, b,
7450 architecture, version,
7451 &num_drivers, &drivers);
7452 if (!W_ERROR_IS_OK(result)) {
7453 goto out;
7455 DEBUG(4, ("we have:[%d] drivers in environment"
7456 " [%s] and version [%d]\n",
7457 num_drivers, architecture, version));
7459 if (num_drivers != 0) {
7460 info = talloc_realloc(tmp_ctx, info,
7461 union spoolss_DriverInfo,
7462 count + num_drivers);
7463 if (!info) {
7464 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7465 "failed to enlarge driver info buffer!\n"));
7466 result = WERR_NOMEM;
7467 goto out;
7471 for (i = 0; i < num_drivers; i++) {
7472 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7474 result = winreg_get_driver(tmp_ctx, b,
7475 architecture, drivers[i],
7476 version, &driver);
7477 if (!W_ERROR_IS_OK(result)) {
7478 goto out;
7481 switch (level) {
7482 case 1:
7483 result = fill_printer_driver_info1(info, &info[count+i].info1,
7484 driver, servername);
7485 break;
7486 case 2:
7487 result = fill_printer_driver_info2(info, &info[count+i].info2,
7488 driver, servername);
7489 break;
7490 case 3:
7491 result = fill_printer_driver_info3(info, &info[count+i].info3,
7492 driver, servername);
7493 break;
7494 case 4:
7495 result = fill_printer_driver_info4(info, &info[count+i].info4,
7496 driver, servername);
7497 break;
7498 case 5:
7499 result = fill_printer_driver_info5(info, &info[count+i].info5,
7500 driver, servername);
7501 break;
7502 case 6:
7503 result = fill_printer_driver_info6(info, &info[count+i].info6,
7504 driver, servername);
7505 break;
7506 case 8:
7507 result = fill_printer_driver_info8(info, &info[count+i].info8,
7508 driver, servername);
7509 break;
7510 default:
7511 result = WERR_UNKNOWN_LEVEL;
7512 break;
7515 TALLOC_FREE(driver);
7517 if (!W_ERROR_IS_OK(result)) {
7518 goto out;
7522 count += num_drivers;
7523 TALLOC_FREE(drivers);
7526 out:
7527 if (W_ERROR_IS_OK(result)) {
7528 *info_p = talloc_move(mem_ctx, &info);
7529 *count_p = count;
7532 talloc_free(tmp_ctx);
7533 return result;
7536 /****************************************************************************
7537 Enumerates all printer drivers by level.
7538 ****************************************************************************/
7540 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7541 const struct auth_session_info *session_info,
7542 struct messaging_context *msg_ctx,
7543 const char *servername,
7544 const char *architecture,
7545 uint32_t level,
7546 union spoolss_DriverInfo **info_p,
7547 uint32_t *count_p)
7549 uint32_t a,i;
7550 WERROR result = WERR_OK;
7552 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7554 for (a=0; archi_table[a].long_archi != NULL; a++) {
7556 union spoolss_DriverInfo *info = NULL;
7557 uint32_t count = 0;
7559 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7560 session_info,
7561 msg_ctx,
7562 servername,
7563 archi_table[a].long_archi,
7564 level,
7565 &info,
7566 &count);
7567 if (!W_ERROR_IS_OK(result)) {
7568 continue;
7571 for (i=0; i < count; i++) {
7572 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7573 info[i], info_p, count_p);
7577 return result;
7580 return enumprinterdrivers_level_by_architecture(mem_ctx,
7581 session_info,
7582 msg_ctx,
7583 servername,
7584 architecture,
7585 level,
7586 info_p,
7587 count_p);
7590 /****************************************************************
7591 _spoolss_EnumPrinterDrivers
7592 ****************************************************************/
7594 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7595 struct spoolss_EnumPrinterDrivers *r)
7597 const char *cservername;
7598 WERROR result;
7600 /* that's an [in out] buffer */
7602 if (!r->in.buffer && (r->in.offered != 0)) {
7603 return WERR_INVALID_PARAM;
7606 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7608 *r->out.needed = 0;
7609 *r->out.count = 0;
7610 *r->out.info = NULL;
7612 cservername = canon_servername(r->in.server);
7614 if (!is_myname_or_ipaddr(cservername)) {
7615 return WERR_UNKNOWN_PRINTER_DRIVER;
7618 result = enumprinterdrivers_level(p->mem_ctx,
7619 get_session_info_system(),
7620 p->msg_ctx,
7621 cservername,
7622 r->in.environment,
7623 r->in.level,
7624 r->out.info,
7625 r->out.count);
7626 if (!W_ERROR_IS_OK(result)) {
7627 return result;
7630 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7631 spoolss_EnumPrinterDrivers,
7632 *r->out.info, r->in.level,
7633 *r->out.count);
7634 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7635 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7637 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7640 /****************************************************************
7641 _spoolss_EnumForms
7642 ****************************************************************/
7644 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7645 struct spoolss_EnumForms *r)
7647 WERROR result;
7649 *r->out.count = 0;
7650 *r->out.needed = 0;
7651 *r->out.info = NULL;
7653 /* that's an [in out] buffer */
7655 if (!r->in.buffer && (r->in.offered != 0) ) {
7656 return WERR_INVALID_PARAM;
7659 DEBUG(4,("_spoolss_EnumForms\n"));
7660 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7661 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7663 switch (r->in.level) {
7664 case 1:
7665 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7666 get_session_info_system(),
7667 p->msg_ctx,
7668 r->out.count,
7669 r->out.info);
7670 break;
7671 default:
7672 result = WERR_UNKNOWN_LEVEL;
7673 break;
7676 if (!W_ERROR_IS_OK(result)) {
7677 return result;
7680 if (*r->out.count == 0) {
7681 return WERR_NO_MORE_ITEMS;
7684 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7685 spoolss_EnumForms,
7686 *r->out.info, r->in.level,
7687 *r->out.count);
7688 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7689 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7691 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7694 /****************************************************************
7695 _spoolss_GetForm
7696 ****************************************************************/
7698 WERROR _spoolss_GetForm(struct pipes_struct *p,
7699 struct spoolss_GetForm *r)
7701 WERROR result;
7703 /* that's an [in out] buffer */
7705 if (!r->in.buffer && (r->in.offered != 0)) {
7706 return WERR_INVALID_PARAM;
7709 DEBUG(4,("_spoolss_GetForm\n"));
7710 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7711 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7713 switch (r->in.level) {
7714 case 1:
7715 result = winreg_printer_getform1_internal(p->mem_ctx,
7716 get_session_info_system(),
7717 p->msg_ctx,
7718 r->in.form_name,
7719 &r->out.info->info1);
7720 break;
7721 default:
7722 result = WERR_UNKNOWN_LEVEL;
7723 break;
7726 if (!W_ERROR_IS_OK(result)) {
7727 TALLOC_FREE(r->out.info);
7728 return result;
7731 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7732 r->out.info, r->in.level);
7733 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7735 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7738 /****************************************************************************
7739 ****************************************************************************/
7741 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7742 struct spoolss_PortInfo1 *r,
7743 const char *name)
7745 r->port_name = talloc_strdup(mem_ctx, name);
7746 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7748 return WERR_OK;
7751 /****************************************************************************
7752 TODO: This probably needs distinguish between TCP/IP and Local ports
7753 somehow.
7754 ****************************************************************************/
7756 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7757 struct spoolss_PortInfo2 *r,
7758 const char *name)
7760 r->port_name = talloc_strdup(mem_ctx, name);
7761 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7763 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7764 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7766 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7767 W_ERROR_HAVE_NO_MEMORY(r->description);
7769 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7770 r->reserved = 0;
7772 return WERR_OK;
7776 /****************************************************************************
7777 wrapper around the enumer ports command
7778 ****************************************************************************/
7780 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7782 char *cmd = lp_enumports_cmd(talloc_tos());
7783 char **qlines = NULL;
7784 char *command = NULL;
7785 int numlines;
7786 int ret;
7787 int fd;
7789 *count = 0;
7790 *lines = NULL;
7792 /* if no hook then just fill in the default port */
7794 if ( !*cmd ) {
7795 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7796 return WERR_NOMEM;
7798 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7799 TALLOC_FREE(qlines);
7800 return WERR_NOMEM;
7802 qlines[1] = NULL;
7803 numlines = 1;
7805 else {
7806 /* we have a valid enumport command */
7808 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7809 if (!command) {
7810 return WERR_NOMEM;
7813 DEBUG(10,("Running [%s]\n", command));
7814 ret = smbrun(command, &fd);
7815 DEBUG(10,("Returned [%d]\n", ret));
7816 TALLOC_FREE(command);
7817 if (ret != 0) {
7818 if (fd != -1) {
7819 close(fd);
7821 return WERR_ACCESS_DENIED;
7824 numlines = 0;
7825 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7826 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7827 close(fd);
7830 *count = numlines;
7831 *lines = qlines;
7833 return WERR_OK;
7836 /****************************************************************************
7837 enumports level 1.
7838 ****************************************************************************/
7840 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7841 union spoolss_PortInfo **info_p,
7842 uint32_t *count)
7844 union spoolss_PortInfo *info = NULL;
7845 int i=0;
7846 WERROR result = WERR_OK;
7847 char **qlines = NULL;
7848 int numlines = 0;
7850 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7851 if (!W_ERROR_IS_OK(result)) {
7852 goto out;
7855 if (numlines) {
7856 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7857 if (!info) {
7858 DEBUG(10,("Returning WERR_NOMEM\n"));
7859 result = WERR_NOMEM;
7860 goto out;
7863 for (i=0; i<numlines; i++) {
7864 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7865 result = fill_port_1(info, &info[i].info1, qlines[i]);
7866 if (!W_ERROR_IS_OK(result)) {
7867 goto out;
7871 TALLOC_FREE(qlines);
7873 out:
7874 if (!W_ERROR_IS_OK(result)) {
7875 TALLOC_FREE(info);
7876 TALLOC_FREE(qlines);
7877 *count = 0;
7878 *info_p = NULL;
7879 return result;
7882 *info_p = info;
7883 *count = numlines;
7885 return WERR_OK;
7888 /****************************************************************************
7889 enumports level 2.
7890 ****************************************************************************/
7892 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7893 union spoolss_PortInfo **info_p,
7894 uint32_t *count)
7896 union spoolss_PortInfo *info = NULL;
7897 int i=0;
7898 WERROR result = WERR_OK;
7899 char **qlines = NULL;
7900 int numlines = 0;
7902 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7903 if (!W_ERROR_IS_OK(result)) {
7904 goto out;
7907 if (numlines) {
7908 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7909 if (!info) {
7910 DEBUG(10,("Returning WERR_NOMEM\n"));
7911 result = WERR_NOMEM;
7912 goto out;
7915 for (i=0; i<numlines; i++) {
7916 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7917 result = fill_port_2(info, &info[i].info2, qlines[i]);
7918 if (!W_ERROR_IS_OK(result)) {
7919 goto out;
7923 TALLOC_FREE(qlines);
7925 out:
7926 if (!W_ERROR_IS_OK(result)) {
7927 TALLOC_FREE(info);
7928 TALLOC_FREE(qlines);
7929 *count = 0;
7930 *info_p = NULL;
7931 return result;
7934 *info_p = info;
7935 *count = numlines;
7937 return WERR_OK;
7940 /****************************************************************
7941 _spoolss_EnumPorts
7942 ****************************************************************/
7944 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7945 struct spoolss_EnumPorts *r)
7947 WERROR result;
7949 /* that's an [in out] buffer */
7951 if (!r->in.buffer && (r->in.offered != 0)) {
7952 return WERR_INVALID_PARAM;
7955 DEBUG(4,("_spoolss_EnumPorts\n"));
7957 *r->out.count = 0;
7958 *r->out.needed = 0;
7959 *r->out.info = NULL;
7961 switch (r->in.level) {
7962 case 1:
7963 result = enumports_level_1(p->mem_ctx, r->out.info,
7964 r->out.count);
7965 break;
7966 case 2:
7967 result = enumports_level_2(p->mem_ctx, r->out.info,
7968 r->out.count);
7969 break;
7970 default:
7971 return WERR_UNKNOWN_LEVEL;
7974 if (!W_ERROR_IS_OK(result)) {
7975 return result;
7978 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7979 spoolss_EnumPorts,
7980 *r->out.info, r->in.level,
7981 *r->out.count);
7982 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7983 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7985 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7988 /****************************************************************************
7989 ****************************************************************************/
7991 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7992 const char *server,
7993 struct spoolss_SetPrinterInfoCtr *info_ctr,
7994 struct spoolss_DeviceMode *devmode,
7995 struct security_descriptor *secdesc,
7996 struct spoolss_UserLevelCtr *user_ctr,
7997 struct policy_handle *handle)
7999 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8000 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8001 int snum;
8002 WERROR err = WERR_OK;
8004 /* samba does not have a concept of local, non-shared printers yet, so
8005 * make sure we always setup sharename - gd */
8006 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8007 (info2->printername != NULL && info2->printername[0] != '\0')) {
8008 DEBUG(5, ("spoolss_addprinterex_level_2: "
8009 "no sharename has been set, setting printername %s as sharename\n",
8010 info2->printername));
8011 info2->sharename = info2->printername;
8014 /* check to see if the printer already exists */
8015 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8016 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8017 info2->sharename));
8018 return WERR_PRINTER_ALREADY_EXISTS;
8021 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8022 if ((snum = print_queue_snum(info2->printername)) != -1) {
8023 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8024 info2->printername));
8025 return WERR_PRINTER_ALREADY_EXISTS;
8029 /* validate printer info struct */
8030 if (!info2->printername || strlen(info2->printername) == 0) {
8031 return WERR_INVALID_PRINTER_NAME;
8033 if (!info2->portname || strlen(info2->portname) == 0) {
8034 return WERR_UNKNOWN_PORT;
8036 if (!info2->drivername || strlen(info2->drivername) == 0) {
8037 return WERR_UNKNOWN_PRINTER_DRIVER;
8039 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8040 return WERR_UNKNOWN_PRINTPROCESSOR;
8043 /* FIXME!!! smbd should check to see if the driver is installed before
8044 trying to add a printer like this --jerry */
8046 if (*lp_addprinter_cmd(talloc_tos()) ) {
8047 char *raddr;
8049 raddr = tsocket_address_inet_addr_string(p->remote_address,
8050 p->mem_ctx);
8051 if (raddr == NULL) {
8052 return WERR_NOMEM;
8055 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8056 info2, raddr,
8057 p->msg_ctx) ) {
8058 return WERR_ACCESS_DENIED;
8060 } else {
8061 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8062 "smb.conf parameter \"addprinter command\" is defined. This "
8063 "parameter must exist for this call to succeed\n",
8064 info2->sharename ));
8067 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8068 return WERR_ACCESS_DENIED;
8071 /* you must be a printer admin to add a new printer */
8072 if (!print_access_check(p->session_info,
8073 p->msg_ctx,
8074 snum,
8075 PRINTER_ACCESS_ADMINISTER)) {
8076 return WERR_ACCESS_DENIED;
8080 * Do sanity check on the requested changes for Samba.
8083 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8084 return WERR_INVALID_PARAM;
8087 if (devmode == NULL) {
8088 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8091 err = update_dsspooler(p->mem_ctx,
8092 get_session_info_system(),
8093 p->msg_ctx,
8095 info2,
8096 NULL);
8097 if (!W_ERROR_IS_OK(err)) {
8098 return err;
8101 err = winreg_update_printer_internal(p->mem_ctx,
8102 get_session_info_system(),
8103 p->msg_ctx,
8104 info2->sharename,
8105 info2_mask,
8106 info2,
8107 devmode,
8108 secdesc);
8109 if (!W_ERROR_IS_OK(err)) {
8110 return err;
8113 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8114 if (!W_ERROR_IS_OK(err)) {
8115 /* Handle open failed - remove addition. */
8116 ZERO_STRUCTP(handle);
8117 return err;
8120 return WERR_OK;
8123 /****************************************************************
8124 _spoolss_AddPrinterEx
8125 ****************************************************************/
8127 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8128 struct spoolss_AddPrinterEx *r)
8130 switch (r->in.info_ctr->level) {
8131 case 1:
8132 /* we don't handle yet */
8133 /* but I know what to do ... */
8134 return WERR_UNKNOWN_LEVEL;
8135 case 2:
8136 return spoolss_addprinterex_level_2(p, r->in.server,
8137 r->in.info_ctr,
8138 r->in.devmode_ctr->devmode,
8139 r->in.secdesc_ctr->sd,
8140 r->in.userlevel_ctr,
8141 r->out.handle);
8142 default:
8143 return WERR_UNKNOWN_LEVEL;
8147 /****************************************************************
8148 _spoolss_AddPrinter
8149 ****************************************************************/
8151 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8152 struct spoolss_AddPrinter *r)
8154 struct spoolss_AddPrinterEx a;
8155 struct spoolss_UserLevelCtr userlevel_ctr;
8157 ZERO_STRUCT(userlevel_ctr);
8159 userlevel_ctr.level = 1;
8161 a.in.server = r->in.server;
8162 a.in.info_ctr = r->in.info_ctr;
8163 a.in.devmode_ctr = r->in.devmode_ctr;
8164 a.in.secdesc_ctr = r->in.secdesc_ctr;
8165 a.in.userlevel_ctr = &userlevel_ctr;
8166 a.out.handle = r->out.handle;
8168 return _spoolss_AddPrinterEx(p, &a);
8171 /****************************************************************
8172 _spoolss_AddPrinterDriverEx
8173 ****************************************************************/
8175 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8176 struct spoolss_AddPrinterDriverEx *r)
8178 WERROR err = WERR_OK;
8179 const char *driver_name = NULL;
8180 uint32_t version;
8181 const char *fn;
8183 switch (p->opnum) {
8184 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8185 fn = "_spoolss_AddPrinterDriver";
8186 break;
8187 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8188 fn = "_spoolss_AddPrinterDriverEx";
8189 break;
8190 default:
8191 return WERR_INVALID_PARAM;
8195 * we only support the semantics of AddPrinterDriver()
8196 * i.e. only copy files that are newer than existing ones
8199 if (r->in.flags == 0) {
8200 return WERR_INVALID_PARAM;
8203 if (r->in.flags != APD_COPY_NEW_FILES) {
8204 return WERR_ACCESS_DENIED;
8207 /* FIXME */
8208 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8209 /* Clever hack from Martin Zielinski <mz@seh.de>
8210 * to allow downgrade from level 8 (Vista).
8212 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8213 r->in.info_ctr->level));
8214 return WERR_UNKNOWN_LEVEL;
8217 DEBUG(5,("Cleaning driver's information\n"));
8218 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8219 if (!W_ERROR_IS_OK(err))
8220 goto done;
8222 DEBUG(5,("Moving driver to final destination\n"));
8223 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8224 if (!W_ERROR_IS_OK(err)) {
8225 goto done;
8228 err = winreg_add_driver_internal(p->mem_ctx,
8229 get_session_info_system(),
8230 p->msg_ctx,
8231 r->in.info_ctr,
8232 &driver_name,
8233 &version);
8234 if (!W_ERROR_IS_OK(err)) {
8235 goto done;
8239 * I think this is where he DrvUpgradePrinter() hook would be
8240 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8241 * server. Right now, we just need to send ourselves a message
8242 * to update each printer bound to this driver. --jerry
8245 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8246 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8247 fn, driver_name));
8250 done:
8251 return err;
8254 /****************************************************************
8255 _spoolss_AddPrinterDriver
8256 ****************************************************************/
8258 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8259 struct spoolss_AddPrinterDriver *r)
8261 struct spoolss_AddPrinterDriverEx a;
8263 switch (r->in.info_ctr->level) {
8264 case 2:
8265 case 3:
8266 case 4:
8267 case 5:
8268 break;
8269 default:
8270 return WERR_UNKNOWN_LEVEL;
8273 a.in.servername = r->in.servername;
8274 a.in.info_ctr = r->in.info_ctr;
8275 a.in.flags = APD_COPY_NEW_FILES;
8277 return _spoolss_AddPrinterDriverEx(p, &a);
8280 /****************************************************************************
8281 ****************************************************************************/
8283 struct _spoolss_paths {
8284 int type;
8285 const char *share;
8286 const char *dir;
8289 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8291 static const struct _spoolss_paths spoolss_paths[]= {
8292 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8293 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8296 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8297 const char *servername,
8298 const char *environment,
8299 int component,
8300 char **path)
8302 const char *pservername = NULL;
8303 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8304 const char *short_archi;
8306 *path = NULL;
8308 /* environment may be empty */
8309 if (environment && strlen(environment)) {
8310 long_archi = environment;
8313 /* servername may be empty */
8314 if (servername && strlen(servername)) {
8315 pservername = canon_servername(servername);
8317 if (!is_myname_or_ipaddr(pservername)) {
8318 return WERR_INVALID_PARAM;
8322 if (!(short_archi = get_short_archi(long_archi))) {
8323 return WERR_INVALID_ENVIRONMENT;
8326 switch (component) {
8327 case SPOOLSS_PRTPROCS_PATH:
8328 case SPOOLSS_DRIVER_PATH:
8329 if (pservername) {
8330 *path = talloc_asprintf(mem_ctx,
8331 "\\\\%s\\%s\\%s",
8332 pservername,
8333 spoolss_paths[component].share,
8334 short_archi);
8335 } else {
8336 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8337 SPOOLSS_DEFAULT_SERVER_PATH,
8338 spoolss_paths[component].dir,
8339 short_archi);
8341 break;
8342 default:
8343 return WERR_INVALID_PARAM;
8346 if (!*path) {
8347 return WERR_NOMEM;
8350 return WERR_OK;
8353 /****************************************************************************
8354 ****************************************************************************/
8356 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8357 const char *servername,
8358 const char *environment,
8359 struct spoolss_DriverDirectoryInfo1 *r)
8361 WERROR werr;
8362 char *path = NULL;
8364 werr = compose_spoolss_server_path(mem_ctx,
8365 servername,
8366 environment,
8367 SPOOLSS_DRIVER_PATH,
8368 &path);
8369 if (!W_ERROR_IS_OK(werr)) {
8370 return werr;
8373 DEBUG(4,("printer driver directory: [%s]\n", path));
8375 r->directory_name = path;
8377 return WERR_OK;
8380 /****************************************************************
8381 _spoolss_GetPrinterDriverDirectory
8382 ****************************************************************/
8384 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8385 struct spoolss_GetPrinterDriverDirectory *r)
8387 WERROR werror;
8389 /* that's an [in out] buffer */
8391 if (!r->in.buffer && (r->in.offered != 0)) {
8392 return WERR_INVALID_PARAM;
8395 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8396 r->in.level));
8398 *r->out.needed = 0;
8400 /* r->in.level is ignored */
8402 werror = getprinterdriverdir_level_1(p->mem_ctx,
8403 r->in.server,
8404 r->in.environment,
8405 &r->out.info->info1);
8406 if (!W_ERROR_IS_OK(werror)) {
8407 TALLOC_FREE(r->out.info);
8408 return werror;
8411 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8412 r->out.info, r->in.level);
8413 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8415 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8418 /****************************************************************
8419 _spoolss_EnumPrinterData
8420 ****************************************************************/
8422 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8423 struct spoolss_EnumPrinterData *r)
8425 WERROR result;
8426 struct spoolss_EnumPrinterDataEx r2;
8427 uint32_t count;
8428 struct spoolss_PrinterEnumValues *info, *val = NULL;
8429 uint32_t needed;
8431 r2.in.handle = r->in.handle;
8432 r2.in.key_name = "PrinterDriverData";
8433 r2.in.offered = 0;
8434 r2.out.count = &count;
8435 r2.out.info = &info;
8436 r2.out.needed = &needed;
8438 result = _spoolss_EnumPrinterDataEx(p, &r2);
8439 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8440 r2.in.offered = needed;
8441 result = _spoolss_EnumPrinterDataEx(p, &r2);
8443 if (!W_ERROR_IS_OK(result)) {
8444 return result;
8448 * The NT machine wants to know the biggest size of value and data
8450 * cf: MSDN EnumPrinterData remark section
8453 if (!r->in.value_offered && !r->in.data_offered) {
8454 uint32_t biggest_valuesize = 0;
8455 uint32_t biggest_datasize = 0;
8456 int i, name_length;
8458 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8460 for (i=0; i<count; i++) {
8462 name_length = strlen(info[i].value_name);
8463 if (strlen(info[i].value_name) > biggest_valuesize) {
8464 biggest_valuesize = name_length;
8467 if (info[i].data_length > biggest_datasize) {
8468 biggest_datasize = info[i].data_length;
8471 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8472 biggest_datasize));
8475 /* the value is an UNICODE string but real_value_size is the length
8476 in bytes including the trailing 0 */
8478 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8479 *r->out.data_needed = biggest_datasize;
8481 DEBUG(6,("final values: [%d], [%d]\n",
8482 *r->out.value_needed, *r->out.data_needed));
8484 return WERR_OK;
8487 if (r->in.enum_index < count) {
8488 val = &info[r->in.enum_index];
8491 if (val == NULL) {
8492 /* out_value should default to "" or else NT4 has
8493 problems unmarshalling the response */
8495 if (r->in.value_offered) {
8496 *r->out.value_needed = 1;
8497 r->out.value_name = talloc_strdup(r, "");
8498 if (!r->out.value_name) {
8499 return WERR_NOMEM;
8501 } else {
8502 r->out.value_name = NULL;
8503 *r->out.value_needed = 0;
8506 /* the data is counted in bytes */
8508 *r->out.data_needed = r->in.data_offered;
8510 result = WERR_NO_MORE_ITEMS;
8511 } else {
8513 * the value is:
8514 * - counted in bytes in the request
8515 * - counted in UNICODE chars in the max reply
8516 * - counted in bytes in the real size
8518 * take a pause *before* coding not *during* coding
8521 /* name */
8522 if (r->in.value_offered) {
8523 r->out.value_name = talloc_strdup(r, val->value_name);
8524 if (!r->out.value_name) {
8525 return WERR_NOMEM;
8527 *r->out.value_needed = val->value_name_len;
8528 } else {
8529 r->out.value_name = NULL;
8530 *r->out.value_needed = 0;
8533 /* type */
8535 *r->out.type = val->type;
8537 /* data - counted in bytes */
8540 * See the section "Dynamically Typed Query Parameters"
8541 * in MS-RPRN.
8544 if (r->out.data && val->data && val->data->data &&
8545 val->data_length && r->in.data_offered) {
8546 memcpy(r->out.data, val->data->data,
8547 MIN(val->data_length,r->in.data_offered));
8550 *r->out.data_needed = val->data_length;
8552 result = WERR_OK;
8555 return result;
8558 /****************************************************************
8559 _spoolss_SetPrinterData
8560 ****************************************************************/
8562 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8563 struct spoolss_SetPrinterData *r)
8565 struct spoolss_SetPrinterDataEx r2;
8567 r2.in.handle = r->in.handle;
8568 r2.in.key_name = "PrinterDriverData";
8569 r2.in.value_name = r->in.value_name;
8570 r2.in.type = r->in.type;
8571 r2.in.data = r->in.data;
8572 r2.in.offered = r->in.offered;
8574 return _spoolss_SetPrinterDataEx(p, &r2);
8577 /****************************************************************
8578 _spoolss_ResetPrinter
8579 ****************************************************************/
8581 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8582 struct spoolss_ResetPrinter *r)
8584 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8585 int snum;
8587 DEBUG(5,("_spoolss_ResetPrinter\n"));
8590 * All we do is to check to see if the handle and queue is valid.
8591 * This call really doesn't mean anything to us because we only
8592 * support RAW printing. --jerry
8595 if (!Printer) {
8596 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8597 OUR_HANDLE(r->in.handle)));
8598 return WERR_BADFID;
8601 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8602 return WERR_BADFID;
8605 /* blindly return success */
8606 return WERR_OK;
8609 /****************************************************************
8610 _spoolss_DeletePrinterData
8611 ****************************************************************/
8613 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8614 struct spoolss_DeletePrinterData *r)
8616 struct spoolss_DeletePrinterDataEx r2;
8618 r2.in.handle = r->in.handle;
8619 r2.in.key_name = "PrinterDriverData";
8620 r2.in.value_name = r->in.value_name;
8622 return _spoolss_DeletePrinterDataEx(p, &r2);
8625 /****************************************************************
8626 _spoolss_AddForm
8627 ****************************************************************/
8629 WERROR _spoolss_AddForm(struct pipes_struct *p,
8630 struct spoolss_AddForm *r)
8632 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8633 int snum = -1;
8634 WERROR status = WERR_OK;
8635 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8636 struct dcerpc_binding_handle *b;
8637 TALLOC_CTX *tmp_ctx = NULL;
8639 DEBUG(5,("_spoolss_AddForm\n"));
8641 if (!Printer) {
8642 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8643 OUR_HANDLE(r->in.handle)));
8644 return WERR_BADFID;
8647 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8648 and not a printer admin, then fail */
8650 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8651 !security_token_has_privilege(p->session_info->security_token,
8652 SEC_PRIV_PRINT_OPERATOR)) {
8653 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8654 return WERR_ACCESS_DENIED;
8657 switch (form->flags) {
8658 case SPOOLSS_FORM_USER:
8659 case SPOOLSS_FORM_BUILTIN:
8660 case SPOOLSS_FORM_PRINTER:
8661 break;
8662 default:
8663 return WERR_INVALID_PARAM;
8666 tmp_ctx = talloc_new(p->mem_ctx);
8667 if (!tmp_ctx) {
8668 return WERR_NOMEM;
8671 status = winreg_printer_binding_handle(tmp_ctx,
8672 get_session_info_system(),
8673 p->msg_ctx,
8674 &b);
8675 if (!W_ERROR_IS_OK(status)) {
8676 goto done;
8679 status = winreg_printer_addform1(tmp_ctx, b, form);
8680 if (!W_ERROR_IS_OK(status)) {
8681 goto done;
8685 * ChangeID must always be set if this is a printer
8687 if (Printer->printer_type == SPLHND_PRINTER) {
8688 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8689 status = WERR_BADFID;
8690 goto done;
8693 status = winreg_printer_update_changeid(tmp_ctx, b,
8694 lp_const_servicename(snum));
8697 done:
8698 talloc_free(tmp_ctx);
8699 return status;
8702 /****************************************************************
8703 _spoolss_DeleteForm
8704 ****************************************************************/
8706 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8707 struct spoolss_DeleteForm *r)
8709 const char *form_name = r->in.form_name;
8710 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8711 int snum = -1;
8712 WERROR status = WERR_OK;
8713 struct dcerpc_binding_handle *b;
8714 TALLOC_CTX *tmp_ctx = NULL;
8716 DEBUG(5,("_spoolss_DeleteForm\n"));
8718 if (!Printer) {
8719 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8720 OUR_HANDLE(r->in.handle)));
8721 return WERR_BADFID;
8724 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8725 !security_token_has_privilege(p->session_info->security_token,
8726 SEC_PRIV_PRINT_OPERATOR)) {
8727 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8728 return WERR_ACCESS_DENIED;
8731 tmp_ctx = talloc_new(p->mem_ctx);
8732 if (!tmp_ctx) {
8733 return WERR_NOMEM;
8736 status = winreg_printer_binding_handle(tmp_ctx,
8737 get_session_info_system(),
8738 p->msg_ctx,
8739 &b);
8740 if (!W_ERROR_IS_OK(status)) {
8741 goto done;
8744 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8745 if (!W_ERROR_IS_OK(status)) {
8746 goto done;
8750 * ChangeID must always be set if this is a printer
8752 if (Printer->printer_type == SPLHND_PRINTER) {
8753 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8754 status = WERR_BADFID;
8755 goto done;
8758 status = winreg_printer_update_changeid(tmp_ctx, b,
8759 lp_const_servicename(snum));
8762 done:
8763 talloc_free(tmp_ctx);
8764 return status;
8767 /****************************************************************
8768 _spoolss_SetForm
8769 ****************************************************************/
8771 WERROR _spoolss_SetForm(struct pipes_struct *p,
8772 struct spoolss_SetForm *r)
8774 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8775 const char *form_name = r->in.form_name;
8776 int snum = -1;
8777 WERROR status = WERR_OK;
8778 struct dcerpc_binding_handle *b;
8779 TALLOC_CTX *tmp_ctx = NULL;
8781 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8783 DEBUG(5,("_spoolss_SetForm\n"));
8785 if (!Printer) {
8786 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8787 OUR_HANDLE(r->in.handle)));
8788 return WERR_BADFID;
8791 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8792 and not a printer admin, then fail */
8794 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8795 !security_token_has_privilege(p->session_info->security_token,
8796 SEC_PRIV_PRINT_OPERATOR)) {
8797 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8798 return WERR_ACCESS_DENIED;
8801 tmp_ctx = talloc_new(p->mem_ctx);
8802 if (!tmp_ctx) {
8803 return WERR_NOMEM;
8806 status = winreg_printer_binding_handle(tmp_ctx,
8807 get_session_info_system(),
8808 p->msg_ctx,
8809 &b);
8810 if (!W_ERROR_IS_OK(status)) {
8811 goto done;
8814 status = winreg_printer_setform1(tmp_ctx, b,
8815 form_name,
8816 form);
8817 if (!W_ERROR_IS_OK(status)) {
8818 goto done;
8822 * ChangeID must always be set if this is a printer
8824 if (Printer->printer_type == SPLHND_PRINTER) {
8825 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8826 status = WERR_BADFID;
8827 goto done;
8830 status = winreg_printer_update_changeid(tmp_ctx, b,
8831 lp_const_servicename(snum));
8834 done:
8835 talloc_free(tmp_ctx);
8836 return status;
8839 /****************************************************************************
8840 fill_print_processor1
8841 ****************************************************************************/
8843 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8844 struct spoolss_PrintProcessorInfo1 *r,
8845 const char *print_processor_name)
8847 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8848 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8850 return WERR_OK;
8853 /****************************************************************************
8854 enumprintprocessors level 1.
8855 ****************************************************************************/
8857 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8858 union spoolss_PrintProcessorInfo **info_p,
8859 uint32_t *count)
8861 union spoolss_PrintProcessorInfo *info;
8862 WERROR result;
8864 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8865 W_ERROR_HAVE_NO_MEMORY(info);
8867 *count = 1;
8869 result = fill_print_processor1(info, &info[0].info1, "winprint");
8870 if (!W_ERROR_IS_OK(result)) {
8871 goto out;
8874 out:
8875 if (!W_ERROR_IS_OK(result)) {
8876 TALLOC_FREE(info);
8877 *count = 0;
8878 return result;
8881 *info_p = info;
8883 return WERR_OK;
8886 /****************************************************************
8887 _spoolss_EnumPrintProcessors
8888 ****************************************************************/
8890 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8891 struct spoolss_EnumPrintProcessors *r)
8893 WERROR result;
8895 /* that's an [in out] buffer */
8897 if (!r->in.buffer && (r->in.offered != 0)) {
8898 return WERR_INVALID_PARAM;
8901 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8904 * Enumerate the print processors ...
8906 * Just reply with "winprint", to keep NT happy
8907 * and I can use my nice printer checker.
8910 *r->out.count = 0;
8911 *r->out.needed = 0;
8912 *r->out.info = NULL;
8914 if (!get_short_archi(r->in.environment)) {
8915 return WERR_INVALID_ENVIRONMENT;
8918 switch (r->in.level) {
8919 case 1:
8920 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8921 r->out.count);
8922 break;
8923 default:
8924 return WERR_UNKNOWN_LEVEL;
8927 if (!W_ERROR_IS_OK(result)) {
8928 return result;
8931 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8932 spoolss_EnumPrintProcessors,
8933 *r->out.info, r->in.level,
8934 *r->out.count);
8935 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8936 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8938 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8941 /****************************************************************************
8942 fill_printprocdatatype1
8943 ****************************************************************************/
8945 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8946 struct spoolss_PrintProcDataTypesInfo1 *r,
8947 const char *name_array)
8949 r->name_array = talloc_strdup(mem_ctx, name_array);
8950 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8952 return WERR_OK;
8955 /****************************************************************************
8956 enumprintprocdatatypes level 1.
8957 ****************************************************************************/
8959 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8960 union spoolss_PrintProcDataTypesInfo **info_p,
8961 uint32_t *count)
8963 WERROR result;
8964 union spoolss_PrintProcDataTypesInfo *info;
8966 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8967 W_ERROR_HAVE_NO_MEMORY(info);
8969 *count = 1;
8971 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8972 if (!W_ERROR_IS_OK(result)) {
8973 goto out;
8976 out:
8977 if (!W_ERROR_IS_OK(result)) {
8978 TALLOC_FREE(info);
8979 *count = 0;
8980 return result;
8983 *info_p = info;
8985 return WERR_OK;
8988 /****************************************************************
8989 _spoolss_EnumPrintProcDataTypes
8990 ****************************************************************/
8992 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8993 struct spoolss_EnumPrintProcDataTypes *r)
8995 WERROR result;
8997 /* that's an [in out] buffer */
8999 if (!r->in.buffer && (r->in.offered != 0)) {
9000 return WERR_INVALID_PARAM;
9003 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9005 *r->out.count = 0;
9006 *r->out.needed = 0;
9007 *r->out.info = NULL;
9009 if (r->in.print_processor_name == NULL ||
9010 !strequal(r->in.print_processor_name, "winprint")) {
9011 return WERR_UNKNOWN_PRINTPROCESSOR;
9014 switch (r->in.level) {
9015 case 1:
9016 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9017 r->out.count);
9018 break;
9019 default:
9020 return WERR_UNKNOWN_LEVEL;
9023 if (!W_ERROR_IS_OK(result)) {
9024 return result;
9027 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9028 spoolss_EnumPrintProcDataTypes,
9029 *r->out.info, r->in.level,
9030 *r->out.count);
9031 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9032 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9034 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9037 /****************************************************************************
9038 fill_monitor_1
9039 ****************************************************************************/
9041 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9042 struct spoolss_MonitorInfo1 *r,
9043 const char *monitor_name)
9045 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9046 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9048 return WERR_OK;
9051 /****************************************************************************
9052 fill_monitor_2
9053 ****************************************************************************/
9055 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9056 struct spoolss_MonitorInfo2 *r,
9057 const char *monitor_name,
9058 const char *environment,
9059 const char *dll_name)
9061 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9062 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9063 r->environment = talloc_strdup(mem_ctx, environment);
9064 W_ERROR_HAVE_NO_MEMORY(r->environment);
9065 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9066 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9068 return WERR_OK;
9071 /****************************************************************************
9072 enumprintmonitors level 1.
9073 ****************************************************************************/
9075 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9076 union spoolss_MonitorInfo **info_p,
9077 uint32_t *count)
9079 union spoolss_MonitorInfo *info;
9080 WERROR result = WERR_OK;
9082 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9083 W_ERROR_HAVE_NO_MEMORY(info);
9085 *count = 2;
9087 result = fill_monitor_1(info, &info[0].info1,
9088 SPL_LOCAL_PORT);
9089 if (!W_ERROR_IS_OK(result)) {
9090 goto out;
9093 result = fill_monitor_1(info, &info[1].info1,
9094 SPL_TCPIP_PORT);
9095 if (!W_ERROR_IS_OK(result)) {
9096 goto out;
9099 out:
9100 if (!W_ERROR_IS_OK(result)) {
9101 TALLOC_FREE(info);
9102 *count = 0;
9103 return result;
9106 *info_p = info;
9108 return WERR_OK;
9111 /****************************************************************************
9112 enumprintmonitors level 2.
9113 ****************************************************************************/
9115 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9116 union spoolss_MonitorInfo **info_p,
9117 uint32_t *count)
9119 union spoolss_MonitorInfo *info;
9120 WERROR result = WERR_OK;
9122 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9123 W_ERROR_HAVE_NO_MEMORY(info);
9125 *count = 2;
9127 result = fill_monitor_2(info, &info[0].info2,
9128 SPL_LOCAL_PORT,
9129 "Windows NT X86", /* FIXME */
9130 "localmon.dll");
9131 if (!W_ERROR_IS_OK(result)) {
9132 goto out;
9135 result = fill_monitor_2(info, &info[1].info2,
9136 SPL_TCPIP_PORT,
9137 "Windows NT X86", /* FIXME */
9138 "tcpmon.dll");
9139 if (!W_ERROR_IS_OK(result)) {
9140 goto out;
9143 out:
9144 if (!W_ERROR_IS_OK(result)) {
9145 TALLOC_FREE(info);
9146 *count = 0;
9147 return result;
9150 *info_p = info;
9152 return WERR_OK;
9155 /****************************************************************
9156 _spoolss_EnumMonitors
9157 ****************************************************************/
9159 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9160 struct spoolss_EnumMonitors *r)
9162 WERROR result;
9164 /* that's an [in out] buffer */
9166 if (!r->in.buffer && (r->in.offered != 0)) {
9167 return WERR_INVALID_PARAM;
9170 DEBUG(5,("_spoolss_EnumMonitors\n"));
9173 * Enumerate the print monitors ...
9175 * Just reply with "Local Port", to keep NT happy
9176 * and I can use my nice printer checker.
9179 *r->out.count = 0;
9180 *r->out.needed = 0;
9181 *r->out.info = NULL;
9183 switch (r->in.level) {
9184 case 1:
9185 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9186 r->out.count);
9187 break;
9188 case 2:
9189 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9190 r->out.count);
9191 break;
9192 default:
9193 return WERR_UNKNOWN_LEVEL;
9196 if (!W_ERROR_IS_OK(result)) {
9197 return result;
9200 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9201 spoolss_EnumMonitors,
9202 *r->out.info, r->in.level,
9203 *r->out.count);
9204 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9205 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9207 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9210 /****************************************************************************
9211 ****************************************************************************/
9213 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9214 const print_queue_struct *queue,
9215 int count, int snum,
9216 struct spoolss_PrinterInfo2 *pinfo2,
9217 uint32_t jobid,
9218 struct spoolss_JobInfo1 *r)
9220 int i = 0;
9221 bool found = false;
9223 for (i=0; i<count; i++) {
9224 if (queue[i].sysjob == (int)jobid) {
9225 found = true;
9226 break;
9230 if (found == false) {
9231 /* NT treats not found as bad param... yet another bad choice */
9232 return WERR_INVALID_PARAM;
9235 return fill_job_info1(mem_ctx,
9237 &queue[i],
9239 snum,
9240 pinfo2);
9243 /****************************************************************************
9244 ****************************************************************************/
9246 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9247 const print_queue_struct *queue,
9248 int count, int snum,
9249 struct spoolss_PrinterInfo2 *pinfo2,
9250 uint32_t jobid,
9251 struct spoolss_JobInfo2 *r)
9253 int i = 0;
9254 bool found = false;
9255 struct spoolss_DeviceMode *devmode;
9256 WERROR result;
9258 for (i=0; i<count; i++) {
9259 if (queue[i].sysjob == (int)jobid) {
9260 found = true;
9261 break;
9265 if (found == false) {
9266 /* NT treats not found as bad param... yet another bad
9267 choice */
9268 return WERR_INVALID_PARAM;
9272 * if the print job does not have a DEVMODE associated with it,
9273 * just use the one for the printer. A NULL devicemode is not
9274 * a failure condition
9277 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9278 if (!devmode) {
9279 result = spoolss_create_default_devmode(mem_ctx,
9280 pinfo2->printername,
9281 &devmode);
9282 if (!W_ERROR_IS_OK(result)) {
9283 DEBUG(3, ("Can't proceed w/o a devmode!"));
9284 return result;
9288 return fill_job_info2(mem_ctx,
9290 &queue[i],
9292 snum,
9293 pinfo2,
9294 devmode);
9297 /****************************************************************
9298 _spoolss_GetJob
9299 ****************************************************************/
9301 WERROR _spoolss_GetJob(struct pipes_struct *p,
9302 struct spoolss_GetJob *r)
9304 WERROR result = WERR_OK;
9305 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9306 int snum;
9307 int count;
9308 print_queue_struct *queue = NULL;
9309 print_status_struct prt_status;
9311 /* that's an [in out] buffer */
9313 if (!r->in.buffer && (r->in.offered != 0)) {
9314 return WERR_INVALID_PARAM;
9317 DEBUG(5,("_spoolss_GetJob\n"));
9319 *r->out.needed = 0;
9321 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9322 return WERR_BADFID;
9325 result = winreg_get_printer_internal(p->mem_ctx,
9326 get_session_info_system(),
9327 p->msg_ctx,
9328 lp_const_servicename(snum),
9329 &pinfo2);
9330 if (!W_ERROR_IS_OK(result)) {
9331 return result;
9334 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9336 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9337 count, prt_status.status, prt_status.message));
9339 switch (r->in.level) {
9340 case 1:
9341 result = getjob_level_1(p->mem_ctx,
9342 queue, count, snum, pinfo2,
9343 r->in.job_id, &r->out.info->info1);
9344 break;
9345 case 2:
9346 result = getjob_level_2(p->mem_ctx,
9347 queue, count, snum, pinfo2,
9348 r->in.job_id, &r->out.info->info2);
9349 break;
9350 default:
9351 result = WERR_UNKNOWN_LEVEL;
9352 break;
9355 SAFE_FREE(queue);
9356 TALLOC_FREE(pinfo2);
9358 if (!W_ERROR_IS_OK(result)) {
9359 TALLOC_FREE(r->out.info);
9360 return result;
9363 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9364 r->in.level);
9365 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9367 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9370 /****************************************************************
9371 _spoolss_GetPrinterDataEx
9372 ****************************************************************/
9374 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9375 struct spoolss_GetPrinterDataEx *r)
9378 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9379 const char *printer;
9380 int snum = 0;
9381 WERROR result = WERR_OK;
9382 DATA_BLOB blob;
9383 enum winreg_Type val_type = REG_NONE;
9384 uint8_t *val_data = NULL;
9385 uint32_t val_size = 0;
9386 struct dcerpc_binding_handle *b;
9387 TALLOC_CTX *tmp_ctx;
9389 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9391 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9392 r->in.key_name, r->in.value_name));
9394 /* in case of problem, return some default values */
9396 *r->out.needed = 0;
9397 *r->out.type = REG_NONE;
9399 tmp_ctx = talloc_new(p->mem_ctx);
9400 if (!tmp_ctx) {
9401 return WERR_NOMEM;
9404 if (!Printer) {
9405 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9406 OUR_HANDLE(r->in.handle)));
9407 result = WERR_BADFID;
9408 goto done;
9411 /* check to see if the keyname is valid */
9412 if (!strlen(r->in.key_name)) {
9413 result = WERR_INVALID_PARAM;
9414 goto done;
9417 /* Is the handle to a printer or to the server? */
9419 if (Printer->printer_type == SPLHND_SERVER) {
9421 union spoolss_PrinterData data;
9423 result = getprinterdata_printer_server(tmp_ctx,
9424 r->in.value_name,
9425 r->out.type,
9426 &data);
9427 if (!W_ERROR_IS_OK(result)) {
9428 goto done;
9431 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9432 *r->out.type, &data);
9433 if (!W_ERROR_IS_OK(result)) {
9434 goto done;
9437 *r->out.needed = blob.length;
9439 if (r->in.offered >= *r->out.needed) {
9440 memcpy(r->out.data, blob.data, blob.length);
9443 result = WERR_OK;
9444 goto done;
9447 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9448 result = WERR_BADFID;
9449 goto done;
9451 printer = lp_const_servicename(snum);
9453 result = winreg_printer_binding_handle(tmp_ctx,
9454 get_session_info_system(),
9455 p->msg_ctx,
9456 &b);
9457 if (!W_ERROR_IS_OK(result)) {
9458 goto done;
9461 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9462 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9463 strequal(r->in.value_name, "ChangeId")) {
9464 *r->out.type = REG_DWORD;
9465 *r->out.needed = 4;
9466 if (r->in.offered >= *r->out.needed) {
9467 uint32_t changeid = 0;
9469 result = winreg_printer_get_changeid(tmp_ctx, b,
9470 printer,
9471 &changeid);
9472 if (!W_ERROR_IS_OK(result)) {
9473 goto done;
9476 SIVAL(r->out.data, 0, changeid);
9477 result = WERR_OK;
9479 goto done;
9482 result = winreg_get_printer_dataex(tmp_ctx, b,
9483 printer,
9484 r->in.key_name,
9485 r->in.value_name,
9486 &val_type,
9487 &val_data,
9488 &val_size);
9489 if (!W_ERROR_IS_OK(result)) {
9490 goto done;
9493 *r->out.needed = val_size;
9494 *r->out.type = val_type;
9496 if (r->in.offered >= *r->out.needed) {
9497 memcpy(r->out.data, val_data, val_size);
9500 done:
9501 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9503 if (W_ERROR_IS_OK(result)) {
9504 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9507 talloc_free(tmp_ctx);
9508 return result;
9511 /****************************************************************
9512 _spoolss_SetPrinterDataEx
9513 ****************************************************************/
9515 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9516 struct spoolss_SetPrinterDataEx *r)
9518 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9519 int snum = 0;
9520 WERROR result = WERR_OK;
9521 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9522 char *oid_string;
9523 struct dcerpc_binding_handle *b;
9524 TALLOC_CTX *tmp_ctx;
9526 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9528 /* From MSDN documentation of SetPrinterDataEx: pass request to
9529 SetPrinterData if key is "PrinterDriverData" */
9531 if (!Printer) {
9532 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9533 OUR_HANDLE(r->in.handle)));
9534 return WERR_BADFID;
9537 if (Printer->printer_type == SPLHND_SERVER) {
9538 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9539 "Not implemented for server handles yet\n"));
9540 return WERR_INVALID_PARAM;
9543 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9544 return WERR_BADFID;
9548 * Access check : NT returns "access denied" if you make a
9549 * SetPrinterData call without the necessary privildge.
9550 * we were originally returning OK if nothing changed
9551 * which made Win2k issue **a lot** of SetPrinterData
9552 * when connecting to a printer --jerry
9555 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9556 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9557 "change denied by handle access permissions\n"));
9558 return WERR_ACCESS_DENIED;
9561 tmp_ctx = talloc_new(p->mem_ctx);
9562 if (!tmp_ctx) {
9563 return WERR_NOMEM;
9566 result = winreg_printer_binding_handle(tmp_ctx,
9567 get_session_info_system(),
9568 p->msg_ctx,
9569 &b);
9570 if (!W_ERROR_IS_OK(result)) {
9571 goto done;
9574 result = winreg_get_printer(tmp_ctx, b,
9575 lp_servicename(talloc_tos(), snum),
9576 &pinfo2);
9577 if (!W_ERROR_IS_OK(result)) {
9578 goto done;
9581 /* check for OID in valuename */
9583 oid_string = strchr(r->in.value_name, ',');
9584 if (oid_string) {
9585 *oid_string = '\0';
9586 oid_string++;
9589 /* save the registry data */
9591 result = winreg_set_printer_dataex(tmp_ctx, b,
9592 pinfo2->sharename,
9593 r->in.key_name,
9594 r->in.value_name,
9595 r->in.type,
9596 r->in.data,
9597 r->in.offered);
9599 if (W_ERROR_IS_OK(result)) {
9600 /* save the OID if one was specified */
9601 if (oid_string) {
9602 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9603 r->in.key_name, SPOOL_OID_KEY);
9604 if (!str) {
9605 result = WERR_NOMEM;
9606 goto done;
9610 * I'm not checking the status here on purpose. Don't know
9611 * if this is right, but I'm returning the status from the
9612 * previous set_printer_dataex() call. I have no idea if
9613 * this is right. --jerry
9615 winreg_set_printer_dataex(tmp_ctx, b,
9616 pinfo2->sharename,
9617 str,
9618 r->in.value_name,
9619 REG_SZ,
9620 (uint8_t *) oid_string,
9621 strlen(oid_string) + 1);
9624 result = winreg_printer_update_changeid(tmp_ctx, b,
9625 lp_const_servicename(snum));
9629 done:
9630 talloc_free(tmp_ctx);
9631 return result;
9634 /****************************************************************
9635 _spoolss_DeletePrinterDataEx
9636 ****************************************************************/
9638 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9639 struct spoolss_DeletePrinterDataEx *r)
9641 const char *printer;
9642 int snum=0;
9643 WERROR status = WERR_OK;
9644 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9646 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9648 if (!Printer) {
9649 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9650 "Invalid handle (%s:%u:%u).\n",
9651 OUR_HANDLE(r->in.handle)));
9652 return WERR_BADFID;
9655 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9656 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9657 "printer properties change denied by handle\n"));
9658 return WERR_ACCESS_DENIED;
9661 if (!r->in.value_name || !r->in.key_name) {
9662 return WERR_NOMEM;
9665 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9666 return WERR_BADFID;
9668 printer = lp_const_servicename(snum);
9670 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9671 get_session_info_system(),
9672 p->msg_ctx,
9673 printer,
9674 r->in.key_name,
9675 r->in.value_name);
9676 if (W_ERROR_IS_OK(status)) {
9677 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9678 get_session_info_system(),
9679 p->msg_ctx,
9680 printer);
9683 return status;
9686 /****************************************************************
9687 _spoolss_EnumPrinterKey
9688 ****************************************************************/
9690 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9691 struct spoolss_EnumPrinterKey *r)
9693 uint32_t num_keys;
9694 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9695 int snum = 0;
9696 WERROR result = WERR_BADFILE;
9697 const char **array = NULL;
9698 DATA_BLOB blob;
9700 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9702 if (!Printer) {
9703 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9704 OUR_HANDLE(r->in.handle)));
9705 return WERR_BADFID;
9708 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9709 return WERR_BADFID;
9712 result = winreg_enum_printer_key_internal(p->mem_ctx,
9713 get_session_info_system(),
9714 p->msg_ctx,
9715 lp_const_servicename(snum),
9716 r->in.key_name,
9717 &num_keys,
9718 &array);
9719 if (!W_ERROR_IS_OK(result)) {
9720 goto done;
9723 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9724 result = WERR_NOMEM;
9725 goto done;
9728 *r->out._ndr_size = r->in.offered / 2;
9729 *r->out.needed = blob.length;
9731 if (r->in.offered < *r->out.needed) {
9732 result = WERR_MORE_DATA;
9733 } else {
9734 result = WERR_OK;
9735 r->out.key_buffer->string_array = array;
9738 done:
9739 if (!W_ERROR_IS_OK(result)) {
9740 TALLOC_FREE(array);
9741 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9742 *r->out.needed = 0;
9746 return result;
9749 /****************************************************************
9750 _spoolss_DeletePrinterKey
9751 ****************************************************************/
9753 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9754 struct spoolss_DeletePrinterKey *r)
9756 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9757 int snum=0;
9758 WERROR status;
9759 const char *printer;
9760 struct dcerpc_binding_handle *b;
9761 TALLOC_CTX *tmp_ctx;
9763 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9765 if (!Printer) {
9766 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9767 OUR_HANDLE(r->in.handle)));
9768 return WERR_BADFID;
9771 /* if keyname == NULL, return error */
9772 if ( !r->in.key_name )
9773 return WERR_INVALID_PARAM;
9775 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9776 return WERR_BADFID;
9779 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9780 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9781 "printer properties change denied by handle\n"));
9782 return WERR_ACCESS_DENIED;
9785 printer = lp_const_servicename(snum);
9787 tmp_ctx = talloc_new(p->mem_ctx);
9788 if (!tmp_ctx) {
9789 return WERR_NOMEM;
9792 status = winreg_printer_binding_handle(tmp_ctx,
9793 get_session_info_system(),
9794 p->msg_ctx,
9795 &b);
9796 if (!W_ERROR_IS_OK(status)) {
9797 goto done;
9800 /* delete the key and all subkeys */
9801 status = winreg_delete_printer_key(tmp_ctx, b,
9802 printer,
9803 r->in.key_name);
9804 if (W_ERROR_IS_OK(status)) {
9805 status = winreg_printer_update_changeid(tmp_ctx, b,
9806 printer);
9809 done:
9810 talloc_free(tmp_ctx);
9811 return status;
9814 /****************************************************************
9815 _spoolss_EnumPrinterDataEx
9816 ****************************************************************/
9818 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9819 struct spoolss_EnumPrinterDataEx *r)
9821 uint32_t count = 0;
9822 struct spoolss_PrinterEnumValues *info = NULL;
9823 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9824 int snum;
9825 WERROR result;
9827 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9829 *r->out.count = 0;
9830 *r->out.needed = 0;
9831 *r->out.info = NULL;
9833 if (!Printer) {
9834 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9835 OUR_HANDLE(r->in.handle)));
9836 return WERR_BADFID;
9840 * first check for a keyname of NULL or "". Win2k seems to send
9841 * this a lot and we should send back WERR_INVALID_PARAM
9842 * no need to spend time looking up the printer in this case.
9843 * --jerry
9846 if (!strlen(r->in.key_name)) {
9847 result = WERR_INVALID_PARAM;
9848 goto done;
9851 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9852 return WERR_BADFID;
9855 /* now look for a match on the key name */
9856 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9857 get_session_info_system(),
9858 p->msg_ctx,
9859 lp_const_servicename(snum),
9860 r->in.key_name,
9861 &count,
9862 &info);
9863 if (!W_ERROR_IS_OK(result)) {
9864 goto done;
9867 #if 0 /* FIXME - gd */
9868 /* housekeeping information in the reply */
9870 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9871 * the hand marshalled container size is a multiple
9872 * of 4 bytes for RPC alignment.
9875 if (needed % 4) {
9876 needed += 4-(needed % 4);
9878 #endif
9879 *r->out.count = count;
9880 *r->out.info = info;
9882 done:
9883 if (!W_ERROR_IS_OK(result)) {
9884 return result;
9887 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9888 spoolss_EnumPrinterDataEx,
9889 *r->out.info,
9890 *r->out.count);
9891 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9892 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9894 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9897 /****************************************************************************
9898 ****************************************************************************/
9900 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9901 const char *servername,
9902 const char *environment,
9903 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9905 WERROR werr;
9906 char *path = NULL;
9908 werr = compose_spoolss_server_path(mem_ctx,
9909 servername,
9910 environment,
9911 SPOOLSS_PRTPROCS_PATH,
9912 &path);
9913 if (!W_ERROR_IS_OK(werr)) {
9914 return werr;
9917 DEBUG(4,("print processor directory: [%s]\n", path));
9919 r->directory_name = path;
9921 return WERR_OK;
9924 /****************************************************************
9925 _spoolss_GetPrintProcessorDirectory
9926 ****************************************************************/
9928 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9929 struct spoolss_GetPrintProcessorDirectory *r)
9931 WERROR result;
9932 char *prnproc_share = NULL;
9933 bool prnproc_share_exists = false;
9934 int snum;
9936 /* that's an [in out] buffer */
9938 if (!r->in.buffer && (r->in.offered != 0)) {
9939 return WERR_INVALID_PARAM;
9942 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9943 r->in.level));
9945 *r->out.needed = 0;
9947 /* r->in.level is ignored */
9949 /* We always should reply with a local print processor directory so that
9950 * users are not forced to have a [prnproc$] share on the Samba spoolss
9951 * server, if users decide to do so, lets announce it though - Guenther */
9953 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9954 if (!prnproc_share) {
9955 return WERR_NOMEM;
9957 if (snum != -1) {
9958 prnproc_share_exists = true;
9961 result = getprintprocessordirectory_level_1(p->mem_ctx,
9962 prnproc_share_exists ? r->in.server : NULL,
9963 r->in.environment,
9964 &r->out.info->info1);
9965 if (!W_ERROR_IS_OK(result)) {
9966 TALLOC_FREE(r->out.info);
9967 return result;
9970 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9971 r->out.info, r->in.level);
9972 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9974 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9977 /*******************************************************************
9978 ********************************************************************/
9980 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9981 const char *dllname)
9983 enum ndr_err_code ndr_err;
9984 struct spoolss_MonitorUi ui;
9986 ui.dll_name = dllname;
9988 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9989 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9990 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9991 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9993 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9996 /*******************************************************************
9997 Streams the monitor UI DLL name in UNICODE
9998 *******************************************************************/
10000 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10001 struct security_token *token, DATA_BLOB *in,
10002 DATA_BLOB *out, uint32_t *needed)
10004 const char *dllname = "tcpmonui.dll";
10006 *needed = (strlen(dllname)+1) * 2;
10008 if (out->length < *needed) {
10009 return WERR_INSUFFICIENT_BUFFER;
10012 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10013 return WERR_NOMEM;
10016 return WERR_OK;
10019 /*******************************************************************
10020 ********************************************************************/
10022 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10023 struct spoolss_PortData1 *port1,
10024 const DATA_BLOB *buf)
10026 enum ndr_err_code ndr_err;
10027 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10028 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10029 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10030 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10032 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10035 /*******************************************************************
10036 ********************************************************************/
10038 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10039 struct spoolss_PortData2 *port2,
10040 const DATA_BLOB *buf)
10042 enum ndr_err_code ndr_err;
10043 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10044 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10045 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10046 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10048 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10051 /*******************************************************************
10052 Create a new TCP/IP port
10053 *******************************************************************/
10055 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10056 struct security_token *token, DATA_BLOB *in,
10057 DATA_BLOB *out, uint32_t *needed)
10059 struct spoolss_PortData1 port1;
10060 struct spoolss_PortData2 port2;
10061 char *device_uri = NULL;
10062 uint32_t version;
10064 const char *portname;
10065 const char *hostaddress;
10066 const char *queue;
10067 uint32_t port_number;
10068 uint32_t protocol;
10070 /* peek for spoolss_PortData version */
10072 if (!in || (in->length < (128 + 4))) {
10073 return WERR_GENERAL_FAILURE;
10076 version = IVAL(in->data, 128);
10078 switch (version) {
10079 case 1:
10080 ZERO_STRUCT(port1);
10082 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10083 return WERR_NOMEM;
10086 portname = port1.portname;
10087 hostaddress = port1.hostaddress;
10088 queue = port1.queue;
10089 protocol = port1.protocol;
10090 port_number = port1.port_number;
10092 break;
10093 case 2:
10094 ZERO_STRUCT(port2);
10096 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10097 return WERR_NOMEM;
10100 portname = port2.portname;
10101 hostaddress = port2.hostaddress;
10102 queue = port2.queue;
10103 protocol = port2.protocol;
10104 port_number = port2.port_number;
10106 break;
10107 default:
10108 DEBUG(1,("xcvtcp_addport: "
10109 "unknown version of port_data: %d\n", version));
10110 return WERR_UNKNOWN_PORT;
10113 /* create the device URI and call the add_port_hook() */
10115 switch (protocol) {
10116 case PROTOCOL_RAWTCP_TYPE:
10117 device_uri = talloc_asprintf(mem_ctx,
10118 "socket://%s:%d/", hostaddress,
10119 port_number);
10120 break;
10122 case PROTOCOL_LPR_TYPE:
10123 device_uri = talloc_asprintf(mem_ctx,
10124 "lpr://%s/%s", hostaddress, queue );
10125 break;
10127 default:
10128 return WERR_UNKNOWN_PORT;
10131 if (!device_uri) {
10132 return WERR_NOMEM;
10135 return add_port_hook(mem_ctx, token, portname, device_uri);
10138 /*******************************************************************
10139 *******************************************************************/
10141 struct xcv_api_table xcvtcp_cmds[] = {
10142 { "MonitorUI", xcvtcp_monitorui },
10143 { "AddPort", xcvtcp_addport},
10144 { NULL, NULL }
10147 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10148 struct security_token *token, const char *command,
10149 DATA_BLOB *inbuf,
10150 DATA_BLOB *outbuf,
10151 uint32_t *needed )
10153 int i;
10155 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10157 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10158 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10159 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10162 return WERR_BADFUNC;
10165 /*******************************************************************
10166 *******************************************************************/
10167 #if 0 /* don't support management using the "Local Port" monitor */
10169 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10170 struct security_token *token, DATA_BLOB *in,
10171 DATA_BLOB *out, uint32_t *needed)
10173 const char *dllname = "localui.dll";
10175 *needed = (strlen(dllname)+1) * 2;
10177 if (out->length < *needed) {
10178 return WERR_INSUFFICIENT_BUFFER;
10181 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10182 return WERR_NOMEM;
10185 return WERR_OK;
10188 /*******************************************************************
10189 *******************************************************************/
10191 struct xcv_api_table xcvlocal_cmds[] = {
10192 { "MonitorUI", xcvlocal_monitorui },
10193 { NULL, NULL }
10195 #else
10196 struct xcv_api_table xcvlocal_cmds[] = {
10197 { NULL, NULL }
10199 #endif
10203 /*******************************************************************
10204 *******************************************************************/
10206 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10207 struct security_token *token, const char *command,
10208 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10209 uint32_t *needed)
10211 int i;
10213 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10215 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10216 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10217 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10219 return WERR_BADFUNC;
10222 /****************************************************************
10223 _spoolss_XcvData
10224 ****************************************************************/
10226 WERROR _spoolss_XcvData(struct pipes_struct *p,
10227 struct spoolss_XcvData *r)
10229 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10230 DATA_BLOB out_data = data_blob_null;
10231 WERROR werror;
10233 if (!Printer) {
10234 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10235 OUR_HANDLE(r->in.handle)));
10236 return WERR_BADFID;
10239 /* Has to be a handle to the TCP/IP port monitor */
10241 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10242 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10243 return WERR_BADFID;
10246 /* requires administrative access to the server */
10248 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10249 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10250 return WERR_ACCESS_DENIED;
10253 /* Allocate the outgoing buffer */
10255 if (r->in.out_data_size) {
10256 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10257 if (out_data.data == NULL) {
10258 return WERR_NOMEM;
10262 switch ( Printer->printer_type ) {
10263 case SPLHND_PORTMON_TCP:
10264 werror = process_xcvtcp_command(p->mem_ctx,
10265 p->session_info->security_token,
10266 r->in.function_name,
10267 &r->in.in_data, &out_data,
10268 r->out.needed);
10269 break;
10270 case SPLHND_PORTMON_LOCAL:
10271 werror = process_xcvlocal_command(p->mem_ctx,
10272 p->session_info->security_token,
10273 r->in.function_name,
10274 &r->in.in_data, &out_data,
10275 r->out.needed);
10276 break;
10277 default:
10278 werror = WERR_INVALID_PRINT_MONITOR;
10281 if (!W_ERROR_IS_OK(werror)) {
10282 return werror;
10285 *r->out.status_code = 0;
10287 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10288 memcpy(r->out.out_data, out_data.data,
10289 MIN(r->in.out_data_size, out_data.length));
10292 return WERR_OK;
10295 /****************************************************************
10296 _spoolss_AddPrintProcessor
10297 ****************************************************************/
10299 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10300 struct spoolss_AddPrintProcessor *r)
10302 /* for now, just indicate success and ignore the add. We'll
10303 automatically set the winprint processor for printer
10304 entries later. Used to debug the LexMark Optra S 1855 PCL
10305 driver --jerry */
10307 return WERR_OK;
10310 /****************************************************************
10311 _spoolss_AddPort
10312 ****************************************************************/
10314 WERROR _spoolss_AddPort(struct pipes_struct *p,
10315 struct spoolss_AddPort *r)
10317 /* do what w2k3 does */
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_GetPrinterDriver
10324 ****************************************************************/
10326 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10327 struct spoolss_GetPrinterDriver *r)
10329 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_ReadPrinter
10335 ****************************************************************/
10337 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10338 struct spoolss_ReadPrinter *r)
10340 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10345 _spoolss_WaitForPrinterChange
10346 ****************************************************************/
10348 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10349 struct spoolss_WaitForPrinterChange *r)
10351 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10356 _spoolss_ConfigurePort
10357 ****************************************************************/
10359 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10360 struct spoolss_ConfigurePort *r)
10362 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10367 _spoolss_DeletePort
10368 ****************************************************************/
10370 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10371 struct spoolss_DeletePort *r)
10373 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10378 _spoolss_CreatePrinterIC
10379 ****************************************************************/
10381 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10382 struct spoolss_CreatePrinterIC *r)
10384 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10389 _spoolss_PlayGDIScriptOnPrinterIC
10390 ****************************************************************/
10392 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10393 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10395 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10400 _spoolss_DeletePrinterIC
10401 ****************************************************************/
10403 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10404 struct spoolss_DeletePrinterIC *r)
10406 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10411 _spoolss_AddPrinterConnection
10412 ****************************************************************/
10414 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10415 struct spoolss_AddPrinterConnection *r)
10417 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_DeletePrinterConnection
10423 ****************************************************************/
10425 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10426 struct spoolss_DeletePrinterConnection *r)
10428 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_PrinterMessageBox
10434 ****************************************************************/
10436 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10437 struct spoolss_PrinterMessageBox *r)
10439 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10440 return WERR_NOT_SUPPORTED;
10443 /****************************************************************
10444 _spoolss_AddMonitor
10445 ****************************************************************/
10447 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10448 struct spoolss_AddMonitor *r)
10450 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10451 return WERR_NOT_SUPPORTED;
10454 /****************************************************************
10455 _spoolss_DeleteMonitor
10456 ****************************************************************/
10458 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10459 struct spoolss_DeleteMonitor *r)
10461 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10462 return WERR_NOT_SUPPORTED;
10465 /****************************************************************
10466 _spoolss_DeletePrintProcessor
10467 ****************************************************************/
10469 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10470 struct spoolss_DeletePrintProcessor *r)
10472 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10473 return WERR_NOT_SUPPORTED;
10476 /****************************************************************
10477 _spoolss_AddPrintProvidor
10478 ****************************************************************/
10480 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10481 struct spoolss_AddPrintProvidor *r)
10483 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10484 return WERR_NOT_SUPPORTED;
10487 /****************************************************************
10488 _spoolss_DeletePrintProvidor
10489 ****************************************************************/
10491 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10492 struct spoolss_DeletePrintProvidor *r)
10494 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10495 return WERR_NOT_SUPPORTED;
10498 /****************************************************************
10499 _spoolss_FindFirstPrinterChangeNotification
10500 ****************************************************************/
10502 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10503 struct spoolss_FindFirstPrinterChangeNotification *r)
10505 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10506 return WERR_NOT_SUPPORTED;
10509 /****************************************************************
10510 _spoolss_FindNextPrinterChangeNotification
10511 ****************************************************************/
10513 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10514 struct spoolss_FindNextPrinterChangeNotification *r)
10516 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10517 return WERR_NOT_SUPPORTED;
10520 /****************************************************************
10521 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10522 ****************************************************************/
10524 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10525 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10527 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10528 return WERR_NOT_SUPPORTED;
10531 /****************************************************************
10532 _spoolss_ReplyOpenPrinter
10533 ****************************************************************/
10535 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10536 struct spoolss_ReplyOpenPrinter *r)
10538 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10539 return WERR_NOT_SUPPORTED;
10542 /****************************************************************
10543 _spoolss_RouterReplyPrinter
10544 ****************************************************************/
10546 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10547 struct spoolss_RouterReplyPrinter *r)
10549 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10550 return WERR_NOT_SUPPORTED;
10553 /****************************************************************
10554 _spoolss_ReplyClosePrinter
10555 ****************************************************************/
10557 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10558 struct spoolss_ReplyClosePrinter *r)
10560 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10561 return WERR_NOT_SUPPORTED;
10564 /****************************************************************
10565 _spoolss_AddPortEx
10566 ****************************************************************/
10568 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10569 struct spoolss_AddPortEx *r)
10571 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10572 return WERR_NOT_SUPPORTED;
10575 /****************************************************************
10576 _spoolss_RouterFindFirstPrinterChangeNotification
10577 ****************************************************************/
10579 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10580 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10582 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10583 return WERR_NOT_SUPPORTED;
10586 /****************************************************************
10587 _spoolss_SpoolerInit
10588 ****************************************************************/
10590 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10591 struct spoolss_SpoolerInit *r)
10593 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10594 return WERR_NOT_SUPPORTED;
10597 /****************************************************************
10598 _spoolss_ResetPrinterEx
10599 ****************************************************************/
10601 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10602 struct spoolss_ResetPrinterEx *r)
10604 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10605 return WERR_NOT_SUPPORTED;
10608 /****************************************************************
10609 _spoolss_RouterReplyPrinterEx
10610 ****************************************************************/
10612 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10613 struct spoolss_RouterReplyPrinterEx *r)
10615 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10616 return WERR_NOT_SUPPORTED;
10619 /****************************************************************
10620 _spoolss_44
10621 ****************************************************************/
10623 WERROR _spoolss_44(struct pipes_struct *p,
10624 struct spoolss_44 *r)
10626 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10627 return WERR_NOT_SUPPORTED;
10630 /****************************************************************
10631 _spoolss_SetPort
10632 ****************************************************************/
10634 WERROR _spoolss_SetPort(struct pipes_struct *p,
10635 struct spoolss_SetPort *r)
10637 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10638 return WERR_NOT_SUPPORTED;
10641 /****************************************************************
10642 _spoolss_4a
10643 ****************************************************************/
10645 WERROR _spoolss_4a(struct pipes_struct *p,
10646 struct spoolss_4a *r)
10648 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10649 return WERR_NOT_SUPPORTED;
10652 /****************************************************************
10653 _spoolss_4b
10654 ****************************************************************/
10656 WERROR _spoolss_4b(struct pipes_struct *p,
10657 struct spoolss_4b *r)
10659 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10660 return WERR_NOT_SUPPORTED;
10663 /****************************************************************
10664 _spoolss_4c
10665 ****************************************************************/
10667 WERROR _spoolss_4c(struct pipes_struct *p,
10668 struct spoolss_4c *r)
10670 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10671 return WERR_NOT_SUPPORTED;
10674 /****************************************************************
10675 _spoolss_53
10676 ****************************************************************/
10678 WERROR _spoolss_53(struct pipes_struct *p,
10679 struct spoolss_53 *r)
10681 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10682 return WERR_NOT_SUPPORTED;
10685 /****************************************************************
10686 _spoolss_AddPerMachineConnection
10687 ****************************************************************/
10689 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10690 struct spoolss_AddPerMachineConnection *r)
10692 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10693 return WERR_NOT_SUPPORTED;
10696 /****************************************************************
10697 _spoolss_DeletePerMachineConnection
10698 ****************************************************************/
10700 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10701 struct spoolss_DeletePerMachineConnection *r)
10703 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10704 return WERR_NOT_SUPPORTED;
10707 /****************************************************************
10708 _spoolss_EnumPerMachineConnections
10709 ****************************************************************/
10711 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10712 struct spoolss_EnumPerMachineConnections *r)
10714 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10715 return WERR_NOT_SUPPORTED;
10718 /****************************************************************
10719 _spoolss_5a
10720 ****************************************************************/
10722 WERROR _spoolss_5a(struct pipes_struct *p,
10723 struct spoolss_5a *r)
10725 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10726 return WERR_NOT_SUPPORTED;
10729 /****************************************************************
10730 _spoolss_5b
10731 ****************************************************************/
10733 WERROR _spoolss_5b(struct pipes_struct *p,
10734 struct spoolss_5b *r)
10736 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10737 return WERR_NOT_SUPPORTED;
10740 /****************************************************************
10741 _spoolss_5c
10742 ****************************************************************/
10744 WERROR _spoolss_5c(struct pipes_struct *p,
10745 struct spoolss_5c *r)
10747 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10748 return WERR_NOT_SUPPORTED;
10751 /****************************************************************
10752 _spoolss_5d
10753 ****************************************************************/
10755 WERROR _spoolss_5d(struct pipes_struct *p,
10756 struct spoolss_5d *r)
10758 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10759 return WERR_NOT_SUPPORTED;
10762 /****************************************************************
10763 _spoolss_5e
10764 ****************************************************************/
10766 WERROR _spoolss_5e(struct pipes_struct *p,
10767 struct spoolss_5e *r)
10769 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10770 return WERR_NOT_SUPPORTED;
10773 /****************************************************************
10774 _spoolss_5f
10775 ****************************************************************/
10777 WERROR _spoolss_5f(struct pipes_struct *p,
10778 struct spoolss_5f *r)
10780 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10781 return WERR_NOT_SUPPORTED;
10784 /****************************************************************
10785 _spoolss_60
10786 ****************************************************************/
10788 WERROR _spoolss_60(struct pipes_struct *p,
10789 struct spoolss_60 *r)
10791 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10792 return WERR_NOT_SUPPORTED;
10795 /****************************************************************
10796 _spoolss_61
10797 ****************************************************************/
10799 WERROR _spoolss_61(struct pipes_struct *p,
10800 struct spoolss_61 *r)
10802 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10803 return WERR_NOT_SUPPORTED;
10806 /****************************************************************
10807 _spoolss_62
10808 ****************************************************************/
10810 WERROR _spoolss_62(struct pipes_struct *p,
10811 struct spoolss_62 *r)
10813 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10814 return WERR_NOT_SUPPORTED;
10817 /****************************************************************
10818 _spoolss_63
10819 ****************************************************************/
10821 WERROR _spoolss_63(struct pipes_struct *p,
10822 struct spoolss_63 *r)
10824 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10825 return WERR_NOT_SUPPORTED;
10828 /****************************************************************
10829 _spoolss_64
10830 ****************************************************************/
10832 WERROR _spoolss_64(struct pipes_struct *p,
10833 struct spoolss_64 *r)
10835 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10836 return WERR_NOT_SUPPORTED;
10839 /****************************************************************
10840 _spoolss_65
10841 ****************************************************************/
10843 WERROR _spoolss_65(struct pipes_struct *p,
10844 struct spoolss_65 *r)
10846 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10847 return WERR_NOT_SUPPORTED;
10850 /****************************************************************
10851 _spoolss_GetCorePrinterDrivers
10852 ****************************************************************/
10854 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10855 struct spoolss_GetCorePrinterDrivers *r)
10857 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10858 return WERR_NOT_SUPPORTED;
10861 /****************************************************************
10862 _spoolss_67
10863 ****************************************************************/
10865 WERROR _spoolss_67(struct pipes_struct *p,
10866 struct spoolss_67 *r)
10868 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10869 return WERR_NOT_SUPPORTED;
10872 /****************************************************************
10873 _spoolss_GetPrinterDriverPackagePath
10874 ****************************************************************/
10876 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10877 struct spoolss_GetPrinterDriverPackagePath *r)
10879 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10880 return WERR_NOT_SUPPORTED;
10883 /****************************************************************
10884 _spoolss_69
10885 ****************************************************************/
10887 WERROR _spoolss_69(struct pipes_struct *p,
10888 struct spoolss_69 *r)
10890 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10891 return WERR_NOT_SUPPORTED;
10894 /****************************************************************
10895 _spoolss_6a
10896 ****************************************************************/
10898 WERROR _spoolss_6a(struct pipes_struct *p,
10899 struct spoolss_6a *r)
10901 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10902 return WERR_NOT_SUPPORTED;
10905 /****************************************************************
10906 _spoolss_6b
10907 ****************************************************************/
10909 WERROR _spoolss_6b(struct pipes_struct *p,
10910 struct spoolss_6b *r)
10912 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10913 return WERR_NOT_SUPPORTED;
10916 /****************************************************************
10917 _spoolss_6c
10918 ****************************************************************/
10920 WERROR _spoolss_6c(struct pipes_struct *p,
10921 struct spoolss_6c *r)
10923 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10924 return WERR_NOT_SUPPORTED;
10927 /****************************************************************
10928 _spoolss_6d
10929 ****************************************************************/
10931 WERROR _spoolss_6d(struct pipes_struct *p,
10932 struct spoolss_6d *r)
10934 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10935 return WERR_NOT_SUPPORTED;