s3-spoolss: fix printer_driver_files_in_use() call ordering
[Samba/gebeck_regimport.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blobc691b4a1f5ac37a1c87cd915a56364ab1b1fda9f
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "smbd/globals.h"
51 #include "auth.h"
52 #include "messages.h"
53 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "util_tdb.h"
55 #include "libsmb/libsmb.h"
56 #include "printing/printer_list.h"
57 #include "../lib/tsocket/tsocket.h"
58 #include "rpc_client/cli_winreg_spoolss.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();
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.level > 3) {
1714 return WERR_INVALID_PARAM;
1716 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1717 (r->in.level == 2 && !r->in.userlevel.level2) ||
1718 (r->in.level == 3 && !r->in.userlevel.level3)) {
1719 return WERR_INVALID_PARAM;
1722 /* some sanity check because you can open a printer or a print server */
1723 /* aka: \\server\printer or \\server */
1725 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1727 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1728 if (!W_ERROR_IS_OK(result)) {
1729 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1730 "for printer %s\n", r->in.printername));
1731 ZERO_STRUCTP(r->out.handle);
1732 return result;
1735 Printer = find_printer_index_by_hnd(p, r->out.handle);
1736 if ( !Printer ) {
1737 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1738 "handle we created for printer %s\n", r->in.printername));
1739 close_printer_handle(p, r->out.handle);
1740 ZERO_STRUCTP(r->out.handle);
1741 return WERR_INVALID_PARAM;
1745 * First case: the user is opening the print server:
1747 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1748 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1750 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1751 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1752 * or if the user is listed in the smb.conf printer admin parameter.
1754 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1755 * client view printer folder, but does not show the MSAPW.
1757 * Note: this test needs code to check access rights here too. Jeremy
1758 * could you look at this?
1760 * Second case: the user is opening a printer:
1761 * NT doesn't let us connect to a printer if the connecting user
1762 * doesn't have print permission.
1764 * Third case: user is opening a Port Monitor
1765 * access checks same as opening a handle to the print server.
1768 switch (Printer->printer_type )
1770 case SPLHND_SERVER:
1771 case SPLHND_PORTMON_TCP:
1772 case SPLHND_PORTMON_LOCAL:
1773 /* Printserver handles use global struct... */
1775 snum = -1;
1777 /* Map standard access rights to object specific access rights */
1779 se_map_standard(&r->in.access_mask,
1780 &printserver_std_mapping);
1782 /* Deny any object specific bits that don't apply to print
1783 servers (i.e printer and job specific bits) */
1785 r->in.access_mask &= SEC_MASK_SPECIFIC;
1787 if (r->in.access_mask &
1788 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1789 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1790 close_printer_handle(p, r->out.handle);
1791 ZERO_STRUCTP(r->out.handle);
1792 return WERR_ACCESS_DENIED;
1795 /* Allow admin access */
1797 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1799 if (!lp_ms_add_printer_wizard()) {
1800 close_printer_handle(p, r->out.handle);
1801 ZERO_STRUCTP(r->out.handle);
1802 return WERR_ACCESS_DENIED;
1805 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1806 and not a printer admin, then fail */
1808 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1809 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1810 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1811 !token_contains_name_in_list(
1812 uidtoname(p->session_info->unix_token->uid),
1813 p->session_info->info->domain_name,
1814 NULL,
1815 p->session_info->security_token,
1816 lp_printer_admin(snum))) {
1817 close_printer_handle(p, r->out.handle);
1818 ZERO_STRUCTP(r->out.handle);
1819 DEBUG(3,("access DENIED as user is not root, "
1820 "has no printoperator privilege, "
1821 "not a member of the printoperator builtin group and "
1822 "is not in printer admin list"));
1823 return WERR_ACCESS_DENIED;
1826 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1828 else
1830 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1833 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1834 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1836 /* We fall through to return WERR_OK */
1837 break;
1839 case SPLHND_PRINTER:
1840 /* NT doesn't let us connect to a printer if the connecting user
1841 doesn't have print permission. */
1843 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1844 close_printer_handle(p, r->out.handle);
1845 ZERO_STRUCTP(r->out.handle);
1846 return WERR_BADFID;
1849 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1850 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1853 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1855 /* map an empty access mask to the minimum access mask */
1856 if (r->in.access_mask == 0x0)
1857 r->in.access_mask = PRINTER_ACCESS_USE;
1860 * If we are not serving the printer driver for this printer,
1861 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1862 * will keep NT clients happy --jerry
1865 if (lp_use_client_driver(snum)
1866 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1868 r->in.access_mask = PRINTER_ACCESS_USE;
1871 /* check smb.conf parameters and the the sec_desc */
1872 raddr = tsocket_address_inet_addr_string(p->remote_address,
1873 p->mem_ctx);
1874 if (raddr == NULL) {
1875 return WERR_NOMEM;
1878 rc = get_remote_hostname(p->remote_address,
1879 &rhost,
1880 p->mem_ctx);
1881 if (rc < 0) {
1882 return WERR_NOMEM;
1884 if (strequal(rhost, "UNKNOWN")) {
1885 rhost = raddr;
1888 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1889 rhost, raddr)) {
1890 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1891 ZERO_STRUCTP(r->out.handle);
1892 return WERR_ACCESS_DENIED;
1895 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1896 p->session_info->security_token, snum) ||
1897 !print_access_check(p->session_info,
1898 p->msg_ctx,
1899 snum,
1900 r->in.access_mask)) {
1901 DEBUG(3, ("access DENIED for printer open\n"));
1902 close_printer_handle(p, r->out.handle);
1903 ZERO_STRUCTP(r->out.handle);
1904 return WERR_ACCESS_DENIED;
1907 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1908 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1909 close_printer_handle(p, r->out.handle);
1910 ZERO_STRUCTP(r->out.handle);
1911 return WERR_ACCESS_DENIED;
1914 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1915 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1916 else
1917 r->in.access_mask = PRINTER_ACCESS_USE;
1919 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1920 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1922 winreg_create_printer_internal(p->mem_ctx,
1923 get_session_info_system(),
1924 p->msg_ctx,
1925 lp_const_servicename(snum));
1927 break;
1929 default:
1930 /* sanity check to prevent programmer error */
1931 ZERO_STRUCTP(r->out.handle);
1932 return WERR_BADFID;
1935 Printer->access_granted = r->in.access_mask;
1938 * If the client sent a devmode in the OpenPrinter() call, then
1939 * save it here in case we get a job submission on this handle
1942 if ((Printer->printer_type != SPLHND_SERVER) &&
1943 r->in.devmode_ctr.devmode) {
1944 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1945 &Printer->devmode);
1948 #if 0 /* JERRY -- I'm doubtful this is really effective */
1949 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1950 optimization in Windows 2000 clients --jerry */
1952 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1953 && (RA_WIN2K == get_remote_arch()) )
1955 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1956 sys_usleep( 500000 );
1958 #endif
1960 return WERR_OK;
1963 /****************************************************************
1964 _spoolss_ClosePrinter
1965 ****************************************************************/
1967 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1968 struct spoolss_ClosePrinter *r)
1970 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1972 if (Printer && Printer->document_started) {
1973 struct spoolss_EndDocPrinter e;
1975 e.in.handle = r->in.handle;
1977 _spoolss_EndDocPrinter(p, &e);
1980 if (!close_printer_handle(p, r->in.handle))
1981 return WERR_BADFID;
1983 /* clear the returned printer handle. Observed behavior
1984 from Win2k server. Don't think this really matters.
1985 Previous code just copied the value of the closed
1986 handle. --jerry */
1988 ZERO_STRUCTP(r->out.handle);
1990 return WERR_OK;
1993 /****************************************************************
1994 _spoolss_DeletePrinter
1995 ****************************************************************/
1997 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1998 struct spoolss_DeletePrinter *r)
2000 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2001 WERROR result;
2002 int snum;
2004 if (Printer && Printer->document_started) {
2005 struct spoolss_EndDocPrinter e;
2007 e.in.handle = r->in.handle;
2009 _spoolss_EndDocPrinter(p, &e);
2012 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2013 winreg_delete_printer_key_internal(p->mem_ctx,
2014 get_session_info_system(),
2015 p->msg_ctx,
2016 lp_const_servicename(snum),
2017 "");
2020 result = delete_printer_handle(p, r->in.handle);
2022 return result;
2025 /*******************************************************************
2026 * static function to lookup the version id corresponding to an
2027 * long architecture string
2028 ******************************************************************/
2030 static const struct print_architecture_table_node archi_table[]= {
2032 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2033 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2034 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2035 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2036 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2037 {"Windows IA64", SPL_ARCH_IA64, 3 },
2038 {"Windows x64", SPL_ARCH_X64, 3 },
2039 {NULL, "", -1 }
2042 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2043 SPOOLSS_DRIVER_VERSION_NT35,
2044 SPOOLSS_DRIVER_VERSION_NT4,
2045 SPOOLSS_DRIVER_VERSION_200X,
2046 -1};
2048 static int get_version_id(const char *arch)
2050 int i;
2052 for (i=0; archi_table[i].long_archi != NULL; i++)
2054 if (strcmp(arch, archi_table[i].long_archi) == 0)
2055 return (archi_table[i].version);
2058 return -1;
2061 /****************************************************************
2062 _spoolss_DeletePrinterDriver
2063 ****************************************************************/
2065 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2066 struct spoolss_DeletePrinterDriver *r)
2069 struct spoolss_DriverInfo8 *info = NULL;
2070 int version;
2071 WERROR status;
2072 struct dcerpc_binding_handle *b;
2073 TALLOC_CTX *tmp_ctx = NULL;
2074 int i;
2075 bool found;
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2081 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2082 && !token_contains_name_in_list(
2083 uidtoname(p->session_info->unix_token->uid),
2084 p->session_info->info->domain_name,
2085 NULL,
2086 p->session_info->security_token,
2087 lp_printer_admin(-1)) )
2089 return WERR_ACCESS_DENIED;
2092 /* check that we have a valid driver name first */
2094 if ((version = get_version_id(r->in.architecture)) == -1) {
2095 return WERR_INVALID_ENVIRONMENT;
2098 tmp_ctx = talloc_new(p->mem_ctx);
2099 if (!tmp_ctx) {
2100 return WERR_NOMEM;
2103 status = winreg_printer_binding_handle(tmp_ctx,
2104 get_session_info_system(),
2105 p->msg_ctx,
2106 &b);
2107 if (!W_ERROR_IS_OK(status)) {
2108 goto done;
2111 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2112 status = winreg_get_driver(tmp_ctx, b,
2113 r->in.architecture, r->in.driver,
2114 drv_cversion[i], &info);
2115 if (!W_ERROR_IS_OK(status)) {
2116 DEBUG(5, ("skipping del of driver with version %d\n",
2117 drv_cversion[i]));
2118 continue;
2120 found = true;
2122 if (printer_driver_in_use(tmp_ctx, b, info)) {
2123 status = WERR_PRINTER_DRIVER_IN_USE;
2124 goto done;
2127 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2128 if (!W_ERROR_IS_OK(status)) {
2129 DEBUG(0, ("failed del of driver with version %d\n",
2130 drv_cversion[i]));
2131 goto done;
2134 if (found == false) {
2135 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2136 status = WERR_UNKNOWN_PRINTER_DRIVER;
2137 } else {
2138 status = WERR_OK;
2141 done:
2142 talloc_free(tmp_ctx);
2144 return status;
2147 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2148 struct pipes_struct *p,
2149 struct spoolss_DeletePrinterDriverEx *r,
2150 struct dcerpc_binding_handle *b,
2151 struct spoolss_DriverInfo8 *info)
2153 WERROR status;
2154 bool delete_files;
2156 if (printer_driver_in_use(mem_ctx, b, info)) {
2157 status = WERR_PRINTER_DRIVER_IN_USE;
2158 goto done;
2162 * we have a couple of cases to consider.
2163 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2164 * then the delete should fail if **any** files overlap with
2165 * other drivers
2166 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2167 * non-overlapping files
2168 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2169 * are set, then do not delete any files
2170 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2173 delete_files = r->in.delete_flags
2174 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2177 if (delete_files) {
2178 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2179 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2180 status = WERR_PRINTER_DRIVER_IN_USE;
2181 goto done;
2184 * printer_driver_files_in_use() has trimmed overlapping files
2185 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2190 status = winreg_del_driver(mem_ctx, b, info, info->version);
2191 if (!W_ERROR_IS_OK(status)) {
2192 goto done;
2196 * now delete any associated files if delete_files is
2197 * true. Even if this part failes, we return succes
2198 * because the driver doesn not exist any more
2200 if (delete_files) {
2201 delete_driver_files(get_session_info_system(), info);
2204 done:
2205 return status;
2208 /****************************************************************
2209 _spoolss_DeletePrinterDriverEx
2210 ****************************************************************/
2212 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2213 struct spoolss_DeletePrinterDriverEx *r)
2215 struct spoolss_DriverInfo8 *info = NULL;
2216 WERROR status;
2217 struct dcerpc_binding_handle *b;
2218 TALLOC_CTX *tmp_ctx = NULL;
2219 int i;
2220 bool found;
2222 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2223 and not a printer admin, then fail */
2225 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2226 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2227 && !token_contains_name_in_list(
2228 uidtoname(p->session_info->unix_token->uid),
2229 p->session_info->info->domain_name,
2230 NULL,
2231 p->session_info->security_token, lp_printer_admin(-1)) )
2233 return WERR_ACCESS_DENIED;
2236 /* check that we have a valid driver name first */
2237 if (get_version_id(r->in.architecture) == -1) {
2238 /* this is what NT returns */
2239 return WERR_INVALID_ENVIRONMENT;
2242 tmp_ctx = talloc_new(p->mem_ctx);
2243 if (!tmp_ctx) {
2244 return WERR_NOMEM;
2247 status = winreg_printer_binding_handle(tmp_ctx,
2248 get_session_info_system(),
2249 p->msg_ctx,
2250 &b);
2251 if (!W_ERROR_IS_OK(status)) {
2252 goto done;
2255 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2256 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2257 && (drv_cversion[i] != r->in.version)) {
2258 continue;
2261 /* check if a driver with this version exists before delete */
2262 status = winreg_get_driver(tmp_ctx, b,
2263 r->in.architecture, r->in.driver,
2264 drv_cversion[i], &info);
2265 if (!W_ERROR_IS_OK(status)) {
2266 DEBUG(5, ("skipping del of driver with version %d\n",
2267 drv_cversion[i]));
2268 continue;
2270 found = true;
2272 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2273 if (!NT_STATUS_IS_OK(status)) {
2274 DEBUG(0, ("failed to delete driver with version %d\n",
2275 drv_cversion[i]));
2276 goto done;
2279 if (found == false) {
2280 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2281 status = WERR_UNKNOWN_PRINTER_DRIVER;
2282 } else {
2283 status = WERR_OK;
2286 done:
2287 talloc_free(tmp_ctx);
2288 return status;
2292 /********************************************************************
2293 GetPrinterData on a printer server Handle.
2294 ********************************************************************/
2296 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2297 const char *value,
2298 enum winreg_Type *type,
2299 union spoolss_PrinterData *data)
2301 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2303 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2304 *type = REG_DWORD;
2305 data->value = 0x00;
2306 return WERR_OK;
2309 if (!strcasecmp_m(value, "BeepEnabled")) {
2310 *type = REG_DWORD;
2311 data->value = 0x00;
2312 return WERR_OK;
2315 if (!strcasecmp_m(value, "EventLog")) {
2316 *type = REG_DWORD;
2317 /* formally was 0x1b */
2318 data->value = 0x00;
2319 return WERR_OK;
2322 if (!strcasecmp_m(value, "NetPopup")) {
2323 *type = REG_DWORD;
2324 data->value = 0x00;
2325 return WERR_OK;
2328 if (!strcasecmp_m(value, "MajorVersion")) {
2329 *type = REG_DWORD;
2331 /* Windows NT 4.0 seems to not allow uploading of drivers
2332 to a server that reports 0x3 as the MajorVersion.
2333 need to investigate more how Win2k gets around this .
2334 -- jerry */
2336 if (RA_WINNT == get_remote_arch()) {
2337 data->value = 0x02;
2338 } else {
2339 data->value = 0x03;
2342 return WERR_OK;
2345 if (!strcasecmp_m(value, "MinorVersion")) {
2346 *type = REG_DWORD;
2347 data->value = 0x00;
2348 return WERR_OK;
2351 /* REG_BINARY
2352 * uint32_t size = 0x114
2353 * uint32_t major = 5
2354 * uint32_t minor = [0|1]
2355 * uint32_t build = [2195|2600]
2356 * extra unicode string = e.g. "Service Pack 3"
2358 if (!strcasecmp_m(value, "OSVersion")) {
2359 DATA_BLOB blob;
2360 enum ndr_err_code ndr_err;
2361 struct spoolss_OSVersion os;
2363 os.major = 5; /* Windows 2000 == 5.0 */
2364 os.minor = 0;
2365 os.build = 2195; /* build */
2366 os.extra_string = ""; /* leave extra string empty */
2368 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2369 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2371 return WERR_GENERAL_FAILURE;
2374 *type = REG_BINARY;
2375 data->binary = blob;
2377 return WERR_OK;
2381 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2382 *type = REG_SZ;
2384 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2385 W_ERROR_HAVE_NO_MEMORY(data->string);
2387 return WERR_OK;
2390 if (!strcasecmp_m(value, "Architecture")) {
2391 *type = REG_SZ;
2392 data->string = talloc_strdup(mem_ctx,
2393 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2394 W_ERROR_HAVE_NO_MEMORY(data->string);
2396 return WERR_OK;
2399 if (!strcasecmp_m(value, "DsPresent")) {
2400 *type = REG_DWORD;
2402 /* only show the publish check box if we are a
2403 member of a AD domain */
2405 if (lp_security() == SEC_ADS) {
2406 data->value = 0x01;
2407 } else {
2408 data->value = 0x00;
2410 return WERR_OK;
2413 if (!strcasecmp_m(value, "DNSMachineName")) {
2414 const char *hostname = get_mydnsfullname();
2416 if (!hostname) {
2417 return WERR_BADFILE;
2420 *type = REG_SZ;
2421 data->string = talloc_strdup(mem_ctx, hostname);
2422 W_ERROR_HAVE_NO_MEMORY(data->string);
2424 return WERR_OK;
2427 *type = REG_NONE;
2429 return WERR_INVALID_PARAM;
2432 /****************************************************************
2433 _spoolss_GetPrinterData
2434 ****************************************************************/
2436 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2437 struct spoolss_GetPrinterData *r)
2439 struct spoolss_GetPrinterDataEx r2;
2441 r2.in.handle = r->in.handle;
2442 r2.in.key_name = "PrinterDriverData";
2443 r2.in.value_name = r->in.value_name;
2444 r2.in.offered = r->in.offered;
2445 r2.out.type = r->out.type;
2446 r2.out.data = r->out.data;
2447 r2.out.needed = r->out.needed;
2449 return _spoolss_GetPrinterDataEx(p, &r2);
2452 /*********************************************************
2453 Connect to the client machine.
2454 **********************************************************/
2456 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2457 struct sockaddr_storage *client_ss, const char *remote_machine)
2459 NTSTATUS ret;
2460 struct cli_state *the_cli;
2461 struct sockaddr_storage rm_addr;
2462 char addr[INET6_ADDRSTRLEN];
2464 if ( is_zero_addr(client_ss) ) {
2465 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2466 remote_machine));
2467 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2468 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2469 return false;
2471 print_sockaddr(addr, sizeof(addr), &rm_addr);
2472 } else {
2473 rm_addr = *client_ss;
2474 print_sockaddr(addr, sizeof(addr), &rm_addr);
2475 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2476 addr));
2479 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2480 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2481 addr));
2482 return false;
2485 /* setup the connection */
2486 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2487 &rm_addr, 0, "IPC$", "IPC",
2488 "", /* username */
2489 "", /* domain */
2490 "", /* password */
2491 0, lp_client_signing());
2493 if ( !NT_STATUS_IS_OK( ret ) ) {
2494 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2495 remote_machine ));
2496 return false;
2499 if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2500 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2501 cli_shutdown(the_cli);
2502 return false;
2506 * Ok - we have an anonymous connection to the IPC$ share.
2507 * Now start the NT Domain stuff :-).
2510 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2511 if (!NT_STATUS_IS_OK(ret)) {
2512 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2513 remote_machine, nt_errstr(ret)));
2514 cli_shutdown(the_cli);
2515 return false;
2518 return true;
2521 /***************************************************************************
2522 Connect to the client.
2523 ****************************************************************************/
2525 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2526 uint32_t localprinter,
2527 enum winreg_Type type,
2528 struct policy_handle *handle,
2529 struct notify_back_channel **_chan,
2530 struct sockaddr_storage *client_ss,
2531 struct messaging_context *msg_ctx)
2533 WERROR result;
2534 NTSTATUS status;
2535 struct notify_back_channel *chan;
2537 for (chan = back_channels; chan; chan = chan->next) {
2538 if (memcmp(&chan->client_address, client_ss,
2539 sizeof(struct sockaddr_storage)) == 0) {
2540 break;
2545 * If it's the first connection, contact the client
2546 * and connect to the IPC$ share anonymously
2548 if (!chan) {
2549 fstring unix_printer;
2551 /* the +2 is to strip the leading 2 backslashs */
2552 fstrcpy(unix_printer, printer + 2);
2554 chan = talloc_zero(NULL, struct notify_back_channel);
2555 if (!chan) {
2556 return false;
2558 chan->client_address = *client_ss;
2560 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2561 TALLOC_FREE(chan);
2562 return false;
2565 DLIST_ADD(back_channels, chan);
2567 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2568 receive_notify2_message_list);
2571 if (chan->cli_pipe == NULL ||
2572 chan->cli_pipe->binding_handle == NULL) {
2573 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2574 "NULL %s for printer %s\n",
2575 chan->cli_pipe == NULL ?
2576 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2577 printer));
2578 return false;
2582 * Tell the specific printing tdb we want messages for this printer
2583 * by registering our PID.
2586 if (!print_notify_register_pid(snum)) {
2587 DEBUG(0, ("Failed to register our pid for printer %s\n",
2588 printer));
2591 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2592 talloc_tos(),
2593 printer,
2594 localprinter,
2595 type,
2597 NULL,
2598 handle,
2599 &result);
2600 if (!NT_STATUS_IS_OK(status)) {
2601 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2602 result = ntstatus_to_werror(status);
2603 } else if (!W_ERROR_IS_OK(result)) {
2604 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2607 chan->active_connections++;
2608 *_chan = chan;
2610 return (W_ERROR_IS_OK(result));
2613 /****************************************************************
2614 ****************************************************************/
2616 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2617 const struct spoolss_NotifyOption *r)
2619 struct spoolss_NotifyOption *option;
2620 uint32_t i,k;
2622 if (!r) {
2623 return NULL;
2626 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2627 if (!option) {
2628 return NULL;
2631 *option = *r;
2633 if (!option->count) {
2634 return option;
2637 option->types = talloc_zero_array(option,
2638 struct spoolss_NotifyOptionType, option->count);
2639 if (!option->types) {
2640 talloc_free(option);
2641 return NULL;
2644 for (i=0; i < option->count; i++) {
2645 option->types[i] = r->types[i];
2647 if (option->types[i].count) {
2648 option->types[i].fields = talloc_zero_array(option,
2649 union spoolss_Field, option->types[i].count);
2650 if (!option->types[i].fields) {
2651 talloc_free(option);
2652 return NULL;
2654 for (k=0; k<option->types[i].count; k++) {
2655 option->types[i].fields[k] =
2656 r->types[i].fields[k];
2661 return option;
2664 /****************************************************************
2665 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2667 * before replying OK: status=0 a rpc call is made to the workstation
2668 * asking ReplyOpenPrinter
2670 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2671 * called from api_spoolss_rffpcnex
2672 ****************************************************************/
2674 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2675 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2677 int snum = -1;
2678 struct spoolss_NotifyOption *option = r->in.notify_options;
2679 struct sockaddr_storage client_ss;
2680 socklen_t client_len;
2682 /* store the notify value in the printer struct */
2684 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2686 if (!Printer) {
2687 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2688 "Invalid handle (%s:%u:%u).\n",
2689 OUR_HANDLE(r->in.handle)));
2690 return WERR_BADFID;
2693 Printer->notify.flags = r->in.flags;
2694 Printer->notify.options = r->in.options;
2695 Printer->notify.printerlocal = r->in.printer_local;
2696 Printer->notify.msg_ctx = p->msg_ctx;
2698 TALLOC_FREE(Printer->notify.option);
2699 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2701 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2703 /* Connect to the client machine and send a ReplyOpenPrinter */
2705 if ( Printer->printer_type == SPLHND_SERVER)
2706 snum = -1;
2707 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2708 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2709 return WERR_BADFID;
2711 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2712 "remote_address is %s\n",
2713 tsocket_address_string(p->remote_address, p->mem_ctx)));
2715 if (!lp_print_notify_backchannel(snum)) {
2716 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2717 "backchannel disabled\n"));
2718 return WERR_SERVER_UNAVAILABLE;
2721 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2722 (struct sockaddr *) &client_ss,
2723 sizeof(struct sockaddr_storage));
2724 if (client_len < 0) {
2725 return WERR_NOMEM;
2728 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2729 Printer->notify.printerlocal, REG_SZ,
2730 &Printer->notify.cli_hnd,
2731 &Printer->notify.cli_chan,
2732 &client_ss, p->msg_ctx)) {
2733 return WERR_SERVER_UNAVAILABLE;
2736 return WERR_OK;
2739 /*******************************************************************
2740 * fill a notify_info_data with the servername
2741 ********************************************************************/
2743 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2744 int snum,
2745 struct spoolss_Notify *data,
2746 print_queue_struct *queue,
2747 struct spoolss_PrinterInfo2 *pinfo2,
2748 TALLOC_CTX *mem_ctx)
2750 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2753 /*******************************************************************
2754 * fill a notify_info_data with the printername (not including the servername).
2755 ********************************************************************/
2757 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2758 int snum,
2759 struct spoolss_Notify *data,
2760 print_queue_struct *queue,
2761 struct spoolss_PrinterInfo2 *pinfo2,
2762 TALLOC_CTX *mem_ctx)
2764 /* the notify name should not contain the \\server\ part */
2765 const char *p = strrchr(pinfo2->printername, '\\');
2767 if (!p) {
2768 p = pinfo2->printername;
2769 } else {
2770 p++;
2773 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2776 /*******************************************************************
2777 * fill a notify_info_data with the servicename
2778 ********************************************************************/
2780 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2781 int snum,
2782 struct spoolss_Notify *data,
2783 print_queue_struct *queue,
2784 struct spoolss_PrinterInfo2 *pinfo2,
2785 TALLOC_CTX *mem_ctx)
2787 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2790 /*******************************************************************
2791 * fill a notify_info_data with the port name
2792 ********************************************************************/
2794 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2795 int snum,
2796 struct spoolss_Notify *data,
2797 print_queue_struct *queue,
2798 struct spoolss_PrinterInfo2 *pinfo2,
2799 TALLOC_CTX *mem_ctx)
2801 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2804 /*******************************************************************
2805 * fill a notify_info_data with the printername
2806 * but it doesn't exist, have to see what to do
2807 ********************************************************************/
2809 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2810 int snum,
2811 struct spoolss_Notify *data,
2812 print_queue_struct *queue,
2813 struct spoolss_PrinterInfo2 *pinfo2,
2814 TALLOC_CTX *mem_ctx)
2816 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2819 /*******************************************************************
2820 * fill a notify_info_data with the comment
2821 ********************************************************************/
2823 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2824 int snum,
2825 struct spoolss_Notify *data,
2826 print_queue_struct *queue,
2827 struct spoolss_PrinterInfo2 *pinfo2,
2828 TALLOC_CTX *mem_ctx)
2830 const char *p;
2832 if (*pinfo2->comment == '\0') {
2833 p = lp_comment(snum);
2834 } else {
2835 p = pinfo2->comment;
2838 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2841 /*******************************************************************
2842 * fill a notify_info_data with the comment
2843 * location = "Room 1, floor 2, building 3"
2844 ********************************************************************/
2846 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2847 int snum,
2848 struct spoolss_Notify *data,
2849 print_queue_struct *queue,
2850 struct spoolss_PrinterInfo2 *pinfo2,
2851 TALLOC_CTX *mem_ctx)
2853 const char *loc = pinfo2->location;
2854 NTSTATUS status;
2856 status = printer_list_get_printer(mem_ctx,
2857 pinfo2->sharename,
2858 NULL,
2859 &loc,
2860 NULL);
2861 if (NT_STATUS_IS_OK(status)) {
2862 if (loc == NULL) {
2863 loc = pinfo2->location;
2867 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2870 /*******************************************************************
2871 * fill a notify_info_data with the device mode
2872 * jfm:xxxx don't to it for know but that's a real problem !!!
2873 ********************************************************************/
2875 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2876 int snum,
2877 struct spoolss_Notify *data,
2878 print_queue_struct *queue,
2879 struct spoolss_PrinterInfo2 *pinfo2,
2880 TALLOC_CTX *mem_ctx)
2882 /* for a dummy implementation we have to zero the fields */
2883 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2886 /*******************************************************************
2887 * fill a notify_info_data with the separator file name
2888 ********************************************************************/
2890 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2891 int snum,
2892 struct spoolss_Notify *data,
2893 print_queue_struct *queue,
2894 struct spoolss_PrinterInfo2 *pinfo2,
2895 TALLOC_CTX *mem_ctx)
2897 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2900 /*******************************************************************
2901 * fill a notify_info_data with the print processor
2902 * jfm:xxxx return always winprint to indicate we don't do anything to it
2903 ********************************************************************/
2905 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2906 int snum,
2907 struct spoolss_Notify *data,
2908 print_queue_struct *queue,
2909 struct spoolss_PrinterInfo2 *pinfo2,
2910 TALLOC_CTX *mem_ctx)
2912 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2915 /*******************************************************************
2916 * fill a notify_info_data with the print processor options
2917 * jfm:xxxx send an empty string
2918 ********************************************************************/
2920 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2921 int snum,
2922 struct spoolss_Notify *data,
2923 print_queue_struct *queue,
2924 struct spoolss_PrinterInfo2 *pinfo2,
2925 TALLOC_CTX *mem_ctx)
2927 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2930 /*******************************************************************
2931 * fill a notify_info_data with the data type
2932 * jfm:xxxx always send RAW as data type
2933 ********************************************************************/
2935 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2936 int snum,
2937 struct spoolss_Notify *data,
2938 print_queue_struct *queue,
2939 struct spoolss_PrinterInfo2 *pinfo2,
2940 TALLOC_CTX *mem_ctx)
2942 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2945 /*******************************************************************
2946 * fill a notify_info_data with the security descriptor
2947 * jfm:xxxx send an null pointer to say no security desc
2948 * have to implement security before !
2949 ********************************************************************/
2951 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2952 int snum,
2953 struct spoolss_Notify *data,
2954 print_queue_struct *queue,
2955 struct spoolss_PrinterInfo2 *pinfo2,
2956 TALLOC_CTX *mem_ctx)
2958 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2961 /*******************************************************************
2962 * fill a notify_info_data with the attributes
2963 * jfm:xxxx a samba printer is always shared
2964 ********************************************************************/
2966 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2967 int snum,
2968 struct spoolss_Notify *data,
2969 print_queue_struct *queue,
2970 struct spoolss_PrinterInfo2 *pinfo2,
2971 TALLOC_CTX *mem_ctx)
2973 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2976 /*******************************************************************
2977 * fill a notify_info_data with the priority
2978 ********************************************************************/
2980 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2981 int snum,
2982 struct spoolss_Notify *data,
2983 print_queue_struct *queue,
2984 struct spoolss_PrinterInfo2 *pinfo2,
2985 TALLOC_CTX *mem_ctx)
2987 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2990 /*******************************************************************
2991 * fill a notify_info_data with the default priority
2992 ********************************************************************/
2994 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2995 int snum,
2996 struct spoolss_Notify *data,
2997 print_queue_struct *queue,
2998 struct spoolss_PrinterInfo2 *pinfo2,
2999 TALLOC_CTX *mem_ctx)
3001 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3004 /*******************************************************************
3005 * fill a notify_info_data with the start time
3006 ********************************************************************/
3008 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3009 int snum,
3010 struct spoolss_Notify *data,
3011 print_queue_struct *queue,
3012 struct spoolss_PrinterInfo2 *pinfo2,
3013 TALLOC_CTX *mem_ctx)
3015 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3018 /*******************************************************************
3019 * fill a notify_info_data with the until time
3020 ********************************************************************/
3022 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3023 int snum,
3024 struct spoolss_Notify *data,
3025 print_queue_struct *queue,
3026 struct spoolss_PrinterInfo2 *pinfo2,
3027 TALLOC_CTX *mem_ctx)
3029 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3032 /*******************************************************************
3033 * fill a notify_info_data with the status
3034 ********************************************************************/
3036 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3037 int snum,
3038 struct spoolss_Notify *data,
3039 print_queue_struct *queue,
3040 struct spoolss_PrinterInfo2 *pinfo2,
3041 TALLOC_CTX *mem_ctx)
3043 print_status_struct status;
3045 print_queue_length(msg_ctx, snum, &status);
3046 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3049 /*******************************************************************
3050 * fill a notify_info_data with the number of jobs queued
3051 ********************************************************************/
3053 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3054 int snum,
3055 struct spoolss_Notify *data,
3056 print_queue_struct *queue,
3057 struct spoolss_PrinterInfo2 *pinfo2,
3058 TALLOC_CTX *mem_ctx)
3060 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3061 data, print_queue_length(msg_ctx, snum, NULL));
3064 /*******************************************************************
3065 * fill a notify_info_data with the average ppm
3066 ********************************************************************/
3068 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3069 int snum,
3070 struct spoolss_Notify *data,
3071 print_queue_struct *queue,
3072 struct spoolss_PrinterInfo2 *pinfo2,
3073 TALLOC_CTX *mem_ctx)
3075 /* always respond 8 pages per minutes */
3076 /* a little hard ! */
3077 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3080 /*******************************************************************
3081 * fill a notify_info_data with username
3082 ********************************************************************/
3084 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3085 int snum,
3086 struct spoolss_Notify *data,
3087 print_queue_struct *queue,
3088 struct spoolss_PrinterInfo2 *pinfo2,
3089 TALLOC_CTX *mem_ctx)
3091 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3094 /*******************************************************************
3095 * fill a notify_info_data with job status
3096 ********************************************************************/
3098 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3099 int snum,
3100 struct spoolss_Notify *data,
3101 print_queue_struct *queue,
3102 struct spoolss_PrinterInfo2 *pinfo2,
3103 TALLOC_CTX *mem_ctx)
3105 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3108 /*******************************************************************
3109 * fill a notify_info_data with job name
3110 ********************************************************************/
3112 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3113 int snum,
3114 struct spoolss_Notify *data,
3115 print_queue_struct *queue,
3116 struct spoolss_PrinterInfo2 *pinfo2,
3117 TALLOC_CTX *mem_ctx)
3119 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3122 /*******************************************************************
3123 * fill a notify_info_data with job status
3124 ********************************************************************/
3126 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3127 int snum,
3128 struct spoolss_Notify *data,
3129 print_queue_struct *queue,
3130 struct spoolss_PrinterInfo2 *pinfo2,
3131 TALLOC_CTX *mem_ctx)
3134 * Now we're returning job status codes we just return a "" here. JRA.
3137 const char *p = "";
3139 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3140 p = "unknown";
3142 switch (queue->status) {
3143 case LPQ_QUEUED:
3144 p = "Queued";
3145 break;
3146 case LPQ_PAUSED:
3147 p = ""; /* NT provides the paused string */
3148 break;
3149 case LPQ_SPOOLING:
3150 p = "Spooling";
3151 break;
3152 case LPQ_PRINTING:
3153 p = "Printing";
3154 break;
3156 #endif /* NO LONGER NEEDED. */
3158 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3161 /*******************************************************************
3162 * fill a notify_info_data with job time
3163 ********************************************************************/
3165 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3166 int snum,
3167 struct spoolss_Notify *data,
3168 print_queue_struct *queue,
3169 struct spoolss_PrinterInfo2 *pinfo2,
3170 TALLOC_CTX *mem_ctx)
3172 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3175 /*******************************************************************
3176 * fill a notify_info_data with job size
3177 ********************************************************************/
3179 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3180 int snum,
3181 struct spoolss_Notify *data,
3182 print_queue_struct *queue,
3183 struct spoolss_PrinterInfo2 *pinfo2,
3184 TALLOC_CTX *mem_ctx)
3186 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3189 /*******************************************************************
3190 * fill a notify_info_data with page info
3191 ********************************************************************/
3192 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3193 int snum,
3194 struct spoolss_Notify *data,
3195 print_queue_struct *queue,
3196 struct spoolss_PrinterInfo2 *pinfo2,
3197 TALLOC_CTX *mem_ctx)
3199 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3202 /*******************************************************************
3203 * fill a notify_info_data with pages printed info.
3204 ********************************************************************/
3205 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3206 int snum,
3207 struct spoolss_Notify *data,
3208 print_queue_struct *queue,
3209 struct spoolss_PrinterInfo2 *pinfo2,
3210 TALLOC_CTX *mem_ctx)
3212 /* Add code when back-end tracks this */
3213 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3216 /*******************************************************************
3217 Fill a notify_info_data with job position.
3218 ********************************************************************/
3220 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3221 int snum,
3222 struct spoolss_Notify *data,
3223 print_queue_struct *queue,
3224 struct spoolss_PrinterInfo2 *pinfo2,
3225 TALLOC_CTX *mem_ctx)
3227 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3230 /*******************************************************************
3231 Fill a notify_info_data with submitted time.
3232 ********************************************************************/
3234 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3235 int snum,
3236 struct spoolss_Notify *data,
3237 print_queue_struct *queue,
3238 struct spoolss_PrinterInfo2 *pinfo2,
3239 TALLOC_CTX *mem_ctx)
3241 data->data.string.string = NULL;
3242 data->data.string.size = 0;
3244 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3245 &data->data.string.string,
3246 &data->data.string.size);
3250 struct s_notify_info_data_table
3252 enum spoolss_NotifyType type;
3253 uint16_t field;
3254 const char *name;
3255 enum spoolss_NotifyTable variable_type;
3256 void (*fn) (struct messaging_context *msg_ctx,
3257 int snum, struct spoolss_Notify *data,
3258 print_queue_struct *queue,
3259 struct spoolss_PrinterInfo2 *pinfo2,
3260 TALLOC_CTX *mem_ctx);
3263 /* A table describing the various print notification constants and
3264 whether the notification data is a pointer to a variable sized
3265 buffer, a one value uint32_t or a two value uint32_t. */
3267 static const struct s_notify_info_data_table notify_info_data_table[] =
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3320 /*******************************************************************
3321 Return the variable_type of info_data structure.
3322 ********************************************************************/
3324 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3325 uint16_t field)
3327 int i=0;
3329 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3330 if ( (notify_info_data_table[i].type == type) &&
3331 (notify_info_data_table[i].field == field) ) {
3332 return notify_info_data_table[i].variable_type;
3336 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3338 return (enum spoolss_NotifyTable) 0;
3341 /****************************************************************************
3342 ****************************************************************************/
3344 static bool search_notify(enum spoolss_NotifyType type,
3345 uint16_t field,
3346 int *value)
3348 int i;
3350 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3351 if (notify_info_data_table[i].type == type &&
3352 notify_info_data_table[i].field == field &&
3353 notify_info_data_table[i].fn != NULL) {
3354 *value = i;
3355 return true;
3359 return false;
3362 /****************************************************************************
3363 ****************************************************************************/
3365 static void construct_info_data(struct spoolss_Notify *info_data,
3366 enum spoolss_NotifyType type,
3367 uint16_t field, int id)
3369 info_data->type = type;
3370 info_data->field.field = field;
3371 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3372 info_data->job_id = id;
3375 /*******************************************************************
3377 * fill a notify_info struct with info asked
3379 ********************************************************************/
3381 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3382 struct printer_handle *print_hnd,
3383 struct spoolss_NotifyInfo *info,
3384 struct spoolss_PrinterInfo2 *pinfo2,
3385 int snum,
3386 const struct spoolss_NotifyOptionType *option_type,
3387 uint32_t id,
3388 TALLOC_CTX *mem_ctx)
3390 int field_num,j;
3391 enum spoolss_NotifyType type;
3392 uint16_t field;
3394 struct spoolss_Notify *current_data;
3396 type = option_type->type;
3398 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3399 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3400 option_type->count, lp_servicename(snum)));
3402 for(field_num=0; field_num < option_type->count; field_num++) {
3403 field = option_type->fields[field_num].field;
3405 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3407 if (!search_notify(type, field, &j) )
3408 continue;
3410 info->notifies = talloc_realloc(info, info->notifies,
3411 struct spoolss_Notify,
3412 info->count + 1);
3413 if (info->notifies == NULL) {
3414 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3415 return false;
3418 current_data = &info->notifies[info->count];
3420 construct_info_data(current_data, type, field, id);
3422 DEBUG(10, ("construct_notify_printer_info: "
3423 "calling [%s] snum=%d printername=[%s])\n",
3424 notify_info_data_table[j].name, snum,
3425 pinfo2->printername));
3427 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3428 NULL, pinfo2, mem_ctx);
3430 info->count++;
3433 return true;
3436 /*******************************************************************
3438 * fill a notify_info struct with info asked
3440 ********************************************************************/
3442 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3443 print_queue_struct *queue,
3444 struct spoolss_NotifyInfo *info,
3445 struct spoolss_PrinterInfo2 *pinfo2,
3446 int snum,
3447 const struct spoolss_NotifyOptionType *option_type,
3448 uint32_t id,
3449 TALLOC_CTX *mem_ctx)
3451 int field_num,j;
3452 enum spoolss_NotifyType type;
3453 uint16_t field;
3454 struct spoolss_Notify *current_data;
3456 DEBUG(4,("construct_notify_jobs_info\n"));
3458 type = option_type->type;
3460 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3461 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3462 option_type->count));
3464 for(field_num=0; field_num<option_type->count; field_num++) {
3465 field = option_type->fields[field_num].field;
3467 if (!search_notify(type, field, &j) )
3468 continue;
3470 info->notifies = talloc_realloc(info, info->notifies,
3471 struct spoolss_Notify,
3472 info->count + 1);
3473 if (info->notifies == NULL) {
3474 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3475 return false;
3478 current_data=&(info->notifies[info->count]);
3480 construct_info_data(current_data, type, field, id);
3481 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3482 queue, pinfo2, mem_ctx);
3483 info->count++;
3486 return true;
3490 * JFM: The enumeration is not that simple, it's even non obvious.
3492 * let's take an example: I want to monitor the PRINTER SERVER for
3493 * the printer's name and the number of jobs currently queued.
3494 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3495 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3497 * I have 3 printers on the back of my server.
3499 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3500 * structures.
3501 * Number Data Id
3502 * 1 printer 1 name 1
3503 * 2 printer 1 cjob 1
3504 * 3 printer 2 name 2
3505 * 4 printer 2 cjob 2
3506 * 5 printer 3 name 3
3507 * 6 printer 3 name 3
3509 * that's the print server case, the printer case is even worse.
3512 /*******************************************************************
3514 * enumerate all printers on the printserver
3515 * fill a notify_info struct with info asked
3517 ********************************************************************/
3519 static WERROR printserver_notify_info(struct pipes_struct *p,
3520 struct policy_handle *hnd,
3521 struct spoolss_NotifyInfo *info,
3522 TALLOC_CTX *mem_ctx)
3524 int snum;
3525 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3526 int n_services=lp_numservices();
3527 int i;
3528 struct spoolss_NotifyOption *option;
3529 struct spoolss_NotifyOptionType option_type;
3530 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3531 WERROR result;
3533 DEBUG(4,("printserver_notify_info\n"));
3535 if (!Printer)
3536 return WERR_BADFID;
3538 option = Printer->notify.option;
3540 info->version = 2;
3541 info->notifies = NULL;
3542 info->count = 0;
3544 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3545 sending a ffpcn() request first */
3547 if ( !option )
3548 return WERR_BADFID;
3550 for (i=0; i<option->count; i++) {
3551 option_type = option->types[i];
3553 if (option_type.type != PRINTER_NOTIFY_TYPE)
3554 continue;
3556 for (snum = 0; snum < n_services; snum++) {
3557 if (!lp_browseable(snum) ||
3558 !lp_snum_ok(snum) ||
3559 !lp_print_ok(snum)) {
3560 continue; /* skip */
3563 /* Maybe we should use the SYSTEM session_info here... */
3564 result = winreg_get_printer_internal(mem_ctx,
3565 get_session_info_system(),
3566 p->msg_ctx,
3567 lp_servicename(snum),
3568 &pinfo2);
3569 if (!W_ERROR_IS_OK(result)) {
3570 DEBUG(4, ("printserver_notify_info: "
3571 "Failed to get printer [%s]\n",
3572 lp_servicename(snum)));
3573 continue;
3577 construct_notify_printer_info(p->msg_ctx,
3578 Printer, info,
3579 pinfo2, snum,
3580 &option_type, snum,
3581 mem_ctx);
3583 TALLOC_FREE(pinfo2);
3587 #if 0
3589 * Debugging information, don't delete.
3592 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3593 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3594 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3596 for (i=0; i<info->count; i++) {
3597 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3598 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3599 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3601 #endif
3603 return WERR_OK;
3606 /*******************************************************************
3608 * fill a notify_info struct with info asked
3610 ********************************************************************/
3612 static WERROR printer_notify_info(struct pipes_struct *p,
3613 struct policy_handle *hnd,
3614 struct spoolss_NotifyInfo *info,
3615 TALLOC_CTX *mem_ctx)
3617 int snum;
3618 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3619 int i;
3620 uint32_t id;
3621 struct spoolss_NotifyOption *option;
3622 struct spoolss_NotifyOptionType option_type;
3623 int count,j;
3624 print_queue_struct *queue=NULL;
3625 print_status_struct status;
3626 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3627 WERROR result;
3629 DEBUG(4,("printer_notify_info\n"));
3631 if (!Printer)
3632 return WERR_BADFID;
3634 option = Printer->notify.option;
3635 id = 0x0;
3637 info->version = 2;
3638 info->notifies = NULL;
3639 info->count = 0;
3641 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3642 sending a ffpcn() request first */
3644 if ( !option )
3645 return WERR_BADFID;
3647 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3648 return WERR_BADFID;
3651 /* Maybe we should use the SYSTEM session_info here... */
3652 result = winreg_get_printer_internal(mem_ctx,
3653 get_session_info_system(),
3654 p->msg_ctx,
3655 lp_servicename(snum), &pinfo2);
3656 if (!W_ERROR_IS_OK(result)) {
3657 return WERR_BADFID;
3661 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3662 * correct servername.
3664 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3665 if (pinfo2->servername == NULL) {
3666 return WERR_NOMEM;
3669 for (i=0; i<option->count; i++) {
3670 option_type = option->types[i];
3672 switch (option_type.type) {
3673 case PRINTER_NOTIFY_TYPE:
3674 if (construct_notify_printer_info(p->msg_ctx,
3675 Printer, info,
3676 pinfo2, snum,
3677 &option_type, id,
3678 mem_ctx)) {
3679 id--;
3681 break;
3683 case JOB_NOTIFY_TYPE:
3685 count = print_queue_status(p->msg_ctx, snum, &queue,
3686 &status);
3688 for (j=0; j<count; j++) {
3689 construct_notify_jobs_info(p->msg_ctx,
3690 &queue[j], info,
3691 pinfo2, snum,
3692 &option_type,
3693 queue[j].job,
3694 mem_ctx);
3697 SAFE_FREE(queue);
3698 break;
3703 * Debugging information, don't delete.
3706 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3707 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3708 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3710 for (i=0; i<info->count; i++) {
3711 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3712 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3713 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3717 talloc_free(pinfo2);
3718 return WERR_OK;
3721 /****************************************************************
3722 _spoolss_RouterRefreshPrinterChangeNotify
3723 ****************************************************************/
3725 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3726 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3728 struct spoolss_NotifyInfo *info;
3730 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3731 WERROR result = WERR_BADFID;
3733 /* we always have a spoolss_NotifyInfo struct */
3734 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3735 if (!info) {
3736 result = WERR_NOMEM;
3737 goto done;
3740 *r->out.info = info;
3742 if (!Printer) {
3743 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3744 "Invalid handle (%s:%u:%u).\n",
3745 OUR_HANDLE(r->in.handle)));
3746 goto done;
3749 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3752 * We are now using the change value, and
3753 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3754 * I don't have a global notification system, I'm sending back all the
3755 * information even when _NOTHING_ has changed.
3758 /* We need to keep track of the change value to send back in
3759 RRPCN replies otherwise our updates are ignored. */
3761 Printer->notify.fnpcn = true;
3763 if (Printer->notify.cli_chan != NULL &&
3764 Printer->notify.cli_chan->active_connections > 0) {
3765 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3766 "Saving change value in request [%x]\n",
3767 r->in.change_low));
3768 Printer->notify.change = r->in.change_low;
3771 /* just ignore the spoolss_NotifyOption */
3773 switch (Printer->printer_type) {
3774 case SPLHND_SERVER:
3775 result = printserver_notify_info(p, r->in.handle,
3776 info, p->mem_ctx);
3777 break;
3779 case SPLHND_PRINTER:
3780 result = printer_notify_info(p, r->in.handle,
3781 info, p->mem_ctx);
3782 break;
3785 Printer->notify.fnpcn = false;
3787 done:
3788 return result;
3791 /********************************************************************
3792 ********************************************************************/
3794 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3795 const char *servername,
3796 const char *printername,
3797 const char **printername_p)
3799 /* FIXME: add lp_force_printername() */
3801 if (servername == NULL) {
3802 *printername_p = talloc_strdup(mem_ctx, printername);
3803 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3804 return WERR_OK;
3807 if (servername[0] == '\\' && servername[1] == '\\') {
3808 servername += 2;
3811 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3812 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3814 return WERR_OK;
3817 /********************************************************************
3818 ********************************************************************/
3820 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3821 const char *printername)
3823 if (dm == NULL) {
3824 return;
3827 dm->devicename = talloc_strndup(dm, printername,
3828 MIN(strlen(printername), 31));
3831 /********************************************************************
3832 * construct_printer_info_0
3833 * fill a printer_info_0 struct
3834 ********************************************************************/
3836 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3837 const struct auth_session_info *session_info,
3838 struct messaging_context *msg_ctx,
3839 struct spoolss_PrinterInfo2 *info2,
3840 const char *servername,
3841 struct spoolss_PrinterInfo0 *r,
3842 int snum)
3844 int count;
3845 struct printer_session_counter *session_counter;
3846 struct timeval setuptime;
3847 print_status_struct status;
3848 WERROR result;
3850 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3851 if (!W_ERROR_IS_OK(result)) {
3852 return result;
3855 if (servername) {
3856 r->servername = talloc_strdup(mem_ctx, servername);
3857 W_ERROR_HAVE_NO_MEMORY(r->servername);
3858 } else {
3859 r->servername = NULL;
3862 count = print_queue_length(msg_ctx, snum, &status);
3864 /* check if we already have a counter for this printer */
3865 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3866 if (session_counter->snum == snum)
3867 break;
3870 /* it's the first time, add it to the list */
3871 if (session_counter == NULL) {
3872 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3873 W_ERROR_HAVE_NO_MEMORY(session_counter);
3874 session_counter->snum = snum;
3875 session_counter->counter = 0;
3876 DLIST_ADD(counter_list, session_counter);
3879 /* increment it */
3880 session_counter->counter++;
3882 r->cjobs = count;
3883 r->total_jobs = 0;
3884 r->total_bytes = 0;
3886 get_startup_time(&setuptime);
3887 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3889 /* JFM:
3890 * the global_counter should be stored in a TDB as it's common to all the clients
3891 * and should be zeroed on samba startup
3893 r->global_counter = session_counter->counter;
3894 r->total_pages = 0;
3895 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3896 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3897 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3898 r->free_build = SPOOLSS_RELEASE_BUILD;
3899 r->spooling = 0;
3900 r->max_spooling = 0;
3901 r->session_counter = session_counter->counter;
3902 r->num_error_out_of_paper = 0x0;
3903 r->num_error_not_ready = 0x0; /* number of print failure */
3904 r->job_error = 0x0;
3905 r->number_of_processors = 0x1;
3906 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3907 r->high_part_total_bytes = 0x0;
3909 /* ChangeID in milliseconds*/
3910 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3911 info2->sharename, &r->change_id);
3913 r->last_error = WERR_OK;
3914 r->status = nt_printq_status(status.status);
3915 r->enumerate_network_printers = 0x0;
3916 r->c_setprinter = 0x0;
3917 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3918 r->processor_level = 0x6; /* 6 ???*/
3919 r->ref_ic = 0;
3920 r->reserved2 = 0;
3921 r->reserved3 = 0;
3923 return WERR_OK;
3927 /********************************************************************
3928 * construct_printer_info1
3929 * fill a spoolss_PrinterInfo1 struct
3930 ********************************************************************/
3932 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3933 const struct spoolss_PrinterInfo2 *info2,
3934 uint32_t flags,
3935 const char *servername,
3936 struct spoolss_PrinterInfo1 *r,
3937 int snum)
3939 WERROR result;
3941 r->flags = flags;
3943 if (info2->comment == NULL || info2->comment[0] == '\0') {
3944 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3945 } else {
3946 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3948 W_ERROR_HAVE_NO_MEMORY(r->comment);
3950 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3951 if (!W_ERROR_IS_OK(result)) {
3952 return result;
3955 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3956 r->name,
3957 info2->drivername,
3958 r->comment);
3959 W_ERROR_HAVE_NO_MEMORY(r->description);
3961 return WERR_OK;
3964 /********************************************************************
3965 * construct_printer_info2
3966 * fill a spoolss_PrinterInfo2 struct
3967 ********************************************************************/
3969 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3970 struct messaging_context *msg_ctx,
3971 const struct spoolss_PrinterInfo2 *info2,
3972 const char *servername,
3973 struct spoolss_PrinterInfo2 *r,
3974 int snum)
3976 int count;
3977 print_status_struct status;
3978 WERROR result;
3980 count = print_queue_length(msg_ctx, snum, &status);
3982 if (servername) {
3983 r->servername = talloc_strdup(mem_ctx, servername);
3984 W_ERROR_HAVE_NO_MEMORY(r->servername);
3985 } else {
3986 r->servername = NULL;
3989 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3990 if (!W_ERROR_IS_OK(result)) {
3991 return result;
3994 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3995 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3996 r->portname = talloc_strdup(mem_ctx, info2->portname);
3997 W_ERROR_HAVE_NO_MEMORY(r->portname);
3998 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3999 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4001 if (info2->comment[0] == '\0') {
4002 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4003 } else {
4004 r->comment = talloc_strdup(mem_ctx, info2->comment);
4006 W_ERROR_HAVE_NO_MEMORY(r->comment);
4008 r->location = talloc_strdup(mem_ctx, info2->location);
4009 if (info2->location[0] == '\0') {
4010 const char *loc = NULL;
4011 NTSTATUS nt_status;
4013 nt_status = printer_list_get_printer(mem_ctx,
4014 info2->sharename,
4015 NULL,
4016 &loc,
4017 NULL);
4018 if (NT_STATUS_IS_OK(nt_status)) {
4019 if (loc != NULL) {
4020 r->location = talloc_strdup(mem_ctx, loc);
4024 W_ERROR_HAVE_NO_MEMORY(r->location);
4026 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4027 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4028 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4029 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4030 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4031 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4032 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4033 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4035 r->attributes = info2->attributes;
4037 r->priority = info2->priority;
4038 r->defaultpriority = info2->defaultpriority;
4039 r->starttime = info2->starttime;
4040 r->untiltime = info2->untiltime;
4041 r->status = nt_printq_status(status.status);
4042 r->cjobs = count;
4043 r->averageppm = info2->averageppm;
4045 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4046 if (!r->devmode) {
4047 DEBUG(8,("Returning NULL Devicemode!\n"));
4050 compose_devicemode_devicename(r->devmode, r->printername);
4052 r->secdesc = NULL;
4054 if (info2->secdesc != NULL) {
4055 /* don't use talloc_steal() here unless you do a deep steal of all
4056 the SEC_DESC members */
4058 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4061 return WERR_OK;
4064 /********************************************************************
4065 * construct_printer_info3
4066 * fill a spoolss_PrinterInfo3 struct
4067 ********************************************************************/
4069 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4070 const struct spoolss_PrinterInfo2 *info2,
4071 const char *servername,
4072 struct spoolss_PrinterInfo3 *r,
4073 int snum)
4075 /* These are the components of the SD we are returning. */
4077 if (info2->secdesc != NULL) {
4078 /* don't use talloc_steal() here unless you do a deep steal of all
4079 the SEC_DESC members */
4081 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4082 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4085 return WERR_OK;
4088 /********************************************************************
4089 * construct_printer_info4
4090 * fill a spoolss_PrinterInfo4 struct
4091 ********************************************************************/
4093 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4094 const struct spoolss_PrinterInfo2 *info2,
4095 const char *servername,
4096 struct spoolss_PrinterInfo4 *r,
4097 int snum)
4099 WERROR result;
4101 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4102 if (!W_ERROR_IS_OK(result)) {
4103 return result;
4106 if (servername) {
4107 r->servername = talloc_strdup(mem_ctx, servername);
4108 W_ERROR_HAVE_NO_MEMORY(r->servername);
4109 } else {
4110 r->servername = NULL;
4113 r->attributes = info2->attributes;
4115 return WERR_OK;
4118 /********************************************************************
4119 * construct_printer_info5
4120 * fill a spoolss_PrinterInfo5 struct
4121 ********************************************************************/
4123 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4124 const struct spoolss_PrinterInfo2 *info2,
4125 const char *servername,
4126 struct spoolss_PrinterInfo5 *r,
4127 int snum)
4129 WERROR result;
4131 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4132 if (!W_ERROR_IS_OK(result)) {
4133 return result;
4136 r->portname = talloc_strdup(mem_ctx, info2->portname);
4137 W_ERROR_HAVE_NO_MEMORY(r->portname);
4139 r->attributes = info2->attributes;
4141 /* these two are not used by NT+ according to MSDN */
4142 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4143 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4145 return WERR_OK;
4148 /********************************************************************
4149 * construct_printer_info_6
4150 * fill a spoolss_PrinterInfo6 struct
4151 ********************************************************************/
4153 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4154 struct messaging_context *msg_ctx,
4155 const struct spoolss_PrinterInfo2 *info2,
4156 const char *servername,
4157 struct spoolss_PrinterInfo6 *r,
4158 int snum)
4160 print_status_struct status;
4162 print_queue_length(msg_ctx, snum, &status);
4164 r->status = nt_printq_status(status.status);
4166 return WERR_OK;
4169 /********************************************************************
4170 * construct_printer_info7
4171 * fill a spoolss_PrinterInfo7 struct
4172 ********************************************************************/
4174 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4175 struct messaging_context *msg_ctx,
4176 const char *servername,
4177 struct spoolss_PrinterInfo7 *r,
4178 int snum)
4180 const struct auth_session_info *session_info = get_session_info_system();
4181 struct GUID guid;
4183 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4184 servername,
4185 lp_servicename(snum), &guid, NULL)) {
4186 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4187 r->action = DSPRINT_PUBLISH;
4188 } else {
4189 r->guid = talloc_strdup(mem_ctx, "");
4190 r->action = DSPRINT_UNPUBLISH;
4192 W_ERROR_HAVE_NO_MEMORY(r->guid);
4194 return WERR_OK;
4197 /********************************************************************
4198 * construct_printer_info8
4199 * fill a spoolss_PrinterInfo8 struct
4200 ********************************************************************/
4202 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4203 const struct spoolss_PrinterInfo2 *info2,
4204 const char *servername,
4205 struct spoolss_DeviceModeInfo *r,
4206 int snum)
4208 WERROR result;
4209 const char *printername;
4211 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4212 if (!W_ERROR_IS_OK(result)) {
4213 return result;
4216 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4217 if (!r->devmode) {
4218 DEBUG(8,("Returning NULL Devicemode!\n"));
4221 compose_devicemode_devicename(r->devmode, printername);
4223 return WERR_OK;
4227 /********************************************************************
4228 ********************************************************************/
4230 static bool snum_is_shared_printer(int snum)
4232 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4235 /********************************************************************
4236 Spoolss_enumprinters.
4237 ********************************************************************/
4239 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4240 const struct auth_session_info *session_info,
4241 struct messaging_context *msg_ctx,
4242 const char *servername,
4243 uint32_t level,
4244 uint32_t flags,
4245 union spoolss_PrinterInfo **info_p,
4246 uint32_t *count_p)
4248 int snum;
4249 int n_services = lp_numservices();
4250 union spoolss_PrinterInfo *info = NULL;
4251 uint32_t count = 0;
4252 WERROR result = WERR_OK;
4253 struct dcerpc_binding_handle *b = NULL;
4254 TALLOC_CTX *tmp_ctx = NULL;
4256 tmp_ctx = talloc_new(mem_ctx);
4257 if (!tmp_ctx) {
4258 return WERR_NOMEM;
4261 *count_p = 0;
4262 *info_p = NULL;
4264 for (snum = 0; snum < n_services; snum++) {
4266 const char *printer;
4267 struct spoolss_PrinterInfo2 *info2;
4269 if (!snum_is_shared_printer(snum)) {
4270 continue;
4273 printer = lp_const_servicename(snum);
4275 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4276 printer, snum));
4278 if (b == NULL) {
4279 result = winreg_printer_binding_handle(tmp_ctx,
4280 session_info,
4281 msg_ctx,
4282 &b);
4283 if (!W_ERROR_IS_OK(result)) {
4284 goto out;
4288 result = winreg_create_printer(tmp_ctx, b,
4289 printer);
4290 if (!W_ERROR_IS_OK(result)) {
4291 goto out;
4294 info = talloc_realloc(tmp_ctx, info,
4295 union spoolss_PrinterInfo,
4296 count + 1);
4297 if (!info) {
4298 result = WERR_NOMEM;
4299 goto out;
4302 result = winreg_get_printer(tmp_ctx, b,
4303 printer, &info2);
4304 if (!W_ERROR_IS_OK(result)) {
4305 goto out;
4308 switch (level) {
4309 case 0:
4310 result = construct_printer_info0(info, session_info,
4311 msg_ctx, info2,
4312 servername,
4313 &info[count].info0, snum);
4314 break;
4315 case 1:
4316 result = construct_printer_info1(info, info2, flags,
4317 servername,
4318 &info[count].info1, snum);
4319 break;
4320 case 2:
4321 result = construct_printer_info2(info, msg_ctx, info2,
4322 servername,
4323 &info[count].info2, snum);
4324 break;
4325 case 4:
4326 result = construct_printer_info4(info, info2,
4327 servername,
4328 &info[count].info4, snum);
4329 break;
4330 case 5:
4331 result = construct_printer_info5(info, info2,
4332 servername,
4333 &info[count].info5, snum);
4334 break;
4336 default:
4337 result = WERR_UNKNOWN_LEVEL;
4338 goto out;
4341 if (!W_ERROR_IS_OK(result)) {
4342 goto out;
4345 count++;
4348 out:
4349 if (W_ERROR_IS_OK(result)) {
4350 *info_p = talloc_move(mem_ctx, &info);
4351 *count_p = count;
4354 talloc_free(tmp_ctx);
4356 return result;
4359 /********************************************************************
4360 * handle enumeration of printers at level 0
4361 ********************************************************************/
4363 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4364 const struct auth_session_info *session_info,
4365 struct messaging_context *msg_ctx,
4366 uint32_t flags,
4367 const char *servername,
4368 union spoolss_PrinterInfo **info,
4369 uint32_t *count)
4371 DEBUG(4,("enum_all_printers_info_0\n"));
4373 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4374 servername, 0, flags, info, count);
4378 /********************************************************************
4379 ********************************************************************/
4381 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4382 const struct auth_session_info *session_info,
4383 struct messaging_context *msg_ctx,
4384 const char *servername,
4385 uint32_t flags,
4386 union spoolss_PrinterInfo **info,
4387 uint32_t *count)
4389 DEBUG(4,("enum_all_printers_info_1\n"));
4391 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4392 servername, 1, flags, info, count);
4395 /********************************************************************
4396 enum_all_printers_info_1_local.
4397 *********************************************************************/
4399 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4400 const struct auth_session_info *session_info,
4401 struct messaging_context *msg_ctx,
4402 const char *servername,
4403 union spoolss_PrinterInfo **info,
4404 uint32_t *count)
4406 DEBUG(4,("enum_all_printers_info_1_local\n"));
4408 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4409 servername, PRINTER_ENUM_ICON8, info, count);
4412 /********************************************************************
4413 enum_all_printers_info_1_name.
4414 *********************************************************************/
4416 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4417 const struct auth_session_info *session_info,
4418 struct messaging_context *msg_ctx,
4419 const char *servername,
4420 union spoolss_PrinterInfo **info,
4421 uint32_t *count)
4423 const char *s = servername;
4425 DEBUG(4,("enum_all_printers_info_1_name\n"));
4427 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4428 s = servername + 2;
4431 if (!is_myname_or_ipaddr(s)) {
4432 return WERR_INVALID_NAME;
4435 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4436 servername, PRINTER_ENUM_ICON8, info, count);
4439 /********************************************************************
4440 enum_all_printers_info_1_network.
4441 *********************************************************************/
4443 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4444 const struct auth_session_info *session_info,
4445 struct messaging_context *msg_ctx,
4446 const char *servername,
4447 union spoolss_PrinterInfo **info,
4448 uint32_t *count)
4450 const char *s = servername;
4452 DEBUG(4,("enum_all_printers_info_1_network\n"));
4454 /* If we respond to a enum_printers level 1 on our name with flags
4455 set to PRINTER_ENUM_REMOTE with a list of printers then these
4456 printers incorrectly appear in the APW browse list.
4457 Specifically the printers for the server appear at the workgroup
4458 level where all the other servers in the domain are
4459 listed. Windows responds to this call with a
4460 WERR_CAN_NOT_COMPLETE so we should do the same. */
4462 if (servername[0] == '\\' && servername[1] == '\\') {
4463 s = servername + 2;
4466 if (is_myname_or_ipaddr(s)) {
4467 return WERR_CAN_NOT_COMPLETE;
4470 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4471 servername, PRINTER_ENUM_NAME, info, count);
4474 /********************************************************************
4475 * api_spoolss_enumprinters
4477 * called from api_spoolss_enumprinters (see this to understand)
4478 ********************************************************************/
4480 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4481 const struct auth_session_info *session_info,
4482 struct messaging_context *msg_ctx,
4483 const char *servername,
4484 union spoolss_PrinterInfo **info,
4485 uint32_t *count)
4487 DEBUG(4,("enum_all_printers_info_2\n"));
4489 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4490 servername, 2, 0, info, count);
4493 /********************************************************************
4494 * handle enumeration of printers at level 1
4495 ********************************************************************/
4497 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4498 const struct auth_session_info *session_info,
4499 struct messaging_context *msg_ctx,
4500 uint32_t flags,
4501 const char *servername,
4502 union spoolss_PrinterInfo **info,
4503 uint32_t *count)
4505 /* Not all the flags are equals */
4507 if (flags & PRINTER_ENUM_LOCAL) {
4508 return enum_all_printers_info_1_local(mem_ctx, session_info,
4509 msg_ctx, servername, info, count);
4512 if (flags & PRINTER_ENUM_NAME) {
4513 return enum_all_printers_info_1_name(mem_ctx, session_info,
4514 msg_ctx, servername, info,
4515 count);
4518 if (flags & PRINTER_ENUM_NETWORK) {
4519 return enum_all_printers_info_1_network(mem_ctx, session_info,
4520 msg_ctx, servername, info,
4521 count);
4524 return WERR_OK; /* NT4sp5 does that */
4527 /********************************************************************
4528 * handle enumeration of printers at level 2
4529 ********************************************************************/
4531 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4532 const struct auth_session_info *session_info,
4533 struct messaging_context *msg_ctx,
4534 uint32_t flags,
4535 const char *servername,
4536 union spoolss_PrinterInfo **info,
4537 uint32_t *count)
4539 if (flags & PRINTER_ENUM_LOCAL) {
4541 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4542 servername,
4543 info, count);
4546 if (flags & PRINTER_ENUM_NAME) {
4547 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4548 return WERR_INVALID_NAME;
4551 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4552 servername,
4553 info, count);
4556 if (flags & PRINTER_ENUM_REMOTE) {
4557 return WERR_UNKNOWN_LEVEL;
4560 return WERR_OK;
4563 /********************************************************************
4564 * handle enumeration of printers at level 4
4565 ********************************************************************/
4567 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4568 const struct auth_session_info *session_info,
4569 struct messaging_context *msg_ctx,
4570 uint32_t flags,
4571 const char *servername,
4572 union spoolss_PrinterInfo **info,
4573 uint32_t *count)
4575 DEBUG(4,("enum_all_printers_info_4\n"));
4577 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4578 servername, 4, flags, info, count);
4582 /********************************************************************
4583 * handle enumeration of printers at level 5
4584 ********************************************************************/
4586 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4587 const struct auth_session_info *session_info,
4588 struct messaging_context *msg_ctx,
4589 uint32_t flags,
4590 const char *servername,
4591 union spoolss_PrinterInfo **info,
4592 uint32_t *count)
4594 DEBUG(4,("enum_all_printers_info_5\n"));
4596 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4597 servername, 5, flags, info, count);
4600 /****************************************************************
4601 _spoolss_EnumPrinters
4602 ****************************************************************/
4604 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4605 struct spoolss_EnumPrinters *r)
4607 const struct auth_session_info *session_info = get_session_info_system();
4608 WERROR result;
4610 /* that's an [in out] buffer */
4612 if (!r->in.buffer && (r->in.offered != 0)) {
4613 return WERR_INVALID_PARAM;
4616 DEBUG(4,("_spoolss_EnumPrinters\n"));
4618 *r->out.needed = 0;
4619 *r->out.count = 0;
4620 *r->out.info = NULL;
4623 * Level 1:
4624 * flags==PRINTER_ENUM_NAME
4625 * if name=="" then enumerates all printers
4626 * if name!="" then enumerate the printer
4627 * flags==PRINTER_ENUM_REMOTE
4628 * name is NULL, enumerate printers
4629 * Level 2: name!="" enumerates printers, name can't be NULL
4630 * Level 3: doesn't exist
4631 * Level 4: does a local registry lookup
4632 * Level 5: same as Level 2
4635 if (r->in.server && r->in.server[0] == '\0') {
4636 r->in.server = NULL;
4639 switch (r->in.level) {
4640 case 0:
4641 result = enumprinters_level0(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 1:
4647 result = enumprinters_level1(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 2:
4653 result = enumprinters_level2(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 case 4:
4659 result = enumprinters_level4(p->mem_ctx, session_info,
4660 p->msg_ctx, r->in.flags,
4661 r->in.server,
4662 r->out.info, r->out.count);
4663 break;
4664 case 5:
4665 result = enumprinters_level5(p->mem_ctx, session_info,
4666 p->msg_ctx, r->in.flags,
4667 r->in.server,
4668 r->out.info, r->out.count);
4669 break;
4670 default:
4671 return WERR_UNKNOWN_LEVEL;
4674 if (!W_ERROR_IS_OK(result)) {
4675 return result;
4678 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4679 spoolss_EnumPrinters,
4680 *r->out.info, r->in.level,
4681 *r->out.count);
4682 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4683 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4685 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4688 /****************************************************************
4689 _spoolss_GetPrinter
4690 ****************************************************************/
4692 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4693 struct spoolss_GetPrinter *r)
4695 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4696 struct spoolss_PrinterInfo2 *info2 = NULL;
4697 WERROR result = WERR_OK;
4698 int snum;
4700 /* that's an [in out] buffer */
4702 if (!r->in.buffer && (r->in.offered != 0)) {
4703 return WERR_INVALID_PARAM;
4706 *r->out.needed = 0;
4708 if (Printer == NULL) {
4709 return WERR_BADFID;
4712 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4713 return WERR_BADFID;
4716 result = winreg_get_printer_internal(p->mem_ctx,
4717 get_session_info_system(),
4718 p->msg_ctx,
4719 lp_const_servicename(snum),
4720 &info2);
4721 if (!W_ERROR_IS_OK(result)) {
4722 goto out;
4725 switch (r->in.level) {
4726 case 0:
4727 result = construct_printer_info0(p->mem_ctx,
4728 get_session_info_system(),
4729 p->msg_ctx,
4730 info2,
4731 Printer->servername,
4732 &r->out.info->info0,
4733 snum);
4734 break;
4735 case 1:
4736 result = construct_printer_info1(p->mem_ctx, info2,
4737 PRINTER_ENUM_ICON8,
4738 Printer->servername,
4739 &r->out.info->info1, snum);
4740 break;
4741 case 2:
4742 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4743 Printer->servername,
4744 &r->out.info->info2, snum);
4745 break;
4746 case 3:
4747 result = construct_printer_info3(p->mem_ctx, info2,
4748 Printer->servername,
4749 &r->out.info->info3, snum);
4750 break;
4751 case 4:
4752 result = construct_printer_info4(p->mem_ctx, info2,
4753 Printer->servername,
4754 &r->out.info->info4, snum);
4755 break;
4756 case 5:
4757 result = construct_printer_info5(p->mem_ctx, info2,
4758 Printer->servername,
4759 &r->out.info->info5, snum);
4760 break;
4761 case 6:
4762 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4763 Printer->servername,
4764 &r->out.info->info6, snum);
4765 break;
4766 case 7:
4767 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4768 Printer->servername,
4769 &r->out.info->info7, snum);
4770 break;
4771 case 8:
4772 result = construct_printer_info8(p->mem_ctx, info2,
4773 Printer->servername,
4774 &r->out.info->info8, snum);
4775 break;
4776 default:
4777 result = WERR_UNKNOWN_LEVEL;
4778 break;
4780 TALLOC_FREE(info2);
4782 out:
4783 if (!W_ERROR_IS_OK(result)) {
4784 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4785 r->in.level, win_errstr(result)));
4786 TALLOC_FREE(r->out.info);
4787 return result;
4790 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4791 r->out.info, r->in.level);
4792 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4794 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4797 /********************************************************************
4798 ********************************************************************/
4800 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4801 do { \
4802 if (in && strlen(in)) { \
4803 out = talloc_strdup(mem_ctx, in); \
4804 } else { \
4805 out = talloc_strdup(mem_ctx, ""); \
4807 W_ERROR_HAVE_NO_MEMORY(out); \
4808 } while (0);
4810 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4811 do { \
4812 if (in && strlen(in)) { \
4813 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4814 } else { \
4815 out = talloc_strdup(mem_ctx, ""); \
4817 W_ERROR_HAVE_NO_MEMORY(out); \
4818 } while (0);
4820 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4821 const char **string_array,
4822 const char ***presult,
4823 const char *cservername,
4824 const char *arch,
4825 int version)
4827 int i, num_strings = 0;
4828 const char **array = NULL;
4830 if (string_array == NULL) {
4831 return WERR_INVALID_PARAMETER;
4834 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4835 const char *str = NULL;
4837 if (cservername == NULL || arch == NULL) {
4838 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4839 } else {
4840 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4843 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4844 TALLOC_FREE(array);
4845 return WERR_NOMEM;
4849 if (i > 0) {
4850 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4851 &array, &num_strings);
4854 if (presult) {
4855 *presult = array;
4858 return WERR_OK;
4861 /********************************************************************
4862 * fill a spoolss_DriverInfo1 struct
4863 ********************************************************************/
4865 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4866 struct spoolss_DriverInfo1 *r,
4867 const struct spoolss_DriverInfo8 *driver,
4868 const char *servername)
4870 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4871 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4873 return WERR_OK;
4876 /********************************************************************
4877 * fill a spoolss_DriverInfo2 struct
4878 ********************************************************************/
4880 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4881 struct spoolss_DriverInfo2 *r,
4882 const struct spoolss_DriverInfo8 *driver,
4883 const char *servername)
4886 const char *cservername = canon_servername(servername);
4888 r->version = driver->version;
4890 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4891 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4892 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4893 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4895 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4896 driver->architecture,
4897 driver->version,
4898 driver->driver_path,
4899 r->driver_path);
4901 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4902 driver->architecture,
4903 driver->version,
4904 driver->data_file,
4905 r->data_file);
4907 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4908 driver->architecture,
4909 driver->version,
4910 driver->config_file,
4911 r->config_file);
4913 return WERR_OK;
4916 /********************************************************************
4917 * fill a spoolss_DriverInfo3 struct
4918 ********************************************************************/
4920 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4921 struct spoolss_DriverInfo3 *r,
4922 const struct spoolss_DriverInfo8 *driver,
4923 const char *servername)
4925 const char *cservername = canon_servername(servername);
4927 r->version = driver->version;
4929 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4930 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4931 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4932 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4934 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4935 driver->architecture,
4936 driver->version,
4937 driver->driver_path,
4938 r->driver_path);
4940 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4941 driver->architecture,
4942 driver->version,
4943 driver->data_file,
4944 r->data_file);
4946 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4947 driver->architecture,
4948 driver->version,
4949 driver->config_file,
4950 r->config_file);
4952 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4953 driver->architecture,
4954 driver->version,
4955 driver->help_file,
4956 r->help_file);
4958 FILL_DRIVER_STRING(mem_ctx,
4959 driver->monitor_name,
4960 r->monitor_name);
4962 FILL_DRIVER_STRING(mem_ctx,
4963 driver->default_datatype,
4964 r->default_datatype);
4966 return string_array_from_driver_info(mem_ctx,
4967 driver->dependent_files,
4968 &r->dependent_files,
4969 cservername,
4970 driver->architecture,
4971 driver->version);
4974 /********************************************************************
4975 * fill a spoolss_DriverInfo4 struct
4976 ********************************************************************/
4978 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4979 struct spoolss_DriverInfo4 *r,
4980 const struct spoolss_DriverInfo8 *driver,
4981 const char *servername)
4983 const char *cservername = canon_servername(servername);
4984 WERROR result;
4986 r->version = driver->version;
4988 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4989 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4990 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4991 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4993 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994 driver->architecture,
4995 driver->version,
4996 driver->driver_path,
4997 r->driver_path);
4999 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000 driver->architecture,
5001 driver->version,
5002 driver->data_file,
5003 r->data_file);
5005 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5006 driver->architecture,
5007 driver->version,
5008 driver->config_file,
5009 r->config_file);
5011 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5012 driver->architecture,
5013 driver->version,
5014 driver->help_file,
5015 r->help_file);
5017 result = string_array_from_driver_info(mem_ctx,
5018 driver->dependent_files,
5019 &r->dependent_files,
5020 cservername,
5021 driver->architecture,
5022 driver->version);
5023 if (!W_ERROR_IS_OK(result)) {
5024 return result;
5027 FILL_DRIVER_STRING(mem_ctx,
5028 driver->monitor_name,
5029 r->monitor_name);
5031 FILL_DRIVER_STRING(mem_ctx,
5032 driver->default_datatype,
5033 r->default_datatype);
5036 result = string_array_from_driver_info(mem_ctx,
5037 driver->previous_names,
5038 &r->previous_names,
5039 NULL, NULL, 0);
5041 return result;
5044 /********************************************************************
5045 * fill a spoolss_DriverInfo5 struct
5046 ********************************************************************/
5048 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5049 struct spoolss_DriverInfo5 *r,
5050 const struct spoolss_DriverInfo8 *driver,
5051 const char *servername)
5053 const char *cservername = canon_servername(servername);
5055 r->version = driver->version;
5057 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5058 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5059 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5060 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5062 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5063 driver->architecture,
5064 driver->version,
5065 driver->driver_path,
5066 r->driver_path);
5068 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5069 driver->architecture,
5070 driver->version,
5071 driver->data_file,
5072 r->data_file);
5074 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5075 driver->architecture,
5076 driver->version,
5077 driver->config_file,
5078 r->config_file);
5080 r->driver_attributes = 0;
5081 r->config_version = 0;
5082 r->driver_version = 0;
5084 return WERR_OK;
5086 /********************************************************************
5087 * fill a spoolss_DriverInfo6 struct
5088 ********************************************************************/
5090 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5091 struct spoolss_DriverInfo6 *r,
5092 const struct spoolss_DriverInfo8 *driver,
5093 const char *servername)
5095 const char *cservername = canon_servername(servername);
5096 WERROR result;
5098 r->version = driver->version;
5100 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5101 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5102 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5103 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5105 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5106 driver->architecture,
5107 driver->version,
5108 driver->driver_path,
5109 r->driver_path);
5111 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5112 driver->architecture,
5113 driver->version,
5114 driver->data_file,
5115 r->data_file);
5117 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5118 driver->architecture,
5119 driver->version,
5120 driver->config_file,
5121 r->config_file);
5123 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5124 driver->architecture,
5125 driver->version,
5126 driver->help_file,
5127 r->help_file);
5129 FILL_DRIVER_STRING(mem_ctx,
5130 driver->monitor_name,
5131 r->monitor_name);
5133 FILL_DRIVER_STRING(mem_ctx,
5134 driver->default_datatype,
5135 r->default_datatype);
5137 result = string_array_from_driver_info(mem_ctx,
5138 driver->dependent_files,
5139 &r->dependent_files,
5140 cservername,
5141 driver->architecture,
5142 driver->version);
5143 if (!W_ERROR_IS_OK(result)) {
5144 return result;
5147 result = string_array_from_driver_info(mem_ctx,
5148 driver->previous_names,
5149 &r->previous_names,
5150 NULL, NULL, 0);
5151 if (!W_ERROR_IS_OK(result)) {
5152 return result;
5155 r->driver_date = driver->driver_date;
5156 r->driver_version = driver->driver_version;
5158 FILL_DRIVER_STRING(mem_ctx,
5159 driver->manufacturer_name,
5160 r->manufacturer_name);
5161 FILL_DRIVER_STRING(mem_ctx,
5162 driver->manufacturer_url,
5163 r->manufacturer_url);
5164 FILL_DRIVER_STRING(mem_ctx,
5165 driver->hardware_id,
5166 r->hardware_id);
5167 FILL_DRIVER_STRING(mem_ctx,
5168 driver->provider,
5169 r->provider);
5171 return WERR_OK;
5174 /********************************************************************
5175 * fill a spoolss_DriverInfo8 struct
5176 ********************************************************************/
5178 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5179 struct spoolss_DriverInfo8 *r,
5180 const struct spoolss_DriverInfo8 *driver,
5181 const char *servername)
5183 const char *cservername = canon_servername(servername);
5184 WERROR result;
5186 r->version = driver->version;
5188 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5189 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5190 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5191 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5193 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5194 driver->architecture,
5195 driver->version,
5196 driver->driver_path,
5197 r->driver_path);
5199 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5200 driver->architecture,
5201 driver->version,
5202 driver->data_file,
5203 r->data_file);
5205 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5206 driver->architecture,
5207 driver->version,
5208 driver->config_file,
5209 r->config_file);
5211 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5212 driver->architecture,
5213 driver->version,
5214 driver->help_file,
5215 r->help_file);
5217 FILL_DRIVER_STRING(mem_ctx,
5218 driver->monitor_name,
5219 r->monitor_name);
5221 FILL_DRIVER_STRING(mem_ctx,
5222 driver->default_datatype,
5223 r->default_datatype);
5225 result = string_array_from_driver_info(mem_ctx,
5226 driver->dependent_files,
5227 &r->dependent_files,
5228 cservername,
5229 driver->architecture,
5230 driver->version);
5231 if (!W_ERROR_IS_OK(result)) {
5232 return result;
5235 result = string_array_from_driver_info(mem_ctx,
5236 driver->previous_names,
5237 &r->previous_names,
5238 NULL, NULL, 0);
5239 if (!W_ERROR_IS_OK(result)) {
5240 return result;
5243 r->driver_date = driver->driver_date;
5244 r->driver_version = driver->driver_version;
5246 FILL_DRIVER_STRING(mem_ctx,
5247 driver->manufacturer_name,
5248 r->manufacturer_name);
5249 FILL_DRIVER_STRING(mem_ctx,
5250 driver->manufacturer_url,
5251 r->manufacturer_url);
5252 FILL_DRIVER_STRING(mem_ctx,
5253 driver->hardware_id,
5254 r->hardware_id);
5255 FILL_DRIVER_STRING(mem_ctx,
5256 driver->provider,
5257 r->provider);
5259 FILL_DRIVER_STRING(mem_ctx,
5260 driver->print_processor,
5261 r->print_processor);
5262 FILL_DRIVER_STRING(mem_ctx,
5263 driver->vendor_setup,
5264 r->vendor_setup);
5266 result = string_array_from_driver_info(mem_ctx,
5267 driver->color_profiles,
5268 &r->color_profiles,
5269 NULL, NULL, 0);
5270 if (!W_ERROR_IS_OK(result)) {
5271 return result;
5274 FILL_DRIVER_STRING(mem_ctx,
5275 driver->inf_path,
5276 r->inf_path);
5278 r->printer_driver_attributes = driver->printer_driver_attributes;
5280 result = string_array_from_driver_info(mem_ctx,
5281 driver->core_driver_dependencies,
5282 &r->core_driver_dependencies,
5283 NULL, NULL, 0);
5284 if (!W_ERROR_IS_OK(result)) {
5285 return result;
5288 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5289 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5291 return WERR_OK;
5294 #if 0 /* disabled until marshalling issues are resolved - gd */
5295 /********************************************************************
5296 ********************************************************************/
5298 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5299 struct spoolss_DriverFileInfo *r,
5300 const char *cservername,
5301 const char *file_name,
5302 enum spoolss_DriverFileType file_type,
5303 uint32_t file_version)
5305 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5306 cservername, file_name);
5307 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5308 r->file_type = file_type;
5309 r->file_version = file_version;
5311 return WERR_OK;
5314 /********************************************************************
5315 ********************************************************************/
5317 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5318 const struct spoolss_DriverInfo8 *driver,
5319 const char *cservername,
5320 struct spoolss_DriverFileInfo **info_p,
5321 uint32_t *count_p)
5323 struct spoolss_DriverFileInfo *info = NULL;
5324 uint32_t count = 0;
5325 WERROR result;
5326 uint32_t i;
5328 *info_p = NULL;
5329 *count_p = 0;
5331 if (strlen(driver->driver_path)) {
5332 info = talloc_realloc(mem_ctx, info,
5333 struct spoolss_DriverFileInfo,
5334 count + 1);
5335 W_ERROR_HAVE_NO_MEMORY(info);
5336 result = fill_spoolss_DriverFileInfo(info,
5337 &info[count],
5338 cservername,
5339 driver->driver_path,
5340 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5342 W_ERROR_NOT_OK_RETURN(result);
5343 count++;
5346 if (strlen(driver->config_file)) {
5347 info = talloc_realloc(mem_ctx, info,
5348 struct spoolss_DriverFileInfo,
5349 count + 1);
5350 W_ERROR_HAVE_NO_MEMORY(info);
5351 result = fill_spoolss_DriverFileInfo(info,
5352 &info[count],
5353 cservername,
5354 driver->config_file,
5355 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5357 W_ERROR_NOT_OK_RETURN(result);
5358 count++;
5361 if (strlen(driver->data_file)) {
5362 info = talloc_realloc(mem_ctx, info,
5363 struct spoolss_DriverFileInfo,
5364 count + 1);
5365 W_ERROR_HAVE_NO_MEMORY(info);
5366 result = fill_spoolss_DriverFileInfo(info,
5367 &info[count],
5368 cservername,
5369 driver->data_file,
5370 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5372 W_ERROR_NOT_OK_RETURN(result);
5373 count++;
5376 if (strlen(driver->help_file)) {
5377 info = talloc_realloc(mem_ctx, info,
5378 struct spoolss_DriverFileInfo,
5379 count + 1);
5380 W_ERROR_HAVE_NO_MEMORY(info);
5381 result = fill_spoolss_DriverFileInfo(info,
5382 &info[count],
5383 cservername,
5384 driver->help_file,
5385 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5387 W_ERROR_NOT_OK_RETURN(result);
5388 count++;
5391 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5392 info = talloc_realloc(mem_ctx, info,
5393 struct spoolss_DriverFileInfo,
5394 count + 1);
5395 W_ERROR_HAVE_NO_MEMORY(info);
5396 result = fill_spoolss_DriverFileInfo(info,
5397 &info[count],
5398 cservername,
5399 driver->dependent_files[i],
5400 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5402 W_ERROR_NOT_OK_RETURN(result);
5403 count++;
5406 *info_p = info;
5407 *count_p = count;
5409 return WERR_OK;
5412 /********************************************************************
5413 * fill a spoolss_DriverInfo101 struct
5414 ********************************************************************/
5416 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5417 struct spoolss_DriverInfo101 *r,
5418 const struct spoolss_DriverInfo8 *driver,
5419 const char *servername)
5421 const char *cservername = canon_servername(servername);
5422 WERROR result;
5424 r->version = driver->version;
5426 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5427 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5428 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5429 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5431 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5432 cservername,
5433 &r->file_info,
5434 &r->file_count);
5435 if (!W_ERROR_IS_OK(result)) {
5436 return result;
5439 FILL_DRIVER_STRING(mem_ctx,
5440 driver->monitor_name,
5441 r->monitor_name);
5443 FILL_DRIVER_STRING(mem_ctx,
5444 driver->default_datatype,
5445 r->default_datatype);
5447 result = string_array_from_driver_info(mem_ctx,
5448 driver->previous_names,
5449 &r->previous_names,
5450 NULL, NULL, 0);
5451 if (!W_ERROR_IS_OK(result)) {
5452 return result;
5455 r->driver_date = driver->driver_date;
5456 r->driver_version = driver->driver_version;
5458 FILL_DRIVER_STRING(mem_ctx,
5459 driver->manufacturer_name,
5460 r->manufacturer_name);
5461 FILL_DRIVER_STRING(mem_ctx,
5462 driver->manufacturer_url,
5463 r->manufacturer_url);
5464 FILL_DRIVER_STRING(mem_ctx,
5465 driver->hardware_id,
5466 r->hardware_id);
5467 FILL_DRIVER_STRING(mem_ctx,
5468 driver->provider,
5469 r->provider);
5471 return WERR_OK;
5473 #endif
5474 /********************************************************************
5475 ********************************************************************/
5477 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5478 const struct auth_session_info *session_info,
5479 struct messaging_context *msg_ctx,
5480 uint32_t level,
5481 union spoolss_DriverInfo *r,
5482 int snum,
5483 const char *servername,
5484 const char *architecture,
5485 uint32_t version)
5487 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5488 struct spoolss_DriverInfo8 *driver;
5489 WERROR result;
5490 struct dcerpc_binding_handle *b;
5491 TALLOC_CTX *tmp_ctx = NULL;
5493 if (level == 101) {
5494 return WERR_UNKNOWN_LEVEL;
5497 tmp_ctx = talloc_new(mem_ctx);
5498 if (!tmp_ctx) {
5499 return WERR_NOMEM;
5502 result = winreg_printer_binding_handle(tmp_ctx,
5503 session_info,
5504 msg_ctx,
5505 &b);
5506 if (!W_ERROR_IS_OK(result)) {
5507 goto done;
5510 result = winreg_get_printer(tmp_ctx, b,
5511 lp_const_servicename(snum),
5512 &pinfo2);
5514 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5515 win_errstr(result)));
5517 if (!W_ERROR_IS_OK(result)) {
5518 result = WERR_INVALID_PRINTER_NAME;
5519 goto done;
5522 result = winreg_get_driver(tmp_ctx, b,
5523 architecture,
5524 pinfo2->drivername, version, &driver);
5526 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5527 win_errstr(result)));
5529 if (!W_ERROR_IS_OK(result)) {
5531 * Is this a W2k client ?
5534 if (version < 3) {
5535 result = WERR_UNKNOWN_PRINTER_DRIVER;
5536 goto done;
5539 /* Yes - try again with a WinNT driver. */
5540 version = 2;
5541 result = winreg_get_driver(tmp_ctx, b,
5542 architecture,
5543 pinfo2->drivername,
5544 version, &driver);
5545 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5546 win_errstr(result)));
5547 if (!W_ERROR_IS_OK(result)) {
5548 result = WERR_UNKNOWN_PRINTER_DRIVER;
5549 goto done;
5553 /* these are allocated on mem_ctx and not tmp_ctx because they are
5554 * the 'return value' and need to utlive this call */
5555 switch (level) {
5556 case 1:
5557 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5558 break;
5559 case 2:
5560 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5561 break;
5562 case 3:
5563 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5564 break;
5565 case 4:
5566 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5567 break;
5568 case 5:
5569 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5570 break;
5571 case 6:
5572 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5573 break;
5574 case 8:
5575 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5576 break;
5577 #if 0 /* disabled until marshalling issues are resolved - gd */
5578 case 101:
5579 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5580 break;
5581 #endif
5582 default:
5583 result = WERR_UNKNOWN_LEVEL;
5584 break;
5587 done:
5588 talloc_free(tmp_ctx);
5589 return result;
5592 /****************************************************************
5593 _spoolss_GetPrinterDriver2
5594 ****************************************************************/
5596 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5597 struct spoolss_GetPrinterDriver2 *r)
5599 struct printer_handle *printer;
5600 WERROR result;
5602 int snum;
5604 /* that's an [in out] buffer */
5606 if (!r->in.buffer && (r->in.offered != 0)) {
5607 return WERR_INVALID_PARAM;
5610 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5612 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5613 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5614 return WERR_INVALID_PRINTER_NAME;
5617 *r->out.needed = 0;
5618 *r->out.server_major_version = 0;
5619 *r->out.server_minor_version = 0;
5621 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5622 return WERR_BADFID;
5625 result = construct_printer_driver_info_level(p->mem_ctx,
5626 get_session_info_system(),
5627 p->msg_ctx,
5628 r->in.level, r->out.info,
5629 snum, printer->servername,
5630 r->in.architecture,
5631 r->in.client_major_version);
5632 if (!W_ERROR_IS_OK(result)) {
5633 TALLOC_FREE(r->out.info);
5634 return result;
5637 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5638 r->out.info, r->in.level);
5639 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5641 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5645 /****************************************************************
5646 _spoolss_StartPagePrinter
5647 ****************************************************************/
5649 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5650 struct spoolss_StartPagePrinter *r)
5652 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5654 if (!Printer) {
5655 DEBUG(3,("_spoolss_StartPagePrinter: "
5656 "Error in startpageprinter printer handle\n"));
5657 return WERR_BADFID;
5660 Printer->page_started = true;
5661 return WERR_OK;
5664 /****************************************************************
5665 _spoolss_EndPagePrinter
5666 ****************************************************************/
5668 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5669 struct spoolss_EndPagePrinter *r)
5671 int snum;
5673 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5675 if (!Printer) {
5676 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5677 OUR_HANDLE(r->in.handle)));
5678 return WERR_BADFID;
5681 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5682 return WERR_BADFID;
5684 Printer->page_started = false;
5685 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5687 return WERR_OK;
5690 /****************************************************************
5691 _spoolss_StartDocPrinter
5692 ****************************************************************/
5694 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5695 struct spoolss_StartDocPrinter *r)
5697 struct spoolss_DocumentInfo1 *info_1;
5698 int snum;
5699 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5700 WERROR werr;
5701 char *rhost;
5702 int rc;
5704 if (!Printer) {
5705 DEBUG(2,("_spoolss_StartDocPrinter: "
5706 "Invalid handle (%s:%u:%u)\n",
5707 OUR_HANDLE(r->in.handle)));
5708 return WERR_BADFID;
5711 if (Printer->jobid) {
5712 DEBUG(2, ("_spoolss_StartDocPrinter: "
5713 "StartDocPrinter called twice! "
5714 "(existing jobid = %d)\n", Printer->jobid));
5715 return WERR_INVALID_HANDLE;
5718 if (r->in.level != 1) {
5719 return WERR_UNKNOWN_LEVEL;
5722 info_1 = r->in.info.info1;
5725 * a nice thing with NT is it doesn't listen to what you tell it.
5726 * when asked to send _only_ RAW datas, it tries to send datas
5727 * in EMF format.
5729 * So I add checks like in NT Server ...
5732 if (info_1->datatype) {
5733 if (strcmp(info_1->datatype, "RAW") != 0) {
5734 *r->out.job_id = 0;
5735 return WERR_INVALID_DATATYPE;
5739 /* get the share number of the printer */
5740 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5741 return WERR_BADFID;
5744 rc = get_remote_hostname(p->remote_address,
5745 &rhost,
5746 p->mem_ctx);
5747 if (rc < 0) {
5748 return WERR_NOMEM;
5750 if (strequal(rhost,"UNKNOWN")) {
5751 rhost = tsocket_address_inet_addr_string(p->remote_address,
5752 p->mem_ctx);
5753 if (rhost == NULL) {
5754 return WERR_NOMEM;
5758 werr = print_job_start(p->session_info,
5759 p->msg_ctx,
5760 rhost,
5761 snum,
5762 info_1->document_name,
5763 info_1->output_file,
5764 Printer->devmode,
5765 &Printer->jobid);
5767 /* An error occured in print_job_start() so return an appropriate
5768 NT error code. */
5770 if (!W_ERROR_IS_OK(werr)) {
5771 return werr;
5774 Printer->document_started = true;
5775 *r->out.job_id = Printer->jobid;
5777 return WERR_OK;
5780 /****************************************************************
5781 _spoolss_EndDocPrinter
5782 ****************************************************************/
5784 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5785 struct spoolss_EndDocPrinter *r)
5787 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5788 NTSTATUS status;
5789 int snum;
5791 if (!Printer) {
5792 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5793 OUR_HANDLE(r->in.handle)));
5794 return WERR_BADFID;
5797 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5798 return WERR_BADFID;
5801 Printer->document_started = false;
5802 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5803 if (!NT_STATUS_IS_OK(status)) {
5804 DEBUG(2, ("_spoolss_EndDocPrinter: "
5805 "print_job_end failed [%s]\n",
5806 nt_errstr(status)));
5809 Printer->jobid = 0;
5810 return ntstatus_to_werror(status);
5813 /****************************************************************
5814 _spoolss_WritePrinter
5815 ****************************************************************/
5817 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5818 struct spoolss_WritePrinter *r)
5820 ssize_t buffer_written;
5821 int snum;
5822 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5824 if (!Printer) {
5825 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5826 OUR_HANDLE(r->in.handle)));
5827 *r->out.num_written = r->in._data_size;
5828 return WERR_BADFID;
5831 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5832 return WERR_BADFID;
5834 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5835 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5836 snum, Printer->jobid,
5837 (const char *)r->in.data.data,
5838 (size_t)r->in._data_size);
5839 if (buffer_written == (ssize_t)-1) {
5840 *r->out.num_written = 0;
5841 if (errno == ENOSPC)
5842 return WERR_NO_SPOOL_SPACE;
5843 else
5844 return WERR_ACCESS_DENIED;
5847 *r->out.num_written = r->in._data_size;
5849 return WERR_OK;
5852 /********************************************************************
5853 * api_spoolss_getprinter
5854 * called from the spoolss dispatcher
5856 ********************************************************************/
5858 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5859 struct pipes_struct *p)
5861 const struct auth_session_info *session_info = p->session_info;
5862 int snum;
5863 WERROR errcode = WERR_BADFUNC;
5864 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5866 if (!Printer) {
5867 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5868 OUR_HANDLE(handle)));
5869 return WERR_BADFID;
5872 if (!get_printer_snum(p, handle, &snum, NULL))
5873 return WERR_BADFID;
5875 switch (command) {
5876 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5877 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5878 break;
5879 case SPOOLSS_PRINTER_CONTROL_RESUME:
5880 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5881 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5882 break;
5883 case SPOOLSS_PRINTER_CONTROL_PURGE:
5884 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5885 break;
5886 default:
5887 return WERR_UNKNOWN_LEVEL;
5890 return errcode;
5894 /****************************************************************
5895 _spoolss_AbortPrinter
5896 * From MSDN: "Deletes printer's spool file if printer is configured
5897 * for spooling"
5898 ****************************************************************/
5900 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5901 struct spoolss_AbortPrinter *r)
5903 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5904 int snum;
5905 WERROR errcode = WERR_OK;
5907 if (!Printer) {
5908 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5909 OUR_HANDLE(r->in.handle)));
5910 return WERR_BADFID;
5913 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5914 return WERR_BADFID;
5916 if (!Printer->document_started) {
5917 return WERR_SPL_NO_STARTDOC;
5920 errcode = print_job_delete(p->session_info,
5921 p->msg_ctx,
5922 snum,
5923 Printer->jobid);
5925 return errcode;
5928 /********************************************************************
5929 * called by spoolss_api_setprinter
5930 * when updating a printer description
5931 ********************************************************************/
5933 static WERROR update_printer_sec(struct policy_handle *handle,
5934 struct pipes_struct *p,
5935 struct sec_desc_buf *secdesc_ctr)
5937 struct spoolss_security_descriptor *new_secdesc = NULL;
5938 struct spoolss_security_descriptor *old_secdesc = NULL;
5939 const char *printer;
5940 WERROR result;
5941 int snum;
5942 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5943 struct dcerpc_binding_handle *b;
5944 TALLOC_CTX *tmp_ctx = NULL;
5946 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5947 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5948 OUR_HANDLE(handle)));
5950 result = WERR_BADFID;
5951 goto done;
5954 if (secdesc_ctr == NULL) {
5955 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5956 result = WERR_INVALID_PARAM;
5957 goto done;
5959 printer = lp_const_servicename(snum);
5961 /* Check the user has permissions to change the security
5962 descriptor. By experimentation with two NT machines, the user
5963 requires Full Access to the printer to change security
5964 information. */
5966 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5967 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5968 result = WERR_ACCESS_DENIED;
5969 goto done;
5972 tmp_ctx = talloc_new(p->mem_ctx);
5973 if (!tmp_ctx) {
5974 return WERR_NOMEM;
5977 result = winreg_printer_binding_handle(tmp_ctx,
5978 get_session_info_system(),
5979 p->msg_ctx,
5980 &b);
5981 if (!W_ERROR_IS_OK(result)) {
5982 goto done;
5985 /* NT seems to like setting the security descriptor even though
5986 nothing may have actually changed. */
5987 result = winreg_get_printer_secdesc(tmp_ctx, b,
5988 printer,
5989 &old_secdesc);
5990 if (!W_ERROR_IS_OK(result)) {
5991 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5992 result = WERR_BADFID;
5993 goto done;
5996 if (DEBUGLEVEL >= 10) {
5997 struct security_acl *the_acl;
5998 int i;
6000 the_acl = old_secdesc->dacl;
6001 DEBUG(10, ("old_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));
6010 the_acl = secdesc_ctr->sd->dacl;
6012 if (the_acl) {
6013 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6014 printer, the_acl->num_aces));
6016 for (i = 0; i < the_acl->num_aces; i++) {
6017 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6018 &the_acl->aces[i].trustee),
6019 the_acl->aces[i].access_mask));
6021 } else {
6022 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6026 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6027 if (new_secdesc == NULL) {
6028 result = WERR_NOMEM;
6029 goto done;
6032 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6033 result = WERR_OK;
6034 goto done;
6037 result = winreg_set_printer_secdesc(tmp_ctx, b,
6038 printer,
6039 new_secdesc);
6041 done:
6042 talloc_free(tmp_ctx);
6043 return result;
6046 /********************************************************************
6047 Canonicalize printer info from a client
6048 ********************************************************************/
6050 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6051 struct spoolss_SetPrinterInfo2 *info2,
6052 int snum)
6054 fstring printername;
6055 const char *p;
6057 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6058 "portname=%s drivername=%s comment=%s location=%s\n",
6059 info2->servername, info2->printername, info2->sharename,
6060 info2->portname, info2->drivername, info2->comment,
6061 info2->location));
6063 /* we force some elements to "correct" values */
6064 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6065 if (info2->servername == NULL) {
6066 return false;
6068 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6069 if (info2->sharename == NULL) {
6070 return false;
6073 /* check to see if we allow printername != sharename */
6074 if (lp_force_printername(snum)) {
6075 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6076 lp_netbios_name(), info2->sharename);
6077 } else {
6078 /* make sure printername is in \\server\printername format */
6079 fstrcpy(printername, info2->printername);
6080 p = printername;
6081 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6082 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6083 p++;
6086 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6087 lp_netbios_name(), p);
6089 if (info2->printername == NULL) {
6090 return false;
6093 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6094 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6096 return true;
6099 /****************************************************************************
6100 ****************************************************************************/
6102 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6104 char *cmd = lp_addport_cmd();
6105 char *command = NULL;
6106 int ret;
6107 bool is_print_op = false;
6109 if ( !*cmd ) {
6110 return WERR_ACCESS_DENIED;
6113 command = talloc_asprintf(ctx,
6114 "%s \"%s\" \"%s\"", cmd, portname, uri );
6115 if (!command) {
6116 return WERR_NOMEM;
6119 if ( token )
6120 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6122 DEBUG(10,("Running [%s]\n", command));
6124 /********* BEGIN SePrintOperatorPrivilege **********/
6126 if ( is_print_op )
6127 become_root();
6129 ret = smbrun(command, NULL);
6131 if ( is_print_op )
6132 unbecome_root();
6134 /********* END SePrintOperatorPrivilege **********/
6136 DEBUGADD(10,("returned [%d]\n", ret));
6138 TALLOC_FREE(command);
6140 if ( ret != 0 ) {
6141 return WERR_ACCESS_DENIED;
6144 return WERR_OK;
6147 /****************************************************************************
6148 ****************************************************************************/
6150 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6151 int snum)
6154 * As we do not know if we are embedded in the file server process
6155 * or not, we have to pretend that all shares are in use.
6157 return true;
6160 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6161 struct spoolss_SetPrinterInfo2 *info2,
6162 const char *remote_machine,
6163 struct messaging_context *msg_ctx)
6165 char *cmd = lp_addprinter_cmd();
6166 char **qlines;
6167 char *command = NULL;
6168 int numlines;
6169 int ret;
6170 int fd;
6171 bool is_print_op = false;
6173 if (!remote_machine) {
6174 return false;
6177 command = talloc_asprintf(ctx,
6178 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6179 cmd, info2->printername, info2->sharename,
6180 info2->portname, info2->drivername,
6181 info2->location, info2->comment, remote_machine);
6182 if (!command) {
6183 return false;
6186 if ( token )
6187 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6189 DEBUG(10,("Running [%s]\n", command));
6191 /********* BEGIN SePrintOperatorPrivilege **********/
6193 if ( is_print_op )
6194 become_root();
6196 if ( (ret = smbrun(command, &fd)) == 0 ) {
6197 /* Tell everyone we updated smb.conf. */
6198 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6201 if ( is_print_op )
6202 unbecome_root();
6204 /********* END SePrintOperatorPrivilege **********/
6206 DEBUGADD(10,("returned [%d]\n", ret));
6208 TALLOC_FREE(command);
6210 if ( ret != 0 ) {
6211 if (fd != -1)
6212 close(fd);
6213 return false;
6216 /* reload our services immediately */
6217 become_root();
6218 reload_services(NULL, spoolss_conn_snum_used, false);
6219 unbecome_root();
6221 numlines = 0;
6222 /* Get lines and convert them back to dos-codepage */
6223 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6224 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6225 close(fd);
6227 /* Set the portname to what the script says the portname should be. */
6228 /* but don't require anything to be return from the script exit a good error code */
6230 if (numlines) {
6231 /* Set the portname to what the script says the portname should be. */
6232 info2->portname = talloc_strdup(ctx, qlines[0]);
6233 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6236 TALLOC_FREE(qlines);
6237 return true;
6240 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6241 const struct auth_session_info *session_info,
6242 struct messaging_context *msg_ctx,
6243 int snum,
6244 struct spoolss_SetPrinterInfo2 *printer,
6245 struct spoolss_PrinterInfo2 *old_printer)
6247 bool force_update = (old_printer == NULL);
6248 const char *dnsdomname;
6249 const char *longname;
6250 const char *uncname;
6251 const char *spooling;
6252 DATA_BLOB buffer;
6253 WERROR result = WERR_OK;
6254 struct dcerpc_binding_handle *b;
6255 TALLOC_CTX *tmp_ctx;
6257 tmp_ctx = talloc_new(mem_ctx);
6258 if (!tmp_ctx) {
6259 return WERR_NOMEM;
6262 result = winreg_printer_binding_handle(tmp_ctx,
6263 session_info,
6264 msg_ctx,
6265 &b);
6266 if (!W_ERROR_IS_OK(result)) {
6267 goto done;
6270 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6271 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6272 winreg_set_printer_dataex(tmp_ctx, b,
6273 printer->sharename,
6274 SPOOL_DSSPOOLER_KEY,
6275 SPOOL_REG_DRIVERNAME,
6276 REG_SZ,
6277 buffer.data,
6278 buffer.length);
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 (force_update || !strequal(printer->comment, old_printer->comment)) {
6291 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6292 winreg_set_printer_dataex(tmp_ctx, b,
6293 printer->sharename,
6294 SPOOL_DSSPOOLER_KEY,
6295 SPOOL_REG_DESCRIPTION,
6296 REG_SZ,
6297 buffer.data,
6298 buffer.length);
6300 if (!force_update) {
6301 notify_printer_comment(server_event_context(), msg_ctx,
6302 snum, printer->comment ?
6303 printer->comment : "");
6307 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6308 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6309 winreg_set_printer_dataex(tmp_ctx, b,
6310 printer->sharename,
6311 SPOOL_DSSPOOLER_KEY,
6312 SPOOL_REG_PRINTSHARENAME,
6313 REG_SZ,
6314 buffer.data,
6315 buffer.length);
6317 if (!force_update) {
6318 notify_printer_sharename(server_event_context(),
6319 msg_ctx,
6320 snum, printer->sharename ?
6321 printer->sharename : "");
6325 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6326 const char *p;
6328 p = strrchr(printer->printername, '\\' );
6329 if (p != NULL) {
6330 p++;
6331 } else {
6332 p = printer->printername;
6335 push_reg_sz(tmp_ctx, &buffer, p);
6336 winreg_set_printer_dataex(tmp_ctx, b,
6337 printer->sharename,
6338 SPOOL_DSSPOOLER_KEY,
6339 SPOOL_REG_PRINTERNAME,
6340 REG_SZ,
6341 buffer.data,
6342 buffer.length);
6344 if (!force_update) {
6345 notify_printer_printername(server_event_context(),
6346 msg_ctx, snum, p ? p : "");
6350 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6351 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6352 winreg_set_printer_dataex(tmp_ctx, b,
6353 printer->sharename,
6354 SPOOL_DSSPOOLER_KEY,
6355 SPOOL_REG_PORTNAME,
6356 REG_SZ,
6357 buffer.data,
6358 buffer.length);
6360 if (!force_update) {
6361 notify_printer_port(server_event_context(),
6362 msg_ctx, snum, printer->portname ?
6363 printer->portname : "");
6367 if (force_update || !strequal(printer->location, old_printer->location)) {
6368 push_reg_sz(tmp_ctx, &buffer, printer->location);
6369 winreg_set_printer_dataex(tmp_ctx, b,
6370 printer->sharename,
6371 SPOOL_DSSPOOLER_KEY,
6372 SPOOL_REG_LOCATION,
6373 REG_SZ,
6374 buffer.data,
6375 buffer.length);
6377 if (!force_update) {
6378 notify_printer_location(server_event_context(),
6379 msg_ctx, snum,
6380 printer->location ?
6381 printer->location : "");
6385 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6386 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6387 winreg_set_printer_dataex(tmp_ctx, b,
6388 printer->sharename,
6389 SPOOL_DSSPOOLER_KEY,
6390 SPOOL_REG_PRINTSEPARATORFILE,
6391 REG_SZ,
6392 buffer.data,
6393 buffer.length);
6395 if (!force_update) {
6396 notify_printer_sepfile(server_event_context(),
6397 msg_ctx, snum,
6398 printer->sepfile ?
6399 printer->sepfile : "");
6403 if (force_update || printer->starttime != old_printer->starttime) {
6404 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6405 SIVAL(buffer.data, 0, printer->starttime);
6406 winreg_set_printer_dataex(tmp_ctx, b,
6407 printer->sharename,
6408 SPOOL_DSSPOOLER_KEY,
6409 SPOOL_REG_PRINTSTARTTIME,
6410 REG_DWORD,
6411 buffer.data,
6412 buffer.length);
6415 if (force_update || printer->untiltime != old_printer->untiltime) {
6416 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6417 SIVAL(buffer.data, 0, printer->untiltime);
6418 winreg_set_printer_dataex(tmp_ctx, b,
6419 printer->sharename,
6420 SPOOL_DSSPOOLER_KEY,
6421 SPOOL_REG_PRINTENDTIME,
6422 REG_DWORD,
6423 buffer.data,
6424 buffer.length);
6427 if (force_update || printer->priority != old_printer->priority) {
6428 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6429 SIVAL(buffer.data, 0, printer->priority);
6430 winreg_set_printer_dataex(tmp_ctx, b,
6431 printer->sharename,
6432 SPOOL_DSSPOOLER_KEY,
6433 SPOOL_REG_PRIORITY,
6434 REG_DWORD,
6435 buffer.data,
6436 buffer.length);
6439 if (force_update || printer->attributes != old_printer->attributes) {
6440 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6441 SIVAL(buffer.data, 0, (printer->attributes &
6442 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6443 winreg_set_printer_dataex(tmp_ctx, b,
6444 printer->sharename,
6445 SPOOL_DSSPOOLER_KEY,
6446 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6447 REG_DWORD,
6448 buffer.data,
6449 buffer.length);
6451 switch (printer->attributes & 0x3) {
6452 case 0:
6453 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6454 break;
6455 case 1:
6456 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6457 break;
6458 case 2:
6459 spooling = SPOOL_REGVAL_PRINTDIRECT;
6460 break;
6461 default:
6462 spooling = "unknown";
6464 push_reg_sz(tmp_ctx, &buffer, spooling);
6465 winreg_set_printer_dataex(tmp_ctx, b,
6466 printer->sharename,
6467 SPOOL_DSSPOOLER_KEY,
6468 SPOOL_REG_PRINTSPOOLING,
6469 REG_SZ,
6470 buffer.data,
6471 buffer.length);
6474 push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6475 winreg_set_printer_dataex(tmp_ctx, b,
6476 printer->sharename,
6477 SPOOL_DSSPOOLER_KEY,
6478 SPOOL_REG_SHORTSERVERNAME,
6479 REG_SZ,
6480 buffer.data,
6481 buffer.length);
6483 dnsdomname = get_mydnsfullname();
6484 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6485 longname = talloc_strdup(tmp_ctx, dnsdomname);
6486 } else {
6487 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6489 if (longname == NULL) {
6490 result = WERR_NOMEM;
6491 goto done;
6494 push_reg_sz(tmp_ctx, &buffer, longname);
6495 winreg_set_printer_dataex(tmp_ctx, b,
6496 printer->sharename,
6497 SPOOL_DSSPOOLER_KEY,
6498 SPOOL_REG_SERVERNAME,
6499 REG_SZ,
6500 buffer.data,
6501 buffer.length);
6503 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6504 lp_netbios_name(), printer->sharename);
6505 push_reg_sz(tmp_ctx, &buffer, uncname);
6506 winreg_set_printer_dataex(tmp_ctx, b,
6507 printer->sharename,
6508 SPOOL_DSSPOOLER_KEY,
6509 SPOOL_REG_UNCNAME,
6510 REG_SZ,
6511 buffer.data,
6512 buffer.length);
6514 done:
6515 talloc_free(tmp_ctx);
6516 return result;
6519 /********************************************************************
6520 * Called by spoolss_api_setprinter
6521 * when updating a printer description.
6522 ********************************************************************/
6524 static WERROR update_printer(struct pipes_struct *p,
6525 struct policy_handle *handle,
6526 struct spoolss_SetPrinterInfoCtr *info_ctr,
6527 struct spoolss_DeviceMode *devmode)
6529 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6530 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6531 struct spoolss_PrinterInfo2 *old_printer;
6532 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6533 int snum;
6534 WERROR result = WERR_OK;
6535 TALLOC_CTX *tmp_ctx;
6536 struct dcerpc_binding_handle *b;
6538 DEBUG(8,("update_printer\n"));
6540 tmp_ctx = talloc_new(p->mem_ctx);
6541 if (tmp_ctx == NULL) {
6542 return WERR_NOMEM;
6545 if (!Printer) {
6546 result = WERR_BADFID;
6547 goto done;
6550 if (!get_printer_snum(p, handle, &snum, NULL)) {
6551 result = WERR_BADFID;
6552 goto done;
6555 result = winreg_printer_binding_handle(tmp_ctx,
6556 get_session_info_system(),
6557 p->msg_ctx,
6558 &b);
6559 if (!W_ERROR_IS_OK(result)) {
6560 goto done;
6563 result = winreg_get_printer(tmp_ctx, b,
6564 lp_const_servicename(snum),
6565 &old_printer);
6566 if (!W_ERROR_IS_OK(result)) {
6567 result = WERR_BADFID;
6568 goto done;
6571 /* Do sanity check on the requested changes for Samba */
6572 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6573 result = WERR_INVALID_PARAM;
6574 goto done;
6577 /* FIXME!!! If the driver has changed we really should verify that
6578 it is installed before doing much else --jerry */
6580 /* Check calling user has permission to update printer description */
6581 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6582 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6583 result = WERR_ACCESS_DENIED;
6584 goto done;
6587 /* Call addprinter hook */
6588 /* Check changes to see if this is really needed */
6590 if (*lp_addprinter_cmd() &&
6591 (!strequal(printer->drivername, old_printer->drivername) ||
6592 !strequal(printer->comment, old_printer->comment) ||
6593 !strequal(printer->portname, old_printer->portname) ||
6594 !strequal(printer->location, old_printer->location)) )
6596 char *raddr;
6598 raddr = tsocket_address_inet_addr_string(p->remote_address,
6599 p->mem_ctx);
6600 if (raddr == NULL) {
6601 return WERR_NOMEM;
6604 /* add_printer_hook() will call reload_services() */
6605 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6606 printer, raddr,
6607 p->msg_ctx)) {
6608 result = WERR_ACCESS_DENIED;
6609 goto done;
6613 update_dsspooler(tmp_ctx,
6614 get_session_info_system(),
6615 p->msg_ctx,
6616 snum,
6617 printer,
6618 old_printer);
6620 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6622 if (devmode == NULL) {
6623 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6625 result = winreg_update_printer(tmp_ctx, b,
6626 printer->sharename,
6627 printer_mask,
6628 printer,
6629 devmode,
6630 NULL);
6632 done:
6633 talloc_free(tmp_ctx);
6635 return result;
6638 /****************************************************************************
6639 ****************************************************************************/
6640 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6641 struct policy_handle *handle,
6642 struct spoolss_SetPrinterInfo7 *info7)
6644 #ifdef HAVE_ADS
6645 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6646 WERROR result;
6647 int snum;
6648 struct printer_handle *Printer;
6650 if ( lp_security() != SEC_ADS ) {
6651 return WERR_UNKNOWN_LEVEL;
6654 Printer = find_printer_index_by_hnd(p, handle);
6656 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6658 if (!Printer)
6659 return WERR_BADFID;
6661 if (!get_printer_snum(p, handle, &snum, NULL))
6662 return WERR_BADFID;
6664 result = winreg_get_printer_internal(p->mem_ctx,
6665 get_session_info_system(),
6666 p->msg_ctx,
6667 lp_servicename(snum),
6668 &pinfo2);
6669 if (!W_ERROR_IS_OK(result)) {
6670 return WERR_BADFID;
6673 nt_printer_publish(pinfo2,
6674 get_session_info_system(),
6675 p->msg_ctx,
6676 pinfo2,
6677 info7->action);
6679 TALLOC_FREE(pinfo2);
6680 return WERR_OK;
6681 #else
6682 return WERR_UNKNOWN_LEVEL;
6683 #endif
6686 /********************************************************************
6687 ********************************************************************/
6689 static WERROR update_printer_devmode(struct pipes_struct *p,
6690 struct policy_handle *handle,
6691 struct spoolss_DeviceMode *devmode)
6693 int snum;
6694 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6695 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6697 DEBUG(8,("update_printer_devmode\n"));
6699 if (!Printer) {
6700 return WERR_BADFID;
6703 if (!get_printer_snum(p, handle, &snum, NULL)) {
6704 return WERR_BADFID;
6707 /* Check calling user has permission to update printer description */
6708 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6709 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6710 return WERR_ACCESS_DENIED;
6713 return winreg_update_printer_internal(p->mem_ctx,
6714 get_session_info_system(),
6715 p->msg_ctx,
6716 lp_const_servicename(snum),
6717 info2_mask,
6718 NULL,
6719 devmode,
6720 NULL);
6724 /****************************************************************
6725 _spoolss_SetPrinter
6726 ****************************************************************/
6728 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6729 struct spoolss_SetPrinter *r)
6731 WERROR result;
6733 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6735 if (!Printer) {
6736 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6737 OUR_HANDLE(r->in.handle)));
6738 return WERR_BADFID;
6741 /* check the level */
6742 switch (r->in.info_ctr->level) {
6743 case 0:
6744 return control_printer(r->in.handle, r->in.command, p);
6745 case 2:
6746 result = update_printer(p, r->in.handle,
6747 r->in.info_ctr,
6748 r->in.devmode_ctr->devmode);
6749 if (!W_ERROR_IS_OK(result))
6750 return result;
6751 if (r->in.secdesc_ctr->sd)
6752 result = update_printer_sec(r->in.handle, p,
6753 r->in.secdesc_ctr);
6754 return result;
6755 case 3:
6756 return update_printer_sec(r->in.handle, p,
6757 r->in.secdesc_ctr);
6758 case 7:
6759 return publish_or_unpublish_printer(p, r->in.handle,
6760 r->in.info_ctr->info.info7);
6761 case 8:
6762 return update_printer_devmode(p, r->in.handle,
6763 r->in.devmode_ctr->devmode);
6764 default:
6765 return WERR_UNKNOWN_LEVEL;
6769 /****************************************************************
6770 _spoolss_FindClosePrinterNotify
6771 ****************************************************************/
6773 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6774 struct spoolss_FindClosePrinterNotify *r)
6776 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6778 if (!Printer) {
6779 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6780 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6781 return WERR_BADFID;
6784 if (Printer->notify.cli_chan != NULL &&
6785 Printer->notify.cli_chan->active_connections > 0) {
6786 int snum = -1;
6788 if (Printer->printer_type == SPLHND_PRINTER) {
6789 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6790 return WERR_BADFID;
6794 srv_spoolss_replycloseprinter(snum, Printer);
6797 Printer->notify.flags=0;
6798 Printer->notify.options=0;
6799 Printer->notify.localmachine[0]='\0';
6800 Printer->notify.printerlocal=0;
6801 TALLOC_FREE(Printer->notify.option);
6803 return WERR_OK;
6806 /****************************************************************
6807 _spoolss_AddJob
6808 ****************************************************************/
6810 WERROR _spoolss_AddJob(struct pipes_struct *p,
6811 struct spoolss_AddJob *r)
6813 if (!r->in.buffer && (r->in.offered != 0)) {
6814 return WERR_INVALID_PARAM;
6817 /* this is what a NT server returns for AddJob. AddJob must fail on
6818 * non-local printers */
6820 if (r->in.level != 1) {
6821 return WERR_UNKNOWN_LEVEL;
6824 return WERR_INVALID_PARAM;
6827 /****************************************************************************
6828 fill_job_info1
6829 ****************************************************************************/
6831 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6832 struct spoolss_JobInfo1 *r,
6833 const print_queue_struct *queue,
6834 int position, int snum,
6835 struct spoolss_PrinterInfo2 *pinfo2)
6837 struct tm *t;
6839 t = gmtime(&queue->time);
6841 r->job_id = queue->job;
6843 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6844 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6845 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6846 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6847 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6848 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6849 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6850 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6851 r->data_type = talloc_strdup(mem_ctx, "RAW");
6852 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6853 r->text_status = talloc_strdup(mem_ctx, "");
6854 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6856 r->status = nt_printj_status(queue->status);
6857 r->priority = queue->priority;
6858 r->position = position;
6859 r->total_pages = queue->page_count;
6860 r->pages_printed = 0; /* ??? */
6862 init_systemtime(&r->submitted, t);
6864 return WERR_OK;
6867 /****************************************************************************
6868 fill_job_info2
6869 ****************************************************************************/
6871 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6872 struct spoolss_JobInfo2 *r,
6873 const print_queue_struct *queue,
6874 int position, int snum,
6875 struct spoolss_PrinterInfo2 *pinfo2,
6876 struct spoolss_DeviceMode *devmode)
6878 struct tm *t;
6880 t = gmtime(&queue->time);
6882 r->job_id = queue->job;
6884 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6885 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6886 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6887 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6888 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6889 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6890 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6891 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6892 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6893 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6894 r->data_type = talloc_strdup(mem_ctx, "RAW");
6895 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6896 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6897 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6898 r->parameters = talloc_strdup(mem_ctx, "");
6899 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6900 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6901 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6903 r->devmode = devmode;
6905 r->text_status = talloc_strdup(mem_ctx, "");
6906 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6908 r->secdesc = NULL;
6910 r->status = nt_printj_status(queue->status);
6911 r->priority = queue->priority;
6912 r->position = position;
6913 r->start_time = 0;
6914 r->until_time = 0;
6915 r->total_pages = queue->page_count;
6916 r->size = queue->size;
6917 init_systemtime(&r->submitted, t);
6918 r->time = 0;
6919 r->pages_printed = 0; /* ??? */
6921 return WERR_OK;
6924 /****************************************************************************
6925 fill_job_info3
6926 ****************************************************************************/
6928 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6929 struct spoolss_JobInfo3 *r,
6930 const print_queue_struct *queue,
6931 const print_queue_struct *next_queue,
6932 int position, int snum,
6933 struct spoolss_PrinterInfo2 *pinfo2)
6935 r->job_id = queue->job;
6936 r->next_job_id = 0;
6937 if (next_queue) {
6938 r->next_job_id = next_queue->job;
6940 r->reserved = 0;
6942 return WERR_OK;
6945 /****************************************************************************
6946 Enumjobs at level 1.
6947 ****************************************************************************/
6949 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6950 const print_queue_struct *queue,
6951 uint32_t num_queues, int snum,
6952 struct spoolss_PrinterInfo2 *pinfo2,
6953 union spoolss_JobInfo **info_p,
6954 uint32_t *count)
6956 union spoolss_JobInfo *info;
6957 int i;
6958 WERROR result = WERR_OK;
6960 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
6961 W_ERROR_HAVE_NO_MEMORY(info);
6963 *count = num_queues;
6965 for (i=0; i<*count; i++) {
6966 result = fill_job_info1(info,
6967 &info[i].info1,
6968 &queue[i],
6970 snum,
6971 pinfo2);
6972 if (!W_ERROR_IS_OK(result)) {
6973 goto out;
6977 out:
6978 if (!W_ERROR_IS_OK(result)) {
6979 TALLOC_FREE(info);
6980 *count = 0;
6981 return result;
6984 *info_p = info;
6986 return WERR_OK;
6989 /****************************************************************************
6990 Enumjobs at level 2.
6991 ****************************************************************************/
6993 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6994 const print_queue_struct *queue,
6995 uint32_t num_queues, int snum,
6996 struct spoolss_PrinterInfo2 *pinfo2,
6997 union spoolss_JobInfo **info_p,
6998 uint32_t *count)
7000 union spoolss_JobInfo *info;
7001 int i;
7002 WERROR result = WERR_OK;
7004 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7005 W_ERROR_HAVE_NO_MEMORY(info);
7007 *count = num_queues;
7009 for (i=0; i<*count; i++) {
7010 struct spoolss_DeviceMode *devmode;
7012 result = spoolss_create_default_devmode(info,
7013 pinfo2->printername,
7014 &devmode);
7015 if (!W_ERROR_IS_OK(result)) {
7016 DEBUG(3, ("Can't proceed w/o a devmode!"));
7017 goto out;
7020 result = fill_job_info2(info,
7021 &info[i].info2,
7022 &queue[i],
7024 snum,
7025 pinfo2,
7026 devmode);
7027 if (!W_ERROR_IS_OK(result)) {
7028 goto out;
7032 out:
7033 if (!W_ERROR_IS_OK(result)) {
7034 TALLOC_FREE(info);
7035 *count = 0;
7036 return result;
7039 *info_p = info;
7041 return WERR_OK;
7044 /****************************************************************************
7045 Enumjobs at level 3.
7046 ****************************************************************************/
7048 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7049 const print_queue_struct *queue,
7050 uint32_t num_queues, int snum,
7051 struct spoolss_PrinterInfo2 *pinfo2,
7052 union spoolss_JobInfo **info_p,
7053 uint32_t *count)
7055 union spoolss_JobInfo *info;
7056 int i;
7057 WERROR result = WERR_OK;
7059 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7060 W_ERROR_HAVE_NO_MEMORY(info);
7062 *count = num_queues;
7064 for (i=0; i<*count; i++) {
7065 const print_queue_struct *next_queue = NULL;
7067 if (i+1 < *count) {
7068 next_queue = &queue[i+1];
7071 result = fill_job_info3(info,
7072 &info[i].info3,
7073 &queue[i],
7074 next_queue,
7076 snum,
7077 pinfo2);
7078 if (!W_ERROR_IS_OK(result)) {
7079 goto out;
7083 out:
7084 if (!W_ERROR_IS_OK(result)) {
7085 TALLOC_FREE(info);
7086 *count = 0;
7087 return result;
7090 *info_p = info;
7092 return WERR_OK;
7095 /****************************************************************
7096 _spoolss_EnumJobs
7097 ****************************************************************/
7099 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7100 struct spoolss_EnumJobs *r)
7102 WERROR result;
7103 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7104 int snum;
7105 print_status_struct prt_status;
7106 print_queue_struct *queue = NULL;
7107 uint32_t count;
7109 /* that's an [in out] buffer */
7111 if (!r->in.buffer && (r->in.offered != 0)) {
7112 return WERR_INVALID_PARAM;
7115 DEBUG(4,("_spoolss_EnumJobs\n"));
7117 *r->out.needed = 0;
7118 *r->out.count = 0;
7119 *r->out.info = NULL;
7121 /* lookup the printer snum and tdb entry */
7123 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7124 return WERR_BADFID;
7127 result = winreg_get_printer_internal(p->mem_ctx,
7128 get_session_info_system(),
7129 p->msg_ctx,
7130 lp_const_servicename(snum),
7131 &pinfo2);
7132 if (!W_ERROR_IS_OK(result)) {
7133 return result;
7136 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7137 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7138 count, prt_status.status, prt_status.message));
7140 if (count == 0) {
7141 SAFE_FREE(queue);
7142 TALLOC_FREE(pinfo2);
7143 return WERR_OK;
7146 switch (r->in.level) {
7147 case 1:
7148 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7149 pinfo2, r->out.info, r->out.count);
7150 break;
7151 case 2:
7152 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7153 pinfo2, r->out.info, r->out.count);
7154 break;
7155 case 3:
7156 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7157 pinfo2, r->out.info, r->out.count);
7158 break;
7159 default:
7160 result = WERR_UNKNOWN_LEVEL;
7161 break;
7164 SAFE_FREE(queue);
7165 TALLOC_FREE(pinfo2);
7167 if (!W_ERROR_IS_OK(result)) {
7168 return result;
7171 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7172 spoolss_EnumJobs,
7173 *r->out.info, r->in.level,
7174 *r->out.count);
7175 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7176 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7178 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7181 /****************************************************************
7182 _spoolss_ScheduleJob
7183 ****************************************************************/
7185 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7186 struct spoolss_ScheduleJob *r)
7188 return WERR_OK;
7191 /****************************************************************
7192 ****************************************************************/
7194 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7195 struct messaging_context *msg_ctx,
7196 const char *printer_name,
7197 uint32_t job_id,
7198 struct spoolss_SetJobInfo1 *r)
7200 char *old_doc_name;
7202 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7203 return WERR_BADFID;
7206 if (strequal(old_doc_name, r->document_name)) {
7207 return WERR_OK;
7210 if (!print_job_set_name(server_event_context(), msg_ctx,
7211 printer_name, job_id, r->document_name)) {
7212 return WERR_BADFID;
7215 return WERR_OK;
7218 /****************************************************************
7219 _spoolss_SetJob
7220 ****************************************************************/
7222 WERROR _spoolss_SetJob(struct pipes_struct *p,
7223 struct spoolss_SetJob *r)
7225 const struct auth_session_info *session_info = p->session_info;
7226 int snum;
7227 WERROR errcode = WERR_BADFUNC;
7229 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7230 return WERR_BADFID;
7233 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7234 return WERR_INVALID_PRINTER_NAME;
7237 switch (r->in.command) {
7238 case SPOOLSS_JOB_CONTROL_CANCEL:
7239 case SPOOLSS_JOB_CONTROL_DELETE:
7240 errcode = print_job_delete(session_info, p->msg_ctx,
7241 snum, r->in.job_id);
7242 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7243 errcode = WERR_OK;
7245 break;
7246 case SPOOLSS_JOB_CONTROL_PAUSE:
7247 if (print_job_pause(session_info, p->msg_ctx,
7248 snum, r->in.job_id, &errcode)) {
7249 errcode = WERR_OK;
7251 break;
7252 case SPOOLSS_JOB_CONTROL_RESTART:
7253 case SPOOLSS_JOB_CONTROL_RESUME:
7254 if (print_job_resume(session_info, p->msg_ctx,
7255 snum, r->in.job_id, &errcode)) {
7256 errcode = WERR_OK;
7258 break;
7259 case 0:
7260 errcode = WERR_OK;
7261 break;
7262 default:
7263 return WERR_UNKNOWN_LEVEL;
7266 if (!W_ERROR_IS_OK(errcode)) {
7267 return errcode;
7270 if (r->in.ctr == NULL) {
7271 return errcode;
7274 switch (r->in.ctr->level) {
7275 case 1:
7276 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7277 lp_const_servicename(snum),
7278 r->in.job_id,
7279 r->in.ctr->info.info1);
7280 break;
7281 case 2:
7282 case 3:
7283 case 4:
7284 default:
7285 return WERR_UNKNOWN_LEVEL;
7288 return errcode;
7291 /****************************************************************************
7292 Enumerates all printer drivers by level and architecture.
7293 ****************************************************************************/
7295 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7296 const struct auth_session_info *session_info,
7297 struct messaging_context *msg_ctx,
7298 const char *servername,
7299 const char *architecture,
7300 uint32_t level,
7301 union spoolss_DriverInfo **info_p,
7302 uint32_t *count_p)
7304 int i;
7305 uint32_t version;
7306 struct spoolss_DriverInfo8 *driver;
7307 union spoolss_DriverInfo *info = NULL;
7308 uint32_t count = 0;
7309 WERROR result = WERR_OK;
7310 uint32_t num_drivers;
7311 const char **drivers;
7312 struct dcerpc_binding_handle *b;
7313 TALLOC_CTX *tmp_ctx = NULL;
7315 *count_p = 0;
7316 *info_p = NULL;
7318 tmp_ctx = talloc_new(mem_ctx);
7319 if (!tmp_ctx) {
7320 return WERR_NOMEM;
7323 result = winreg_printer_binding_handle(tmp_ctx,
7324 session_info,
7325 msg_ctx,
7326 &b);
7327 if (!W_ERROR_IS_OK(result)) {
7328 goto out;
7331 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7332 result = winreg_get_driver_list(tmp_ctx, b,
7333 architecture, version,
7334 &num_drivers, &drivers);
7335 if (!W_ERROR_IS_OK(result)) {
7336 goto out;
7338 DEBUG(4, ("we have:[%d] drivers in environment"
7339 " [%s] and version [%d]\n",
7340 num_drivers, architecture, version));
7342 if (num_drivers != 0) {
7343 info = talloc_realloc(tmp_ctx, info,
7344 union spoolss_DriverInfo,
7345 count + num_drivers);
7346 if (!info) {
7347 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7348 "failed to enlarge driver info buffer!\n"));
7349 result = WERR_NOMEM;
7350 goto out;
7354 for (i = 0; i < num_drivers; i++) {
7355 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7357 result = winreg_get_driver(tmp_ctx, b,
7358 architecture, drivers[i],
7359 version, &driver);
7360 if (!W_ERROR_IS_OK(result)) {
7361 goto out;
7364 switch (level) {
7365 case 1:
7366 result = fill_printer_driver_info1(info, &info[count+i].info1,
7367 driver, servername);
7368 break;
7369 case 2:
7370 result = fill_printer_driver_info2(info, &info[count+i].info2,
7371 driver, servername);
7372 break;
7373 case 3:
7374 result = fill_printer_driver_info3(info, &info[count+i].info3,
7375 driver, servername);
7376 break;
7377 case 4:
7378 result = fill_printer_driver_info4(info, &info[count+i].info4,
7379 driver, servername);
7380 break;
7381 case 5:
7382 result = fill_printer_driver_info5(info, &info[count+i].info5,
7383 driver, servername);
7384 break;
7385 case 6:
7386 result = fill_printer_driver_info6(info, &info[count+i].info6,
7387 driver, servername);
7388 break;
7389 case 8:
7390 result = fill_printer_driver_info8(info, &info[count+i].info8,
7391 driver, servername);
7392 break;
7393 default:
7394 result = WERR_UNKNOWN_LEVEL;
7395 break;
7398 TALLOC_FREE(driver);
7400 if (!W_ERROR_IS_OK(result)) {
7401 goto out;
7405 count += num_drivers;
7406 TALLOC_FREE(drivers);
7409 out:
7410 if (W_ERROR_IS_OK(result)) {
7411 *info_p = talloc_move(mem_ctx, &info);
7412 *count_p = count;
7415 talloc_free(tmp_ctx);
7416 return result;
7419 /****************************************************************************
7420 Enumerates all printer drivers by level.
7421 ****************************************************************************/
7423 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7424 const struct auth_session_info *session_info,
7425 struct messaging_context *msg_ctx,
7426 const char *servername,
7427 const char *architecture,
7428 uint32_t level,
7429 union spoolss_DriverInfo **info_p,
7430 uint32_t *count_p)
7432 uint32_t a,i;
7433 WERROR result = WERR_OK;
7435 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7437 for (a=0; archi_table[a].long_archi != NULL; a++) {
7439 union spoolss_DriverInfo *info = NULL;
7440 uint32_t count = 0;
7442 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7443 session_info,
7444 msg_ctx,
7445 servername,
7446 archi_table[a].long_archi,
7447 level,
7448 &info,
7449 &count);
7450 if (!W_ERROR_IS_OK(result)) {
7451 continue;
7454 for (i=0; i < count; i++) {
7455 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7456 info[i], info_p, count_p);
7460 return result;
7463 return enumprinterdrivers_level_by_architecture(mem_ctx,
7464 session_info,
7465 msg_ctx,
7466 servername,
7467 architecture,
7468 level,
7469 info_p,
7470 count_p);
7473 /****************************************************************
7474 _spoolss_EnumPrinterDrivers
7475 ****************************************************************/
7477 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7478 struct spoolss_EnumPrinterDrivers *r)
7480 const char *cservername;
7481 WERROR result;
7483 /* that's an [in out] buffer */
7485 if (!r->in.buffer && (r->in.offered != 0)) {
7486 return WERR_INVALID_PARAM;
7489 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7491 *r->out.needed = 0;
7492 *r->out.count = 0;
7493 *r->out.info = NULL;
7495 cservername = canon_servername(r->in.server);
7497 if (!is_myname_or_ipaddr(cservername)) {
7498 return WERR_UNKNOWN_PRINTER_DRIVER;
7501 result = enumprinterdrivers_level(p->mem_ctx,
7502 get_session_info_system(),
7503 p->msg_ctx,
7504 cservername,
7505 r->in.environment,
7506 r->in.level,
7507 r->out.info,
7508 r->out.count);
7509 if (!W_ERROR_IS_OK(result)) {
7510 return result;
7513 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7514 spoolss_EnumPrinterDrivers,
7515 *r->out.info, r->in.level,
7516 *r->out.count);
7517 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7518 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7520 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7523 /****************************************************************
7524 _spoolss_EnumForms
7525 ****************************************************************/
7527 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7528 struct spoolss_EnumForms *r)
7530 WERROR result;
7532 *r->out.count = 0;
7533 *r->out.needed = 0;
7534 *r->out.info = NULL;
7536 /* that's an [in out] buffer */
7538 if (!r->in.buffer && (r->in.offered != 0) ) {
7539 return WERR_INVALID_PARAM;
7542 DEBUG(4,("_spoolss_EnumForms\n"));
7543 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7544 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7546 switch (r->in.level) {
7547 case 1:
7548 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7549 get_session_info_system(),
7550 p->msg_ctx,
7551 r->out.count,
7552 r->out.info);
7553 break;
7554 default:
7555 result = WERR_UNKNOWN_LEVEL;
7556 break;
7559 if (!W_ERROR_IS_OK(result)) {
7560 return result;
7563 if (*r->out.count == 0) {
7564 return WERR_NO_MORE_ITEMS;
7567 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7568 spoolss_EnumForms,
7569 *r->out.info, r->in.level,
7570 *r->out.count);
7571 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7572 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7574 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7577 /****************************************************************
7578 _spoolss_GetForm
7579 ****************************************************************/
7581 WERROR _spoolss_GetForm(struct pipes_struct *p,
7582 struct spoolss_GetForm *r)
7584 WERROR result;
7586 /* that's an [in out] buffer */
7588 if (!r->in.buffer && (r->in.offered != 0)) {
7589 return WERR_INVALID_PARAM;
7592 DEBUG(4,("_spoolss_GetForm\n"));
7593 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7594 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7596 switch (r->in.level) {
7597 case 1:
7598 result = winreg_printer_getform1_internal(p->mem_ctx,
7599 get_session_info_system(),
7600 p->msg_ctx,
7601 r->in.form_name,
7602 &r->out.info->info1);
7603 break;
7604 default:
7605 result = WERR_UNKNOWN_LEVEL;
7606 break;
7609 if (!W_ERROR_IS_OK(result)) {
7610 TALLOC_FREE(r->out.info);
7611 return result;
7614 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7615 r->out.info, r->in.level);
7616 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7618 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7621 /****************************************************************************
7622 ****************************************************************************/
7624 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7625 struct spoolss_PortInfo1 *r,
7626 const char *name)
7628 r->port_name = talloc_strdup(mem_ctx, name);
7629 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7631 return WERR_OK;
7634 /****************************************************************************
7635 TODO: This probably needs distinguish between TCP/IP and Local ports
7636 somehow.
7637 ****************************************************************************/
7639 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7640 struct spoolss_PortInfo2 *r,
7641 const char *name)
7643 r->port_name = talloc_strdup(mem_ctx, name);
7644 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7646 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7647 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7649 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7650 W_ERROR_HAVE_NO_MEMORY(r->description);
7652 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7653 r->reserved = 0;
7655 return WERR_OK;
7659 /****************************************************************************
7660 wrapper around the enumer ports command
7661 ****************************************************************************/
7663 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7665 char *cmd = lp_enumports_cmd();
7666 char **qlines = NULL;
7667 char *command = NULL;
7668 int numlines;
7669 int ret;
7670 int fd;
7672 *count = 0;
7673 *lines = NULL;
7675 /* if no hook then just fill in the default port */
7677 if ( !*cmd ) {
7678 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7679 return WERR_NOMEM;
7681 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7682 TALLOC_FREE(qlines);
7683 return WERR_NOMEM;
7685 qlines[1] = NULL;
7686 numlines = 1;
7688 else {
7689 /* we have a valid enumport command */
7691 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7692 if (!command) {
7693 return WERR_NOMEM;
7696 DEBUG(10,("Running [%s]\n", command));
7697 ret = smbrun(command, &fd);
7698 DEBUG(10,("Returned [%d]\n", ret));
7699 TALLOC_FREE(command);
7700 if (ret != 0) {
7701 if (fd != -1) {
7702 close(fd);
7704 return WERR_ACCESS_DENIED;
7707 numlines = 0;
7708 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7709 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7710 close(fd);
7713 *count = numlines;
7714 *lines = qlines;
7716 return WERR_OK;
7719 /****************************************************************************
7720 enumports level 1.
7721 ****************************************************************************/
7723 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7724 union spoolss_PortInfo **info_p,
7725 uint32_t *count)
7727 union spoolss_PortInfo *info = NULL;
7728 int i=0;
7729 WERROR result = WERR_OK;
7730 char **qlines = NULL;
7731 int numlines = 0;
7733 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7734 if (!W_ERROR_IS_OK(result)) {
7735 goto out;
7738 if (numlines) {
7739 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7740 if (!info) {
7741 DEBUG(10,("Returning WERR_NOMEM\n"));
7742 result = WERR_NOMEM;
7743 goto out;
7746 for (i=0; i<numlines; i++) {
7747 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7748 result = fill_port_1(info, &info[i].info1, qlines[i]);
7749 if (!W_ERROR_IS_OK(result)) {
7750 goto out;
7754 TALLOC_FREE(qlines);
7756 out:
7757 if (!W_ERROR_IS_OK(result)) {
7758 TALLOC_FREE(info);
7759 TALLOC_FREE(qlines);
7760 *count = 0;
7761 *info_p = NULL;
7762 return result;
7765 *info_p = info;
7766 *count = numlines;
7768 return WERR_OK;
7771 /****************************************************************************
7772 enumports level 2.
7773 ****************************************************************************/
7775 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7776 union spoolss_PortInfo **info_p,
7777 uint32_t *count)
7779 union spoolss_PortInfo *info = NULL;
7780 int i=0;
7781 WERROR result = WERR_OK;
7782 char **qlines = NULL;
7783 int numlines = 0;
7785 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7786 if (!W_ERROR_IS_OK(result)) {
7787 goto out;
7790 if (numlines) {
7791 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7792 if (!info) {
7793 DEBUG(10,("Returning WERR_NOMEM\n"));
7794 result = WERR_NOMEM;
7795 goto out;
7798 for (i=0; i<numlines; i++) {
7799 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7800 result = fill_port_2(info, &info[i].info2, qlines[i]);
7801 if (!W_ERROR_IS_OK(result)) {
7802 goto out;
7806 TALLOC_FREE(qlines);
7808 out:
7809 if (!W_ERROR_IS_OK(result)) {
7810 TALLOC_FREE(info);
7811 TALLOC_FREE(qlines);
7812 *count = 0;
7813 *info_p = NULL;
7814 return result;
7817 *info_p = info;
7818 *count = numlines;
7820 return WERR_OK;
7823 /****************************************************************
7824 _spoolss_EnumPorts
7825 ****************************************************************/
7827 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7828 struct spoolss_EnumPorts *r)
7830 WERROR result;
7832 /* that's an [in out] buffer */
7834 if (!r->in.buffer && (r->in.offered != 0)) {
7835 return WERR_INVALID_PARAM;
7838 DEBUG(4,("_spoolss_EnumPorts\n"));
7840 *r->out.count = 0;
7841 *r->out.needed = 0;
7842 *r->out.info = NULL;
7844 switch (r->in.level) {
7845 case 1:
7846 result = enumports_level_1(p->mem_ctx, r->out.info,
7847 r->out.count);
7848 break;
7849 case 2:
7850 result = enumports_level_2(p->mem_ctx, r->out.info,
7851 r->out.count);
7852 break;
7853 default:
7854 return WERR_UNKNOWN_LEVEL;
7857 if (!W_ERROR_IS_OK(result)) {
7858 return result;
7861 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7862 spoolss_EnumPorts,
7863 *r->out.info, r->in.level,
7864 *r->out.count);
7865 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7866 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7868 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7871 /****************************************************************************
7872 ****************************************************************************/
7874 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7875 const char *server,
7876 struct spoolss_SetPrinterInfoCtr *info_ctr,
7877 struct spoolss_DeviceMode *devmode,
7878 struct security_descriptor *secdesc,
7879 struct spoolss_UserLevelCtr *user_ctr,
7880 struct policy_handle *handle)
7882 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7883 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7884 int snum;
7885 WERROR err = WERR_OK;
7887 /* samba does not have a concept of local, non-shared printers yet, so
7888 * make sure we always setup sharename - gd */
7889 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7890 (info2->printername != NULL && info2->printername[0] != '\0')) {
7891 DEBUG(5, ("spoolss_addprinterex_level_2: "
7892 "no sharename has been set, setting printername %s as sharename\n",
7893 info2->printername));
7894 info2->sharename = info2->printername;
7897 /* check to see if the printer already exists */
7898 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7899 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7900 info2->sharename));
7901 return WERR_PRINTER_ALREADY_EXISTS;
7904 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7905 if ((snum = print_queue_snum(info2->printername)) != -1) {
7906 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7907 info2->printername));
7908 return WERR_PRINTER_ALREADY_EXISTS;
7912 /* validate printer info struct */
7913 if (!info2->printername || strlen(info2->printername) == 0) {
7914 return WERR_INVALID_PRINTER_NAME;
7916 if (!info2->portname || strlen(info2->portname) == 0) {
7917 return WERR_UNKNOWN_PORT;
7919 if (!info2->drivername || strlen(info2->drivername) == 0) {
7920 return WERR_UNKNOWN_PRINTER_DRIVER;
7922 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7923 return WERR_UNKNOWN_PRINTPROCESSOR;
7926 /* FIXME!!! smbd should check to see if the driver is installed before
7927 trying to add a printer like this --jerry */
7929 if (*lp_addprinter_cmd() ) {
7930 char *raddr;
7932 raddr = tsocket_address_inet_addr_string(p->remote_address,
7933 p->mem_ctx);
7934 if (raddr == NULL) {
7935 return WERR_NOMEM;
7938 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7939 info2, raddr,
7940 p->msg_ctx) ) {
7941 return WERR_ACCESS_DENIED;
7943 } else {
7944 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7945 "smb.conf parameter \"addprinter command\" is defined. This "
7946 "parameter must exist for this call to succeed\n",
7947 info2->sharename ));
7950 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7951 return WERR_ACCESS_DENIED;
7954 /* you must be a printer admin to add a new printer */
7955 if (!print_access_check(p->session_info,
7956 p->msg_ctx,
7957 snum,
7958 PRINTER_ACCESS_ADMINISTER)) {
7959 return WERR_ACCESS_DENIED;
7963 * Do sanity check on the requested changes for Samba.
7966 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7967 return WERR_INVALID_PARAM;
7970 if (devmode == NULL) {
7971 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7974 update_dsspooler(p->mem_ctx,
7975 get_session_info_system(),
7976 p->msg_ctx,
7978 info2,
7979 NULL);
7981 err = winreg_update_printer_internal(p->mem_ctx,
7982 get_session_info_system(),
7983 p->msg_ctx,
7984 info2->sharename,
7985 info2_mask,
7986 info2,
7987 devmode,
7988 secdesc);
7989 if (!W_ERROR_IS_OK(err)) {
7990 return err;
7993 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7994 if (!W_ERROR_IS_OK(err)) {
7995 /* Handle open failed - remove addition. */
7996 ZERO_STRUCTP(handle);
7997 return err;
8000 return WERR_OK;
8003 /****************************************************************
8004 _spoolss_AddPrinterEx
8005 ****************************************************************/
8007 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8008 struct spoolss_AddPrinterEx *r)
8010 switch (r->in.info_ctr->level) {
8011 case 1:
8012 /* we don't handle yet */
8013 /* but I know what to do ... */
8014 return WERR_UNKNOWN_LEVEL;
8015 case 2:
8016 return spoolss_addprinterex_level_2(p, r->in.server,
8017 r->in.info_ctr,
8018 r->in.devmode_ctr->devmode,
8019 r->in.secdesc_ctr->sd,
8020 r->in.userlevel_ctr,
8021 r->out.handle);
8022 default:
8023 return WERR_UNKNOWN_LEVEL;
8027 /****************************************************************
8028 _spoolss_AddPrinter
8029 ****************************************************************/
8031 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8032 struct spoolss_AddPrinter *r)
8034 struct spoolss_AddPrinterEx a;
8035 struct spoolss_UserLevelCtr userlevel_ctr;
8037 ZERO_STRUCT(userlevel_ctr);
8039 userlevel_ctr.level = 1;
8041 a.in.server = r->in.server;
8042 a.in.info_ctr = r->in.info_ctr;
8043 a.in.devmode_ctr = r->in.devmode_ctr;
8044 a.in.secdesc_ctr = r->in.secdesc_ctr;
8045 a.in.userlevel_ctr = &userlevel_ctr;
8046 a.out.handle = r->out.handle;
8048 return _spoolss_AddPrinterEx(p, &a);
8051 /****************************************************************
8052 _spoolss_AddPrinterDriverEx
8053 ****************************************************************/
8055 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8056 struct spoolss_AddPrinterDriverEx *r)
8058 WERROR err = WERR_OK;
8059 const char *driver_name = NULL;
8060 uint32_t version;
8061 const char *fn;
8063 switch (p->opnum) {
8064 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8065 fn = "_spoolss_AddPrinterDriver";
8066 break;
8067 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8068 fn = "_spoolss_AddPrinterDriverEx";
8069 break;
8070 default:
8071 return WERR_INVALID_PARAM;
8075 * we only support the semantics of AddPrinterDriver()
8076 * i.e. only copy files that are newer than existing ones
8079 if (r->in.flags == 0) {
8080 return WERR_INVALID_PARAM;
8083 if (r->in.flags != APD_COPY_NEW_FILES) {
8084 return WERR_ACCESS_DENIED;
8087 /* FIXME */
8088 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8089 /* Clever hack from Martin Zielinski <mz@seh.de>
8090 * to allow downgrade from level 8 (Vista).
8092 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8093 r->in.info_ctr->level));
8094 return WERR_UNKNOWN_LEVEL;
8097 DEBUG(5,("Cleaning driver's information\n"));
8098 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8099 if (!W_ERROR_IS_OK(err))
8100 goto done;
8102 DEBUG(5,("Moving driver to final destination\n"));
8103 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8104 if (!W_ERROR_IS_OK(err)) {
8105 goto done;
8108 err = winreg_add_driver_internal(p->mem_ctx,
8109 get_session_info_system(),
8110 p->msg_ctx,
8111 r->in.info_ctr,
8112 &driver_name,
8113 &version);
8114 if (!W_ERROR_IS_OK(err)) {
8115 goto done;
8119 * I think this is where he DrvUpgradePrinter() hook would be
8120 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8121 * server. Right now, we just need to send ourselves a message
8122 * to update each printer bound to this driver. --jerry
8125 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8126 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8127 fn, driver_name));
8130 done:
8131 return err;
8134 /****************************************************************
8135 _spoolss_AddPrinterDriver
8136 ****************************************************************/
8138 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8139 struct spoolss_AddPrinterDriver *r)
8141 struct spoolss_AddPrinterDriverEx a;
8143 switch (r->in.info_ctr->level) {
8144 case 2:
8145 case 3:
8146 case 4:
8147 case 5:
8148 break;
8149 default:
8150 return WERR_UNKNOWN_LEVEL;
8153 a.in.servername = r->in.servername;
8154 a.in.info_ctr = r->in.info_ctr;
8155 a.in.flags = APD_COPY_NEW_FILES;
8157 return _spoolss_AddPrinterDriverEx(p, &a);
8160 /****************************************************************************
8161 ****************************************************************************/
8163 struct _spoolss_paths {
8164 int type;
8165 const char *share;
8166 const char *dir;
8169 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8171 static const struct _spoolss_paths spoolss_paths[]= {
8172 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8173 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8176 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8177 const char *servername,
8178 const char *environment,
8179 int component,
8180 char **path)
8182 const char *pservername = NULL;
8183 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8184 const char *short_archi;
8186 *path = NULL;
8188 /* environment may be empty */
8189 if (environment && strlen(environment)) {
8190 long_archi = environment;
8193 /* servername may be empty */
8194 if (servername && strlen(servername)) {
8195 pservername = canon_servername(servername);
8197 if (!is_myname_or_ipaddr(pservername)) {
8198 return WERR_INVALID_PARAM;
8202 if (!(short_archi = get_short_archi(long_archi))) {
8203 return WERR_INVALID_ENVIRONMENT;
8206 switch (component) {
8207 case SPOOLSS_PRTPROCS_PATH:
8208 case SPOOLSS_DRIVER_PATH:
8209 if (pservername) {
8210 *path = talloc_asprintf(mem_ctx,
8211 "\\\\%s\\%s\\%s",
8212 pservername,
8213 spoolss_paths[component].share,
8214 short_archi);
8215 } else {
8216 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8217 SPOOLSS_DEFAULT_SERVER_PATH,
8218 spoolss_paths[component].dir,
8219 short_archi);
8221 break;
8222 default:
8223 return WERR_INVALID_PARAM;
8226 if (!*path) {
8227 return WERR_NOMEM;
8230 return WERR_OK;
8233 /****************************************************************************
8234 ****************************************************************************/
8236 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8237 const char *servername,
8238 const char *environment,
8239 struct spoolss_DriverDirectoryInfo1 *r)
8241 WERROR werr;
8242 char *path = NULL;
8244 werr = compose_spoolss_server_path(mem_ctx,
8245 servername,
8246 environment,
8247 SPOOLSS_DRIVER_PATH,
8248 &path);
8249 if (!W_ERROR_IS_OK(werr)) {
8250 return werr;
8253 DEBUG(4,("printer driver directory: [%s]\n", path));
8255 r->directory_name = path;
8257 return WERR_OK;
8260 /****************************************************************
8261 _spoolss_GetPrinterDriverDirectory
8262 ****************************************************************/
8264 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8265 struct spoolss_GetPrinterDriverDirectory *r)
8267 WERROR werror;
8269 /* that's an [in out] buffer */
8271 if (!r->in.buffer && (r->in.offered != 0)) {
8272 return WERR_INVALID_PARAM;
8275 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8276 r->in.level));
8278 *r->out.needed = 0;
8280 /* r->in.level is ignored */
8282 werror = getprinterdriverdir_level_1(p->mem_ctx,
8283 r->in.server,
8284 r->in.environment,
8285 &r->out.info->info1);
8286 if (!W_ERROR_IS_OK(werror)) {
8287 TALLOC_FREE(r->out.info);
8288 return werror;
8291 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8292 r->out.info, r->in.level);
8293 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8295 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8298 /****************************************************************
8299 _spoolss_EnumPrinterData
8300 ****************************************************************/
8302 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8303 struct spoolss_EnumPrinterData *r)
8305 WERROR result;
8306 struct spoolss_EnumPrinterDataEx r2;
8307 uint32_t count;
8308 struct spoolss_PrinterEnumValues *info, *val = NULL;
8309 uint32_t needed;
8311 r2.in.handle = r->in.handle;
8312 r2.in.key_name = "PrinterDriverData";
8313 r2.in.offered = 0;
8314 r2.out.count = &count;
8315 r2.out.info = &info;
8316 r2.out.needed = &needed;
8318 result = _spoolss_EnumPrinterDataEx(p, &r2);
8319 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8320 r2.in.offered = needed;
8321 result = _spoolss_EnumPrinterDataEx(p, &r2);
8323 if (!W_ERROR_IS_OK(result)) {
8324 return result;
8328 * The NT machine wants to know the biggest size of value and data
8330 * cf: MSDN EnumPrinterData remark section
8333 if (!r->in.value_offered && !r->in.data_offered) {
8334 uint32_t biggest_valuesize = 0;
8335 uint32_t biggest_datasize = 0;
8336 int i, name_length;
8338 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8340 for (i=0; i<count; i++) {
8342 name_length = strlen(info[i].value_name);
8343 if (strlen(info[i].value_name) > biggest_valuesize) {
8344 biggest_valuesize = name_length;
8347 if (info[i].data_length > biggest_datasize) {
8348 biggest_datasize = info[i].data_length;
8351 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8352 biggest_datasize));
8355 /* the value is an UNICODE string but real_value_size is the length
8356 in bytes including the trailing 0 */
8358 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8359 *r->out.data_needed = biggest_datasize;
8361 DEBUG(6,("final values: [%d], [%d]\n",
8362 *r->out.value_needed, *r->out.data_needed));
8364 return WERR_OK;
8367 if (r->in.enum_index < count) {
8368 val = &info[r->in.enum_index];
8371 if (val == NULL) {
8372 /* out_value should default to "" or else NT4 has
8373 problems unmarshalling the response */
8375 if (r->in.value_offered) {
8376 *r->out.value_needed = 1;
8377 r->out.value_name = talloc_strdup(r, "");
8378 if (!r->out.value_name) {
8379 return WERR_NOMEM;
8381 } else {
8382 r->out.value_name = NULL;
8383 *r->out.value_needed = 0;
8386 /* the data is counted in bytes */
8388 *r->out.data_needed = r->in.data_offered;
8390 result = WERR_NO_MORE_ITEMS;
8391 } else {
8393 * the value is:
8394 * - counted in bytes in the request
8395 * - counted in UNICODE chars in the max reply
8396 * - counted in bytes in the real size
8398 * take a pause *before* coding not *during* coding
8401 /* name */
8402 if (r->in.value_offered) {
8403 r->out.value_name = talloc_strdup(r, val->value_name);
8404 if (!r->out.value_name) {
8405 return WERR_NOMEM;
8407 *r->out.value_needed = val->value_name_len;
8408 } else {
8409 r->out.value_name = NULL;
8410 *r->out.value_needed = 0;
8413 /* type */
8415 *r->out.type = val->type;
8417 /* data - counted in bytes */
8420 * See the section "Dynamically Typed Query Parameters"
8421 * in MS-RPRN.
8424 if (r->out.data && val->data && val->data->data &&
8425 val->data_length && r->in.data_offered) {
8426 memcpy(r->out.data, val->data->data,
8427 MIN(val->data_length,r->in.data_offered));
8430 *r->out.data_needed = val->data_length;
8432 result = WERR_OK;
8435 return result;
8438 /****************************************************************
8439 _spoolss_SetPrinterData
8440 ****************************************************************/
8442 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8443 struct spoolss_SetPrinterData *r)
8445 struct spoolss_SetPrinterDataEx r2;
8447 r2.in.handle = r->in.handle;
8448 r2.in.key_name = "PrinterDriverData";
8449 r2.in.value_name = r->in.value_name;
8450 r2.in.type = r->in.type;
8451 r2.in.data = r->in.data;
8452 r2.in.offered = r->in.offered;
8454 return _spoolss_SetPrinterDataEx(p, &r2);
8457 /****************************************************************
8458 _spoolss_ResetPrinter
8459 ****************************************************************/
8461 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8462 struct spoolss_ResetPrinter *r)
8464 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8465 int snum;
8467 DEBUG(5,("_spoolss_ResetPrinter\n"));
8470 * All we do is to check to see if the handle and queue is valid.
8471 * This call really doesn't mean anything to us because we only
8472 * support RAW printing. --jerry
8475 if (!Printer) {
8476 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8477 OUR_HANDLE(r->in.handle)));
8478 return WERR_BADFID;
8481 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8482 return WERR_BADFID;
8485 /* blindly return success */
8486 return WERR_OK;
8489 /****************************************************************
8490 _spoolss_DeletePrinterData
8491 ****************************************************************/
8493 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8494 struct spoolss_DeletePrinterData *r)
8496 struct spoolss_DeletePrinterDataEx r2;
8498 r2.in.handle = r->in.handle;
8499 r2.in.key_name = "PrinterDriverData";
8500 r2.in.value_name = r->in.value_name;
8502 return _spoolss_DeletePrinterDataEx(p, &r2);
8505 /****************************************************************
8506 _spoolss_AddForm
8507 ****************************************************************/
8509 WERROR _spoolss_AddForm(struct pipes_struct *p,
8510 struct spoolss_AddForm *r)
8512 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8513 int snum = -1;
8514 WERROR status = WERR_OK;
8515 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8516 struct dcerpc_binding_handle *b;
8517 TALLOC_CTX *tmp_ctx = NULL;
8519 DEBUG(5,("_spoolss_AddForm\n"));
8521 if (!Printer) {
8522 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8523 OUR_HANDLE(r->in.handle)));
8524 return WERR_BADFID;
8527 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8528 and not a printer admin, then fail */
8530 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8531 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8532 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8533 p->session_info->info->domain_name,
8534 NULL,
8535 p->session_info->security_token,
8536 lp_printer_admin(snum))) {
8537 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8538 return WERR_ACCESS_DENIED;
8541 switch (form->flags) {
8542 case SPOOLSS_FORM_USER:
8543 case SPOOLSS_FORM_BUILTIN:
8544 case SPOOLSS_FORM_PRINTER:
8545 break;
8546 default:
8547 return WERR_INVALID_PARAM;
8550 tmp_ctx = talloc_new(p->mem_ctx);
8551 if (!tmp_ctx) {
8552 return WERR_NOMEM;
8555 status = winreg_printer_binding_handle(tmp_ctx,
8556 get_session_info_system(),
8557 p->msg_ctx,
8558 &b);
8559 if (!W_ERROR_IS_OK(status)) {
8560 goto done;
8563 status = winreg_printer_addform1(tmp_ctx, b, form);
8564 if (!W_ERROR_IS_OK(status)) {
8565 goto done;
8569 * ChangeID must always be set if this is a printer
8571 if (Printer->printer_type == SPLHND_PRINTER) {
8572 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8573 status = WERR_BADFID;
8574 goto done;
8577 status = winreg_printer_update_changeid(tmp_ctx, b,
8578 lp_const_servicename(snum));
8581 done:
8582 talloc_free(tmp_ctx);
8583 return status;
8586 /****************************************************************
8587 _spoolss_DeleteForm
8588 ****************************************************************/
8590 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8591 struct spoolss_DeleteForm *r)
8593 const char *form_name = r->in.form_name;
8594 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8595 int snum = -1;
8596 WERROR status = WERR_OK;
8597 struct dcerpc_binding_handle *b;
8598 TALLOC_CTX *tmp_ctx = NULL;
8600 DEBUG(5,("_spoolss_DeleteForm\n"));
8602 if (!Printer) {
8603 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8604 OUR_HANDLE(r->in.handle)));
8605 return WERR_BADFID;
8608 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8609 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8610 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8611 p->session_info->info->domain_name,
8612 NULL,
8613 p->session_info->security_token,
8614 lp_printer_admin(snum))) {
8615 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8616 return WERR_ACCESS_DENIED;
8619 tmp_ctx = talloc_new(p->mem_ctx);
8620 if (!tmp_ctx) {
8621 return WERR_NOMEM;
8624 status = winreg_printer_binding_handle(tmp_ctx,
8625 get_session_info_system(),
8626 p->msg_ctx,
8627 &b);
8628 if (!W_ERROR_IS_OK(status)) {
8629 goto done;
8632 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8633 if (!W_ERROR_IS_OK(status)) {
8634 goto done;
8638 * ChangeID must always be set if this is a printer
8640 if (Printer->printer_type == SPLHND_PRINTER) {
8641 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8642 status = WERR_BADFID;
8643 goto done;
8646 status = winreg_printer_update_changeid(tmp_ctx, b,
8647 lp_const_servicename(snum));
8650 done:
8651 talloc_free(tmp_ctx);
8652 return status;
8655 /****************************************************************
8656 _spoolss_SetForm
8657 ****************************************************************/
8659 WERROR _spoolss_SetForm(struct pipes_struct *p,
8660 struct spoolss_SetForm *r)
8662 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8663 const char *form_name = r->in.form_name;
8664 int snum = -1;
8665 WERROR status = WERR_OK;
8666 struct dcerpc_binding_handle *b;
8667 TALLOC_CTX *tmp_ctx = NULL;
8669 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8671 DEBUG(5,("_spoolss_SetForm\n"));
8673 if (!Printer) {
8674 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8675 OUR_HANDLE(r->in.handle)));
8676 return WERR_BADFID;
8679 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8680 and not a printer admin, then fail */
8682 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8683 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8684 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8685 p->session_info->info->domain_name,
8686 NULL,
8687 p->session_info->security_token,
8688 lp_printer_admin(snum))) {
8689 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8690 return WERR_ACCESS_DENIED;
8693 tmp_ctx = talloc_new(p->mem_ctx);
8694 if (!tmp_ctx) {
8695 return WERR_NOMEM;
8698 status = winreg_printer_binding_handle(tmp_ctx,
8699 get_session_info_system(),
8700 p->msg_ctx,
8701 &b);
8702 if (!W_ERROR_IS_OK(status)) {
8703 goto done;
8706 status = winreg_printer_setform1(tmp_ctx, b,
8707 form_name,
8708 form);
8709 if (!W_ERROR_IS_OK(status)) {
8710 goto done;
8714 * ChangeID must always be set if this is a printer
8716 if (Printer->printer_type == SPLHND_PRINTER) {
8717 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8718 status = WERR_BADFID;
8719 goto done;
8722 status = winreg_printer_update_changeid(tmp_ctx, b,
8723 lp_const_servicename(snum));
8726 done:
8727 talloc_free(tmp_ctx);
8728 return status;
8731 /****************************************************************************
8732 fill_print_processor1
8733 ****************************************************************************/
8735 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8736 struct spoolss_PrintProcessorInfo1 *r,
8737 const char *print_processor_name)
8739 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8740 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8742 return WERR_OK;
8745 /****************************************************************************
8746 enumprintprocessors level 1.
8747 ****************************************************************************/
8749 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8750 union spoolss_PrintProcessorInfo **info_p,
8751 uint32_t *count)
8753 union spoolss_PrintProcessorInfo *info;
8754 WERROR result;
8756 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8757 W_ERROR_HAVE_NO_MEMORY(info);
8759 *count = 1;
8761 result = fill_print_processor1(info, &info[0].info1, "winprint");
8762 if (!W_ERROR_IS_OK(result)) {
8763 goto out;
8766 out:
8767 if (!W_ERROR_IS_OK(result)) {
8768 TALLOC_FREE(info);
8769 *count = 0;
8770 return result;
8773 *info_p = info;
8775 return WERR_OK;
8778 /****************************************************************
8779 _spoolss_EnumPrintProcessors
8780 ****************************************************************/
8782 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8783 struct spoolss_EnumPrintProcessors *r)
8785 WERROR result;
8787 /* that's an [in out] buffer */
8789 if (!r->in.buffer && (r->in.offered != 0)) {
8790 return WERR_INVALID_PARAM;
8793 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8796 * Enumerate the print processors ...
8798 * Just reply with "winprint", to keep NT happy
8799 * and I can use my nice printer checker.
8802 *r->out.count = 0;
8803 *r->out.needed = 0;
8804 *r->out.info = NULL;
8806 if (!get_short_archi(r->in.environment)) {
8807 return WERR_INVALID_ENVIRONMENT;
8810 switch (r->in.level) {
8811 case 1:
8812 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8813 r->out.count);
8814 break;
8815 default:
8816 return WERR_UNKNOWN_LEVEL;
8819 if (!W_ERROR_IS_OK(result)) {
8820 return result;
8823 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8824 spoolss_EnumPrintProcessors,
8825 *r->out.info, r->in.level,
8826 *r->out.count);
8827 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8828 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8830 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8833 /****************************************************************************
8834 fill_printprocdatatype1
8835 ****************************************************************************/
8837 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8838 struct spoolss_PrintProcDataTypesInfo1 *r,
8839 const char *name_array)
8841 r->name_array = talloc_strdup(mem_ctx, name_array);
8842 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8844 return WERR_OK;
8847 /****************************************************************************
8848 enumprintprocdatatypes level 1.
8849 ****************************************************************************/
8851 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8852 union spoolss_PrintProcDataTypesInfo **info_p,
8853 uint32_t *count)
8855 WERROR result;
8856 union spoolss_PrintProcDataTypesInfo *info;
8858 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8859 W_ERROR_HAVE_NO_MEMORY(info);
8861 *count = 1;
8863 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8864 if (!W_ERROR_IS_OK(result)) {
8865 goto out;
8868 out:
8869 if (!W_ERROR_IS_OK(result)) {
8870 TALLOC_FREE(info);
8871 *count = 0;
8872 return result;
8875 *info_p = info;
8877 return WERR_OK;
8880 /****************************************************************
8881 _spoolss_EnumPrintProcDataTypes
8882 ****************************************************************/
8884 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8885 struct spoolss_EnumPrintProcDataTypes *r)
8887 WERROR result;
8889 /* that's an [in out] buffer */
8891 if (!r->in.buffer && (r->in.offered != 0)) {
8892 return WERR_INVALID_PARAM;
8895 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8897 *r->out.count = 0;
8898 *r->out.needed = 0;
8899 *r->out.info = NULL;
8901 if (r->in.print_processor_name == NULL ||
8902 !strequal(r->in.print_processor_name, "winprint")) {
8903 return WERR_UNKNOWN_PRINTPROCESSOR;
8906 switch (r->in.level) {
8907 case 1:
8908 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8909 r->out.count);
8910 break;
8911 default:
8912 return WERR_UNKNOWN_LEVEL;
8915 if (!W_ERROR_IS_OK(result)) {
8916 return result;
8919 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8920 spoolss_EnumPrintProcDataTypes,
8921 *r->out.info, r->in.level,
8922 *r->out.count);
8923 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8924 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8926 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8929 /****************************************************************************
8930 fill_monitor_1
8931 ****************************************************************************/
8933 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8934 struct spoolss_MonitorInfo1 *r,
8935 const char *monitor_name)
8937 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8938 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8940 return WERR_OK;
8943 /****************************************************************************
8944 fill_monitor_2
8945 ****************************************************************************/
8947 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8948 struct spoolss_MonitorInfo2 *r,
8949 const char *monitor_name,
8950 const char *environment,
8951 const char *dll_name)
8953 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8954 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8955 r->environment = talloc_strdup(mem_ctx, environment);
8956 W_ERROR_HAVE_NO_MEMORY(r->environment);
8957 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8958 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8960 return WERR_OK;
8963 /****************************************************************************
8964 enumprintmonitors level 1.
8965 ****************************************************************************/
8967 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8968 union spoolss_MonitorInfo **info_p,
8969 uint32_t *count)
8971 union spoolss_MonitorInfo *info;
8972 WERROR result = WERR_OK;
8974 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
8975 W_ERROR_HAVE_NO_MEMORY(info);
8977 *count = 2;
8979 result = fill_monitor_1(info, &info[0].info1,
8980 SPL_LOCAL_PORT);
8981 if (!W_ERROR_IS_OK(result)) {
8982 goto out;
8985 result = fill_monitor_1(info, &info[1].info1,
8986 SPL_TCPIP_PORT);
8987 if (!W_ERROR_IS_OK(result)) {
8988 goto out;
8991 out:
8992 if (!W_ERROR_IS_OK(result)) {
8993 TALLOC_FREE(info);
8994 *count = 0;
8995 return result;
8998 *info_p = info;
9000 return WERR_OK;
9003 /****************************************************************************
9004 enumprintmonitors level 2.
9005 ****************************************************************************/
9007 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9008 union spoolss_MonitorInfo **info_p,
9009 uint32_t *count)
9011 union spoolss_MonitorInfo *info;
9012 WERROR result = WERR_OK;
9014 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9015 W_ERROR_HAVE_NO_MEMORY(info);
9017 *count = 2;
9019 result = fill_monitor_2(info, &info[0].info2,
9020 SPL_LOCAL_PORT,
9021 "Windows NT X86", /* FIXME */
9022 "localmon.dll");
9023 if (!W_ERROR_IS_OK(result)) {
9024 goto out;
9027 result = fill_monitor_2(info, &info[1].info2,
9028 SPL_TCPIP_PORT,
9029 "Windows NT X86", /* FIXME */
9030 "tcpmon.dll");
9031 if (!W_ERROR_IS_OK(result)) {
9032 goto out;
9035 out:
9036 if (!W_ERROR_IS_OK(result)) {
9037 TALLOC_FREE(info);
9038 *count = 0;
9039 return result;
9042 *info_p = info;
9044 return WERR_OK;
9047 /****************************************************************
9048 _spoolss_EnumMonitors
9049 ****************************************************************/
9051 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9052 struct spoolss_EnumMonitors *r)
9054 WERROR result;
9056 /* that's an [in out] buffer */
9058 if (!r->in.buffer && (r->in.offered != 0)) {
9059 return WERR_INVALID_PARAM;
9062 DEBUG(5,("_spoolss_EnumMonitors\n"));
9065 * Enumerate the print monitors ...
9067 * Just reply with "Local Port", to keep NT happy
9068 * and I can use my nice printer checker.
9071 *r->out.count = 0;
9072 *r->out.needed = 0;
9073 *r->out.info = NULL;
9075 switch (r->in.level) {
9076 case 1:
9077 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9078 r->out.count);
9079 break;
9080 case 2:
9081 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9082 r->out.count);
9083 break;
9084 default:
9085 return WERR_UNKNOWN_LEVEL;
9088 if (!W_ERROR_IS_OK(result)) {
9089 return result;
9092 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9093 spoolss_EnumMonitors,
9094 *r->out.info, r->in.level,
9095 *r->out.count);
9096 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9097 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9099 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9102 /****************************************************************************
9103 ****************************************************************************/
9105 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9106 const print_queue_struct *queue,
9107 int count, int snum,
9108 struct spoolss_PrinterInfo2 *pinfo2,
9109 uint32_t jobid,
9110 struct spoolss_JobInfo1 *r)
9112 int i = 0;
9113 bool found = false;
9115 for (i=0; i<count; i++) {
9116 if (queue[i].job == (int)jobid) {
9117 found = true;
9118 break;
9122 if (found == false) {
9123 /* NT treats not found as bad param... yet another bad choice */
9124 return WERR_INVALID_PARAM;
9127 return fill_job_info1(mem_ctx,
9129 &queue[i],
9131 snum,
9132 pinfo2);
9135 /****************************************************************************
9136 ****************************************************************************/
9138 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9139 const print_queue_struct *queue,
9140 int count, int snum,
9141 struct spoolss_PrinterInfo2 *pinfo2,
9142 uint32_t jobid,
9143 struct spoolss_JobInfo2 *r)
9145 int i = 0;
9146 bool found = false;
9147 struct spoolss_DeviceMode *devmode;
9148 WERROR result;
9150 for (i=0; i<count; i++) {
9151 if (queue[i].job == (int)jobid) {
9152 found = true;
9153 break;
9157 if (found == false) {
9158 /* NT treats not found as bad param... yet another bad
9159 choice */
9160 return WERR_INVALID_PARAM;
9164 * if the print job does not have a DEVMODE associated with it,
9165 * just use the one for the printer. A NULL devicemode is not
9166 * a failure condition
9169 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9170 if (!devmode) {
9171 result = spoolss_create_default_devmode(mem_ctx,
9172 pinfo2->printername,
9173 &devmode);
9174 if (!W_ERROR_IS_OK(result)) {
9175 DEBUG(3, ("Can't proceed w/o a devmode!"));
9176 return result;
9180 return fill_job_info2(mem_ctx,
9182 &queue[i],
9184 snum,
9185 pinfo2,
9186 devmode);
9189 /****************************************************************
9190 _spoolss_GetJob
9191 ****************************************************************/
9193 WERROR _spoolss_GetJob(struct pipes_struct *p,
9194 struct spoolss_GetJob *r)
9196 WERROR result = WERR_OK;
9197 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9198 int snum;
9199 int count;
9200 print_queue_struct *queue = NULL;
9201 print_status_struct prt_status;
9203 /* that's an [in out] buffer */
9205 if (!r->in.buffer && (r->in.offered != 0)) {
9206 return WERR_INVALID_PARAM;
9209 DEBUG(5,("_spoolss_GetJob\n"));
9211 *r->out.needed = 0;
9213 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9214 return WERR_BADFID;
9217 result = winreg_get_printer_internal(p->mem_ctx,
9218 get_session_info_system(),
9219 p->msg_ctx,
9220 lp_const_servicename(snum),
9221 &pinfo2);
9222 if (!W_ERROR_IS_OK(result)) {
9223 return result;
9226 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9228 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9229 count, prt_status.status, prt_status.message));
9231 switch (r->in.level) {
9232 case 1:
9233 result = getjob_level_1(p->mem_ctx,
9234 queue, count, snum, pinfo2,
9235 r->in.job_id, &r->out.info->info1);
9236 break;
9237 case 2:
9238 result = getjob_level_2(p->mem_ctx,
9239 queue, count, snum, pinfo2,
9240 r->in.job_id, &r->out.info->info2);
9241 break;
9242 default:
9243 result = WERR_UNKNOWN_LEVEL;
9244 break;
9247 SAFE_FREE(queue);
9248 TALLOC_FREE(pinfo2);
9250 if (!W_ERROR_IS_OK(result)) {
9251 TALLOC_FREE(r->out.info);
9252 return result;
9255 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9256 r->in.level);
9257 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9259 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9262 /****************************************************************
9263 _spoolss_GetPrinterDataEx
9264 ****************************************************************/
9266 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9267 struct spoolss_GetPrinterDataEx *r)
9270 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9271 const char *printer;
9272 int snum = 0;
9273 WERROR result = WERR_OK;
9274 DATA_BLOB blob;
9275 enum winreg_Type val_type = REG_NONE;
9276 uint8_t *val_data = NULL;
9277 uint32_t val_size = 0;
9278 struct dcerpc_binding_handle *b;
9279 TALLOC_CTX *tmp_ctx;
9281 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9283 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9284 r->in.key_name, r->in.value_name));
9286 /* in case of problem, return some default values */
9288 *r->out.needed = 0;
9289 *r->out.type = REG_NONE;
9291 tmp_ctx = talloc_new(p->mem_ctx);
9292 if (!tmp_ctx) {
9293 return WERR_NOMEM;
9296 if (!Printer) {
9297 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9298 OUR_HANDLE(r->in.handle)));
9299 result = WERR_BADFID;
9300 goto done;
9303 /* check to see if the keyname is valid */
9304 if (!strlen(r->in.key_name)) {
9305 result = WERR_INVALID_PARAM;
9306 goto done;
9309 /* Is the handle to a printer or to the server? */
9311 if (Printer->printer_type == SPLHND_SERVER) {
9313 union spoolss_PrinterData data;
9315 result = getprinterdata_printer_server(tmp_ctx,
9316 r->in.value_name,
9317 r->out.type,
9318 &data);
9319 if (!W_ERROR_IS_OK(result)) {
9320 goto done;
9323 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9324 *r->out.type, &data);
9325 if (!W_ERROR_IS_OK(result)) {
9326 goto done;
9329 *r->out.needed = blob.length;
9331 if (r->in.offered >= *r->out.needed) {
9332 memcpy(r->out.data, blob.data, blob.length);
9335 result = WERR_OK;
9336 goto done;
9339 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9340 result = WERR_BADFID;
9341 goto done;
9343 printer = lp_const_servicename(snum);
9345 result = winreg_printer_binding_handle(tmp_ctx,
9346 get_session_info_system(),
9347 p->msg_ctx,
9348 &b);
9349 if (!W_ERROR_IS_OK(result)) {
9350 goto done;
9353 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9354 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9355 strequal(r->in.value_name, "ChangeId")) {
9356 *r->out.type = REG_DWORD;
9357 *r->out.needed = 4;
9358 if (r->in.offered >= *r->out.needed) {
9359 uint32_t changeid = 0;
9361 result = winreg_printer_get_changeid(tmp_ctx, b,
9362 printer,
9363 &changeid);
9364 if (!W_ERROR_IS_OK(result)) {
9365 goto done;
9368 SIVAL(r->out.data, 0, changeid);
9369 result = WERR_OK;
9371 goto done;
9374 result = winreg_get_printer_dataex(tmp_ctx, b,
9375 printer,
9376 r->in.key_name,
9377 r->in.value_name,
9378 &val_type,
9379 &val_data,
9380 &val_size);
9381 if (!W_ERROR_IS_OK(result)) {
9382 goto done;
9385 *r->out.needed = val_size;
9386 *r->out.type = val_type;
9388 if (r->in.offered >= *r->out.needed) {
9389 memcpy(r->out.data, val_data, val_size);
9392 done:
9393 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9395 if (W_ERROR_IS_OK(result)) {
9396 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9399 talloc_free(tmp_ctx);
9400 return result;
9403 /****************************************************************
9404 _spoolss_SetPrinterDataEx
9405 ****************************************************************/
9407 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9408 struct spoolss_SetPrinterDataEx *r)
9410 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9411 int snum = 0;
9412 WERROR result = WERR_OK;
9413 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9414 char *oid_string;
9415 struct dcerpc_binding_handle *b;
9416 TALLOC_CTX *tmp_ctx;
9418 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9420 /* From MSDN documentation of SetPrinterDataEx: pass request to
9421 SetPrinterData if key is "PrinterDriverData" */
9423 if (!Printer) {
9424 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9425 OUR_HANDLE(r->in.handle)));
9426 return WERR_BADFID;
9429 if (Printer->printer_type == SPLHND_SERVER) {
9430 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9431 "Not implemented for server handles yet\n"));
9432 return WERR_INVALID_PARAM;
9435 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9436 return WERR_BADFID;
9440 * Access check : NT returns "access denied" if you make a
9441 * SetPrinterData call without the necessary privildge.
9442 * we were originally returning OK if nothing changed
9443 * which made Win2k issue **a lot** of SetPrinterData
9444 * when connecting to a printer --jerry
9447 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9448 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9449 "change denied by handle access permissions\n"));
9450 return WERR_ACCESS_DENIED;
9453 tmp_ctx = talloc_new(p->mem_ctx);
9454 if (!tmp_ctx) {
9455 return WERR_NOMEM;
9458 result = winreg_printer_binding_handle(tmp_ctx,
9459 get_session_info_system(),
9460 p->msg_ctx,
9461 &b);
9462 if (!W_ERROR_IS_OK(result)) {
9463 goto done;
9466 result = winreg_get_printer(tmp_ctx, b,
9467 lp_servicename(snum),
9468 &pinfo2);
9469 if (!W_ERROR_IS_OK(result)) {
9470 goto done;
9473 /* check for OID in valuename */
9475 oid_string = strchr(r->in.value_name, ',');
9476 if (oid_string) {
9477 *oid_string = '\0';
9478 oid_string++;
9481 /* save the registry data */
9483 result = winreg_set_printer_dataex(tmp_ctx, b,
9484 pinfo2->sharename,
9485 r->in.key_name,
9486 r->in.value_name,
9487 r->in.type,
9488 r->in.data,
9489 r->in.offered);
9491 if (W_ERROR_IS_OK(result)) {
9492 /* save the OID if one was specified */
9493 if (oid_string) {
9494 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9495 r->in.key_name, SPOOL_OID_KEY);
9496 if (!str) {
9497 result = WERR_NOMEM;
9498 goto done;
9502 * I'm not checking the status here on purpose. Don't know
9503 * if this is right, but I'm returning the status from the
9504 * previous set_printer_dataex() call. I have no idea if
9505 * this is right. --jerry
9507 winreg_set_printer_dataex(tmp_ctx, b,
9508 pinfo2->sharename,
9509 str,
9510 r->in.value_name,
9511 REG_SZ,
9512 (uint8_t *) oid_string,
9513 strlen(oid_string) + 1);
9516 result = winreg_printer_update_changeid(tmp_ctx, b,
9517 lp_const_servicename(snum));
9521 done:
9522 talloc_free(tmp_ctx);
9523 return result;
9526 /****************************************************************
9527 _spoolss_DeletePrinterDataEx
9528 ****************************************************************/
9530 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9531 struct spoolss_DeletePrinterDataEx *r)
9533 const char *printer;
9534 int snum=0;
9535 WERROR status = WERR_OK;
9536 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9538 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9540 if (!Printer) {
9541 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9542 "Invalid handle (%s:%u:%u).\n",
9543 OUR_HANDLE(r->in.handle)));
9544 return WERR_BADFID;
9547 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9548 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9549 "printer properties change denied by handle\n"));
9550 return WERR_ACCESS_DENIED;
9553 if (!r->in.value_name || !r->in.key_name) {
9554 return WERR_NOMEM;
9557 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9558 return WERR_BADFID;
9560 printer = lp_const_servicename(snum);
9562 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9563 get_session_info_system(),
9564 p->msg_ctx,
9565 printer,
9566 r->in.key_name,
9567 r->in.value_name);
9568 if (W_ERROR_IS_OK(status)) {
9569 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9570 get_session_info_system(),
9571 p->msg_ctx,
9572 printer);
9575 return status;
9578 /****************************************************************
9579 _spoolss_EnumPrinterKey
9580 ****************************************************************/
9582 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9583 struct spoolss_EnumPrinterKey *r)
9585 uint32_t num_keys;
9586 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9587 int snum = 0;
9588 WERROR result = WERR_BADFILE;
9589 const char **array = NULL;
9590 DATA_BLOB blob;
9592 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9594 if (!Printer) {
9595 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9596 OUR_HANDLE(r->in.handle)));
9597 return WERR_BADFID;
9600 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9601 return WERR_BADFID;
9604 result = winreg_enum_printer_key_internal(p->mem_ctx,
9605 get_session_info_system(),
9606 p->msg_ctx,
9607 lp_const_servicename(snum),
9608 r->in.key_name,
9609 &num_keys,
9610 &array);
9611 if (!W_ERROR_IS_OK(result)) {
9612 goto done;
9615 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9616 result = WERR_NOMEM;
9617 goto done;
9620 *r->out._ndr_size = r->in.offered / 2;
9621 *r->out.needed = blob.length;
9623 if (r->in.offered < *r->out.needed) {
9624 result = WERR_MORE_DATA;
9625 } else {
9626 result = WERR_OK;
9627 r->out.key_buffer->string_array = array;
9630 done:
9631 if (!W_ERROR_IS_OK(result)) {
9632 TALLOC_FREE(array);
9633 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9634 *r->out.needed = 0;
9638 return result;
9641 /****************************************************************
9642 _spoolss_DeletePrinterKey
9643 ****************************************************************/
9645 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9646 struct spoolss_DeletePrinterKey *r)
9648 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9649 int snum=0;
9650 WERROR status;
9651 const char *printer;
9652 struct dcerpc_binding_handle *b;
9653 TALLOC_CTX *tmp_ctx;
9655 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9657 if (!Printer) {
9658 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9659 OUR_HANDLE(r->in.handle)));
9660 return WERR_BADFID;
9663 /* if keyname == NULL, return error */
9664 if ( !r->in.key_name )
9665 return WERR_INVALID_PARAM;
9667 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9668 return WERR_BADFID;
9671 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9672 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9673 "printer properties change denied by handle\n"));
9674 return WERR_ACCESS_DENIED;
9677 printer = lp_const_servicename(snum);
9679 tmp_ctx = talloc_new(p->mem_ctx);
9680 if (!tmp_ctx) {
9681 return WERR_NOMEM;
9684 status = winreg_printer_binding_handle(tmp_ctx,
9685 get_session_info_system(),
9686 p->msg_ctx,
9687 &b);
9688 if (!W_ERROR_IS_OK(status)) {
9689 goto done;
9692 /* delete the key and all subkeys */
9693 status = winreg_delete_printer_key(tmp_ctx, b,
9694 printer,
9695 r->in.key_name);
9696 if (W_ERROR_IS_OK(status)) {
9697 status = winreg_printer_update_changeid(tmp_ctx, b,
9698 printer);
9701 done:
9702 talloc_free(tmp_ctx);
9703 return status;
9706 /****************************************************************
9707 _spoolss_EnumPrinterDataEx
9708 ****************************************************************/
9710 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9711 struct spoolss_EnumPrinterDataEx *r)
9713 uint32_t count = 0;
9714 struct spoolss_PrinterEnumValues *info = NULL;
9715 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9716 int snum;
9717 WERROR result;
9719 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9721 *r->out.count = 0;
9722 *r->out.needed = 0;
9723 *r->out.info = NULL;
9725 if (!Printer) {
9726 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9727 OUR_HANDLE(r->in.handle)));
9728 return WERR_BADFID;
9732 * first check for a keyname of NULL or "". Win2k seems to send
9733 * this a lot and we should send back WERR_INVALID_PARAM
9734 * no need to spend time looking up the printer in this case.
9735 * --jerry
9738 if (!strlen(r->in.key_name)) {
9739 result = WERR_INVALID_PARAM;
9740 goto done;
9743 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9744 return WERR_BADFID;
9747 /* now look for a match on the key name */
9748 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9749 get_session_info_system(),
9750 p->msg_ctx,
9751 lp_const_servicename(snum),
9752 r->in.key_name,
9753 &count,
9754 &info);
9755 if (!W_ERROR_IS_OK(result)) {
9756 goto done;
9759 #if 0 /* FIXME - gd */
9760 /* housekeeping information in the reply */
9762 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9763 * the hand marshalled container size is a multiple
9764 * of 4 bytes for RPC alignment.
9767 if (needed % 4) {
9768 needed += 4-(needed % 4);
9770 #endif
9771 *r->out.count = count;
9772 *r->out.info = info;
9774 done:
9775 if (!W_ERROR_IS_OK(result)) {
9776 return result;
9779 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9780 spoolss_EnumPrinterDataEx,
9781 *r->out.info,
9782 *r->out.count);
9783 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9784 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9786 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9789 /****************************************************************************
9790 ****************************************************************************/
9792 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9793 const char *servername,
9794 const char *environment,
9795 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9797 WERROR werr;
9798 char *path = NULL;
9800 werr = compose_spoolss_server_path(mem_ctx,
9801 servername,
9802 environment,
9803 SPOOLSS_PRTPROCS_PATH,
9804 &path);
9805 if (!W_ERROR_IS_OK(werr)) {
9806 return werr;
9809 DEBUG(4,("print processor directory: [%s]\n", path));
9811 r->directory_name = path;
9813 return WERR_OK;
9816 /****************************************************************
9817 _spoolss_GetPrintProcessorDirectory
9818 ****************************************************************/
9820 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9821 struct spoolss_GetPrintProcessorDirectory *r)
9823 WERROR result;
9824 char *prnproc_share = NULL;
9825 bool prnproc_share_exists = false;
9826 int snum;
9828 /* that's an [in out] buffer */
9830 if (!r->in.buffer && (r->in.offered != 0)) {
9831 return WERR_INVALID_PARAM;
9834 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9835 r->in.level));
9837 *r->out.needed = 0;
9839 /* r->in.level is ignored */
9841 /* We always should reply with a local print processor directory so that
9842 * users are not forced to have a [prnproc$] share on the Samba spoolss
9843 * server, if users decide to do so, lets announce it though - Guenther */
9845 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9846 if (!prnproc_share) {
9847 return WERR_NOMEM;
9849 if (snum != -1) {
9850 prnproc_share_exists = true;
9853 result = getprintprocessordirectory_level_1(p->mem_ctx,
9854 prnproc_share_exists ? r->in.server : NULL,
9855 r->in.environment,
9856 &r->out.info->info1);
9857 if (!W_ERROR_IS_OK(result)) {
9858 TALLOC_FREE(r->out.info);
9859 return result;
9862 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9863 r->out.info, r->in.level);
9864 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9866 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9869 /*******************************************************************
9870 ********************************************************************/
9872 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9873 const char *dllname)
9875 enum ndr_err_code ndr_err;
9876 struct spoolss_MonitorUi ui;
9878 ui.dll_name = dllname;
9880 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9881 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9882 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9883 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9885 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9888 /*******************************************************************
9889 Streams the monitor UI DLL name in UNICODE
9890 *******************************************************************/
9892 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9893 struct security_token *token, DATA_BLOB *in,
9894 DATA_BLOB *out, uint32_t *needed)
9896 const char *dllname = "tcpmonui.dll";
9898 *needed = (strlen(dllname)+1) * 2;
9900 if (out->length < *needed) {
9901 return WERR_INSUFFICIENT_BUFFER;
9904 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9905 return WERR_NOMEM;
9908 return WERR_OK;
9911 /*******************************************************************
9912 ********************************************************************/
9914 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9915 struct spoolss_PortData1 *port1,
9916 const DATA_BLOB *buf)
9918 enum ndr_err_code ndr_err;
9919 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9920 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9921 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9922 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9924 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9927 /*******************************************************************
9928 ********************************************************************/
9930 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9931 struct spoolss_PortData2 *port2,
9932 const DATA_BLOB *buf)
9934 enum ndr_err_code ndr_err;
9935 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9936 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9937 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9938 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9940 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9943 /*******************************************************************
9944 Create a new TCP/IP port
9945 *******************************************************************/
9947 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9948 struct security_token *token, DATA_BLOB *in,
9949 DATA_BLOB *out, uint32_t *needed)
9951 struct spoolss_PortData1 port1;
9952 struct spoolss_PortData2 port2;
9953 char *device_uri = NULL;
9954 uint32_t version;
9956 const char *portname;
9957 const char *hostaddress;
9958 const char *queue;
9959 uint32_t port_number;
9960 uint32_t protocol;
9962 /* peek for spoolss_PortData version */
9964 if (!in || (in->length < (128 + 4))) {
9965 return WERR_GENERAL_FAILURE;
9968 version = IVAL(in->data, 128);
9970 switch (version) {
9971 case 1:
9972 ZERO_STRUCT(port1);
9974 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9975 return WERR_NOMEM;
9978 portname = port1.portname;
9979 hostaddress = port1.hostaddress;
9980 queue = port1.queue;
9981 protocol = port1.protocol;
9982 port_number = port1.port_number;
9984 break;
9985 case 2:
9986 ZERO_STRUCT(port2);
9988 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9989 return WERR_NOMEM;
9992 portname = port2.portname;
9993 hostaddress = port2.hostaddress;
9994 queue = port2.queue;
9995 protocol = port2.protocol;
9996 port_number = port2.port_number;
9998 break;
9999 default:
10000 DEBUG(1,("xcvtcp_addport: "
10001 "unknown version of port_data: %d\n", version));
10002 return WERR_UNKNOWN_PORT;
10005 /* create the device URI and call the add_port_hook() */
10007 switch (protocol) {
10008 case PROTOCOL_RAWTCP_TYPE:
10009 device_uri = talloc_asprintf(mem_ctx,
10010 "socket://%s:%d/", hostaddress,
10011 port_number);
10012 break;
10014 case PROTOCOL_LPR_TYPE:
10015 device_uri = talloc_asprintf(mem_ctx,
10016 "lpr://%s/%s", hostaddress, queue );
10017 break;
10019 default:
10020 return WERR_UNKNOWN_PORT;
10023 if (!device_uri) {
10024 return WERR_NOMEM;
10027 return add_port_hook(mem_ctx, token, portname, device_uri);
10030 /*******************************************************************
10031 *******************************************************************/
10033 struct xcv_api_table xcvtcp_cmds[] = {
10034 { "MonitorUI", xcvtcp_monitorui },
10035 { "AddPort", xcvtcp_addport},
10036 { NULL, NULL }
10039 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10040 struct security_token *token, const char *command,
10041 DATA_BLOB *inbuf,
10042 DATA_BLOB *outbuf,
10043 uint32_t *needed )
10045 int i;
10047 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10049 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10050 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10051 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10054 return WERR_BADFUNC;
10057 /*******************************************************************
10058 *******************************************************************/
10059 #if 0 /* don't support management using the "Local Port" monitor */
10061 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10062 struct security_token *token, DATA_BLOB *in,
10063 DATA_BLOB *out, uint32_t *needed)
10065 const char *dllname = "localui.dll";
10067 *needed = (strlen(dllname)+1) * 2;
10069 if (out->length < *needed) {
10070 return WERR_INSUFFICIENT_BUFFER;
10073 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10074 return WERR_NOMEM;
10077 return WERR_OK;
10080 /*******************************************************************
10081 *******************************************************************/
10083 struct xcv_api_table xcvlocal_cmds[] = {
10084 { "MonitorUI", xcvlocal_monitorui },
10085 { NULL, NULL }
10087 #else
10088 struct xcv_api_table xcvlocal_cmds[] = {
10089 { NULL, NULL }
10091 #endif
10095 /*******************************************************************
10096 *******************************************************************/
10098 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10099 struct security_token *token, const char *command,
10100 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10101 uint32_t *needed)
10103 int i;
10105 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10107 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10108 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10109 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10111 return WERR_BADFUNC;
10114 /****************************************************************
10115 _spoolss_XcvData
10116 ****************************************************************/
10118 WERROR _spoolss_XcvData(struct pipes_struct *p,
10119 struct spoolss_XcvData *r)
10121 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10122 DATA_BLOB out_data = data_blob_null;
10123 WERROR werror;
10125 if (!Printer) {
10126 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10127 OUR_HANDLE(r->in.handle)));
10128 return WERR_BADFID;
10131 /* Has to be a handle to the TCP/IP port monitor */
10133 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10134 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10135 return WERR_BADFID;
10138 /* requires administrative access to the server */
10140 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10141 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10142 return WERR_ACCESS_DENIED;
10145 /* Allocate the outgoing buffer */
10147 if (r->in.out_data_size) {
10148 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10149 if (out_data.data == NULL) {
10150 return WERR_NOMEM;
10154 switch ( Printer->printer_type ) {
10155 case SPLHND_PORTMON_TCP:
10156 werror = process_xcvtcp_command(p->mem_ctx,
10157 p->session_info->security_token,
10158 r->in.function_name,
10159 &r->in.in_data, &out_data,
10160 r->out.needed);
10161 break;
10162 case SPLHND_PORTMON_LOCAL:
10163 werror = process_xcvlocal_command(p->mem_ctx,
10164 p->session_info->security_token,
10165 r->in.function_name,
10166 &r->in.in_data, &out_data,
10167 r->out.needed);
10168 break;
10169 default:
10170 werror = WERR_INVALID_PRINT_MONITOR;
10173 if (!W_ERROR_IS_OK(werror)) {
10174 return werror;
10177 *r->out.status_code = 0;
10179 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10180 memcpy(r->out.out_data, out_data.data,
10181 MIN(r->in.out_data_size, out_data.length));
10184 return WERR_OK;
10187 /****************************************************************
10188 _spoolss_AddPrintProcessor
10189 ****************************************************************/
10191 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10192 struct spoolss_AddPrintProcessor *r)
10194 /* for now, just indicate success and ignore the add. We'll
10195 automatically set the winprint processor for printer
10196 entries later. Used to debug the LexMark Optra S 1855 PCL
10197 driver --jerry */
10199 return WERR_OK;
10202 /****************************************************************
10203 _spoolss_AddPort
10204 ****************************************************************/
10206 WERROR _spoolss_AddPort(struct pipes_struct *p,
10207 struct spoolss_AddPort *r)
10209 /* do what w2k3 does */
10211 return WERR_NOT_SUPPORTED;
10214 /****************************************************************
10215 _spoolss_GetPrinterDriver
10216 ****************************************************************/
10218 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10219 struct spoolss_GetPrinterDriver *r)
10221 p->rng_fault_state = true;
10222 return WERR_NOT_SUPPORTED;
10225 /****************************************************************
10226 _spoolss_ReadPrinter
10227 ****************************************************************/
10229 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10230 struct spoolss_ReadPrinter *r)
10232 p->rng_fault_state = true;
10233 return WERR_NOT_SUPPORTED;
10236 /****************************************************************
10237 _spoolss_WaitForPrinterChange
10238 ****************************************************************/
10240 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10241 struct spoolss_WaitForPrinterChange *r)
10243 p->rng_fault_state = true;
10244 return WERR_NOT_SUPPORTED;
10247 /****************************************************************
10248 _spoolss_ConfigurePort
10249 ****************************************************************/
10251 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10252 struct spoolss_ConfigurePort *r)
10254 p->rng_fault_state = true;
10255 return WERR_NOT_SUPPORTED;
10258 /****************************************************************
10259 _spoolss_DeletePort
10260 ****************************************************************/
10262 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10263 struct spoolss_DeletePort *r)
10265 p->rng_fault_state = true;
10266 return WERR_NOT_SUPPORTED;
10269 /****************************************************************
10270 _spoolss_CreatePrinterIC
10271 ****************************************************************/
10273 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10274 struct spoolss_CreatePrinterIC *r)
10276 p->rng_fault_state = true;
10277 return WERR_NOT_SUPPORTED;
10280 /****************************************************************
10281 _spoolss_PlayGDIScriptOnPrinterIC
10282 ****************************************************************/
10284 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10285 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10287 p->rng_fault_state = true;
10288 return WERR_NOT_SUPPORTED;
10291 /****************************************************************
10292 _spoolss_DeletePrinterIC
10293 ****************************************************************/
10295 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10296 struct spoolss_DeletePrinterIC *r)
10298 p->rng_fault_state = true;
10299 return WERR_NOT_SUPPORTED;
10302 /****************************************************************
10303 _spoolss_AddPrinterConnection
10304 ****************************************************************/
10306 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10307 struct spoolss_AddPrinterConnection *r)
10309 p->rng_fault_state = true;
10310 return WERR_NOT_SUPPORTED;
10313 /****************************************************************
10314 _spoolss_DeletePrinterConnection
10315 ****************************************************************/
10317 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10318 struct spoolss_DeletePrinterConnection *r)
10320 p->rng_fault_state = true;
10321 return WERR_NOT_SUPPORTED;
10324 /****************************************************************
10325 _spoolss_PrinterMessageBox
10326 ****************************************************************/
10328 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10329 struct spoolss_PrinterMessageBox *r)
10331 p->rng_fault_state = true;
10332 return WERR_NOT_SUPPORTED;
10335 /****************************************************************
10336 _spoolss_AddMonitor
10337 ****************************************************************/
10339 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10340 struct spoolss_AddMonitor *r)
10342 p->rng_fault_state = true;
10343 return WERR_NOT_SUPPORTED;
10346 /****************************************************************
10347 _spoolss_DeleteMonitor
10348 ****************************************************************/
10350 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10351 struct spoolss_DeleteMonitor *r)
10353 p->rng_fault_state = true;
10354 return WERR_NOT_SUPPORTED;
10357 /****************************************************************
10358 _spoolss_DeletePrintProcessor
10359 ****************************************************************/
10361 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10362 struct spoolss_DeletePrintProcessor *r)
10364 p->rng_fault_state = true;
10365 return WERR_NOT_SUPPORTED;
10368 /****************************************************************
10369 _spoolss_AddPrintProvidor
10370 ****************************************************************/
10372 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10373 struct spoolss_AddPrintProvidor *r)
10375 p->rng_fault_state = true;
10376 return WERR_NOT_SUPPORTED;
10379 /****************************************************************
10380 _spoolss_DeletePrintProvidor
10381 ****************************************************************/
10383 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10384 struct spoolss_DeletePrintProvidor *r)
10386 p->rng_fault_state = true;
10387 return WERR_NOT_SUPPORTED;
10390 /****************************************************************
10391 _spoolss_FindFirstPrinterChangeNotification
10392 ****************************************************************/
10394 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10395 struct spoolss_FindFirstPrinterChangeNotification *r)
10397 p->rng_fault_state = true;
10398 return WERR_NOT_SUPPORTED;
10401 /****************************************************************
10402 _spoolss_FindNextPrinterChangeNotification
10403 ****************************************************************/
10405 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10406 struct spoolss_FindNextPrinterChangeNotification *r)
10408 p->rng_fault_state = true;
10409 return WERR_NOT_SUPPORTED;
10412 /****************************************************************
10413 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10414 ****************************************************************/
10416 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10417 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10419 p->rng_fault_state = true;
10420 return WERR_NOT_SUPPORTED;
10423 /****************************************************************
10424 _spoolss_ReplyOpenPrinter
10425 ****************************************************************/
10427 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10428 struct spoolss_ReplyOpenPrinter *r)
10430 p->rng_fault_state = true;
10431 return WERR_NOT_SUPPORTED;
10434 /****************************************************************
10435 _spoolss_RouterReplyPrinter
10436 ****************************************************************/
10438 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10439 struct spoolss_RouterReplyPrinter *r)
10441 p->rng_fault_state = true;
10442 return WERR_NOT_SUPPORTED;
10445 /****************************************************************
10446 _spoolss_ReplyClosePrinter
10447 ****************************************************************/
10449 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10450 struct spoolss_ReplyClosePrinter *r)
10452 p->rng_fault_state = true;
10453 return WERR_NOT_SUPPORTED;
10456 /****************************************************************
10457 _spoolss_AddPortEx
10458 ****************************************************************/
10460 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10461 struct spoolss_AddPortEx *r)
10463 p->rng_fault_state = true;
10464 return WERR_NOT_SUPPORTED;
10467 /****************************************************************
10468 _spoolss_RouterFindFirstPrinterChangeNotification
10469 ****************************************************************/
10471 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10472 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10474 p->rng_fault_state = true;
10475 return WERR_NOT_SUPPORTED;
10478 /****************************************************************
10479 _spoolss_SpoolerInit
10480 ****************************************************************/
10482 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10483 struct spoolss_SpoolerInit *r)
10485 p->rng_fault_state = true;
10486 return WERR_NOT_SUPPORTED;
10489 /****************************************************************
10490 _spoolss_ResetPrinterEx
10491 ****************************************************************/
10493 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10494 struct spoolss_ResetPrinterEx *r)
10496 p->rng_fault_state = true;
10497 return WERR_NOT_SUPPORTED;
10500 /****************************************************************
10501 _spoolss_RouterReplyPrinterEx
10502 ****************************************************************/
10504 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10505 struct spoolss_RouterReplyPrinterEx *r)
10507 p->rng_fault_state = true;
10508 return WERR_NOT_SUPPORTED;
10511 /****************************************************************
10512 _spoolss_44
10513 ****************************************************************/
10515 WERROR _spoolss_44(struct pipes_struct *p,
10516 struct spoolss_44 *r)
10518 p->rng_fault_state = true;
10519 return WERR_NOT_SUPPORTED;
10522 /****************************************************************
10523 _spoolss_SetPort
10524 ****************************************************************/
10526 WERROR _spoolss_SetPort(struct pipes_struct *p,
10527 struct spoolss_SetPort *r)
10529 p->rng_fault_state = true;
10530 return WERR_NOT_SUPPORTED;
10533 /****************************************************************
10534 _spoolss_4a
10535 ****************************************************************/
10537 WERROR _spoolss_4a(struct pipes_struct *p,
10538 struct spoolss_4a *r)
10540 p->rng_fault_state = true;
10541 return WERR_NOT_SUPPORTED;
10544 /****************************************************************
10545 _spoolss_4b
10546 ****************************************************************/
10548 WERROR _spoolss_4b(struct pipes_struct *p,
10549 struct spoolss_4b *r)
10551 p->rng_fault_state = true;
10552 return WERR_NOT_SUPPORTED;
10555 /****************************************************************
10556 _spoolss_4c
10557 ****************************************************************/
10559 WERROR _spoolss_4c(struct pipes_struct *p,
10560 struct spoolss_4c *r)
10562 p->rng_fault_state = true;
10563 return WERR_NOT_SUPPORTED;
10566 /****************************************************************
10567 _spoolss_53
10568 ****************************************************************/
10570 WERROR _spoolss_53(struct pipes_struct *p,
10571 struct spoolss_53 *r)
10573 p->rng_fault_state = true;
10574 return WERR_NOT_SUPPORTED;
10577 /****************************************************************
10578 _spoolss_AddPerMachineConnection
10579 ****************************************************************/
10581 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10582 struct spoolss_AddPerMachineConnection *r)
10584 p->rng_fault_state = true;
10585 return WERR_NOT_SUPPORTED;
10588 /****************************************************************
10589 _spoolss_DeletePerMachineConnection
10590 ****************************************************************/
10592 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10593 struct spoolss_DeletePerMachineConnection *r)
10595 p->rng_fault_state = true;
10596 return WERR_NOT_SUPPORTED;
10599 /****************************************************************
10600 _spoolss_EnumPerMachineConnections
10601 ****************************************************************/
10603 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10604 struct spoolss_EnumPerMachineConnections *r)
10606 p->rng_fault_state = true;
10607 return WERR_NOT_SUPPORTED;
10610 /****************************************************************
10611 _spoolss_5a
10612 ****************************************************************/
10614 WERROR _spoolss_5a(struct pipes_struct *p,
10615 struct spoolss_5a *r)
10617 p->rng_fault_state = true;
10618 return WERR_NOT_SUPPORTED;
10621 /****************************************************************
10622 _spoolss_5b
10623 ****************************************************************/
10625 WERROR _spoolss_5b(struct pipes_struct *p,
10626 struct spoolss_5b *r)
10628 p->rng_fault_state = true;
10629 return WERR_NOT_SUPPORTED;
10632 /****************************************************************
10633 _spoolss_5c
10634 ****************************************************************/
10636 WERROR _spoolss_5c(struct pipes_struct *p,
10637 struct spoolss_5c *r)
10639 p->rng_fault_state = true;
10640 return WERR_NOT_SUPPORTED;
10643 /****************************************************************
10644 _spoolss_5d
10645 ****************************************************************/
10647 WERROR _spoolss_5d(struct pipes_struct *p,
10648 struct spoolss_5d *r)
10650 p->rng_fault_state = true;
10651 return WERR_NOT_SUPPORTED;
10654 /****************************************************************
10655 _spoolss_5e
10656 ****************************************************************/
10658 WERROR _spoolss_5e(struct pipes_struct *p,
10659 struct spoolss_5e *r)
10661 p->rng_fault_state = true;
10662 return WERR_NOT_SUPPORTED;
10665 /****************************************************************
10666 _spoolss_5f
10667 ****************************************************************/
10669 WERROR _spoolss_5f(struct pipes_struct *p,
10670 struct spoolss_5f *r)
10672 p->rng_fault_state = true;
10673 return WERR_NOT_SUPPORTED;
10676 /****************************************************************
10677 _spoolss_60
10678 ****************************************************************/
10680 WERROR _spoolss_60(struct pipes_struct *p,
10681 struct spoolss_60 *r)
10683 p->rng_fault_state = true;
10684 return WERR_NOT_SUPPORTED;
10687 /****************************************************************
10688 _spoolss_61
10689 ****************************************************************/
10691 WERROR _spoolss_61(struct pipes_struct *p,
10692 struct spoolss_61 *r)
10694 p->rng_fault_state = true;
10695 return WERR_NOT_SUPPORTED;
10698 /****************************************************************
10699 _spoolss_62
10700 ****************************************************************/
10702 WERROR _spoolss_62(struct pipes_struct *p,
10703 struct spoolss_62 *r)
10705 p->rng_fault_state = true;
10706 return WERR_NOT_SUPPORTED;
10709 /****************************************************************
10710 _spoolss_63
10711 ****************************************************************/
10713 WERROR _spoolss_63(struct pipes_struct *p,
10714 struct spoolss_63 *r)
10716 p->rng_fault_state = true;
10717 return WERR_NOT_SUPPORTED;
10720 /****************************************************************
10721 _spoolss_64
10722 ****************************************************************/
10724 WERROR _spoolss_64(struct pipes_struct *p,
10725 struct spoolss_64 *r)
10727 p->rng_fault_state = true;
10728 return WERR_NOT_SUPPORTED;
10731 /****************************************************************
10732 _spoolss_65
10733 ****************************************************************/
10735 WERROR _spoolss_65(struct pipes_struct *p,
10736 struct spoolss_65 *r)
10738 p->rng_fault_state = true;
10739 return WERR_NOT_SUPPORTED;
10742 /****************************************************************
10743 _spoolss_GetCorePrinterDrivers
10744 ****************************************************************/
10746 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10747 struct spoolss_GetCorePrinterDrivers *r)
10749 p->rng_fault_state = true;
10750 return WERR_NOT_SUPPORTED;
10753 /****************************************************************
10754 _spoolss_67
10755 ****************************************************************/
10757 WERROR _spoolss_67(struct pipes_struct *p,
10758 struct spoolss_67 *r)
10760 p->rng_fault_state = true;
10761 return WERR_NOT_SUPPORTED;
10764 /****************************************************************
10765 _spoolss_GetPrinterDriverPackagePath
10766 ****************************************************************/
10768 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10769 struct spoolss_GetPrinterDriverPackagePath *r)
10771 p->rng_fault_state = true;
10772 return WERR_NOT_SUPPORTED;
10775 /****************************************************************
10776 _spoolss_69
10777 ****************************************************************/
10779 WERROR _spoolss_69(struct pipes_struct *p,
10780 struct spoolss_69 *r)
10782 p->rng_fault_state = true;
10783 return WERR_NOT_SUPPORTED;
10786 /****************************************************************
10787 _spoolss_6a
10788 ****************************************************************/
10790 WERROR _spoolss_6a(struct pipes_struct *p,
10791 struct spoolss_6a *r)
10793 p->rng_fault_state = true;
10794 return WERR_NOT_SUPPORTED;
10797 /****************************************************************
10798 _spoolss_6b
10799 ****************************************************************/
10801 WERROR _spoolss_6b(struct pipes_struct *p,
10802 struct spoolss_6b *r)
10804 p->rng_fault_state = true;
10805 return WERR_NOT_SUPPORTED;
10808 /****************************************************************
10809 _spoolss_6c
10810 ****************************************************************/
10812 WERROR _spoolss_6c(struct pipes_struct *p,
10813 struct spoolss_6c *r)
10815 p->rng_fault_state = true;
10816 return WERR_NOT_SUPPORTED;
10819 /****************************************************************
10820 _spoolss_6d
10821 ****************************************************************/
10823 WERROR _spoolss_6d(struct pipes_struct *p,
10824 struct spoolss_6d *r)
10826 p->rng_fault_state = true;
10827 return WERR_NOT_SUPPORTED;