s3-messaging: Remove obsolete class.
[Samba/gebeck_regimport.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
bloba2f8d686659d0ec1c758ea26da21fcfedbe4797c
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 struct dcerpc_binding_handle *binding_handle;
142 uint32_t active_connections;
145 static struct notify_back_channel *back_channels;
147 /* Map generic permissions to printer object specific permissions */
149 const struct standard_mapping printer_std_mapping = {
150 PRINTER_READ,
151 PRINTER_WRITE,
152 PRINTER_EXECUTE,
153 PRINTER_ALL_ACCESS
156 /* Map generic permissions to print server object specific permissions */
158 const struct standard_mapping printserver_std_mapping = {
159 SERVER_READ,
160 SERVER_WRITE,
161 SERVER_EXECUTE,
162 SERVER_ALL_ACCESS
165 /* API table for Xcv Monitor functions */
167 struct xcv_api_table {
168 const char *name;
169 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
172 static void prune_printername_cache(void);
174 /********************************************************************
175 * Canonicalize servername.
176 ********************************************************************/
178 static const char *canon_servername(const char *servername)
180 const char *pservername = servername;
181 while (*pservername == '\\') {
182 pservername++;
184 return pservername;
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
190 switch (v) {
191 case LPQ_QUEUED:
192 return 0;
193 case LPQ_PAUSED:
194 return JOB_STATUS_PAUSED;
195 case LPQ_SPOOLING:
196 return JOB_STATUS_SPOOLING;
197 case LPQ_PRINTING:
198 return JOB_STATUS_PRINTING;
199 case LPQ_ERROR:
200 return JOB_STATUS_ERROR;
201 case LPQ_DELETING:
202 return JOB_STATUS_DELETING;
203 case LPQ_OFFLINE:
204 return JOB_STATUS_OFFLINE;
205 case LPQ_PAPEROUT:
206 return JOB_STATUS_PAPEROUT;
207 case LPQ_PRINTED:
208 return JOB_STATUS_PRINTED;
209 case LPQ_DELETED:
210 return JOB_STATUS_DELETED;
211 case LPQ_BLOCKED:
212 return JOB_STATUS_BLOCKED_DEVQ;
213 case LPQ_USER_INTERVENTION:
214 return JOB_STATUS_USER_INTERVENTION;
216 return 0;
219 static int nt_printq_status(int v)
221 switch (v) {
222 case LPQ_PAUSED:
223 return PRINTER_STATUS_PAUSED;
224 case LPQ_QUEUED:
225 case LPQ_SPOOLING:
226 case LPQ_PRINTING:
227 return 0;
229 return 0;
232 /***************************************************************************
233 Disconnect from the client
234 ****************************************************************************/
236 static void srv_spoolss_replycloseprinter(int snum,
237 struct printer_handle *prn_hnd)
239 WERROR result;
240 NTSTATUS status;
243 * Tell the specific printing tdb we no longer want messages for this printer
244 * by deregistering our PID.
247 if (!print_notify_deregister_pid(snum)) {
248 DEBUG(0, ("Failed to register our pid for printer %s\n",
249 lp_const_servicename(snum)));
252 /* weird if the test succeeds !!! */
253 if (prn_hnd->notify.cli_chan == NULL ||
254 prn_hnd->notify.cli_chan->active_connections == 0) {
255 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
256 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
257 TALLOC_FREE(prn_hnd->notify.cli_chan);
258 return;
261 status = dcerpc_spoolss_ReplyClosePrinter(
262 prn_hnd->notify.cli_chan->binding_handle,
263 talloc_tos(),
264 &prn_hnd->notify.cli_hnd,
265 &result);
266 if (!NT_STATUS_IS_OK(status)) {
267 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
268 nt_errstr(status)));
269 result = ntstatus_to_werror(status);
270 } else if (!W_ERROR_IS_OK(result)) {
271 DEBUG(0, ("reply_close_printer failed [%s].\n",
272 win_errstr(result)));
275 /* if it's the last connection, deconnect the IPC$ share */
276 if (prn_hnd->notify.cli_chan->active_connections == 1) {
278 prn_hnd->notify.cli_chan->binding_handle = NULL;
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--;
294 /****************************************************************************
295 Functions to free a printer entry datastruct.
296 ****************************************************************************/
298 static int printer_entry_destructor(struct printer_handle *Printer)
300 if (Printer->notify.cli_chan != NULL &&
301 Printer->notify.cli_chan->active_connections > 0) {
302 int snum = -1;
304 switch(Printer->printer_type) {
305 case SPLHND_SERVER:
306 srv_spoolss_replycloseprinter(snum, Printer);
307 break;
309 case SPLHND_PRINTER:
310 snum = print_queue_snum(Printer->sharename);
311 if (snum != -1) {
312 srv_spoolss_replycloseprinter(snum, Printer);
314 break;
315 default:
316 break;
320 Printer->notify.flags=0;
321 Printer->notify.options=0;
322 Printer->notify.localmachine[0]='\0';
323 Printer->notify.printerlocal=0;
324 TALLOC_FREE(Printer->notify.option);
325 TALLOC_FREE(Printer->devmode);
327 /* Remove from the internal list. */
328 DLIST_REMOVE(printers_list, Printer);
329 return 0;
332 /****************************************************************************
333 find printer index by handle
334 ****************************************************************************/
336 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
337 struct policy_handle *hnd)
339 struct printer_handle *find_printer = NULL;
341 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
342 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
343 return NULL;
346 return find_printer;
349 /****************************************************************************
350 Close printer index by handle.
351 ****************************************************************************/
353 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357 if (!Printer) {
358 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
359 OUR_HANDLE(hnd)));
360 return false;
363 close_policy_hnd(p, hnd);
365 return true;
368 /****************************************************************************
369 Delete a printer given a handle.
370 ****************************************************************************/
372 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
373 const char *sharename,
374 struct messaging_context *msg_ctx)
376 char *cmd = lp_deleteprinter_cmd();
377 char *command = NULL;
378 int ret;
379 bool is_print_op = false;
381 /* can't fail if we don't try */
383 if ( !*cmd )
384 return WERR_OK;
386 command = talloc_asprintf(ctx,
387 "%s \"%s\"",
388 cmd, sharename);
389 if (!command) {
390 return WERR_NOMEM;
392 if ( token )
393 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395 DEBUG(10,("Running [%s]\n", command));
397 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399 if ( is_print_op )
400 become_root();
402 if ( (ret = smbrun(command, NULL)) == 0 ) {
403 /* Tell everyone we updated smb.conf. */
404 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
407 if ( is_print_op )
408 unbecome_root();
410 /********** END SePrintOperatorPrivlege BLOCK **********/
412 DEBUGADD(10,("returned [%d]\n", ret));
414 TALLOC_FREE(command);
416 if (ret != 0)
417 return WERR_BADFID; /* What to return here? */
419 /* go ahead and re-read the services immediately */
420 become_root();
421 reload_services(msg_ctx, -1, false);
422 unbecome_root();
424 if ( lp_servicenumber( sharename ) >= 0 )
425 return WERR_ACCESS_DENIED;
427 return WERR_OK;
430 /****************************************************************************
431 Delete a printer given a handle.
432 ****************************************************************************/
434 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
436 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
437 WERROR result;
439 if (!Printer) {
440 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
441 OUR_HANDLE(hnd)));
442 return WERR_BADFID;
446 * It turns out that Windows allows delete printer on a handle
447 * opened by an admin user, then used on a pipe handle created
448 * by an anonymous user..... but they're working on security.... riiight !
449 * JRA.
452 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
453 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
454 return WERR_ACCESS_DENIED;
457 /* this does not need a become root since the access check has been
458 done on the handle already */
460 result = winreg_delete_printer_key_internal(p->mem_ctx,
461 get_session_info_system(),
462 p->msg_ctx,
463 Printer->sharename,
464 "");
465 if (!W_ERROR_IS_OK(result)) {
466 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
467 return WERR_BADFID;
470 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
471 Printer->sharename, p->msg_ctx);
472 if (!W_ERROR_IS_OK(result)) {
473 return result;
475 prune_printername_cache();
476 return WERR_OK;
479 /****************************************************************************
480 Return the snum of a printer corresponding to an handle.
481 ****************************************************************************/
483 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
484 int *number, struct share_params **params)
486 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
488 if (!Printer) {
489 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
490 OUR_HANDLE(hnd)));
491 return false;
494 switch (Printer->printer_type) {
495 case SPLHND_PRINTER:
496 DEBUG(4,("short name:%s\n", Printer->sharename));
497 *number = print_queue_snum(Printer->sharename);
498 return (*number != -1);
499 case SPLHND_SERVER:
500 return false;
501 default:
502 return false;
506 /****************************************************************************
507 Set printer handle type.
508 Check if it's \\server or \\server\printer
509 ****************************************************************************/
511 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
513 DEBUG(3,("Setting printer type=%s\n", handlename));
515 /* it's a print server */
516 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
517 DEBUGADD(4,("Printer is a print server\n"));
518 Printer->printer_type = SPLHND_SERVER;
520 /* it's a printer (set_printer_hnd_name() will handle port monitors */
521 else {
522 DEBUGADD(4,("Printer is a printer\n"));
523 Printer->printer_type = SPLHND_PRINTER;
526 return true;
529 static void prune_printername_cache_fn(const char *key, const char *value,
530 time_t timeout, void *private_data)
532 gencache_del(key);
535 static void prune_printername_cache(void)
537 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
540 /****************************************************************************
541 Set printer handle name.. Accept names like \\server, \\server\printer,
542 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
543 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
544 XcvDataPort() interface.
545 ****************************************************************************/
547 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
548 const struct auth_session_info *session_info,
549 struct messaging_context *msg_ctx,
550 struct printer_handle *Printer,
551 const char *handlename)
553 int snum;
554 int n_services=lp_numservices();
555 char *aprinter;
556 const char *printername;
557 const char *servername = NULL;
558 fstring sname;
559 bool found = false;
560 struct spoolss_PrinterInfo2 *info2 = NULL;
561 WERROR result;
562 char *p;
565 * Hopefully nobody names his printers like this. Maybe \ or ,
566 * are illegal in printer names even?
568 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
569 char *cache_key;
570 char *tmp;
572 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
573 (unsigned long)strlen(handlename)));
575 aprinter = discard_const_p(char, handlename);
576 if ( *handlename == '\\' ) {
577 servername = canon_servername(handlename);
578 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
579 *aprinter = '\0';
580 aprinter++;
582 if (!is_myname_or_ipaddr(servername)) {
583 return WERR_INVALID_PRINTER_NAME;
585 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
586 if (Printer->servername == NULL) {
587 return WERR_NOMEM;
591 if (Printer->printer_type == SPLHND_SERVER) {
592 return WERR_OK;
595 if (Printer->printer_type != SPLHND_PRINTER) {
596 return WERR_INVALID_HANDLE;
599 DEBUGADD(5, ("searching for [%s]\n", aprinter));
601 p = strchr(aprinter, ',');
602 if (p != NULL) {
603 char *p2 = p;
604 p++;
605 if (*p == ' ') {
606 p++;
608 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
609 *p2 = '\0';
610 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
611 *p2 = '\0';
615 if (p) {
616 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
619 /* check for the Port Monitor Interface */
620 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
621 Printer->printer_type = SPLHND_PORTMON_TCP;
622 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
623 found = true;
625 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
626 Printer->printer_type = SPLHND_PORTMON_LOCAL;
627 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
628 found = true;
632 * With hundreds of printers, the "for" loop iterating all
633 * shares can be quite expensive, as it is done on every
634 * OpenPrinter. The loop maps "aprinter" to "sname", the
635 * result of which we cache in gencache.
638 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
639 aprinter);
640 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
642 found = (strcmp(tmp, printer_not_found) != 0);
643 if (!found) {
644 DEBUG(4, ("Printer %s not found\n", aprinter));
645 SAFE_FREE(tmp);
646 return WERR_INVALID_PRINTER_NAME;
648 fstrcpy(sname, tmp);
649 SAFE_FREE(tmp);
652 /* Search all sharenames first as this is easier than pulling
653 the printer_info_2 off of disk. Don't use find_service() since
654 that calls out to map_username() */
656 /* do another loop to look for printernames */
657 for (snum = 0; !found && snum < n_services; snum++) {
658 const char *printer = lp_const_servicename(snum);
660 /* no point going on if this is not a printer */
661 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
662 continue;
665 /* ignore [printers] share */
666 if (strequal(printer, "printers")) {
667 continue;
670 fstrcpy(sname, printer);
671 if (strequal(aprinter, printer)) {
672 found = true;
673 break;
676 /* no point looking up the printer object if
677 we aren't allowing printername != sharename */
678 if (lp_force_printername(snum)) {
679 continue;
682 result = winreg_get_printer_internal(mem_ctx,
683 session_info,
684 msg_ctx,
685 sname,
686 &info2);
687 if ( !W_ERROR_IS_OK(result) ) {
688 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
689 sname, win_errstr(result)));
690 continue;
693 printername = strrchr(info2->printername, '\\');
694 if (printername == NULL) {
695 printername = info2->printername;
696 } else {
697 printername++;
700 if (strequal(printername, aprinter)) {
701 found = true;
702 break;
705 DEBUGADD(10, ("printername: %s\n", printername));
707 TALLOC_FREE(info2);
710 if ( !found ) {
711 if (cache_key != NULL) {
712 gencache_set(cache_key, printer_not_found,
713 time(NULL)+300);
714 TALLOC_FREE(cache_key);
716 DEBUGADD(4,("Printer not found\n"));
717 return WERR_INVALID_PRINTER_NAME;
720 if (cache_key != NULL) {
721 gencache_set(cache_key, sname, time(NULL)+300);
722 TALLOC_FREE(cache_key);
725 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
727 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
729 return WERR_OK;
732 /****************************************************************************
733 Find first available printer slot. creates a printer handle for you.
734 ****************************************************************************/
736 static WERROR open_printer_hnd(struct pipes_struct *p,
737 struct policy_handle *hnd,
738 const char *name,
739 uint32_t access_granted)
741 struct printer_handle *new_printer;
742 WERROR result;
744 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
746 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
747 if (new_printer == NULL) {
748 return WERR_NOMEM;
750 talloc_set_destructor(new_printer, printer_entry_destructor);
752 /* This also steals the printer_handle on the policy_handle */
753 if (!create_policy_hnd(p, hnd, new_printer)) {
754 TALLOC_FREE(new_printer);
755 return WERR_INVALID_HANDLE;
758 /* Add to the internal list. */
759 DLIST_ADD(printers_list, new_printer);
761 new_printer->notify.option=NULL;
763 if (!set_printer_hnd_printertype(new_printer, name)) {
764 close_printer_handle(p, hnd);
765 return WERR_INVALID_HANDLE;
768 result = set_printer_hnd_name(p->mem_ctx,
769 get_session_info_system(),
770 p->msg_ctx,
771 new_printer, name);
772 if (!W_ERROR_IS_OK(result)) {
773 close_printer_handle(p, hnd);
774 return result;
777 new_printer->access_granted = access_granted;
779 DEBUG(5, ("%d printer handles active\n",
780 (int)num_pipe_handles(p)));
782 return WERR_OK;
785 /***************************************************************************
786 check to see if the client motify handle is monitoring the notification
787 given by (notify_type, notify_field).
788 **************************************************************************/
790 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
791 uint16_t notify_field)
793 return true;
796 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
797 uint16_t notify_field)
799 struct spoolss_NotifyOption *option = p->notify.option;
800 uint32_t i, j;
803 * Flags should always be zero when the change notify
804 * is registered by the client's spooler. A user Win32 app
805 * might use the flags though instead of the NOTIFY_OPTION_INFO
806 * --jerry
809 if (!option) {
810 return false;
813 if (p->notify.flags)
814 return is_monitoring_event_flags(
815 p->notify.flags, notify_type, notify_field);
817 for (i = 0; i < option->count; i++) {
819 /* Check match for notify_type */
821 if (option->types[i].type != notify_type)
822 continue;
824 /* Check match for field */
826 for (j = 0; j < option->types[i].count; j++) {
827 if (option->types[i].fields[j].field == notify_field) {
828 return true;
833 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
834 p->servername, p->sharename, notify_type, notify_field));
836 return false;
839 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
840 _data->data.integer[0] = _integer; \
841 _data->data.integer[1] = 0;
844 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
845 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
846 if (!_data->data.string.string) {\
847 _data->data.string.size = 0; \
849 _data->data.string.size = strlen_m_term(_p) * 2;
851 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
852 _data->data.devmode.devmode = _devmode;
854 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
855 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
856 if (!_data->data.sd.sd) { \
857 _data->data.sd.sd_size = 0; \
859 _data->data.sd.sd_size = \
860 ndr_size_security_descriptor(_data->data.sd.sd, 0);
862 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
863 struct tm *t,
864 const char **pp,
865 uint32_t *plen)
867 struct spoolss_Time st;
868 uint32_t len = 16;
869 char *p;
871 if (!init_systemtime(&st, t)) {
872 return;
875 p = talloc_array(mem_ctx, char, len);
876 if (!p) {
877 return;
881 * Systemtime must be linearized as a set of UINT16's.
882 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
885 SSVAL(p, 0, st.year);
886 SSVAL(p, 2, st.month);
887 SSVAL(p, 4, st.day_of_week);
888 SSVAL(p, 6, st.day);
889 SSVAL(p, 8, st.hour);
890 SSVAL(p, 10, st.minute);
891 SSVAL(p, 12, st.second);
892 SSVAL(p, 14, st.millisecond);
894 *pp = p;
895 *plen = len;
898 /* Convert a notification message to a struct spoolss_Notify */
900 static void notify_one_value(struct spoolss_notify_msg *msg,
901 struct spoolss_Notify *data,
902 TALLOC_CTX *mem_ctx)
904 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
907 static void notify_string(struct spoolss_notify_msg *msg,
908 struct spoolss_Notify *data,
909 TALLOC_CTX *mem_ctx)
911 /* The length of the message includes the trailing \0 */
913 data->data.string.size = msg->len * 2;
914 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
915 if (!data->data.string.string) {
916 data->data.string.size = 0;
917 return;
921 static void notify_system_time(struct spoolss_notify_msg *msg,
922 struct spoolss_Notify *data,
923 TALLOC_CTX *mem_ctx)
925 data->data.string.string = NULL;
926 data->data.string.size = 0;
928 if (msg->len != sizeof(time_t)) {
929 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
930 msg->len));
931 return;
934 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
935 &data->data.string.string,
936 &data->data.string.size);
939 struct notify2_message_table {
940 const char *name;
941 void (*fn)(struct spoolss_notify_msg *msg,
942 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
945 static struct notify2_message_table printer_notify_table[] = {
946 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
947 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
948 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
949 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
950 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
951 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
952 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
953 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
954 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
955 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
956 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
957 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
958 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
959 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
960 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
961 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
962 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
963 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
964 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
967 static struct notify2_message_table job_notify_table[] = {
968 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
969 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
970 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
971 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
972 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
973 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
974 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
975 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
976 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
977 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
978 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
979 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
980 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
981 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
982 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
983 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
984 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
985 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
986 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
987 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
988 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
989 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
990 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
991 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
995 /***********************************************************************
996 Allocate talloc context for container object
997 **********************************************************************/
999 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1001 if ( !ctr )
1002 return;
1004 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1006 return;
1009 /***********************************************************************
1010 release all allocated memory and zero out structure
1011 **********************************************************************/
1013 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1015 if ( !ctr )
1016 return;
1018 if ( ctr->ctx )
1019 talloc_destroy(ctr->ctx);
1021 ZERO_STRUCTP(ctr);
1023 return;
1026 /***********************************************************************
1027 **********************************************************************/
1029 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1031 if ( !ctr )
1032 return NULL;
1034 return ctr->ctx;
1037 /***********************************************************************
1038 **********************************************************************/
1040 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1042 if ( !ctr || !ctr->msg_groups )
1043 return NULL;
1045 if ( idx >= ctr->num_groups )
1046 return NULL;
1048 return &ctr->msg_groups[idx];
1052 /***********************************************************************
1053 How many groups of change messages do we have ?
1054 **********************************************************************/
1056 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1058 if ( !ctr )
1059 return 0;
1061 return ctr->num_groups;
1064 /***********************************************************************
1065 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1066 **********************************************************************/
1068 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1070 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1071 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1072 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1073 int i, new_slot;
1075 if ( !ctr || !msg )
1076 return 0;
1078 /* loop over all groups looking for a matching printer name */
1080 for ( i=0; i<ctr->num_groups; i++ ) {
1081 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1082 break;
1085 /* add a new group? */
1087 if ( i == ctr->num_groups ) {
1088 ctr->num_groups++;
1090 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1091 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1092 return 0;
1094 ctr->msg_groups = groups;
1096 /* clear the new entry and set the printer name */
1098 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1099 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1102 /* add the change messages; 'i' is the correct index now regardless */
1104 msg_grp = &ctr->msg_groups[i];
1106 msg_grp->num_msgs++;
1108 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1109 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1110 return 0;
1112 msg_grp->msgs = msg_list;
1114 new_slot = msg_grp->num_msgs-1;
1115 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1117 /* need to allocate own copy of data */
1119 if ( msg->len != 0 )
1120 msg_grp->msgs[new_slot].notify.data = (char *)
1121 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1123 return ctr->num_groups;
1126 static void construct_info_data(struct spoolss_Notify *info_data,
1127 enum spoolss_NotifyType type,
1128 uint16_t field, int id);
1130 /***********************************************************************
1131 Send a change notication message on all handles which have a call
1132 back registered
1133 **********************************************************************/
1135 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1136 struct printer_handle *prn_hnd,
1137 SPOOLSS_NOTIFY_MSG *messages,
1138 uint32_t num_msgs,
1139 struct spoolss_Notify **_notifies,
1140 int *_count)
1142 struct spoolss_Notify *notifies;
1143 SPOOLSS_NOTIFY_MSG *msg;
1144 int count = 0;
1145 uint32_t id;
1146 int i;
1148 notifies = talloc_zero_array(mem_ctx,
1149 struct spoolss_Notify, num_msgs);
1150 if (!notifies) {
1151 return ENOMEM;
1154 for (i = 0; i < num_msgs; i++) {
1156 msg = &messages[i];
1158 /* Are we monitoring this event? */
1160 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1161 continue;
1164 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1165 "for printer [%s]\n",
1166 msg->type, msg->field, prn_hnd->sharename));
1169 * if the is a printer notification handle and not a job
1170 * notification type, then set the id to 0.
1171 * Otherwise just use what was specified in the message.
1173 * When registering change notification on a print server
1174 * handle we always need to send back the id (snum) matching
1175 * the printer for which the change took place.
1176 * For change notify registered on a printer handle,
1177 * this does not matter and the id should be 0.
1179 * --jerry
1182 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1183 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1184 id = 0;
1185 } else {
1186 id = msg->id;
1189 /* Convert unix jobid to smb jobid */
1191 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1192 id = sysjob_to_jobid(msg->id);
1194 if (id == -1) {
1195 DEBUG(3, ("no such unix jobid %d\n",
1196 msg->id));
1197 continue;
1201 construct_info_data(&notifies[count],
1202 msg->type, msg->field, id);
1204 switch(msg->type) {
1205 case PRINTER_NOTIFY_TYPE:
1206 if (printer_notify_table[msg->field].fn) {
1207 printer_notify_table[msg->field].fn(msg,
1208 &notifies[count], mem_ctx);
1210 break;
1212 case JOB_NOTIFY_TYPE:
1213 if (job_notify_table[msg->field].fn) {
1214 job_notify_table[msg->field].fn(msg,
1215 &notifies[count], mem_ctx);
1217 break;
1219 default:
1220 DEBUG(5, ("Unknown notification type %d\n",
1221 msg->type));
1222 continue;
1225 count++;
1228 *_notifies = notifies;
1229 *_count = count;
1231 return 0;
1234 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1235 struct printer_handle *prn_hnd,
1236 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1238 struct spoolss_Notify *notifies;
1239 int count = 0;
1240 union spoolss_ReplyPrinterInfo info;
1241 struct spoolss_NotifyInfo info0;
1242 uint32_t reply_result;
1243 NTSTATUS status;
1244 WERROR werr;
1245 int ret;
1247 /* Is there notification on this handle? */
1248 if (prn_hnd->notify.cli_chan == NULL ||
1249 prn_hnd->notify.cli_chan->active_connections == 0) {
1250 return 0;
1253 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1254 prn_hnd->servername, prn_hnd->sharename));
1256 /* For this printer? Print servers always receive notifications. */
1257 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1258 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1259 return 0;
1262 DEBUG(10,("Our printer\n"));
1264 /* build the array of change notifications */
1265 ret = build_notify2_messages(mem_ctx, prn_hnd,
1266 msg_group->msgs,
1267 msg_group->num_msgs,
1268 &notifies, &count);
1269 if (ret) {
1270 return ret;
1273 info0.version = 0x2;
1274 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1275 info0.count = count;
1276 info0.notifies = notifies;
1278 info.info0 = &info0;
1280 status = dcerpc_spoolss_RouterReplyPrinterEx(
1281 prn_hnd->notify.cli_chan->binding_handle,
1282 mem_ctx,
1283 &prn_hnd->notify.cli_hnd,
1284 prn_hnd->notify.change, /* color */
1285 prn_hnd->notify.flags,
1286 &reply_result,
1287 0, /* reply_type, must be 0 */
1288 info, &werr);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1291 "failed: %s\n",
1292 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1293 nt_errstr(status)));
1294 werr = ntstatus_to_werror(status);
1295 } else if (!W_ERROR_IS_OK(werr)) {
1296 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1297 "failed: %s\n",
1298 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1299 win_errstr(werr)));
1301 switch (reply_result) {
1302 case 0:
1303 break;
1304 case PRINTER_NOTIFY_INFO_DISCARDED:
1305 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1306 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1307 break;
1308 default:
1309 break;
1312 return 0;
1315 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1317 struct printer_handle *p;
1318 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1319 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1320 int ret;
1322 if ( !msg_group ) {
1323 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1324 return;
1327 if (!msg_group->msgs) {
1328 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1329 return;
1332 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1334 /* loop over all printers */
1336 for (p = printers_list; p; p = p->next) {
1337 ret = send_notify2_printer(mem_ctx, p, msg_group);
1338 if (ret) {
1339 goto done;
1343 done:
1344 DEBUG(8,("send_notify2_changes: Exit...\n"));
1345 return;
1348 /***********************************************************************
1349 **********************************************************************/
1351 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1354 uint32_t tv_sec, tv_usec;
1355 size_t offset = 0;
1357 /* Unpack message */
1359 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1360 msg->printer);
1362 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1363 &tv_sec, &tv_usec,
1364 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1366 if (msg->len == 0)
1367 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1368 &msg->notify.value[0], &msg->notify.value[1]);
1369 else
1370 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1371 &msg->len, &msg->notify.data);
1373 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1374 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1376 tv->tv_sec = tv_sec;
1377 tv->tv_usec = tv_usec;
1379 if (msg->len == 0)
1380 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1381 msg->notify.value[1]));
1382 else
1383 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1385 return true;
1388 /********************************************************************
1389 Receive a notify2 message list
1390 ********************************************************************/
1392 static void receive_notify2_message_list(struct messaging_context *msg,
1393 void *private_data,
1394 uint32_t msg_type,
1395 struct server_id server_id,
1396 DATA_BLOB *data)
1398 size_t msg_count, i;
1399 char *buf = (char *)data->data;
1400 char *msg_ptr;
1401 size_t msg_len;
1402 SPOOLSS_NOTIFY_MSG notify;
1403 SPOOLSS_NOTIFY_MSG_CTR messages;
1404 int num_groups;
1406 if (data->length < 4) {
1407 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1408 return;
1411 msg_count = IVAL(buf, 0);
1412 msg_ptr = buf + 4;
1414 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1416 if (msg_count == 0) {
1417 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1418 return;
1421 /* initialize the container */
1423 ZERO_STRUCT( messages );
1424 notify_msg_ctr_init( &messages );
1427 * build message groups for each printer identified
1428 * in a change_notify msg. Remember that a PCN message
1429 * includes the handle returned for the srv_spoolss_replyopenprinter()
1430 * call. Therefore messages are grouped according to printer handle.
1433 for ( i=0; i<msg_count; i++ ) {
1434 struct timeval msg_tv;
1436 if (msg_ptr + 4 - buf > data->length) {
1437 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1438 return;
1441 msg_len = IVAL(msg_ptr,0);
1442 msg_ptr += 4;
1444 if (msg_ptr + msg_len - buf > data->length) {
1445 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1446 return;
1449 /* unpack messages */
1451 ZERO_STRUCT( notify );
1452 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1453 msg_ptr += msg_len;
1455 /* add to correct list in container */
1457 notify_msg_ctr_addmsg( &messages, &notify );
1459 /* free memory that might have been allocated by notify2_unpack_msg() */
1461 if ( notify.len != 0 )
1462 SAFE_FREE( notify.notify.data );
1465 /* process each group of messages */
1467 num_groups = notify_msg_ctr_numgroups( &messages );
1468 for ( i=0; i<num_groups; i++ )
1469 send_notify2_changes( &messages, i );
1472 /* cleanup */
1474 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1475 (uint32_t)msg_count ));
1477 notify_msg_ctr_destroy( &messages );
1479 return;
1482 /********************************************************************
1483 Send a message to ourself about new driver being installed
1484 so we can upgrade the information for each printer bound to this
1485 driver
1486 ********************************************************************/
1488 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1489 struct messaging_context *msg_ctx)
1491 int len = strlen(drivername);
1493 if (!len)
1494 return false;
1496 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1497 drivername));
1499 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1500 MSG_PRINTER_DRVUPGRADE,
1501 (const uint8_t *)drivername, len+1);
1503 return true;
1506 void srv_spoolss_cleanup(void)
1508 struct printer_session_counter *session_counter;
1510 for (session_counter = counter_list;
1511 session_counter != NULL;
1512 session_counter = counter_list) {
1513 DLIST_REMOVE(counter_list, session_counter);
1514 TALLOC_FREE(session_counter);
1518 /**********************************************************************
1519 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1520 over all printers, upgrading ones as necessary
1521 **********************************************************************/
1523 void do_drv_upgrade_printer(struct messaging_context *msg,
1524 void *private_data,
1525 uint32_t msg_type,
1526 struct server_id server_id,
1527 DATA_BLOB *data)
1529 TALLOC_CTX *tmp_ctx;
1530 const struct auth_session_info *session_info = get_session_info_system();
1531 struct spoolss_PrinterInfo2 *pinfo2;
1532 WERROR result;
1533 const char *drivername;
1534 int snum;
1535 int n_services = lp_numservices();
1536 struct dcerpc_binding_handle *b = NULL;
1538 tmp_ctx = talloc_new(NULL);
1539 if (!tmp_ctx) return;
1541 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1542 if (!drivername) {
1543 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1544 goto done;
1547 DEBUG(10, ("do_drv_upgrade_printer: "
1548 "Got message for new driver [%s]\n", drivername));
1550 /* Iterate the printer list */
1552 for (snum = 0; snum < n_services; snum++) {
1553 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1554 continue;
1557 /* ignore [printers] share */
1558 if (strequal(lp_const_servicename(snum), "printers")) {
1559 continue;
1562 if (b == NULL) {
1563 result = winreg_printer_binding_handle(tmp_ctx,
1564 session_info,
1565 msg,
1566 &b);
1567 if (!W_ERROR_IS_OK(result)) {
1568 break;
1572 result = winreg_get_printer(tmp_ctx, b,
1573 lp_const_servicename(snum),
1574 &pinfo2);
1576 if (!W_ERROR_IS_OK(result)) {
1577 continue;
1580 if (!pinfo2->drivername) {
1581 continue;
1584 if (strcmp(drivername, pinfo2->drivername) != 0) {
1585 continue;
1588 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1590 /* all we care about currently is the change_id */
1591 result = winreg_printer_update_changeid(tmp_ctx, b,
1592 pinfo2->printername);
1594 if (!W_ERROR_IS_OK(result)) {
1595 DEBUG(3, ("do_drv_upgrade_printer: "
1596 "Failed to update changeid [%s]\n",
1597 win_errstr(result)));
1601 /* all done */
1602 done:
1603 talloc_free(tmp_ctx);
1606 /********************************************************************
1607 Update the cache for all printq's with a registered client
1608 connection
1609 ********************************************************************/
1611 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1613 struct printer_handle *printer = printers_list;
1614 int snum;
1616 /* loop through all printers and update the cache where
1617 a client is connected */
1618 while (printer) {
1619 if ((printer->printer_type == SPLHND_PRINTER) &&
1620 ((printer->notify.cli_chan != NULL) &&
1621 (printer->notify.cli_chan->active_connections > 0))) {
1622 snum = print_queue_snum(printer->sharename);
1623 print_queue_status(msg_ctx, snum, NULL, NULL);
1626 printer = printer->next;
1629 return;
1632 /****************************************************************
1633 _spoolss_OpenPrinter
1634 ****************************************************************/
1636 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1637 struct spoolss_OpenPrinter *r)
1639 struct spoolss_OpenPrinterEx e;
1640 WERROR werr;
1642 ZERO_STRUCT(e.in.userlevel);
1644 e.in.printername = r->in.printername;
1645 e.in.datatype = r->in.datatype;
1646 e.in.devmode_ctr = r->in.devmode_ctr;
1647 e.in.access_mask = r->in.access_mask;
1648 e.in.level = 0;
1650 e.out.handle = r->out.handle;
1652 werr = _spoolss_OpenPrinterEx(p, &e);
1654 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1655 /* OpenPrinterEx returns this for a bad
1656 * printer name. We must return WERR_INVALID_PRINTER_NAME
1657 * instead.
1659 werr = WERR_INVALID_PRINTER_NAME;
1662 return werr;
1665 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1666 struct spoolss_DeviceMode *orig,
1667 struct spoolss_DeviceMode **dest)
1669 struct spoolss_DeviceMode *dm;
1671 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1672 if (!dm) {
1673 return WERR_NOMEM;
1676 /* copy all values, then duplicate strings and structs */
1677 *dm = *orig;
1679 dm->devicename = talloc_strdup(dm, orig->devicename);
1680 if (!dm->devicename) {
1681 return WERR_NOMEM;
1683 dm->formname = talloc_strdup(dm, orig->formname);
1684 if (!dm->formname) {
1685 return WERR_NOMEM;
1687 if (orig->driverextra_data.data) {
1688 dm->driverextra_data.data =
1689 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1690 orig->driverextra_data.length);
1691 if (!dm->driverextra_data.data) {
1692 return WERR_NOMEM;
1696 *dest = dm;
1697 return WERR_OK;
1700 /****************************************************************
1701 _spoolss_OpenPrinterEx
1702 ****************************************************************/
1704 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1705 struct spoolss_OpenPrinterEx *r)
1707 int snum;
1708 char *raddr;
1709 char *rhost;
1710 struct printer_handle *Printer=NULL;
1711 WERROR result;
1712 int rc;
1714 if (!r->in.printername) {
1715 return WERR_INVALID_PARAM;
1718 if (r->in.level > 3) {
1719 return WERR_INVALID_PARAM;
1721 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1722 (r->in.level == 2 && !r->in.userlevel.level2) ||
1723 (r->in.level == 3 && !r->in.userlevel.level3)) {
1724 return WERR_INVALID_PARAM;
1727 /* some sanity check because you can open a printer or a print server */
1728 /* aka: \\server\printer or \\server */
1730 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1732 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1733 if (!W_ERROR_IS_OK(result)) {
1734 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1735 "for printer %s\n", r->in.printername));
1736 ZERO_STRUCTP(r->out.handle);
1737 return result;
1740 Printer = find_printer_index_by_hnd(p, r->out.handle);
1741 if ( !Printer ) {
1742 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1743 "handle we created for printer %s\n", r->in.printername));
1744 close_printer_handle(p, r->out.handle);
1745 ZERO_STRUCTP(r->out.handle);
1746 return WERR_INVALID_PARAM;
1750 * First case: the user is opening the print server:
1752 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1753 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1755 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1756 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1757 * or if the user is listed in the smb.conf printer admin parameter.
1759 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1760 * client view printer folder, but does not show the MSAPW.
1762 * Note: this test needs code to check access rights here too. Jeremy
1763 * could you look at this?
1765 * Second case: the user is opening a printer:
1766 * NT doesn't let us connect to a printer if the connecting user
1767 * doesn't have print permission.
1769 * Third case: user is opening a Port Monitor
1770 * access checks same as opening a handle to the print server.
1773 switch (Printer->printer_type )
1775 case SPLHND_SERVER:
1776 case SPLHND_PORTMON_TCP:
1777 case SPLHND_PORTMON_LOCAL:
1778 /* Printserver handles use global struct... */
1780 snum = -1;
1782 /* Map standard access rights to object specific access rights */
1784 se_map_standard(&r->in.access_mask,
1785 &printserver_std_mapping);
1787 /* Deny any object specific bits that don't apply to print
1788 servers (i.e printer and job specific bits) */
1790 r->in.access_mask &= SEC_MASK_SPECIFIC;
1792 if (r->in.access_mask &
1793 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1794 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1795 close_printer_handle(p, r->out.handle);
1796 ZERO_STRUCTP(r->out.handle);
1797 return WERR_ACCESS_DENIED;
1800 /* Allow admin access */
1802 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1804 if (!lp_ms_add_printer_wizard()) {
1805 close_printer_handle(p, r->out.handle);
1806 ZERO_STRUCTP(r->out.handle);
1807 return WERR_ACCESS_DENIED;
1810 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1811 and not a printer admin, then fail */
1813 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1814 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1815 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1816 !token_contains_name_in_list(
1817 uidtoname(p->session_info->unix_token->uid),
1818 p->session_info->info->domain_name,
1819 NULL,
1820 p->session_info->security_token,
1821 lp_printer_admin(snum))) {
1822 close_printer_handle(p, r->out.handle);
1823 ZERO_STRUCTP(r->out.handle);
1824 DEBUG(3,("access DENIED as user is not root, "
1825 "has no printoperator privilege, "
1826 "not a member of the printoperator builtin group and "
1827 "is not in printer admin list"));
1828 return WERR_ACCESS_DENIED;
1831 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1833 else
1835 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1838 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1839 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1841 /* We fall through to return WERR_OK */
1842 break;
1844 case SPLHND_PRINTER:
1845 /* NT doesn't let us connect to a printer if the connecting user
1846 doesn't have print permission. */
1848 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1849 close_printer_handle(p, r->out.handle);
1850 ZERO_STRUCTP(r->out.handle);
1851 return WERR_BADFID;
1854 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1855 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1858 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1860 /* map an empty access mask to the minimum access mask */
1861 if (r->in.access_mask == 0x0)
1862 r->in.access_mask = PRINTER_ACCESS_USE;
1865 * If we are not serving the printer driver for this printer,
1866 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1867 * will keep NT clients happy --jerry
1870 if (lp_use_client_driver(snum)
1871 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1873 r->in.access_mask = PRINTER_ACCESS_USE;
1876 /* check smb.conf parameters and the the sec_desc */
1877 raddr = tsocket_address_inet_addr_string(p->remote_address,
1878 p->mem_ctx);
1879 if (raddr == NULL) {
1880 return WERR_NOMEM;
1883 rc = get_remote_hostname(p->remote_address,
1884 &rhost,
1885 p->mem_ctx);
1886 if (rc < 0) {
1887 return WERR_NOMEM;
1889 if (strequal(rhost, "UNKNOWN")) {
1890 rhost = raddr;
1893 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1894 rhost, raddr)) {
1895 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1896 ZERO_STRUCTP(r->out.handle);
1897 return WERR_ACCESS_DENIED;
1900 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1901 p->session_info->security_token, snum) ||
1902 !print_access_check(p->session_info,
1903 p->msg_ctx,
1904 snum,
1905 r->in.access_mask)) {
1906 DEBUG(3, ("access DENIED for printer open\n"));
1907 close_printer_handle(p, r->out.handle);
1908 ZERO_STRUCTP(r->out.handle);
1909 return WERR_ACCESS_DENIED;
1912 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1913 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1914 close_printer_handle(p, r->out.handle);
1915 ZERO_STRUCTP(r->out.handle);
1916 return WERR_ACCESS_DENIED;
1919 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1920 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1921 else
1922 r->in.access_mask = PRINTER_ACCESS_USE;
1924 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1925 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1927 winreg_create_printer_internal(p->mem_ctx,
1928 get_session_info_system(),
1929 p->msg_ctx,
1930 lp_const_servicename(snum));
1932 break;
1934 default:
1935 /* sanity check to prevent programmer error */
1936 ZERO_STRUCTP(r->out.handle);
1937 return WERR_BADFID;
1940 Printer->access_granted = r->in.access_mask;
1943 * If the client sent a devmode in the OpenPrinter() call, then
1944 * save it here in case we get a job submission on this handle
1947 if ((Printer->printer_type != SPLHND_SERVER) &&
1948 r->in.devmode_ctr.devmode) {
1949 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1950 &Printer->devmode);
1953 #if 0 /* JERRY -- I'm doubtful this is really effective */
1954 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1955 optimization in Windows 2000 clients --jerry */
1957 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1958 && (RA_WIN2K == get_remote_arch()) )
1960 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1961 sys_usleep( 500000 );
1963 #endif
1965 return WERR_OK;
1968 /****************************************************************
1969 _spoolss_ClosePrinter
1970 ****************************************************************/
1972 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1973 struct spoolss_ClosePrinter *r)
1975 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1977 if (Printer && Printer->document_started) {
1978 struct spoolss_EndDocPrinter e;
1980 e.in.handle = r->in.handle;
1982 _spoolss_EndDocPrinter(p, &e);
1985 if (!close_printer_handle(p, r->in.handle))
1986 return WERR_BADFID;
1988 /* clear the returned printer handle. Observed behavior
1989 from Win2k server. Don't think this really matters.
1990 Previous code just copied the value of the closed
1991 handle. --jerry */
1993 ZERO_STRUCTP(r->out.handle);
1995 return WERR_OK;
1998 /****************************************************************
1999 _spoolss_DeletePrinter
2000 ****************************************************************/
2002 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2003 struct spoolss_DeletePrinter *r)
2005 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2006 WERROR result;
2007 int snum;
2009 if (Printer && Printer->document_started) {
2010 struct spoolss_EndDocPrinter e;
2012 e.in.handle = r->in.handle;
2014 _spoolss_EndDocPrinter(p, &e);
2017 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2018 winreg_delete_printer_key_internal(p->mem_ctx,
2019 get_session_info_system(),
2020 p->msg_ctx,
2021 lp_const_servicename(snum),
2022 "");
2025 result = delete_printer_handle(p, r->in.handle);
2027 return result;
2030 /*******************************************************************
2031 * static function to lookup the version id corresponding to an
2032 * long architecture string
2033 ******************************************************************/
2035 static const struct print_architecture_table_node archi_table[]= {
2037 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2038 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2039 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2040 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2041 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2042 {"Windows IA64", SPL_ARCH_IA64, 3 },
2043 {"Windows x64", SPL_ARCH_X64, 3 },
2044 {NULL, "", -1 }
2047 static int get_version_id(const char *arch)
2049 int i;
2051 for (i=0; archi_table[i].long_archi != NULL; i++)
2053 if (strcmp(arch, archi_table[i].long_archi) == 0)
2054 return (archi_table[i].version);
2057 return -1;
2060 /****************************************************************
2061 _spoolss_DeletePrinterDriver
2062 ****************************************************************/
2064 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2065 struct spoolss_DeletePrinterDriver *r)
2068 struct spoolss_DriverInfo8 *info = NULL;
2069 struct spoolss_DriverInfo8 *info_win2k = NULL;
2070 int version;
2071 WERROR status;
2072 struct dcerpc_binding_handle *b;
2073 TALLOC_CTX *tmp_ctx = NULL;
2075 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2076 and not a printer admin, then fail */
2078 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2079 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2080 && !token_contains_name_in_list(
2081 uidtoname(p->session_info->unix_token->uid),
2082 p->session_info->info->domain_name,
2083 NULL,
2084 p->session_info->security_token,
2085 lp_printer_admin(-1)) )
2087 return WERR_ACCESS_DENIED;
2090 /* check that we have a valid driver name first */
2092 if ((version = get_version_id(r->in.architecture)) == -1) {
2093 return WERR_INVALID_ENVIRONMENT;
2096 tmp_ctx = talloc_new(p->mem_ctx);
2097 if (!tmp_ctx) {
2098 return WERR_NOMEM;
2101 status = winreg_printer_binding_handle(tmp_ctx,
2102 get_session_info_system(),
2103 p->msg_ctx,
2104 &b);
2105 if (!W_ERROR_IS_OK(status)) {
2106 goto done;
2109 status = winreg_get_driver(tmp_ctx, b,
2110 r->in.architecture, r->in.driver,
2111 version, &info);
2112 if (!W_ERROR_IS_OK(status)) {
2113 /* try for Win2k driver if "Windows NT x86" */
2115 if ( version == 2 ) {
2116 version = 3;
2118 status = winreg_get_driver(tmp_ctx, b,
2119 r->in.architecture,
2120 r->in.driver,
2121 version, &info);
2122 if (!W_ERROR_IS_OK(status)) {
2123 status = WERR_UNKNOWN_PRINTER_DRIVER;
2124 goto done;
2127 /* otherwise it was a failure */
2128 else {
2129 status = WERR_UNKNOWN_PRINTER_DRIVER;
2130 goto done;
2135 if (printer_driver_in_use(tmp_ctx,
2137 info)) {
2138 status = WERR_PRINTER_DRIVER_IN_USE;
2139 goto done;
2142 if (version == 2) {
2143 status = winreg_get_driver(tmp_ctx, b,
2144 r->in.architecture,
2145 r->in.driver, 3, &info_win2k);
2146 if (W_ERROR_IS_OK(status)) {
2147 /* if we get to here, we now have 2 driver info structures to remove */
2148 /* remove the Win2k driver first*/
2150 status = winreg_del_driver(tmp_ctx, b,
2151 info_win2k, 3);
2152 talloc_free(info_win2k);
2154 /* this should not have failed---if it did, report to client */
2155 if (!W_ERROR_IS_OK(status)) {
2156 goto done;
2161 status = winreg_del_driver(tmp_ctx, b,
2162 info, version);
2164 done:
2165 talloc_free(tmp_ctx);
2167 return status;
2170 /****************************************************************
2171 _spoolss_DeletePrinterDriverEx
2172 ****************************************************************/
2174 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2175 struct spoolss_DeletePrinterDriverEx *r)
2177 struct spoolss_DriverInfo8 *info = NULL;
2178 struct spoolss_DriverInfo8 *info_win2k = NULL;
2179 int version;
2180 bool delete_files;
2181 WERROR status;
2182 struct dcerpc_binding_handle *b;
2183 TALLOC_CTX *tmp_ctx = NULL;
2185 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2186 and not a printer admin, then fail */
2188 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2189 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2190 && !token_contains_name_in_list(
2191 uidtoname(p->session_info->unix_token->uid),
2192 p->session_info->info->domain_name,
2193 NULL,
2194 p->session_info->security_token, lp_printer_admin(-1)) )
2196 return WERR_ACCESS_DENIED;
2199 /* check that we have a valid driver name first */
2200 if ((version = get_version_id(r->in.architecture)) == -1) {
2201 /* this is what NT returns */
2202 return WERR_INVALID_ENVIRONMENT;
2205 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2206 version = r->in.version;
2209 tmp_ctx = talloc_new(p->mem_ctx);
2210 if (!tmp_ctx) {
2211 return WERR_NOMEM;
2214 status = winreg_printer_binding_handle(tmp_ctx,
2215 get_session_info_system(),
2216 p->msg_ctx,
2217 &b);
2218 if (!W_ERROR_IS_OK(status)) {
2219 goto done;
2222 status = winreg_get_driver(tmp_ctx, b,
2223 r->in.architecture,
2224 r->in.driver,
2225 version,
2226 &info);
2227 if (!W_ERROR_IS_OK(status)) {
2228 status = WERR_UNKNOWN_PRINTER_DRIVER;
2231 * if the client asked for a specific version,
2232 * or this is something other than Windows NT x86,
2233 * then we've failed
2236 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2237 goto done;
2239 /* try for Win2k driver if "Windows NT x86" */
2241 version = 3;
2242 status = winreg_get_driver(tmp_ctx, b,
2243 r->in.architecture,
2244 r->in.driver,
2245 version, &info);
2246 if (!W_ERROR_IS_OK(status)) {
2247 status = WERR_UNKNOWN_PRINTER_DRIVER;
2248 goto done;
2252 if (printer_driver_in_use(tmp_ctx,
2254 info)) {
2255 status = WERR_PRINTER_DRIVER_IN_USE;
2256 goto done;
2260 * we have a couple of cases to consider.
2261 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2262 * then the delete should fail if **any** files overlap with
2263 * other drivers
2264 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2265 * non-overlapping files
2266 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2267 * is set, the do not delete any files
2268 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2271 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2273 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2275 if (delete_files &&
2276 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2277 printer_driver_files_in_use(tmp_ctx,
2279 info)) {
2280 /* no idea of the correct error here */
2281 status = WERR_ACCESS_DENIED;
2282 goto done;
2286 /* also check for W32X86/3 if necessary; maybe we already have? */
2288 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2289 status = winreg_get_driver(tmp_ctx, b,
2290 r->in.architecture,
2291 r->in.driver, 3, &info_win2k);
2292 if (W_ERROR_IS_OK(status)) {
2294 if (delete_files &&
2295 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2296 printer_driver_files_in_use(info,
2298 info_win2k)) {
2299 /* no idea of the correct error here */
2300 talloc_free(info_win2k);
2301 status = WERR_ACCESS_DENIED;
2302 goto done;
2305 /* if we get to here, we now have 2 driver info structures to remove */
2306 /* remove the Win2k driver first*/
2308 status = winreg_del_driver(tmp_ctx, b,
2309 info_win2k,
2312 /* this should not have failed---if it did, report to client */
2314 if (!W_ERROR_IS_OK(status)) {
2315 goto done;
2319 * now delete any associated files if delete_files is
2320 * true. Even if this part failes, we return succes
2321 * because the driver doesn not exist any more
2323 if (delete_files) {
2324 delete_driver_files(get_session_info_system(),
2325 info_win2k);
2330 status = winreg_del_driver(tmp_ctx, b,
2331 info,
2332 version);
2333 if (!W_ERROR_IS_OK(status)) {
2334 goto done;
2338 * now delete any associated files if delete_files is
2339 * true. Even if this part failes, we return succes
2340 * because the driver doesn not exist any more
2342 if (delete_files) {
2343 delete_driver_files(get_session_info_system(), info);
2346 done:
2347 talloc_free(tmp_ctx);
2348 return status;
2352 /********************************************************************
2353 GetPrinterData on a printer server Handle.
2354 ********************************************************************/
2356 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2357 const char *value,
2358 enum winreg_Type *type,
2359 union spoolss_PrinterData *data)
2361 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2363 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2364 *type = REG_DWORD;
2365 data->value = 0x00;
2366 return WERR_OK;
2369 if (!strcasecmp_m(value, "BeepEnabled")) {
2370 *type = REG_DWORD;
2371 data->value = 0x00;
2372 return WERR_OK;
2375 if (!strcasecmp_m(value, "EventLog")) {
2376 *type = REG_DWORD;
2377 /* formally was 0x1b */
2378 data->value = 0x00;
2379 return WERR_OK;
2382 if (!strcasecmp_m(value, "NetPopup")) {
2383 *type = REG_DWORD;
2384 data->value = 0x00;
2385 return WERR_OK;
2388 if (!strcasecmp_m(value, "MajorVersion")) {
2389 *type = REG_DWORD;
2391 /* Windows NT 4.0 seems to not allow uploading of drivers
2392 to a server that reports 0x3 as the MajorVersion.
2393 need to investigate more how Win2k gets around this .
2394 -- jerry */
2396 if (RA_WINNT == get_remote_arch()) {
2397 data->value = 0x02;
2398 } else {
2399 data->value = 0x03;
2402 return WERR_OK;
2405 if (!strcasecmp_m(value, "MinorVersion")) {
2406 *type = REG_DWORD;
2407 data->value = 0x00;
2408 return WERR_OK;
2411 /* REG_BINARY
2412 * uint32_t size = 0x114
2413 * uint32_t major = 5
2414 * uint32_t minor = [0|1]
2415 * uint32_t build = [2195|2600]
2416 * extra unicode string = e.g. "Service Pack 3"
2418 if (!strcasecmp_m(value, "OSVersion")) {
2419 DATA_BLOB blob;
2420 enum ndr_err_code ndr_err;
2421 struct spoolss_OSVersion os;
2423 os.major = 5; /* Windows 2000 == 5.0 */
2424 os.minor = 0;
2425 os.build = 2195; /* build */
2426 os.extra_string = ""; /* leave extra string empty */
2428 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2429 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2430 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2431 return WERR_GENERAL_FAILURE;
2434 *type = REG_BINARY;
2435 data->binary = blob;
2437 return WERR_OK;
2441 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2442 *type = REG_SZ;
2444 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2445 W_ERROR_HAVE_NO_MEMORY(data->string);
2447 return WERR_OK;
2450 if (!strcasecmp_m(value, "Architecture")) {
2451 *type = REG_SZ;
2452 data->string = talloc_strdup(mem_ctx,
2453 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2454 W_ERROR_HAVE_NO_MEMORY(data->string);
2456 return WERR_OK;
2459 if (!strcasecmp_m(value, "DsPresent")) {
2460 *type = REG_DWORD;
2462 /* only show the publish check box if we are a
2463 member of a AD domain */
2465 if (lp_security() == SEC_ADS) {
2466 data->value = 0x01;
2467 } else {
2468 data->value = 0x00;
2470 return WERR_OK;
2473 if (!strcasecmp_m(value, "DNSMachineName")) {
2474 const char *hostname = get_mydnsfullname();
2476 if (!hostname) {
2477 return WERR_BADFILE;
2480 *type = REG_SZ;
2481 data->string = talloc_strdup(mem_ctx, hostname);
2482 W_ERROR_HAVE_NO_MEMORY(data->string);
2484 return WERR_OK;
2487 *type = REG_NONE;
2489 return WERR_INVALID_PARAM;
2492 /****************************************************************
2493 _spoolss_GetPrinterData
2494 ****************************************************************/
2496 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2497 struct spoolss_GetPrinterData *r)
2499 struct spoolss_GetPrinterDataEx r2;
2501 r2.in.handle = r->in.handle;
2502 r2.in.key_name = "PrinterDriverData";
2503 r2.in.value_name = r->in.value_name;
2504 r2.in.offered = r->in.offered;
2505 r2.out.type = r->out.type;
2506 r2.out.data = r->out.data;
2507 r2.out.needed = r->out.needed;
2509 return _spoolss_GetPrinterDataEx(p, &r2);
2512 /*********************************************************
2513 Connect to the client machine.
2514 **********************************************************/
2516 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2517 struct sockaddr_storage *client_ss, const char *remote_machine)
2519 NTSTATUS ret;
2520 struct cli_state *the_cli;
2521 struct sockaddr_storage rm_addr;
2522 char addr[INET6_ADDRSTRLEN];
2524 if ( is_zero_addr(client_ss) ) {
2525 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2526 remote_machine));
2527 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2528 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2529 return false;
2531 print_sockaddr(addr, sizeof(addr), &rm_addr);
2532 } else {
2533 rm_addr = *client_ss;
2534 print_sockaddr(addr, sizeof(addr), &rm_addr);
2535 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2536 addr));
2539 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2540 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2541 addr));
2542 return false;
2545 /* setup the connection */
2546 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2547 &rm_addr, 0, "IPC$", "IPC",
2548 "", /* username */
2549 "", /* domain */
2550 "", /* password */
2551 0, lp_client_signing());
2553 if ( !NT_STATUS_IS_OK( ret ) ) {
2554 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2555 remote_machine ));
2556 return false;
2559 if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2560 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2561 cli_shutdown(the_cli);
2562 return false;
2566 * Ok - we have an anonymous connection to the IPC$ share.
2567 * Now start the NT Domain stuff :-).
2570 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2571 if (!NT_STATUS_IS_OK(ret)) {
2572 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2573 remote_machine, nt_errstr(ret)));
2574 cli_shutdown(the_cli);
2575 return false;
2578 return true;
2581 /***************************************************************************
2582 Connect to the client.
2583 ****************************************************************************/
2585 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2586 uint32_t localprinter,
2587 enum winreg_Type type,
2588 struct policy_handle *handle,
2589 struct notify_back_channel **_chan,
2590 struct sockaddr_storage *client_ss,
2591 struct messaging_context *msg_ctx)
2593 WERROR result;
2594 NTSTATUS status;
2595 struct notify_back_channel *chan;
2597 for (chan = back_channels; chan; chan = chan->next) {
2598 if (memcmp(&chan->client_address, client_ss,
2599 sizeof(struct sockaddr_storage)) == 0) {
2600 break;
2605 * If it's the first connection, contact the client
2606 * and connect to the IPC$ share anonymously
2608 if (!chan) {
2609 fstring unix_printer;
2611 /* the +2 is to strip the leading 2 backslashs */
2612 fstrcpy(unix_printer, printer + 2);
2614 chan = talloc_zero(back_channels, struct notify_back_channel);
2615 if (!chan) {
2616 return false;
2618 chan->client_address = *client_ss;
2620 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2621 TALLOC_FREE(chan);
2622 return false;
2624 chan->binding_handle = chan->cli_pipe->binding_handle;
2626 DLIST_ADD(back_channels, chan);
2628 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2629 receive_notify2_message_list);
2633 * Tell the specific printing tdb we want messages for this printer
2634 * by registering our PID.
2637 if (!print_notify_register_pid(snum)) {
2638 DEBUG(0, ("Failed to register our pid for printer %s\n",
2639 printer));
2642 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2643 talloc_tos(),
2644 printer,
2645 localprinter,
2646 type,
2648 NULL,
2649 handle,
2650 &result);
2651 if (!NT_STATUS_IS_OK(status)) {
2652 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2653 result = ntstatus_to_werror(status);
2654 } else if (!W_ERROR_IS_OK(result)) {
2655 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2658 chan->active_connections++;
2659 *_chan = chan;
2661 return (W_ERROR_IS_OK(result));
2664 /****************************************************************
2665 ****************************************************************/
2667 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2668 const struct spoolss_NotifyOption *r)
2670 struct spoolss_NotifyOption *option;
2671 uint32_t i,k;
2673 if (!r) {
2674 return NULL;
2677 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2678 if (!option) {
2679 return NULL;
2682 *option = *r;
2684 if (!option->count) {
2685 return option;
2688 option->types = talloc_zero_array(option,
2689 struct spoolss_NotifyOptionType, option->count);
2690 if (!option->types) {
2691 talloc_free(option);
2692 return NULL;
2695 for (i=0; i < option->count; i++) {
2696 option->types[i] = r->types[i];
2698 if (option->types[i].count) {
2699 option->types[i].fields = talloc_zero_array(option,
2700 union spoolss_Field, option->types[i].count);
2701 if (!option->types[i].fields) {
2702 talloc_free(option);
2703 return NULL;
2705 for (k=0; k<option->types[i].count; k++) {
2706 option->types[i].fields[k] =
2707 r->types[i].fields[k];
2712 return option;
2715 /****************************************************************
2716 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2718 * before replying OK: status=0 a rpc call is made to the workstation
2719 * asking ReplyOpenPrinter
2721 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2722 * called from api_spoolss_rffpcnex
2723 ****************************************************************/
2725 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2726 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2728 int snum = -1;
2729 struct spoolss_NotifyOption *option = r->in.notify_options;
2730 struct sockaddr_storage client_ss;
2731 socklen_t client_len;
2733 /* store the notify value in the printer struct */
2735 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2737 if (!Printer) {
2738 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2739 "Invalid handle (%s:%u:%u).\n",
2740 OUR_HANDLE(r->in.handle)));
2741 return WERR_BADFID;
2744 Printer->notify.flags = r->in.flags;
2745 Printer->notify.options = r->in.options;
2746 Printer->notify.printerlocal = r->in.printer_local;
2747 Printer->notify.msg_ctx = p->msg_ctx;
2749 TALLOC_FREE(Printer->notify.option);
2750 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2752 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2754 /* Connect to the client machine and send a ReplyOpenPrinter */
2756 if ( Printer->printer_type == SPLHND_SERVER)
2757 snum = -1;
2758 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2759 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2760 return WERR_BADFID;
2762 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2763 "remote_address is %s\n",
2764 tsocket_address_string(p->remote_address, p->mem_ctx)));
2766 if (!lp_print_notify_backchannel(snum)) {
2767 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2768 "backchannel disabled\n"));
2769 return WERR_SERVER_UNAVAILABLE;
2772 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2773 (struct sockaddr *) &client_ss,
2774 sizeof(struct sockaddr_storage));
2775 if (client_len < 0) {
2776 return WERR_NOMEM;
2779 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2780 Printer->notify.printerlocal, REG_SZ,
2781 &Printer->notify.cli_hnd,
2782 &Printer->notify.cli_chan,
2783 &client_ss, p->msg_ctx)) {
2784 return WERR_SERVER_UNAVAILABLE;
2787 return WERR_OK;
2790 /*******************************************************************
2791 * fill a notify_info_data with the servername
2792 ********************************************************************/
2794 static void spoolss_notify_server_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->servername);
2804 /*******************************************************************
2805 * fill a notify_info_data with the printername (not including the servername).
2806 ********************************************************************/
2808 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2809 int snum,
2810 struct spoolss_Notify *data,
2811 print_queue_struct *queue,
2812 struct spoolss_PrinterInfo2 *pinfo2,
2813 TALLOC_CTX *mem_ctx)
2815 /* the notify name should not contain the \\server\ part */
2816 const char *p = strrchr(pinfo2->printername, '\\');
2818 if (!p) {
2819 p = pinfo2->printername;
2820 } else {
2821 p++;
2824 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2827 /*******************************************************************
2828 * fill a notify_info_data with the servicename
2829 ********************************************************************/
2831 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2832 int snum,
2833 struct spoolss_Notify *data,
2834 print_queue_struct *queue,
2835 struct spoolss_PrinterInfo2 *pinfo2,
2836 TALLOC_CTX *mem_ctx)
2838 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2841 /*******************************************************************
2842 * fill a notify_info_data with the port name
2843 ********************************************************************/
2845 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2846 int snum,
2847 struct spoolss_Notify *data,
2848 print_queue_struct *queue,
2849 struct spoolss_PrinterInfo2 *pinfo2,
2850 TALLOC_CTX *mem_ctx)
2852 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2855 /*******************************************************************
2856 * fill a notify_info_data with the printername
2857 * but it doesn't exist, have to see what to do
2858 ********************************************************************/
2860 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2861 int snum,
2862 struct spoolss_Notify *data,
2863 print_queue_struct *queue,
2864 struct spoolss_PrinterInfo2 *pinfo2,
2865 TALLOC_CTX *mem_ctx)
2867 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2870 /*******************************************************************
2871 * fill a notify_info_data with the comment
2872 ********************************************************************/
2874 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2875 int snum,
2876 struct spoolss_Notify *data,
2877 print_queue_struct *queue,
2878 struct spoolss_PrinterInfo2 *pinfo2,
2879 TALLOC_CTX *mem_ctx)
2881 const char *p;
2883 if (*pinfo2->comment == '\0') {
2884 p = lp_comment(snum);
2885 } else {
2886 p = pinfo2->comment;
2889 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2892 /*******************************************************************
2893 * fill a notify_info_data with the comment
2894 * location = "Room 1, floor 2, building 3"
2895 ********************************************************************/
2897 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2898 int snum,
2899 struct spoolss_Notify *data,
2900 print_queue_struct *queue,
2901 struct spoolss_PrinterInfo2 *pinfo2,
2902 TALLOC_CTX *mem_ctx)
2904 const char *loc = pinfo2->location;
2905 NTSTATUS status;
2907 status = printer_list_get_printer(mem_ctx,
2908 pinfo2->sharename,
2909 NULL,
2910 &loc,
2911 NULL);
2912 if (NT_STATUS_IS_OK(status)) {
2913 if (loc == NULL) {
2914 loc = pinfo2->location;
2918 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2921 /*******************************************************************
2922 * fill a notify_info_data with the device mode
2923 * jfm:xxxx don't to it for know but that's a real problem !!!
2924 ********************************************************************/
2926 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2927 int snum,
2928 struct spoolss_Notify *data,
2929 print_queue_struct *queue,
2930 struct spoolss_PrinterInfo2 *pinfo2,
2931 TALLOC_CTX *mem_ctx)
2933 /* for a dummy implementation we have to zero the fields */
2934 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2937 /*******************************************************************
2938 * fill a notify_info_data with the separator file name
2939 ********************************************************************/
2941 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2942 int snum,
2943 struct spoolss_Notify *data,
2944 print_queue_struct *queue,
2945 struct spoolss_PrinterInfo2 *pinfo2,
2946 TALLOC_CTX *mem_ctx)
2948 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2951 /*******************************************************************
2952 * fill a notify_info_data with the print processor
2953 * jfm:xxxx return always winprint to indicate we don't do anything to it
2954 ********************************************************************/
2956 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2957 int snum,
2958 struct spoolss_Notify *data,
2959 print_queue_struct *queue,
2960 struct spoolss_PrinterInfo2 *pinfo2,
2961 TALLOC_CTX *mem_ctx)
2963 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2966 /*******************************************************************
2967 * fill a notify_info_data with the print processor options
2968 * jfm:xxxx send an empty string
2969 ********************************************************************/
2971 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2972 int snum,
2973 struct spoolss_Notify *data,
2974 print_queue_struct *queue,
2975 struct spoolss_PrinterInfo2 *pinfo2,
2976 TALLOC_CTX *mem_ctx)
2978 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2981 /*******************************************************************
2982 * fill a notify_info_data with the data type
2983 * jfm:xxxx always send RAW as data type
2984 ********************************************************************/
2986 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2987 int snum,
2988 struct spoolss_Notify *data,
2989 print_queue_struct *queue,
2990 struct spoolss_PrinterInfo2 *pinfo2,
2991 TALLOC_CTX *mem_ctx)
2993 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2996 /*******************************************************************
2997 * fill a notify_info_data with the security descriptor
2998 * jfm:xxxx send an null pointer to say no security desc
2999 * have to implement security before !
3000 ********************************************************************/
3002 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3003 int snum,
3004 struct spoolss_Notify *data,
3005 print_queue_struct *queue,
3006 struct spoolss_PrinterInfo2 *pinfo2,
3007 TALLOC_CTX *mem_ctx)
3009 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3012 /*******************************************************************
3013 * fill a notify_info_data with the attributes
3014 * jfm:xxxx a samba printer is always shared
3015 ********************************************************************/
3017 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3018 int snum,
3019 struct spoolss_Notify *data,
3020 print_queue_struct *queue,
3021 struct spoolss_PrinterInfo2 *pinfo2,
3022 TALLOC_CTX *mem_ctx)
3024 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3027 /*******************************************************************
3028 * fill a notify_info_data with the priority
3029 ********************************************************************/
3031 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3032 int snum,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 struct spoolss_PrinterInfo2 *pinfo2,
3036 TALLOC_CTX *mem_ctx)
3038 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3041 /*******************************************************************
3042 * fill a notify_info_data with the default priority
3043 ********************************************************************/
3045 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3046 int snum,
3047 struct spoolss_Notify *data,
3048 print_queue_struct *queue,
3049 struct spoolss_PrinterInfo2 *pinfo2,
3050 TALLOC_CTX *mem_ctx)
3052 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3055 /*******************************************************************
3056 * fill a notify_info_data with the start time
3057 ********************************************************************/
3059 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3060 int snum,
3061 struct spoolss_Notify *data,
3062 print_queue_struct *queue,
3063 struct spoolss_PrinterInfo2 *pinfo2,
3064 TALLOC_CTX *mem_ctx)
3066 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3069 /*******************************************************************
3070 * fill a notify_info_data with the until time
3071 ********************************************************************/
3073 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3074 int snum,
3075 struct spoolss_Notify *data,
3076 print_queue_struct *queue,
3077 struct spoolss_PrinterInfo2 *pinfo2,
3078 TALLOC_CTX *mem_ctx)
3080 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3083 /*******************************************************************
3084 * fill a notify_info_data with the status
3085 ********************************************************************/
3087 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3088 int snum,
3089 struct spoolss_Notify *data,
3090 print_queue_struct *queue,
3091 struct spoolss_PrinterInfo2 *pinfo2,
3092 TALLOC_CTX *mem_ctx)
3094 print_status_struct status;
3096 print_queue_length(msg_ctx, snum, &status);
3097 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3100 /*******************************************************************
3101 * fill a notify_info_data with the number of jobs queued
3102 ********************************************************************/
3104 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3105 int snum,
3106 struct spoolss_Notify *data,
3107 print_queue_struct *queue,
3108 struct spoolss_PrinterInfo2 *pinfo2,
3109 TALLOC_CTX *mem_ctx)
3111 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3112 data, print_queue_length(msg_ctx, snum, NULL));
3115 /*******************************************************************
3116 * fill a notify_info_data with the average ppm
3117 ********************************************************************/
3119 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3120 int snum,
3121 struct spoolss_Notify *data,
3122 print_queue_struct *queue,
3123 struct spoolss_PrinterInfo2 *pinfo2,
3124 TALLOC_CTX *mem_ctx)
3126 /* always respond 8 pages per minutes */
3127 /* a little hard ! */
3128 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3131 /*******************************************************************
3132 * fill a notify_info_data with username
3133 ********************************************************************/
3135 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3136 int snum,
3137 struct spoolss_Notify *data,
3138 print_queue_struct *queue,
3139 struct spoolss_PrinterInfo2 *pinfo2,
3140 TALLOC_CTX *mem_ctx)
3142 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3145 /*******************************************************************
3146 * fill a notify_info_data with job status
3147 ********************************************************************/
3149 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3150 int snum,
3151 struct spoolss_Notify *data,
3152 print_queue_struct *queue,
3153 struct spoolss_PrinterInfo2 *pinfo2,
3154 TALLOC_CTX *mem_ctx)
3156 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3159 /*******************************************************************
3160 * fill a notify_info_data with job name
3161 ********************************************************************/
3163 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3164 int snum,
3165 struct spoolss_Notify *data,
3166 print_queue_struct *queue,
3167 struct spoolss_PrinterInfo2 *pinfo2,
3168 TALLOC_CTX *mem_ctx)
3170 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3173 /*******************************************************************
3174 * fill a notify_info_data with job status
3175 ********************************************************************/
3177 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3178 int snum,
3179 struct spoolss_Notify *data,
3180 print_queue_struct *queue,
3181 struct spoolss_PrinterInfo2 *pinfo2,
3182 TALLOC_CTX *mem_ctx)
3185 * Now we're returning job status codes we just return a "" here. JRA.
3188 const char *p = "";
3190 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3191 p = "unknown";
3193 switch (queue->status) {
3194 case LPQ_QUEUED:
3195 p = "Queued";
3196 break;
3197 case LPQ_PAUSED:
3198 p = ""; /* NT provides the paused string */
3199 break;
3200 case LPQ_SPOOLING:
3201 p = "Spooling";
3202 break;
3203 case LPQ_PRINTING:
3204 p = "Printing";
3205 break;
3207 #endif /* NO LONGER NEEDED. */
3209 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3212 /*******************************************************************
3213 * fill a notify_info_data with job time
3214 ********************************************************************/
3216 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3217 int snum,
3218 struct spoolss_Notify *data,
3219 print_queue_struct *queue,
3220 struct spoolss_PrinterInfo2 *pinfo2,
3221 TALLOC_CTX *mem_ctx)
3223 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3226 /*******************************************************************
3227 * fill a notify_info_data with job size
3228 ********************************************************************/
3230 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3231 int snum,
3232 struct spoolss_Notify *data,
3233 print_queue_struct *queue,
3234 struct spoolss_PrinterInfo2 *pinfo2,
3235 TALLOC_CTX *mem_ctx)
3237 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3240 /*******************************************************************
3241 * fill a notify_info_data with page info
3242 ********************************************************************/
3243 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3244 int snum,
3245 struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 struct spoolss_PrinterInfo2 *pinfo2,
3248 TALLOC_CTX *mem_ctx)
3250 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3253 /*******************************************************************
3254 * fill a notify_info_data with pages printed info.
3255 ********************************************************************/
3256 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3257 int snum,
3258 struct spoolss_Notify *data,
3259 print_queue_struct *queue,
3260 struct spoolss_PrinterInfo2 *pinfo2,
3261 TALLOC_CTX *mem_ctx)
3263 /* Add code when back-end tracks this */
3264 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3267 /*******************************************************************
3268 Fill a notify_info_data with job position.
3269 ********************************************************************/
3271 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3272 int snum,
3273 struct spoolss_Notify *data,
3274 print_queue_struct *queue,
3275 struct spoolss_PrinterInfo2 *pinfo2,
3276 TALLOC_CTX *mem_ctx)
3278 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3281 /*******************************************************************
3282 Fill a notify_info_data with submitted time.
3283 ********************************************************************/
3285 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3286 int snum,
3287 struct spoolss_Notify *data,
3288 print_queue_struct *queue,
3289 struct spoolss_PrinterInfo2 *pinfo2,
3290 TALLOC_CTX *mem_ctx)
3292 data->data.string.string = NULL;
3293 data->data.string.size = 0;
3295 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3296 &data->data.string.string,
3297 &data->data.string.size);
3301 struct s_notify_info_data_table
3303 enum spoolss_NotifyType type;
3304 uint16_t field;
3305 const char *name;
3306 enum spoolss_NotifyTable variable_type;
3307 void (*fn) (struct messaging_context *msg_ctx,
3308 int snum, struct spoolss_Notify *data,
3309 print_queue_struct *queue,
3310 struct spoolss_PrinterInfo2 *pinfo2,
3311 TALLOC_CTX *mem_ctx);
3314 /* A table describing the various print notification constants and
3315 whether the notification data is a pointer to a variable sized
3316 buffer, a one value uint32_t or a two value uint32_t. */
3318 static const struct s_notify_info_data_table notify_info_data_table[] =
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3328 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3329 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3330 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3334 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3349 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3350 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3351 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3352 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3353 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3354 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3355 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3356 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3357 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3358 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3359 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3360 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3361 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3362 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3363 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3364 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3365 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3366 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3367 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3368 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3371 /*******************************************************************
3372 Return the variable_type of info_data structure.
3373 ********************************************************************/
3375 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3376 uint16_t field)
3378 int i=0;
3380 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3381 if ( (notify_info_data_table[i].type == type) &&
3382 (notify_info_data_table[i].field == field) ) {
3383 return notify_info_data_table[i].variable_type;
3387 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3389 return (enum spoolss_NotifyTable) 0;
3392 /****************************************************************************
3393 ****************************************************************************/
3395 static bool search_notify(enum spoolss_NotifyType type,
3396 uint16_t field,
3397 int *value)
3399 int i;
3401 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3402 if (notify_info_data_table[i].type == type &&
3403 notify_info_data_table[i].field == field &&
3404 notify_info_data_table[i].fn != NULL) {
3405 *value = i;
3406 return true;
3410 return false;
3413 /****************************************************************************
3414 ****************************************************************************/
3416 static void construct_info_data(struct spoolss_Notify *info_data,
3417 enum spoolss_NotifyType type,
3418 uint16_t field, int id)
3420 info_data->type = type;
3421 info_data->field.field = field;
3422 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3423 info_data->job_id = id;
3426 /*******************************************************************
3428 * fill a notify_info struct with info asked
3430 ********************************************************************/
3432 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3433 struct printer_handle *print_hnd,
3434 struct spoolss_NotifyInfo *info,
3435 struct spoolss_PrinterInfo2 *pinfo2,
3436 int snum,
3437 const struct spoolss_NotifyOptionType *option_type,
3438 uint32_t id,
3439 TALLOC_CTX *mem_ctx)
3441 int field_num,j;
3442 enum spoolss_NotifyType type;
3443 uint16_t field;
3445 struct spoolss_Notify *current_data;
3447 type = option_type->type;
3449 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3450 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3451 option_type->count, lp_servicename(snum)));
3453 for(field_num=0; field_num < option_type->count; field_num++) {
3454 field = option_type->fields[field_num].field;
3456 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3458 if (!search_notify(type, field, &j) )
3459 continue;
3461 info->notifies = talloc_realloc(info, info->notifies,
3462 struct spoolss_Notify,
3463 info->count + 1);
3464 if (info->notifies == NULL) {
3465 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3466 return false;
3469 current_data = &info->notifies[info->count];
3471 construct_info_data(current_data, type, field, id);
3473 DEBUG(10, ("construct_notify_printer_info: "
3474 "calling [%s] snum=%d printername=[%s])\n",
3475 notify_info_data_table[j].name, snum,
3476 pinfo2->printername));
3478 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3479 NULL, pinfo2, mem_ctx);
3481 info->count++;
3484 return true;
3487 /*******************************************************************
3489 * fill a notify_info struct with info asked
3491 ********************************************************************/
3493 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3494 print_queue_struct *queue,
3495 struct spoolss_NotifyInfo *info,
3496 struct spoolss_PrinterInfo2 *pinfo2,
3497 int snum,
3498 const struct spoolss_NotifyOptionType *option_type,
3499 uint32_t id,
3500 TALLOC_CTX *mem_ctx)
3502 int field_num,j;
3503 enum spoolss_NotifyType type;
3504 uint16_t field;
3505 struct spoolss_Notify *current_data;
3507 DEBUG(4,("construct_notify_jobs_info\n"));
3509 type = option_type->type;
3511 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3512 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3513 option_type->count));
3515 for(field_num=0; field_num<option_type->count; field_num++) {
3516 field = option_type->fields[field_num].field;
3518 if (!search_notify(type, field, &j) )
3519 continue;
3521 info->notifies = talloc_realloc(info, info->notifies,
3522 struct spoolss_Notify,
3523 info->count + 1);
3524 if (info->notifies == NULL) {
3525 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3526 return false;
3529 current_data=&(info->notifies[info->count]);
3531 construct_info_data(current_data, type, field, id);
3532 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3533 queue, pinfo2, mem_ctx);
3534 info->count++;
3537 return true;
3541 * JFM: The enumeration is not that simple, it's even non obvious.
3543 * let's take an example: I want to monitor the PRINTER SERVER for
3544 * the printer's name and the number of jobs currently queued.
3545 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3546 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3548 * I have 3 printers on the back of my server.
3550 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3551 * structures.
3552 * Number Data Id
3553 * 1 printer 1 name 1
3554 * 2 printer 1 cjob 1
3555 * 3 printer 2 name 2
3556 * 4 printer 2 cjob 2
3557 * 5 printer 3 name 3
3558 * 6 printer 3 name 3
3560 * that's the print server case, the printer case is even worse.
3563 /*******************************************************************
3565 * enumerate all printers on the printserver
3566 * fill a notify_info struct with info asked
3568 ********************************************************************/
3570 static WERROR printserver_notify_info(struct pipes_struct *p,
3571 struct policy_handle *hnd,
3572 struct spoolss_NotifyInfo *info,
3573 TALLOC_CTX *mem_ctx)
3575 int snum;
3576 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3577 int n_services=lp_numservices();
3578 int i;
3579 struct spoolss_NotifyOption *option;
3580 struct spoolss_NotifyOptionType option_type;
3581 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3582 WERROR result;
3584 DEBUG(4,("printserver_notify_info\n"));
3586 if (!Printer)
3587 return WERR_BADFID;
3589 option = Printer->notify.option;
3591 info->version = 2;
3592 info->notifies = NULL;
3593 info->count = 0;
3595 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3596 sending a ffpcn() request first */
3598 if ( !option )
3599 return WERR_BADFID;
3601 for (i=0; i<option->count; i++) {
3602 option_type = option->types[i];
3604 if (option_type.type != PRINTER_NOTIFY_TYPE)
3605 continue;
3607 for (snum = 0; snum < n_services; snum++) {
3608 if (!lp_browseable(snum) ||
3609 !lp_snum_ok(snum) ||
3610 !lp_print_ok(snum)) {
3611 continue; /* skip */
3614 /* Maybe we should use the SYSTEM session_info here... */
3615 result = winreg_get_printer_internal(mem_ctx,
3616 get_session_info_system(),
3617 p->msg_ctx,
3618 lp_servicename(snum),
3619 &pinfo2);
3620 if (!W_ERROR_IS_OK(result)) {
3621 DEBUG(4, ("printserver_notify_info: "
3622 "Failed to get printer [%s]\n",
3623 lp_servicename(snum)));
3624 continue;
3628 construct_notify_printer_info(p->msg_ctx,
3629 Printer, info,
3630 pinfo2, snum,
3631 &option_type, snum,
3632 mem_ctx);
3634 TALLOC_FREE(pinfo2);
3638 #if 0
3640 * Debugging information, don't delete.
3643 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3644 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3645 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3647 for (i=0; i<info->count; i++) {
3648 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3649 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3650 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3652 #endif
3654 return WERR_OK;
3657 /*******************************************************************
3659 * fill a notify_info struct with info asked
3661 ********************************************************************/
3663 static WERROR printer_notify_info(struct pipes_struct *p,
3664 struct policy_handle *hnd,
3665 struct spoolss_NotifyInfo *info,
3666 TALLOC_CTX *mem_ctx)
3668 int snum;
3669 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3670 int i;
3671 uint32_t id;
3672 struct spoolss_NotifyOption *option;
3673 struct spoolss_NotifyOptionType option_type;
3674 int count,j;
3675 print_queue_struct *queue=NULL;
3676 print_status_struct status;
3677 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3678 WERROR result;
3680 DEBUG(4,("printer_notify_info\n"));
3682 if (!Printer)
3683 return WERR_BADFID;
3685 option = Printer->notify.option;
3686 id = 0x0;
3688 info->version = 2;
3689 info->notifies = NULL;
3690 info->count = 0;
3692 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3693 sending a ffpcn() request first */
3695 if ( !option )
3696 return WERR_BADFID;
3698 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3699 return WERR_BADFID;
3702 /* Maybe we should use the SYSTEM session_info here... */
3703 result = winreg_get_printer_internal(mem_ctx,
3704 get_session_info_system(),
3705 p->msg_ctx,
3706 lp_servicename(snum), &pinfo2);
3707 if (!W_ERROR_IS_OK(result)) {
3708 return WERR_BADFID;
3711 for (i=0; i<option->count; i++) {
3712 option_type = option->types[i];
3714 switch (option_type.type) {
3715 case PRINTER_NOTIFY_TYPE:
3716 if (construct_notify_printer_info(p->msg_ctx,
3717 Printer, info,
3718 pinfo2, snum,
3719 &option_type, id,
3720 mem_ctx)) {
3721 id--;
3723 break;
3725 case JOB_NOTIFY_TYPE:
3727 count = print_queue_status(p->msg_ctx, snum, &queue,
3728 &status);
3730 for (j=0; j<count; j++) {
3731 construct_notify_jobs_info(p->msg_ctx,
3732 &queue[j], info,
3733 pinfo2, snum,
3734 &option_type,
3735 queue[j].job,
3736 mem_ctx);
3739 SAFE_FREE(queue);
3740 break;
3745 * Debugging information, don't delete.
3748 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3749 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3750 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3752 for (i=0; i<info->count; i++) {
3753 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3754 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3755 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3759 talloc_free(pinfo2);
3760 return WERR_OK;
3763 /****************************************************************
3764 _spoolss_RouterRefreshPrinterChangeNotify
3765 ****************************************************************/
3767 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3768 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3770 struct spoolss_NotifyInfo *info;
3772 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3773 WERROR result = WERR_BADFID;
3775 /* we always have a spoolss_NotifyInfo struct */
3776 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3777 if (!info) {
3778 result = WERR_NOMEM;
3779 goto done;
3782 *r->out.info = info;
3784 if (!Printer) {
3785 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3786 "Invalid handle (%s:%u:%u).\n",
3787 OUR_HANDLE(r->in.handle)));
3788 goto done;
3791 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3794 * We are now using the change value, and
3795 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3796 * I don't have a global notification system, I'm sending back all the
3797 * information even when _NOTHING_ has changed.
3800 /* We need to keep track of the change value to send back in
3801 RRPCN replies otherwise our updates are ignored. */
3803 Printer->notify.fnpcn = true;
3805 if (Printer->notify.cli_chan != NULL &&
3806 Printer->notify.cli_chan->active_connections > 0) {
3807 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3808 "Saving change value in request [%x]\n",
3809 r->in.change_low));
3810 Printer->notify.change = r->in.change_low;
3813 /* just ignore the spoolss_NotifyOption */
3815 switch (Printer->printer_type) {
3816 case SPLHND_SERVER:
3817 result = printserver_notify_info(p, r->in.handle,
3818 info, p->mem_ctx);
3819 break;
3821 case SPLHND_PRINTER:
3822 result = printer_notify_info(p, r->in.handle,
3823 info, p->mem_ctx);
3824 break;
3827 Printer->notify.fnpcn = false;
3829 done:
3830 return result;
3833 /********************************************************************
3834 ********************************************************************/
3836 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3837 const char *servername,
3838 const char *printername,
3839 const char **printername_p)
3841 /* FIXME: add lp_force_printername() */
3843 if (servername == NULL) {
3844 *printername_p = talloc_strdup(mem_ctx, printername);
3845 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3846 return WERR_OK;
3849 if (servername[0] == '\\' && servername[1] == '\\') {
3850 servername += 2;
3853 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3854 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3856 return WERR_OK;
3859 /********************************************************************
3860 ********************************************************************/
3862 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3863 const char *printername)
3865 if (dm == NULL) {
3866 return;
3869 dm->devicename = talloc_strndup(dm, printername,
3870 MIN(strlen(printername), 31));
3873 /********************************************************************
3874 * construct_printer_info_0
3875 * fill a printer_info_0 struct
3876 ********************************************************************/
3878 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3879 const struct auth_session_info *session_info,
3880 struct messaging_context *msg_ctx,
3881 struct spoolss_PrinterInfo2 *info2,
3882 const char *servername,
3883 struct spoolss_PrinterInfo0 *r,
3884 int snum)
3886 int count;
3887 struct printer_session_counter *session_counter;
3888 struct timeval setuptime;
3889 print_status_struct status;
3890 WERROR result;
3892 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3893 if (!W_ERROR_IS_OK(result)) {
3894 return result;
3897 if (servername) {
3898 r->servername = talloc_strdup(mem_ctx, servername);
3899 W_ERROR_HAVE_NO_MEMORY(r->servername);
3900 } else {
3901 r->servername = NULL;
3904 count = print_queue_length(msg_ctx, snum, &status);
3906 /* check if we already have a counter for this printer */
3907 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3908 if (session_counter->snum == snum)
3909 break;
3912 /* it's the first time, add it to the list */
3913 if (session_counter == NULL) {
3914 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3915 W_ERROR_HAVE_NO_MEMORY(session_counter);
3916 session_counter->snum = snum;
3917 session_counter->counter = 0;
3918 DLIST_ADD(counter_list, session_counter);
3921 /* increment it */
3922 session_counter->counter++;
3924 r->cjobs = count;
3925 r->total_jobs = 0;
3926 r->total_bytes = 0;
3928 get_startup_time(&setuptime);
3929 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3931 /* JFM:
3932 * the global_counter should be stored in a TDB as it's common to all the clients
3933 * and should be zeroed on samba startup
3935 r->global_counter = session_counter->counter;
3936 r->total_pages = 0;
3937 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3938 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3939 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3940 r->free_build = SPOOLSS_RELEASE_BUILD;
3941 r->spooling = 0;
3942 r->max_spooling = 0;
3943 r->session_counter = session_counter->counter;
3944 r->num_error_out_of_paper = 0x0;
3945 r->num_error_not_ready = 0x0; /* number of print failure */
3946 r->job_error = 0x0;
3947 r->number_of_processors = 0x1;
3948 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3949 r->high_part_total_bytes = 0x0;
3951 /* ChangeID in milliseconds*/
3952 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3953 info2->sharename, &r->change_id);
3955 r->last_error = WERR_OK;
3956 r->status = nt_printq_status(status.status);
3957 r->enumerate_network_printers = 0x0;
3958 r->c_setprinter = 0x0;
3959 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3960 r->processor_level = 0x6; /* 6 ???*/
3961 r->ref_ic = 0;
3962 r->reserved2 = 0;
3963 r->reserved3 = 0;
3965 return WERR_OK;
3969 /********************************************************************
3970 * construct_printer_info1
3971 * fill a spoolss_PrinterInfo1 struct
3972 ********************************************************************/
3974 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3975 const struct spoolss_PrinterInfo2 *info2,
3976 uint32_t flags,
3977 const char *servername,
3978 struct spoolss_PrinterInfo1 *r,
3979 int snum)
3981 WERROR result;
3983 r->flags = flags;
3985 if (info2->comment == NULL || info2->comment[0] == '\0') {
3986 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3987 } else {
3988 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3990 W_ERROR_HAVE_NO_MEMORY(r->comment);
3992 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3993 if (!W_ERROR_IS_OK(result)) {
3994 return result;
3997 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3998 r->name,
3999 info2->drivername,
4000 r->comment);
4001 W_ERROR_HAVE_NO_MEMORY(r->description);
4003 return WERR_OK;
4006 /********************************************************************
4007 * construct_printer_info2
4008 * fill a spoolss_PrinterInfo2 struct
4009 ********************************************************************/
4011 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4012 struct messaging_context *msg_ctx,
4013 const struct spoolss_PrinterInfo2 *info2,
4014 const char *servername,
4015 struct spoolss_PrinterInfo2 *r,
4016 int snum)
4018 int count;
4019 print_status_struct status;
4020 WERROR result;
4022 count = print_queue_length(msg_ctx, snum, &status);
4024 if (servername) {
4025 r->servername = talloc_strdup(mem_ctx, servername);
4026 W_ERROR_HAVE_NO_MEMORY(r->servername);
4027 } else {
4028 r->servername = NULL;
4031 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4032 if (!W_ERROR_IS_OK(result)) {
4033 return result;
4036 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4037 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4038 r->portname = talloc_strdup(mem_ctx, info2->portname);
4039 W_ERROR_HAVE_NO_MEMORY(r->portname);
4040 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4041 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4043 if (info2->comment[0] == '\0') {
4044 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4045 } else {
4046 r->comment = talloc_strdup(mem_ctx, info2->comment);
4048 W_ERROR_HAVE_NO_MEMORY(r->comment);
4050 r->location = talloc_strdup(mem_ctx, info2->location);
4051 if (info2->location[0] == '\0') {
4052 const char *loc = NULL;
4053 NTSTATUS nt_status;
4055 nt_status = printer_list_get_printer(mem_ctx,
4056 info2->sharename,
4057 NULL,
4058 &loc,
4059 NULL);
4060 if (NT_STATUS_IS_OK(nt_status)) {
4061 if (loc != NULL) {
4062 r->location = talloc_strdup(mem_ctx, loc);
4066 W_ERROR_HAVE_NO_MEMORY(r->location);
4068 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4069 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4070 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4071 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4072 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4073 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4074 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4075 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4077 r->attributes = info2->attributes;
4079 r->priority = info2->priority;
4080 r->defaultpriority = info2->defaultpriority;
4081 r->starttime = info2->starttime;
4082 r->untiltime = info2->untiltime;
4083 r->status = nt_printq_status(status.status);
4084 r->cjobs = count;
4085 r->averageppm = info2->averageppm;
4087 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4088 if (!r->devmode) {
4089 DEBUG(8,("Returning NULL Devicemode!\n"));
4092 compose_devicemode_devicename(r->devmode, r->printername);
4094 r->secdesc = NULL;
4096 if (info2->secdesc != NULL) {
4097 /* don't use talloc_steal() here unless you do a deep steal of all
4098 the SEC_DESC members */
4100 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4103 return WERR_OK;
4106 /********************************************************************
4107 * construct_printer_info3
4108 * fill a spoolss_PrinterInfo3 struct
4109 ********************************************************************/
4111 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4112 const struct spoolss_PrinterInfo2 *info2,
4113 const char *servername,
4114 struct spoolss_PrinterInfo3 *r,
4115 int snum)
4117 /* These are the components of the SD we are returning. */
4119 if (info2->secdesc != NULL) {
4120 /* don't use talloc_steal() here unless you do a deep steal of all
4121 the SEC_DESC members */
4123 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4124 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4127 return WERR_OK;
4130 /********************************************************************
4131 * construct_printer_info4
4132 * fill a spoolss_PrinterInfo4 struct
4133 ********************************************************************/
4135 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4136 const struct spoolss_PrinterInfo2 *info2,
4137 const char *servername,
4138 struct spoolss_PrinterInfo4 *r,
4139 int snum)
4141 WERROR result;
4143 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4144 if (!W_ERROR_IS_OK(result)) {
4145 return result;
4148 if (servername) {
4149 r->servername = talloc_strdup(mem_ctx, servername);
4150 W_ERROR_HAVE_NO_MEMORY(r->servername);
4151 } else {
4152 r->servername = NULL;
4155 r->attributes = info2->attributes;
4157 return WERR_OK;
4160 /********************************************************************
4161 * construct_printer_info5
4162 * fill a spoolss_PrinterInfo5 struct
4163 ********************************************************************/
4165 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4166 const struct spoolss_PrinterInfo2 *info2,
4167 const char *servername,
4168 struct spoolss_PrinterInfo5 *r,
4169 int snum)
4171 WERROR result;
4173 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4174 if (!W_ERROR_IS_OK(result)) {
4175 return result;
4178 r->portname = talloc_strdup(mem_ctx, info2->portname);
4179 W_ERROR_HAVE_NO_MEMORY(r->portname);
4181 r->attributes = info2->attributes;
4183 /* these two are not used by NT+ according to MSDN */
4184 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4185 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4187 return WERR_OK;
4190 /********************************************************************
4191 * construct_printer_info_6
4192 * fill a spoolss_PrinterInfo6 struct
4193 ********************************************************************/
4195 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4196 struct messaging_context *msg_ctx,
4197 const struct spoolss_PrinterInfo2 *info2,
4198 const char *servername,
4199 struct spoolss_PrinterInfo6 *r,
4200 int snum)
4202 print_status_struct status;
4204 print_queue_length(msg_ctx, snum, &status);
4206 r->status = nt_printq_status(status.status);
4208 return WERR_OK;
4211 /********************************************************************
4212 * construct_printer_info7
4213 * fill a spoolss_PrinterInfo7 struct
4214 ********************************************************************/
4216 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4217 struct messaging_context *msg_ctx,
4218 const char *servername,
4219 struct spoolss_PrinterInfo7 *r,
4220 int snum)
4222 const struct auth_session_info *session_info = get_session_info_system();
4223 struct GUID guid;
4225 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4226 servername,
4227 lp_servicename(snum), &guid, NULL)) {
4228 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4229 r->action = DSPRINT_PUBLISH;
4230 } else {
4231 r->guid = talloc_strdup(mem_ctx, "");
4232 r->action = DSPRINT_UNPUBLISH;
4234 W_ERROR_HAVE_NO_MEMORY(r->guid);
4236 return WERR_OK;
4239 /********************************************************************
4240 * construct_printer_info8
4241 * fill a spoolss_PrinterInfo8 struct
4242 ********************************************************************/
4244 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4245 const struct spoolss_PrinterInfo2 *info2,
4246 const char *servername,
4247 struct spoolss_DeviceModeInfo *r,
4248 int snum)
4250 WERROR result;
4251 const char *printername;
4253 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4254 if (!W_ERROR_IS_OK(result)) {
4255 return result;
4258 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4259 if (!r->devmode) {
4260 DEBUG(8,("Returning NULL Devicemode!\n"));
4263 compose_devicemode_devicename(r->devmode, printername);
4265 return WERR_OK;
4269 /********************************************************************
4270 ********************************************************************/
4272 static bool snum_is_shared_printer(int snum)
4274 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4277 /********************************************************************
4278 Spoolss_enumprinters.
4279 ********************************************************************/
4281 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4282 const struct auth_session_info *session_info,
4283 struct messaging_context *msg_ctx,
4284 const char *servername,
4285 uint32_t level,
4286 uint32_t flags,
4287 union spoolss_PrinterInfo **info_p,
4288 uint32_t *count_p)
4290 int snum;
4291 int n_services = lp_numservices();
4292 union spoolss_PrinterInfo *info = NULL;
4293 uint32_t count = 0;
4294 WERROR result = WERR_OK;
4295 struct dcerpc_binding_handle *b = NULL;
4296 TALLOC_CTX *tmp_ctx = NULL;
4298 tmp_ctx = talloc_new(mem_ctx);
4299 if (!tmp_ctx) {
4300 return WERR_NOMEM;
4303 *count_p = 0;
4304 *info_p = NULL;
4306 for (snum = 0; snum < n_services; snum++) {
4308 const char *printer;
4309 struct spoolss_PrinterInfo2 *info2;
4311 if (!snum_is_shared_printer(snum)) {
4312 continue;
4315 printer = lp_const_servicename(snum);
4317 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4318 printer, snum));
4320 if (b == NULL) {
4321 result = winreg_printer_binding_handle(tmp_ctx,
4322 session_info,
4323 msg_ctx,
4324 &b);
4325 if (!W_ERROR_IS_OK(result)) {
4326 goto out;
4330 result = winreg_create_printer(tmp_ctx, b,
4331 printer);
4332 if (!W_ERROR_IS_OK(result)) {
4333 goto out;
4336 info = talloc_realloc(tmp_ctx, info,
4337 union spoolss_PrinterInfo,
4338 count + 1);
4339 if (!info) {
4340 result = WERR_NOMEM;
4341 goto out;
4344 result = winreg_get_printer(tmp_ctx, b,
4345 printer, &info2);
4346 if (!W_ERROR_IS_OK(result)) {
4347 goto out;
4350 switch (level) {
4351 case 0:
4352 result = construct_printer_info0(info, session_info,
4353 msg_ctx, info2,
4354 servername,
4355 &info[count].info0, snum);
4356 break;
4357 case 1:
4358 result = construct_printer_info1(info, info2, flags,
4359 servername,
4360 &info[count].info1, snum);
4361 break;
4362 case 2:
4363 result = construct_printer_info2(info, msg_ctx, info2,
4364 servername,
4365 &info[count].info2, snum);
4366 break;
4367 case 4:
4368 result = construct_printer_info4(info, info2,
4369 servername,
4370 &info[count].info4, snum);
4371 break;
4372 case 5:
4373 result = construct_printer_info5(info, info2,
4374 servername,
4375 &info[count].info5, snum);
4376 break;
4378 default:
4379 result = WERR_UNKNOWN_LEVEL;
4380 goto out;
4383 if (!W_ERROR_IS_OK(result)) {
4384 goto out;
4387 count++;
4390 out:
4391 if (W_ERROR_IS_OK(result)) {
4392 *info_p = talloc_move(mem_ctx, &info);
4393 *count_p = count;
4396 talloc_free(tmp_ctx);
4398 return result;
4401 /********************************************************************
4402 * handle enumeration of printers at level 0
4403 ********************************************************************/
4405 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4406 const struct auth_session_info *session_info,
4407 struct messaging_context *msg_ctx,
4408 uint32_t flags,
4409 const char *servername,
4410 union spoolss_PrinterInfo **info,
4411 uint32_t *count)
4413 DEBUG(4,("enum_all_printers_info_0\n"));
4415 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4416 servername, 0, flags, info, count);
4420 /********************************************************************
4421 ********************************************************************/
4423 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4424 const struct auth_session_info *session_info,
4425 struct messaging_context *msg_ctx,
4426 const char *servername,
4427 uint32_t flags,
4428 union spoolss_PrinterInfo **info,
4429 uint32_t *count)
4431 DEBUG(4,("enum_all_printers_info_1\n"));
4433 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4434 servername, 1, flags, info, count);
4437 /********************************************************************
4438 enum_all_printers_info_1_local.
4439 *********************************************************************/
4441 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4442 const struct auth_session_info *session_info,
4443 struct messaging_context *msg_ctx,
4444 const char *servername,
4445 union spoolss_PrinterInfo **info,
4446 uint32_t *count)
4448 DEBUG(4,("enum_all_printers_info_1_local\n"));
4450 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4451 servername, PRINTER_ENUM_ICON8, info, count);
4454 /********************************************************************
4455 enum_all_printers_info_1_name.
4456 *********************************************************************/
4458 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4459 const struct auth_session_info *session_info,
4460 struct messaging_context *msg_ctx,
4461 const char *servername,
4462 union spoolss_PrinterInfo **info,
4463 uint32_t *count)
4465 const char *s = servername;
4467 DEBUG(4,("enum_all_printers_info_1_name\n"));
4469 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4470 s = servername + 2;
4473 if (!is_myname_or_ipaddr(s)) {
4474 return WERR_INVALID_NAME;
4477 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4478 servername, PRINTER_ENUM_ICON8, info, count);
4481 /********************************************************************
4482 enum_all_printers_info_1_network.
4483 *********************************************************************/
4485 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4486 const struct auth_session_info *session_info,
4487 struct messaging_context *msg_ctx,
4488 const char *servername,
4489 union spoolss_PrinterInfo **info,
4490 uint32_t *count)
4492 const char *s = servername;
4494 DEBUG(4,("enum_all_printers_info_1_network\n"));
4496 /* If we respond to a enum_printers level 1 on our name with flags
4497 set to PRINTER_ENUM_REMOTE with a list of printers then these
4498 printers incorrectly appear in the APW browse list.
4499 Specifically the printers for the server appear at the workgroup
4500 level where all the other servers in the domain are
4501 listed. Windows responds to this call with a
4502 WERR_CAN_NOT_COMPLETE so we should do the same. */
4504 if (servername[0] == '\\' && servername[1] == '\\') {
4505 s = servername + 2;
4508 if (is_myname_or_ipaddr(s)) {
4509 return WERR_CAN_NOT_COMPLETE;
4512 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4513 servername, PRINTER_ENUM_NAME, info, count);
4516 /********************************************************************
4517 * api_spoolss_enumprinters
4519 * called from api_spoolss_enumprinters (see this to understand)
4520 ********************************************************************/
4522 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4523 const struct auth_session_info *session_info,
4524 struct messaging_context *msg_ctx,
4525 const char *servername,
4526 union spoolss_PrinterInfo **info,
4527 uint32_t *count)
4529 DEBUG(4,("enum_all_printers_info_2\n"));
4531 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4532 servername, 2, 0, info, count);
4535 /********************************************************************
4536 * handle enumeration of printers at level 1
4537 ********************************************************************/
4539 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4540 const struct auth_session_info *session_info,
4541 struct messaging_context *msg_ctx,
4542 uint32_t flags,
4543 const char *servername,
4544 union spoolss_PrinterInfo **info,
4545 uint32_t *count)
4547 /* Not all the flags are equals */
4549 if (flags & PRINTER_ENUM_LOCAL) {
4550 return enum_all_printers_info_1_local(mem_ctx, session_info,
4551 msg_ctx, servername, info, count);
4554 if (flags & PRINTER_ENUM_NAME) {
4555 return enum_all_printers_info_1_name(mem_ctx, session_info,
4556 msg_ctx, servername, info,
4557 count);
4560 if (flags & PRINTER_ENUM_NETWORK) {
4561 return enum_all_printers_info_1_network(mem_ctx, session_info,
4562 msg_ctx, servername, info,
4563 count);
4566 return WERR_OK; /* NT4sp5 does that */
4569 /********************************************************************
4570 * handle enumeration of printers at level 2
4571 ********************************************************************/
4573 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4574 const struct auth_session_info *session_info,
4575 struct messaging_context *msg_ctx,
4576 uint32_t flags,
4577 const char *servername,
4578 union spoolss_PrinterInfo **info,
4579 uint32_t *count)
4581 if (flags & PRINTER_ENUM_LOCAL) {
4583 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4584 servername,
4585 info, count);
4588 if (flags & PRINTER_ENUM_NAME) {
4589 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4590 return WERR_INVALID_NAME;
4593 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4594 servername,
4595 info, count);
4598 if (flags & PRINTER_ENUM_REMOTE) {
4599 return WERR_UNKNOWN_LEVEL;
4602 return WERR_OK;
4605 /********************************************************************
4606 * handle enumeration of printers at level 4
4607 ********************************************************************/
4609 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4610 const struct auth_session_info *session_info,
4611 struct messaging_context *msg_ctx,
4612 uint32_t flags,
4613 const char *servername,
4614 union spoolss_PrinterInfo **info,
4615 uint32_t *count)
4617 DEBUG(4,("enum_all_printers_info_4\n"));
4619 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4620 servername, 4, flags, info, count);
4624 /********************************************************************
4625 * handle enumeration of printers at level 5
4626 ********************************************************************/
4628 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4629 const struct auth_session_info *session_info,
4630 struct messaging_context *msg_ctx,
4631 uint32_t flags,
4632 const char *servername,
4633 union spoolss_PrinterInfo **info,
4634 uint32_t *count)
4636 DEBUG(4,("enum_all_printers_info_5\n"));
4638 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4639 servername, 5, flags, info, count);
4642 /****************************************************************
4643 _spoolss_EnumPrinters
4644 ****************************************************************/
4646 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4647 struct spoolss_EnumPrinters *r)
4649 const struct auth_session_info *session_info = get_session_info_system();
4650 WERROR result;
4652 /* that's an [in out] buffer */
4654 if (!r->in.buffer && (r->in.offered != 0)) {
4655 return WERR_INVALID_PARAM;
4658 DEBUG(4,("_spoolss_EnumPrinters\n"));
4660 *r->out.needed = 0;
4661 *r->out.count = 0;
4662 *r->out.info = NULL;
4665 * Level 1:
4666 * flags==PRINTER_ENUM_NAME
4667 * if name=="" then enumerates all printers
4668 * if name!="" then enumerate the printer
4669 * flags==PRINTER_ENUM_REMOTE
4670 * name is NULL, enumerate printers
4671 * Level 2: name!="" enumerates printers, name can't be NULL
4672 * Level 3: doesn't exist
4673 * Level 4: does a local registry lookup
4674 * Level 5: same as Level 2
4677 if (r->in.server && r->in.server[0] == '\0') {
4678 r->in.server = NULL;
4681 switch (r->in.level) {
4682 case 0:
4683 result = enumprinters_level0(p->mem_ctx, session_info,
4684 p->msg_ctx, r->in.flags,
4685 r->in.server,
4686 r->out.info, r->out.count);
4687 break;
4688 case 1:
4689 result = enumprinters_level1(p->mem_ctx, session_info,
4690 p->msg_ctx, r->in.flags,
4691 r->in.server,
4692 r->out.info, r->out.count);
4693 break;
4694 case 2:
4695 result = enumprinters_level2(p->mem_ctx, session_info,
4696 p->msg_ctx, r->in.flags,
4697 r->in.server,
4698 r->out.info, r->out.count);
4699 break;
4700 case 4:
4701 result = enumprinters_level4(p->mem_ctx, session_info,
4702 p->msg_ctx, r->in.flags,
4703 r->in.server,
4704 r->out.info, r->out.count);
4705 break;
4706 case 5:
4707 result = enumprinters_level5(p->mem_ctx, session_info,
4708 p->msg_ctx, r->in.flags,
4709 r->in.server,
4710 r->out.info, r->out.count);
4711 break;
4712 default:
4713 return WERR_UNKNOWN_LEVEL;
4716 if (!W_ERROR_IS_OK(result)) {
4717 return result;
4720 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4721 spoolss_EnumPrinters,
4722 *r->out.info, r->in.level,
4723 *r->out.count);
4724 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4725 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4727 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4730 /****************************************************************
4731 _spoolss_GetPrinter
4732 ****************************************************************/
4734 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4735 struct spoolss_GetPrinter *r)
4737 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4738 struct spoolss_PrinterInfo2 *info2 = NULL;
4739 WERROR result = WERR_OK;
4740 int snum;
4742 /* that's an [in out] buffer */
4744 if (!r->in.buffer && (r->in.offered != 0)) {
4745 return WERR_INVALID_PARAM;
4748 *r->out.needed = 0;
4750 if (Printer == NULL) {
4751 return WERR_BADFID;
4754 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4755 return WERR_BADFID;
4758 result = winreg_get_printer_internal(p->mem_ctx,
4759 get_session_info_system(),
4760 p->msg_ctx,
4761 lp_const_servicename(snum),
4762 &info2);
4763 if (!W_ERROR_IS_OK(result)) {
4764 goto out;
4767 switch (r->in.level) {
4768 case 0:
4769 result = construct_printer_info0(p->mem_ctx,
4770 get_session_info_system(),
4771 p->msg_ctx,
4772 info2,
4773 Printer->servername,
4774 &r->out.info->info0,
4775 snum);
4776 break;
4777 case 1:
4778 result = construct_printer_info1(p->mem_ctx, info2,
4779 PRINTER_ENUM_ICON8,
4780 Printer->servername,
4781 &r->out.info->info1, snum);
4782 break;
4783 case 2:
4784 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4785 Printer->servername,
4786 &r->out.info->info2, snum);
4787 break;
4788 case 3:
4789 result = construct_printer_info3(p->mem_ctx, info2,
4790 Printer->servername,
4791 &r->out.info->info3, snum);
4792 break;
4793 case 4:
4794 result = construct_printer_info4(p->mem_ctx, info2,
4795 Printer->servername,
4796 &r->out.info->info4, snum);
4797 break;
4798 case 5:
4799 result = construct_printer_info5(p->mem_ctx, info2,
4800 Printer->servername,
4801 &r->out.info->info5, snum);
4802 break;
4803 case 6:
4804 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4805 Printer->servername,
4806 &r->out.info->info6, snum);
4807 break;
4808 case 7:
4809 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4810 Printer->servername,
4811 &r->out.info->info7, snum);
4812 break;
4813 case 8:
4814 result = construct_printer_info8(p->mem_ctx, info2,
4815 Printer->servername,
4816 &r->out.info->info8, snum);
4817 break;
4818 default:
4819 result = WERR_UNKNOWN_LEVEL;
4820 break;
4822 TALLOC_FREE(info2);
4824 out:
4825 if (!W_ERROR_IS_OK(result)) {
4826 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4827 r->in.level, win_errstr(result)));
4828 TALLOC_FREE(r->out.info);
4829 return result;
4832 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4833 r->out.info, r->in.level);
4834 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4836 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4839 /********************************************************************
4840 ********************************************************************/
4842 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4843 do { \
4844 if (in && strlen(in)) { \
4845 out = talloc_strdup(mem_ctx, in); \
4846 } else { \
4847 out = talloc_strdup(mem_ctx, ""); \
4849 W_ERROR_HAVE_NO_MEMORY(out); \
4850 } while (0);
4852 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4853 do { \
4854 if (in && strlen(in)) { \
4855 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4856 } else { \
4857 out = talloc_strdup(mem_ctx, ""); \
4859 W_ERROR_HAVE_NO_MEMORY(out); \
4860 } while (0);
4862 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4863 const char **string_array,
4864 const char ***presult,
4865 const char *cservername,
4866 const char *arch,
4867 int version)
4869 int i, num_strings = 0;
4870 const char **array = NULL;
4872 if (string_array == NULL) {
4873 return WERR_INVALID_PARAMETER;
4876 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4877 const char *str = NULL;
4879 if (cservername == NULL || arch == NULL) {
4880 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4881 } else {
4882 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4885 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4886 TALLOC_FREE(array);
4887 return WERR_NOMEM;
4891 if (i > 0) {
4892 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4893 &array, &num_strings);
4896 if (presult) {
4897 *presult = array;
4900 return WERR_OK;
4903 /********************************************************************
4904 * fill a spoolss_DriverInfo1 struct
4905 ********************************************************************/
4907 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4908 struct spoolss_DriverInfo1 *r,
4909 const struct spoolss_DriverInfo8 *driver,
4910 const char *servername)
4912 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4913 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4915 return WERR_OK;
4918 /********************************************************************
4919 * fill a spoolss_DriverInfo2 struct
4920 ********************************************************************/
4922 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4923 struct spoolss_DriverInfo2 *r,
4924 const struct spoolss_DriverInfo8 *driver,
4925 const char *servername)
4928 const char *cservername = canon_servername(servername);
4930 r->version = driver->version;
4932 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4933 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4934 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4935 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4937 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938 driver->architecture,
4939 driver->version,
4940 driver->driver_path,
4941 r->driver_path);
4943 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4944 driver->architecture,
4945 driver->version,
4946 driver->data_file,
4947 r->data_file);
4949 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4950 driver->architecture,
4951 driver->version,
4952 driver->config_file,
4953 r->config_file);
4955 return WERR_OK;
4958 /********************************************************************
4959 * fill a spoolss_DriverInfo3 struct
4960 ********************************************************************/
4962 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4963 struct spoolss_DriverInfo3 *r,
4964 const struct spoolss_DriverInfo8 *driver,
4965 const char *servername)
4967 const char *cservername = canon_servername(servername);
4969 r->version = driver->version;
4971 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4972 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4973 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4974 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4976 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4977 driver->architecture,
4978 driver->version,
4979 driver->driver_path,
4980 r->driver_path);
4982 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4983 driver->architecture,
4984 driver->version,
4985 driver->data_file,
4986 r->data_file);
4988 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4989 driver->architecture,
4990 driver->version,
4991 driver->config_file,
4992 r->config_file);
4994 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995 driver->architecture,
4996 driver->version,
4997 driver->help_file,
4998 r->help_file);
5000 FILL_DRIVER_STRING(mem_ctx,
5001 driver->monitor_name,
5002 r->monitor_name);
5004 FILL_DRIVER_STRING(mem_ctx,
5005 driver->default_datatype,
5006 r->default_datatype);
5008 return string_array_from_driver_info(mem_ctx,
5009 driver->dependent_files,
5010 &r->dependent_files,
5011 cservername,
5012 driver->architecture,
5013 driver->version);
5016 /********************************************************************
5017 * fill a spoolss_DriverInfo4 struct
5018 ********************************************************************/
5020 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5021 struct spoolss_DriverInfo4 *r,
5022 const struct spoolss_DriverInfo8 *driver,
5023 const char *servername)
5025 const char *cservername = canon_servername(servername);
5026 WERROR result;
5028 r->version = driver->version;
5030 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5031 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5032 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5033 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5035 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5036 driver->architecture,
5037 driver->version,
5038 driver->driver_path,
5039 r->driver_path);
5041 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5042 driver->architecture,
5043 driver->version,
5044 driver->data_file,
5045 r->data_file);
5047 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5048 driver->architecture,
5049 driver->version,
5050 driver->config_file,
5051 r->config_file);
5053 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5054 driver->architecture,
5055 driver->version,
5056 driver->help_file,
5057 r->help_file);
5059 result = string_array_from_driver_info(mem_ctx,
5060 driver->dependent_files,
5061 &r->dependent_files,
5062 cservername,
5063 driver->architecture,
5064 driver->version);
5065 if (!W_ERROR_IS_OK(result)) {
5066 return result;
5069 FILL_DRIVER_STRING(mem_ctx,
5070 driver->monitor_name,
5071 r->monitor_name);
5073 FILL_DRIVER_STRING(mem_ctx,
5074 driver->default_datatype,
5075 r->default_datatype);
5078 result = string_array_from_driver_info(mem_ctx,
5079 driver->previous_names,
5080 &r->previous_names,
5081 NULL, NULL, 0);
5083 return result;
5086 /********************************************************************
5087 * fill a spoolss_DriverInfo5 struct
5088 ********************************************************************/
5090 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5091 struct spoolss_DriverInfo5 *r,
5092 const struct spoolss_DriverInfo8 *driver,
5093 const char *servername)
5095 const char *cservername = canon_servername(servername);
5097 r->version = driver->version;
5099 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5100 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5101 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5102 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5104 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105 driver->architecture,
5106 driver->version,
5107 driver->driver_path,
5108 r->driver_path);
5110 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5111 driver->architecture,
5112 driver->version,
5113 driver->data_file,
5114 r->data_file);
5116 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5117 driver->architecture,
5118 driver->version,
5119 driver->config_file,
5120 r->config_file);
5122 r->driver_attributes = 0;
5123 r->config_version = 0;
5124 r->driver_version = 0;
5126 return WERR_OK;
5128 /********************************************************************
5129 * fill a spoolss_DriverInfo6 struct
5130 ********************************************************************/
5132 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5133 struct spoolss_DriverInfo6 *r,
5134 const struct spoolss_DriverInfo8 *driver,
5135 const char *servername)
5137 const char *cservername = canon_servername(servername);
5138 WERROR result;
5140 r->version = driver->version;
5142 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5143 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5144 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5145 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5147 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5148 driver->architecture,
5149 driver->version,
5150 driver->driver_path,
5151 r->driver_path);
5153 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5154 driver->architecture,
5155 driver->version,
5156 driver->data_file,
5157 r->data_file);
5159 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5160 driver->architecture,
5161 driver->version,
5162 driver->config_file,
5163 r->config_file);
5165 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5166 driver->architecture,
5167 driver->version,
5168 driver->help_file,
5169 r->help_file);
5171 FILL_DRIVER_STRING(mem_ctx,
5172 driver->monitor_name,
5173 r->monitor_name);
5175 FILL_DRIVER_STRING(mem_ctx,
5176 driver->default_datatype,
5177 r->default_datatype);
5179 result = string_array_from_driver_info(mem_ctx,
5180 driver->dependent_files,
5181 &r->dependent_files,
5182 cservername,
5183 driver->architecture,
5184 driver->version);
5185 if (!W_ERROR_IS_OK(result)) {
5186 return result;
5189 result = string_array_from_driver_info(mem_ctx,
5190 driver->previous_names,
5191 &r->previous_names,
5192 NULL, NULL, 0);
5193 if (!W_ERROR_IS_OK(result)) {
5194 return result;
5197 r->driver_date = driver->driver_date;
5198 r->driver_version = driver->driver_version;
5200 FILL_DRIVER_STRING(mem_ctx,
5201 driver->manufacturer_name,
5202 r->manufacturer_name);
5203 FILL_DRIVER_STRING(mem_ctx,
5204 driver->manufacturer_url,
5205 r->manufacturer_url);
5206 FILL_DRIVER_STRING(mem_ctx,
5207 driver->hardware_id,
5208 r->hardware_id);
5209 FILL_DRIVER_STRING(mem_ctx,
5210 driver->provider,
5211 r->provider);
5213 return WERR_OK;
5216 /********************************************************************
5217 * fill a spoolss_DriverInfo8 struct
5218 ********************************************************************/
5220 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5221 struct spoolss_DriverInfo8 *r,
5222 const struct spoolss_DriverInfo8 *driver,
5223 const char *servername)
5225 const char *cservername = canon_servername(servername);
5226 WERROR result;
5228 r->version = driver->version;
5230 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5231 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5232 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5233 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5235 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5236 driver->architecture,
5237 driver->version,
5238 driver->driver_path,
5239 r->driver_path);
5241 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5242 driver->architecture,
5243 driver->version,
5244 driver->data_file,
5245 r->data_file);
5247 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5248 driver->architecture,
5249 driver->version,
5250 driver->config_file,
5251 r->config_file);
5253 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5254 driver->architecture,
5255 driver->version,
5256 driver->help_file,
5257 r->help_file);
5259 FILL_DRIVER_STRING(mem_ctx,
5260 driver->monitor_name,
5261 r->monitor_name);
5263 FILL_DRIVER_STRING(mem_ctx,
5264 driver->default_datatype,
5265 r->default_datatype);
5267 result = string_array_from_driver_info(mem_ctx,
5268 driver->dependent_files,
5269 &r->dependent_files,
5270 cservername,
5271 driver->architecture,
5272 driver->version);
5273 if (!W_ERROR_IS_OK(result)) {
5274 return result;
5277 result = string_array_from_driver_info(mem_ctx,
5278 driver->previous_names,
5279 &r->previous_names,
5280 NULL, NULL, 0);
5281 if (!W_ERROR_IS_OK(result)) {
5282 return result;
5285 r->driver_date = driver->driver_date;
5286 r->driver_version = driver->driver_version;
5288 FILL_DRIVER_STRING(mem_ctx,
5289 driver->manufacturer_name,
5290 r->manufacturer_name);
5291 FILL_DRIVER_STRING(mem_ctx,
5292 driver->manufacturer_url,
5293 r->manufacturer_url);
5294 FILL_DRIVER_STRING(mem_ctx,
5295 driver->hardware_id,
5296 r->hardware_id);
5297 FILL_DRIVER_STRING(mem_ctx,
5298 driver->provider,
5299 r->provider);
5301 FILL_DRIVER_STRING(mem_ctx,
5302 driver->print_processor,
5303 r->print_processor);
5304 FILL_DRIVER_STRING(mem_ctx,
5305 driver->vendor_setup,
5306 r->vendor_setup);
5308 result = string_array_from_driver_info(mem_ctx,
5309 driver->color_profiles,
5310 &r->color_profiles,
5311 NULL, NULL, 0);
5312 if (!W_ERROR_IS_OK(result)) {
5313 return result;
5316 FILL_DRIVER_STRING(mem_ctx,
5317 driver->inf_path,
5318 r->inf_path);
5320 r->printer_driver_attributes = driver->printer_driver_attributes;
5322 result = string_array_from_driver_info(mem_ctx,
5323 driver->core_driver_dependencies,
5324 &r->core_driver_dependencies,
5325 NULL, NULL, 0);
5326 if (!W_ERROR_IS_OK(result)) {
5327 return result;
5330 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5331 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5333 return WERR_OK;
5336 #if 0 /* disabled until marshalling issues are resolved - gd */
5337 /********************************************************************
5338 ********************************************************************/
5340 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5341 struct spoolss_DriverFileInfo *r,
5342 const char *cservername,
5343 const char *file_name,
5344 enum spoolss_DriverFileType file_type,
5345 uint32_t file_version)
5347 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5348 cservername, file_name);
5349 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5350 r->file_type = file_type;
5351 r->file_version = file_version;
5353 return WERR_OK;
5356 /********************************************************************
5357 ********************************************************************/
5359 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5360 const struct spoolss_DriverInfo8 *driver,
5361 const char *cservername,
5362 struct spoolss_DriverFileInfo **info_p,
5363 uint32_t *count_p)
5365 struct spoolss_DriverFileInfo *info = NULL;
5366 uint32_t count = 0;
5367 WERROR result;
5368 uint32_t i;
5370 *info_p = NULL;
5371 *count_p = 0;
5373 if (strlen(driver->driver_path)) {
5374 info = talloc_realloc(mem_ctx, info,
5375 struct spoolss_DriverFileInfo,
5376 count + 1);
5377 W_ERROR_HAVE_NO_MEMORY(info);
5378 result = fill_spoolss_DriverFileInfo(info,
5379 &info[count],
5380 cservername,
5381 driver->driver_path,
5382 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5384 W_ERROR_NOT_OK_RETURN(result);
5385 count++;
5388 if (strlen(driver->config_file)) {
5389 info = talloc_realloc(mem_ctx, info,
5390 struct spoolss_DriverFileInfo,
5391 count + 1);
5392 W_ERROR_HAVE_NO_MEMORY(info);
5393 result = fill_spoolss_DriverFileInfo(info,
5394 &info[count],
5395 cservername,
5396 driver->config_file,
5397 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5399 W_ERROR_NOT_OK_RETURN(result);
5400 count++;
5403 if (strlen(driver->data_file)) {
5404 info = talloc_realloc(mem_ctx, info,
5405 struct spoolss_DriverFileInfo,
5406 count + 1);
5407 W_ERROR_HAVE_NO_MEMORY(info);
5408 result = fill_spoolss_DriverFileInfo(info,
5409 &info[count],
5410 cservername,
5411 driver->data_file,
5412 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5414 W_ERROR_NOT_OK_RETURN(result);
5415 count++;
5418 if (strlen(driver->help_file)) {
5419 info = talloc_realloc(mem_ctx, info,
5420 struct spoolss_DriverFileInfo,
5421 count + 1);
5422 W_ERROR_HAVE_NO_MEMORY(info);
5423 result = fill_spoolss_DriverFileInfo(info,
5424 &info[count],
5425 cservername,
5426 driver->help_file,
5427 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5429 W_ERROR_NOT_OK_RETURN(result);
5430 count++;
5433 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5434 info = talloc_realloc(mem_ctx, info,
5435 struct spoolss_DriverFileInfo,
5436 count + 1);
5437 W_ERROR_HAVE_NO_MEMORY(info);
5438 result = fill_spoolss_DriverFileInfo(info,
5439 &info[count],
5440 cservername,
5441 driver->dependent_files[i],
5442 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5444 W_ERROR_NOT_OK_RETURN(result);
5445 count++;
5448 *info_p = info;
5449 *count_p = count;
5451 return WERR_OK;
5454 /********************************************************************
5455 * fill a spoolss_DriverInfo101 struct
5456 ********************************************************************/
5458 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5459 struct spoolss_DriverInfo101 *r,
5460 const struct spoolss_DriverInfo8 *driver,
5461 const char *servername)
5463 const char *cservername = canon_servername(servername);
5464 WERROR result;
5466 r->version = driver->version;
5468 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5469 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5470 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5471 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5473 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5474 cservername,
5475 &r->file_info,
5476 &r->file_count);
5477 if (!W_ERROR_IS_OK(result)) {
5478 return result;
5481 FILL_DRIVER_STRING(mem_ctx,
5482 driver->monitor_name,
5483 r->monitor_name);
5485 FILL_DRIVER_STRING(mem_ctx,
5486 driver->default_datatype,
5487 r->default_datatype);
5489 result = string_array_from_driver_info(mem_ctx,
5490 driver->previous_names,
5491 &r->previous_names,
5492 NULL, NULL, 0);
5493 if (!W_ERROR_IS_OK(result)) {
5494 return result;
5497 r->driver_date = driver->driver_date;
5498 r->driver_version = driver->driver_version;
5500 FILL_DRIVER_STRING(mem_ctx,
5501 driver->manufacturer_name,
5502 r->manufacturer_name);
5503 FILL_DRIVER_STRING(mem_ctx,
5504 driver->manufacturer_url,
5505 r->manufacturer_url);
5506 FILL_DRIVER_STRING(mem_ctx,
5507 driver->hardware_id,
5508 r->hardware_id);
5509 FILL_DRIVER_STRING(mem_ctx,
5510 driver->provider,
5511 r->provider);
5513 return WERR_OK;
5515 #endif
5516 /********************************************************************
5517 ********************************************************************/
5519 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5520 const struct auth_session_info *session_info,
5521 struct messaging_context *msg_ctx,
5522 uint32_t level,
5523 union spoolss_DriverInfo *r,
5524 int snum,
5525 const char *servername,
5526 const char *architecture,
5527 uint32_t version)
5529 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5530 struct spoolss_DriverInfo8 *driver;
5531 WERROR result;
5532 struct dcerpc_binding_handle *b;
5533 TALLOC_CTX *tmp_ctx = NULL;
5535 if (level == 101) {
5536 return WERR_UNKNOWN_LEVEL;
5539 tmp_ctx = talloc_new(mem_ctx);
5540 if (!tmp_ctx) {
5541 return WERR_NOMEM;
5544 result = winreg_printer_binding_handle(tmp_ctx,
5545 session_info,
5546 msg_ctx,
5547 &b);
5548 if (!W_ERROR_IS_OK(result)) {
5549 goto done;
5552 result = winreg_get_printer(tmp_ctx, b,
5553 lp_const_servicename(snum),
5554 &pinfo2);
5556 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5557 win_errstr(result)));
5559 if (!W_ERROR_IS_OK(result)) {
5560 result = WERR_INVALID_PRINTER_NAME;
5561 goto done;
5564 result = winreg_get_driver(tmp_ctx, b,
5565 architecture,
5566 pinfo2->drivername, version, &driver);
5568 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5569 win_errstr(result)));
5571 if (!W_ERROR_IS_OK(result)) {
5573 * Is this a W2k client ?
5576 if (version < 3) {
5577 result = WERR_UNKNOWN_PRINTER_DRIVER;
5578 goto done;
5581 /* Yes - try again with a WinNT driver. */
5582 version = 2;
5583 result = winreg_get_driver(tmp_ctx, b,
5584 architecture,
5585 pinfo2->drivername,
5586 version, &driver);
5587 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5588 win_errstr(result)));
5589 if (!W_ERROR_IS_OK(result)) {
5590 result = WERR_UNKNOWN_PRINTER_DRIVER;
5591 goto done;
5595 /* these are allocated on mem_ctx and not tmp_ctx because they are
5596 * the 'return value' and need to utlive this call */
5597 switch (level) {
5598 case 1:
5599 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5600 break;
5601 case 2:
5602 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5603 break;
5604 case 3:
5605 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5606 break;
5607 case 4:
5608 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5609 break;
5610 case 5:
5611 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5612 break;
5613 case 6:
5614 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5615 break;
5616 case 8:
5617 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5618 break;
5619 #if 0 /* disabled until marshalling issues are resolved - gd */
5620 case 101:
5621 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5622 break;
5623 #endif
5624 default:
5625 result = WERR_UNKNOWN_LEVEL;
5626 break;
5629 done:
5630 talloc_free(tmp_ctx);
5631 return result;
5634 /****************************************************************
5635 _spoolss_GetPrinterDriver2
5636 ****************************************************************/
5638 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5639 struct spoolss_GetPrinterDriver2 *r)
5641 struct printer_handle *printer;
5642 WERROR result;
5644 int snum;
5646 /* that's an [in out] buffer */
5648 if (!r->in.buffer && (r->in.offered != 0)) {
5649 return WERR_INVALID_PARAM;
5652 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5654 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5655 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5656 return WERR_INVALID_PRINTER_NAME;
5659 *r->out.needed = 0;
5660 *r->out.server_major_version = 0;
5661 *r->out.server_minor_version = 0;
5663 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5664 return WERR_BADFID;
5667 result = construct_printer_driver_info_level(p->mem_ctx,
5668 get_session_info_system(),
5669 p->msg_ctx,
5670 r->in.level, r->out.info,
5671 snum, printer->servername,
5672 r->in.architecture,
5673 r->in.client_major_version);
5674 if (!W_ERROR_IS_OK(result)) {
5675 TALLOC_FREE(r->out.info);
5676 return result;
5679 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5680 r->out.info, r->in.level);
5681 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5683 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5687 /****************************************************************
5688 _spoolss_StartPagePrinter
5689 ****************************************************************/
5691 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5692 struct spoolss_StartPagePrinter *r)
5694 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5696 if (!Printer) {
5697 DEBUG(3,("_spoolss_StartPagePrinter: "
5698 "Error in startpageprinter printer handle\n"));
5699 return WERR_BADFID;
5702 Printer->page_started = true;
5703 return WERR_OK;
5706 /****************************************************************
5707 _spoolss_EndPagePrinter
5708 ****************************************************************/
5710 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5711 struct spoolss_EndPagePrinter *r)
5713 int snum;
5715 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5717 if (!Printer) {
5718 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5719 OUR_HANDLE(r->in.handle)));
5720 return WERR_BADFID;
5723 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5724 return WERR_BADFID;
5726 Printer->page_started = false;
5727 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5729 return WERR_OK;
5732 /****************************************************************
5733 _spoolss_StartDocPrinter
5734 ****************************************************************/
5736 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5737 struct spoolss_StartDocPrinter *r)
5739 struct spoolss_DocumentInfo1 *info_1;
5740 int snum;
5741 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5742 WERROR werr;
5743 char *rhost;
5744 int rc;
5746 if (!Printer) {
5747 DEBUG(2,("_spoolss_StartDocPrinter: "
5748 "Invalid handle (%s:%u:%u)\n",
5749 OUR_HANDLE(r->in.handle)));
5750 return WERR_BADFID;
5753 if (Printer->jobid) {
5754 DEBUG(2, ("_spoolss_StartDocPrinter: "
5755 "StartDocPrinter called twice! "
5756 "(existing jobid = %d)\n", Printer->jobid));
5757 return WERR_INVALID_HANDLE;
5760 if (r->in.level != 1) {
5761 return WERR_UNKNOWN_LEVEL;
5764 info_1 = r->in.info.info1;
5767 * a nice thing with NT is it doesn't listen to what you tell it.
5768 * when asked to send _only_ RAW datas, it tries to send datas
5769 * in EMF format.
5771 * So I add checks like in NT Server ...
5774 if (info_1->datatype) {
5775 if (strcmp(info_1->datatype, "RAW") != 0) {
5776 *r->out.job_id = 0;
5777 return WERR_INVALID_DATATYPE;
5781 /* get the share number of the printer */
5782 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5783 return WERR_BADFID;
5786 rc = get_remote_hostname(p->remote_address,
5787 &rhost,
5788 p->mem_ctx);
5789 if (rc < 0) {
5790 return WERR_NOMEM;
5792 if (strequal(rhost,"UNKNOWN")) {
5793 rhost = tsocket_address_inet_addr_string(p->remote_address,
5794 p->mem_ctx);
5795 if (rhost == NULL) {
5796 return WERR_NOMEM;
5800 werr = print_job_start(p->session_info,
5801 p->msg_ctx,
5802 rhost,
5803 snum,
5804 info_1->document_name,
5805 info_1->output_file,
5806 Printer->devmode,
5807 &Printer->jobid);
5809 /* An error occured in print_job_start() so return an appropriate
5810 NT error code. */
5812 if (!W_ERROR_IS_OK(werr)) {
5813 return werr;
5816 Printer->document_started = true;
5817 *r->out.job_id = Printer->jobid;
5819 return WERR_OK;
5822 /****************************************************************
5823 _spoolss_EndDocPrinter
5824 ****************************************************************/
5826 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5827 struct spoolss_EndDocPrinter *r)
5829 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5830 NTSTATUS status;
5831 int snum;
5833 if (!Printer) {
5834 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5835 OUR_HANDLE(r->in.handle)));
5836 return WERR_BADFID;
5839 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5840 return WERR_BADFID;
5843 Printer->document_started = false;
5844 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5845 if (!NT_STATUS_IS_OK(status)) {
5846 DEBUG(2, ("_spoolss_EndDocPrinter: "
5847 "print_job_end failed [%s]\n",
5848 nt_errstr(status)));
5851 Printer->jobid = 0;
5852 return ntstatus_to_werror(status);
5855 /****************************************************************
5856 _spoolss_WritePrinter
5857 ****************************************************************/
5859 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5860 struct spoolss_WritePrinter *r)
5862 ssize_t buffer_written;
5863 int snum;
5864 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5866 if (!Printer) {
5867 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5868 OUR_HANDLE(r->in.handle)));
5869 *r->out.num_written = r->in._data_size;
5870 return WERR_BADFID;
5873 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5874 return WERR_BADFID;
5876 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5877 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5878 snum, Printer->jobid,
5879 (const char *)r->in.data.data,
5880 (size_t)r->in._data_size);
5881 if (buffer_written == (ssize_t)-1) {
5882 *r->out.num_written = 0;
5883 if (errno == ENOSPC)
5884 return WERR_NO_SPOOL_SPACE;
5885 else
5886 return WERR_ACCESS_DENIED;
5889 *r->out.num_written = r->in._data_size;
5891 return WERR_OK;
5894 /********************************************************************
5895 * api_spoolss_getprinter
5896 * called from the spoolss dispatcher
5898 ********************************************************************/
5900 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5901 struct pipes_struct *p)
5903 const struct auth_session_info *session_info = p->session_info;
5904 int snum;
5905 WERROR errcode = WERR_BADFUNC;
5906 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5908 if (!Printer) {
5909 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5910 OUR_HANDLE(handle)));
5911 return WERR_BADFID;
5914 if (!get_printer_snum(p, handle, &snum, NULL))
5915 return WERR_BADFID;
5917 switch (command) {
5918 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5919 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5920 break;
5921 case SPOOLSS_PRINTER_CONTROL_RESUME:
5922 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5923 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5924 break;
5925 case SPOOLSS_PRINTER_CONTROL_PURGE:
5926 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5927 break;
5928 default:
5929 return WERR_UNKNOWN_LEVEL;
5932 return errcode;
5936 /****************************************************************
5937 _spoolss_AbortPrinter
5938 * From MSDN: "Deletes printer's spool file if printer is configured
5939 * for spooling"
5940 ****************************************************************/
5942 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5943 struct spoolss_AbortPrinter *r)
5945 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5946 int snum;
5947 WERROR errcode = WERR_OK;
5949 if (!Printer) {
5950 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5951 OUR_HANDLE(r->in.handle)));
5952 return WERR_BADFID;
5955 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5956 return WERR_BADFID;
5958 if (!Printer->document_started) {
5959 return WERR_SPL_NO_STARTDOC;
5962 errcode = print_job_delete(p->session_info,
5963 p->msg_ctx,
5964 snum,
5965 Printer->jobid);
5967 return errcode;
5970 /********************************************************************
5971 * called by spoolss_api_setprinter
5972 * when updating a printer description
5973 ********************************************************************/
5975 static WERROR update_printer_sec(struct policy_handle *handle,
5976 struct pipes_struct *p,
5977 struct sec_desc_buf *secdesc_ctr)
5979 struct spoolss_security_descriptor *new_secdesc = NULL;
5980 struct spoolss_security_descriptor *old_secdesc = NULL;
5981 const char *printer;
5982 WERROR result;
5983 int snum;
5984 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5985 struct dcerpc_binding_handle *b;
5986 TALLOC_CTX *tmp_ctx = NULL;
5988 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5989 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5990 OUR_HANDLE(handle)));
5992 result = WERR_BADFID;
5993 goto done;
5996 if (secdesc_ctr == NULL) {
5997 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5998 result = WERR_INVALID_PARAM;
5999 goto done;
6001 printer = lp_const_servicename(snum);
6003 /* Check the user has permissions to change the security
6004 descriptor. By experimentation with two NT machines, the user
6005 requires Full Access to the printer to change security
6006 information. */
6008 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6009 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6010 result = WERR_ACCESS_DENIED;
6011 goto done;
6014 tmp_ctx = talloc_new(p->mem_ctx);
6015 if (!tmp_ctx) {
6016 return WERR_NOMEM;
6019 result = winreg_printer_binding_handle(tmp_ctx,
6020 get_session_info_system(),
6021 p->msg_ctx,
6022 &b);
6023 if (!W_ERROR_IS_OK(result)) {
6024 goto done;
6027 /* NT seems to like setting the security descriptor even though
6028 nothing may have actually changed. */
6029 result = winreg_get_printer_secdesc(tmp_ctx, b,
6030 printer,
6031 &old_secdesc);
6032 if (!W_ERROR_IS_OK(result)) {
6033 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6034 result = WERR_BADFID;
6035 goto done;
6038 if (DEBUGLEVEL >= 10) {
6039 struct security_acl *the_acl;
6040 int i;
6042 the_acl = old_secdesc->dacl;
6043 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6044 printer, the_acl->num_aces));
6046 for (i = 0; i < the_acl->num_aces; i++) {
6047 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6048 &the_acl->aces[i].trustee),
6049 the_acl->aces[i].access_mask));
6052 the_acl = secdesc_ctr->sd->dacl;
6054 if (the_acl) {
6055 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6056 printer, the_acl->num_aces));
6058 for (i = 0; i < the_acl->num_aces; i++) {
6059 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6060 &the_acl->aces[i].trustee),
6061 the_acl->aces[i].access_mask));
6063 } else {
6064 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6068 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6069 if (new_secdesc == NULL) {
6070 result = WERR_NOMEM;
6071 goto done;
6074 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6075 result = WERR_OK;
6076 goto done;
6079 result = winreg_set_printer_secdesc(tmp_ctx, b,
6080 printer,
6081 new_secdesc);
6083 done:
6084 talloc_free(tmp_ctx);
6085 return result;
6088 /********************************************************************
6089 Canonicalize printer info from a client
6090 ********************************************************************/
6092 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6093 struct spoolss_SetPrinterInfo2 *info2,
6094 int snum)
6096 fstring printername;
6097 const char *p;
6099 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6100 "portname=%s drivername=%s comment=%s location=%s\n",
6101 info2->servername, info2->printername, info2->sharename,
6102 info2->portname, info2->drivername, info2->comment,
6103 info2->location));
6105 /* we force some elements to "correct" values */
6106 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6107 if (info2->servername == NULL) {
6108 return false;
6110 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6111 if (info2->sharename == NULL) {
6112 return false;
6115 /* check to see if we allow printername != sharename */
6116 if (lp_force_printername(snum)) {
6117 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6118 lp_netbios_name(), info2->sharename);
6119 } else {
6120 /* make sure printername is in \\server\printername format */
6121 fstrcpy(printername, info2->printername);
6122 p = printername;
6123 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6124 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6125 p++;
6128 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6129 lp_netbios_name(), p);
6131 if (info2->printername == NULL) {
6132 return false;
6135 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6136 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6138 return true;
6141 /****************************************************************************
6142 ****************************************************************************/
6144 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6146 char *cmd = lp_addport_cmd();
6147 char *command = NULL;
6148 int ret;
6149 bool is_print_op = false;
6151 if ( !*cmd ) {
6152 return WERR_ACCESS_DENIED;
6155 command = talloc_asprintf(ctx,
6156 "%s \"%s\" \"%s\"", cmd, portname, uri );
6157 if (!command) {
6158 return WERR_NOMEM;
6161 if ( token )
6162 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6164 DEBUG(10,("Running [%s]\n", command));
6166 /********* BEGIN SePrintOperatorPrivilege **********/
6168 if ( is_print_op )
6169 become_root();
6171 ret = smbrun(command, NULL);
6173 if ( is_print_op )
6174 unbecome_root();
6176 /********* END SePrintOperatorPrivilege **********/
6178 DEBUGADD(10,("returned [%d]\n", ret));
6180 TALLOC_FREE(command);
6182 if ( ret != 0 ) {
6183 return WERR_ACCESS_DENIED;
6186 return WERR_OK;
6189 /****************************************************************************
6190 ****************************************************************************/
6192 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6193 struct spoolss_SetPrinterInfo2 *info2,
6194 const char *remote_machine,
6195 struct messaging_context *msg_ctx)
6197 char *cmd = lp_addprinter_cmd();
6198 char **qlines;
6199 char *command = NULL;
6200 int numlines;
6201 int ret;
6202 int fd;
6203 bool is_print_op = false;
6205 if (!remote_machine) {
6206 return false;
6209 command = talloc_asprintf(ctx,
6210 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6211 cmd, info2->printername, info2->sharename,
6212 info2->portname, info2->drivername,
6213 info2->location, info2->comment, remote_machine);
6214 if (!command) {
6215 return false;
6218 if ( token )
6219 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6221 DEBUG(10,("Running [%s]\n", command));
6223 /********* BEGIN SePrintOperatorPrivilege **********/
6225 if ( is_print_op )
6226 become_root();
6228 if ( (ret = smbrun(command, &fd)) == 0 ) {
6229 /* Tell everyone we updated smb.conf. */
6230 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6233 if ( is_print_op )
6234 unbecome_root();
6236 /********* END SePrintOperatorPrivilege **********/
6238 DEBUGADD(10,("returned [%d]\n", ret));
6240 TALLOC_FREE(command);
6242 if ( ret != 0 ) {
6243 if (fd != -1)
6244 close(fd);
6245 return false;
6248 /* reload our services immediately */
6249 become_root();
6250 reload_services(msg_ctx, -1, false);
6251 unbecome_root();
6253 numlines = 0;
6254 /* Get lines and convert them back to dos-codepage */
6255 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6256 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6257 close(fd);
6259 /* Set the portname to what the script says the portname should be. */
6260 /* but don't require anything to be return from the script exit a good error code */
6262 if (numlines) {
6263 /* Set the portname to what the script says the portname should be. */
6264 info2->portname = talloc_strdup(ctx, qlines[0]);
6265 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6268 TALLOC_FREE(qlines);
6269 return true;
6272 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6273 const struct auth_session_info *session_info,
6274 struct messaging_context *msg_ctx,
6275 int snum,
6276 struct spoolss_SetPrinterInfo2 *printer,
6277 struct spoolss_PrinterInfo2 *old_printer)
6279 bool force_update = (old_printer == NULL);
6280 const char *dnsdomname;
6281 const char *longname;
6282 const char *uncname;
6283 const char *spooling;
6284 DATA_BLOB buffer;
6285 WERROR result = WERR_OK;
6286 struct dcerpc_binding_handle *b;
6287 TALLOC_CTX *tmp_ctx;
6289 tmp_ctx = talloc_new(mem_ctx);
6290 if (!tmp_ctx) {
6291 return WERR_NOMEM;
6294 result = winreg_printer_binding_handle(tmp_ctx,
6295 session_info,
6296 msg_ctx,
6297 &b);
6298 if (!W_ERROR_IS_OK(result)) {
6299 goto done;
6302 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6303 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6304 winreg_set_printer_dataex(tmp_ctx, b,
6305 printer->sharename,
6306 SPOOL_DSSPOOLER_KEY,
6307 SPOOL_REG_DRIVERNAME,
6308 REG_SZ,
6309 buffer.data,
6310 buffer.length);
6312 if (!force_update) {
6313 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6314 printer->drivername));
6316 notify_printer_driver(server_event_context(), msg_ctx,
6317 snum, printer->drivername ?
6318 printer->drivername : "");
6322 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6323 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6324 winreg_set_printer_dataex(tmp_ctx, b,
6325 printer->sharename,
6326 SPOOL_DSSPOOLER_KEY,
6327 SPOOL_REG_DESCRIPTION,
6328 REG_SZ,
6329 buffer.data,
6330 buffer.length);
6332 if (!force_update) {
6333 notify_printer_comment(server_event_context(), msg_ctx,
6334 snum, printer->comment ?
6335 printer->comment : "");
6339 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6340 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6341 winreg_set_printer_dataex(tmp_ctx, b,
6342 printer->sharename,
6343 SPOOL_DSSPOOLER_KEY,
6344 SPOOL_REG_PRINTSHARENAME,
6345 REG_SZ,
6346 buffer.data,
6347 buffer.length);
6349 if (!force_update) {
6350 notify_printer_sharename(server_event_context(),
6351 msg_ctx,
6352 snum, printer->sharename ?
6353 printer->sharename : "");
6357 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6358 const char *p;
6360 p = strrchr(printer->printername, '\\' );
6361 if (p != NULL) {
6362 p++;
6363 } else {
6364 p = printer->printername;
6367 push_reg_sz(tmp_ctx, &buffer, p);
6368 winreg_set_printer_dataex(tmp_ctx, b,
6369 printer->sharename,
6370 SPOOL_DSSPOOLER_KEY,
6371 SPOOL_REG_PRINTERNAME,
6372 REG_SZ,
6373 buffer.data,
6374 buffer.length);
6376 if (!force_update) {
6377 notify_printer_printername(server_event_context(),
6378 msg_ctx, snum, p ? p : "");
6382 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6383 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6384 winreg_set_printer_dataex(tmp_ctx, b,
6385 printer->sharename,
6386 SPOOL_DSSPOOLER_KEY,
6387 SPOOL_REG_PORTNAME,
6388 REG_SZ,
6389 buffer.data,
6390 buffer.length);
6392 if (!force_update) {
6393 notify_printer_port(server_event_context(),
6394 msg_ctx, snum, printer->portname ?
6395 printer->portname : "");
6399 if (force_update || !strequal(printer->location, old_printer->location)) {
6400 push_reg_sz(tmp_ctx, &buffer, printer->location);
6401 winreg_set_printer_dataex(tmp_ctx, b,
6402 printer->sharename,
6403 SPOOL_DSSPOOLER_KEY,
6404 SPOOL_REG_LOCATION,
6405 REG_SZ,
6406 buffer.data,
6407 buffer.length);
6409 if (!force_update) {
6410 notify_printer_location(server_event_context(),
6411 msg_ctx, snum,
6412 printer->location ?
6413 printer->location : "");
6417 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6418 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6419 winreg_set_printer_dataex(tmp_ctx, b,
6420 printer->sharename,
6421 SPOOL_DSSPOOLER_KEY,
6422 SPOOL_REG_PRINTSEPARATORFILE,
6423 REG_SZ,
6424 buffer.data,
6425 buffer.length);
6427 if (!force_update) {
6428 notify_printer_sepfile(server_event_context(),
6429 msg_ctx, snum,
6430 printer->sepfile ?
6431 printer->sepfile : "");
6435 if (force_update || printer->starttime != old_printer->starttime) {
6436 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6437 SIVAL(buffer.data, 0, printer->starttime);
6438 winreg_set_printer_dataex(tmp_ctx, b,
6439 printer->sharename,
6440 SPOOL_DSSPOOLER_KEY,
6441 SPOOL_REG_PRINTSTARTTIME,
6442 REG_DWORD,
6443 buffer.data,
6444 buffer.length);
6447 if (force_update || printer->untiltime != old_printer->untiltime) {
6448 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6449 SIVAL(buffer.data, 0, printer->untiltime);
6450 winreg_set_printer_dataex(tmp_ctx, b,
6451 printer->sharename,
6452 SPOOL_DSSPOOLER_KEY,
6453 SPOOL_REG_PRINTENDTIME,
6454 REG_DWORD,
6455 buffer.data,
6456 buffer.length);
6459 if (force_update || printer->priority != old_printer->priority) {
6460 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6461 SIVAL(buffer.data, 0, printer->priority);
6462 winreg_set_printer_dataex(tmp_ctx, b,
6463 printer->sharename,
6464 SPOOL_DSSPOOLER_KEY,
6465 SPOOL_REG_PRIORITY,
6466 REG_DWORD,
6467 buffer.data,
6468 buffer.length);
6471 if (force_update || printer->attributes != old_printer->attributes) {
6472 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6473 SIVAL(buffer.data, 0, (printer->attributes &
6474 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6475 winreg_set_printer_dataex(tmp_ctx, b,
6476 printer->sharename,
6477 SPOOL_DSSPOOLER_KEY,
6478 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6479 REG_DWORD,
6480 buffer.data,
6481 buffer.length);
6483 switch (printer->attributes & 0x3) {
6484 case 0:
6485 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6486 break;
6487 case 1:
6488 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6489 break;
6490 case 2:
6491 spooling = SPOOL_REGVAL_PRINTDIRECT;
6492 break;
6493 default:
6494 spooling = "unknown";
6496 push_reg_sz(tmp_ctx, &buffer, spooling);
6497 winreg_set_printer_dataex(tmp_ctx, b,
6498 printer->sharename,
6499 SPOOL_DSSPOOLER_KEY,
6500 SPOOL_REG_PRINTSPOOLING,
6501 REG_SZ,
6502 buffer.data,
6503 buffer.length);
6506 push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6507 winreg_set_printer_dataex(tmp_ctx, b,
6508 printer->sharename,
6509 SPOOL_DSSPOOLER_KEY,
6510 SPOOL_REG_SHORTSERVERNAME,
6511 REG_SZ,
6512 buffer.data,
6513 buffer.length);
6515 dnsdomname = get_mydnsfullname();
6516 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6517 longname = talloc_strdup(tmp_ctx, dnsdomname);
6518 } else {
6519 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6521 if (longname == NULL) {
6522 result = WERR_NOMEM;
6523 goto done;
6526 push_reg_sz(tmp_ctx, &buffer, longname);
6527 winreg_set_printer_dataex(tmp_ctx, b,
6528 printer->sharename,
6529 SPOOL_DSSPOOLER_KEY,
6530 SPOOL_REG_SERVERNAME,
6531 REG_SZ,
6532 buffer.data,
6533 buffer.length);
6535 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6536 lp_netbios_name(), printer->sharename);
6537 push_reg_sz(tmp_ctx, &buffer, uncname);
6538 winreg_set_printer_dataex(tmp_ctx, b,
6539 printer->sharename,
6540 SPOOL_DSSPOOLER_KEY,
6541 SPOOL_REG_UNCNAME,
6542 REG_SZ,
6543 buffer.data,
6544 buffer.length);
6546 done:
6547 talloc_free(tmp_ctx);
6548 return result;
6551 /********************************************************************
6552 * Called by spoolss_api_setprinter
6553 * when updating a printer description.
6554 ********************************************************************/
6556 static WERROR update_printer(struct pipes_struct *p,
6557 struct policy_handle *handle,
6558 struct spoolss_SetPrinterInfoCtr *info_ctr,
6559 struct spoolss_DeviceMode *devmode)
6561 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6562 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6563 struct spoolss_PrinterInfo2 *old_printer;
6564 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6565 int snum;
6566 WERROR result = WERR_OK;
6567 TALLOC_CTX *tmp_ctx;
6568 struct dcerpc_binding_handle *b;
6570 DEBUG(8,("update_printer\n"));
6572 tmp_ctx = talloc_new(p->mem_ctx);
6573 if (tmp_ctx == NULL) {
6574 return WERR_NOMEM;
6577 if (!Printer) {
6578 result = WERR_BADFID;
6579 goto done;
6582 if (!get_printer_snum(p, handle, &snum, NULL)) {
6583 result = WERR_BADFID;
6584 goto done;
6587 result = winreg_printer_binding_handle(tmp_ctx,
6588 get_session_info_system(),
6589 p->msg_ctx,
6590 &b);
6591 if (!W_ERROR_IS_OK(result)) {
6592 goto done;
6595 result = winreg_get_printer(tmp_ctx, b,
6596 lp_const_servicename(snum),
6597 &old_printer);
6598 if (!W_ERROR_IS_OK(result)) {
6599 result = WERR_BADFID;
6600 goto done;
6603 /* Do sanity check on the requested changes for Samba */
6604 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6605 result = WERR_INVALID_PARAM;
6606 goto done;
6609 /* FIXME!!! If the driver has changed we really should verify that
6610 it is installed before doing much else --jerry */
6612 /* Check calling user has permission to update printer description */
6613 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6614 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6615 result = WERR_ACCESS_DENIED;
6616 goto done;
6619 /* Call addprinter hook */
6620 /* Check changes to see if this is really needed */
6622 if (*lp_addprinter_cmd() &&
6623 (!strequal(printer->drivername, old_printer->drivername) ||
6624 !strequal(printer->comment, old_printer->comment) ||
6625 !strequal(printer->portname, old_printer->portname) ||
6626 !strequal(printer->location, old_printer->location)) )
6628 char *raddr;
6630 raddr = tsocket_address_inet_addr_string(p->remote_address,
6631 p->mem_ctx);
6632 if (raddr == NULL) {
6633 return WERR_NOMEM;
6636 /* add_printer_hook() will call reload_services() */
6637 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6638 printer, raddr,
6639 p->msg_ctx)) {
6640 result = WERR_ACCESS_DENIED;
6641 goto done;
6645 update_dsspooler(tmp_ctx,
6646 get_session_info_system(),
6647 p->msg_ctx,
6648 snum,
6649 printer,
6650 old_printer);
6652 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6654 if (devmode == NULL) {
6655 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6657 result = winreg_update_printer(tmp_ctx, b,
6658 printer->sharename,
6659 printer_mask,
6660 printer,
6661 devmode,
6662 NULL);
6664 done:
6665 talloc_free(tmp_ctx);
6667 return result;
6670 /****************************************************************************
6671 ****************************************************************************/
6672 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6673 struct policy_handle *handle,
6674 struct spoolss_SetPrinterInfo7 *info7)
6676 #ifdef HAVE_ADS
6677 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6678 WERROR result;
6679 int snum;
6680 struct printer_handle *Printer;
6682 if ( lp_security() != SEC_ADS ) {
6683 return WERR_UNKNOWN_LEVEL;
6686 Printer = find_printer_index_by_hnd(p, handle);
6688 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6690 if (!Printer)
6691 return WERR_BADFID;
6693 if (!get_printer_snum(p, handle, &snum, NULL))
6694 return WERR_BADFID;
6696 result = winreg_get_printer_internal(p->mem_ctx,
6697 get_session_info_system(),
6698 p->msg_ctx,
6699 lp_servicename(snum),
6700 &pinfo2);
6701 if (!W_ERROR_IS_OK(result)) {
6702 return WERR_BADFID;
6705 nt_printer_publish(pinfo2,
6706 get_session_info_system(),
6707 p->msg_ctx,
6708 pinfo2,
6709 info7->action);
6711 TALLOC_FREE(pinfo2);
6712 return WERR_OK;
6713 #else
6714 return WERR_UNKNOWN_LEVEL;
6715 #endif
6718 /********************************************************************
6719 ********************************************************************/
6721 static WERROR update_printer_devmode(struct pipes_struct *p,
6722 struct policy_handle *handle,
6723 struct spoolss_DeviceMode *devmode)
6725 int snum;
6726 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6727 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6729 DEBUG(8,("update_printer_devmode\n"));
6731 if (!Printer) {
6732 return WERR_BADFID;
6735 if (!get_printer_snum(p, handle, &snum, NULL)) {
6736 return WERR_BADFID;
6739 /* Check calling user has permission to update printer description */
6740 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6741 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6742 return WERR_ACCESS_DENIED;
6745 return winreg_update_printer_internal(p->mem_ctx,
6746 get_session_info_system(),
6747 p->msg_ctx,
6748 lp_const_servicename(snum),
6749 info2_mask,
6750 NULL,
6751 devmode,
6752 NULL);
6756 /****************************************************************
6757 _spoolss_SetPrinter
6758 ****************************************************************/
6760 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6761 struct spoolss_SetPrinter *r)
6763 WERROR result;
6765 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6767 if (!Printer) {
6768 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6769 OUR_HANDLE(r->in.handle)));
6770 return WERR_BADFID;
6773 /* check the level */
6774 switch (r->in.info_ctr->level) {
6775 case 0:
6776 return control_printer(r->in.handle, r->in.command, p);
6777 case 2:
6778 result = update_printer(p, r->in.handle,
6779 r->in.info_ctr,
6780 r->in.devmode_ctr->devmode);
6781 if (!W_ERROR_IS_OK(result))
6782 return result;
6783 if (r->in.secdesc_ctr->sd)
6784 result = update_printer_sec(r->in.handle, p,
6785 r->in.secdesc_ctr);
6786 return result;
6787 case 3:
6788 return update_printer_sec(r->in.handle, p,
6789 r->in.secdesc_ctr);
6790 case 7:
6791 return publish_or_unpublish_printer(p, r->in.handle,
6792 r->in.info_ctr->info.info7);
6793 case 8:
6794 return update_printer_devmode(p, r->in.handle,
6795 r->in.devmode_ctr->devmode);
6796 default:
6797 return WERR_UNKNOWN_LEVEL;
6801 /****************************************************************
6802 _spoolss_FindClosePrinterNotify
6803 ****************************************************************/
6805 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6806 struct spoolss_FindClosePrinterNotify *r)
6808 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6810 if (!Printer) {
6811 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6812 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6813 return WERR_BADFID;
6816 if (Printer->notify.cli_chan != NULL &&
6817 Printer->notify.cli_chan->active_connections > 0) {
6818 int snum = -1;
6820 if (Printer->printer_type == SPLHND_PRINTER) {
6821 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6822 return WERR_BADFID;
6826 srv_spoolss_replycloseprinter(snum, Printer);
6829 Printer->notify.flags=0;
6830 Printer->notify.options=0;
6831 Printer->notify.localmachine[0]='\0';
6832 Printer->notify.printerlocal=0;
6833 TALLOC_FREE(Printer->notify.option);
6835 return WERR_OK;
6838 /****************************************************************
6839 _spoolss_AddJob
6840 ****************************************************************/
6842 WERROR _spoolss_AddJob(struct pipes_struct *p,
6843 struct spoolss_AddJob *r)
6845 if (!r->in.buffer && (r->in.offered != 0)) {
6846 return WERR_INVALID_PARAM;
6849 /* this is what a NT server returns for AddJob. AddJob must fail on
6850 * non-local printers */
6852 if (r->in.level != 1) {
6853 return WERR_UNKNOWN_LEVEL;
6856 return WERR_INVALID_PARAM;
6859 /****************************************************************************
6860 fill_job_info1
6861 ****************************************************************************/
6863 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6864 struct spoolss_JobInfo1 *r,
6865 const print_queue_struct *queue,
6866 int position, int snum,
6867 struct spoolss_PrinterInfo2 *pinfo2)
6869 struct tm *t;
6871 t = gmtime(&queue->time);
6873 r->job_id = queue->job;
6875 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6876 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6877 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6878 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6879 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6880 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6881 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6882 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6883 r->data_type = talloc_strdup(mem_ctx, "RAW");
6884 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6885 r->text_status = talloc_strdup(mem_ctx, "");
6886 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6888 r->status = nt_printj_status(queue->status);
6889 r->priority = queue->priority;
6890 r->position = position;
6891 r->total_pages = queue->page_count;
6892 r->pages_printed = 0; /* ??? */
6894 init_systemtime(&r->submitted, t);
6896 return WERR_OK;
6899 /****************************************************************************
6900 fill_job_info2
6901 ****************************************************************************/
6903 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6904 struct spoolss_JobInfo2 *r,
6905 const print_queue_struct *queue,
6906 int position, int snum,
6907 struct spoolss_PrinterInfo2 *pinfo2,
6908 struct spoolss_DeviceMode *devmode)
6910 struct tm *t;
6912 t = gmtime(&queue->time);
6914 r->job_id = queue->job;
6916 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6917 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6918 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6919 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6920 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6921 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6922 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6923 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6924 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6925 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6926 r->data_type = talloc_strdup(mem_ctx, "RAW");
6927 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6928 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6929 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6930 r->parameters = talloc_strdup(mem_ctx, "");
6931 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6932 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6933 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6935 r->devmode = devmode;
6937 r->text_status = talloc_strdup(mem_ctx, "");
6938 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6940 r->secdesc = NULL;
6942 r->status = nt_printj_status(queue->status);
6943 r->priority = queue->priority;
6944 r->position = position;
6945 r->start_time = 0;
6946 r->until_time = 0;
6947 r->total_pages = queue->page_count;
6948 r->size = queue->size;
6949 init_systemtime(&r->submitted, t);
6950 r->time = 0;
6951 r->pages_printed = 0; /* ??? */
6953 return WERR_OK;
6956 /****************************************************************************
6957 fill_job_info3
6958 ****************************************************************************/
6960 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6961 struct spoolss_JobInfo3 *r,
6962 const print_queue_struct *queue,
6963 const print_queue_struct *next_queue,
6964 int position, int snum,
6965 struct spoolss_PrinterInfo2 *pinfo2)
6967 r->job_id = queue->job;
6968 r->next_job_id = 0;
6969 if (next_queue) {
6970 r->next_job_id = next_queue->job;
6972 r->reserved = 0;
6974 return WERR_OK;
6977 /****************************************************************************
6978 Enumjobs at level 1.
6979 ****************************************************************************/
6981 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6982 const print_queue_struct *queue,
6983 uint32_t num_queues, int snum,
6984 struct spoolss_PrinterInfo2 *pinfo2,
6985 union spoolss_JobInfo **info_p,
6986 uint32_t *count)
6988 union spoolss_JobInfo *info;
6989 int i;
6990 WERROR result = WERR_OK;
6992 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
6993 W_ERROR_HAVE_NO_MEMORY(info);
6995 *count = num_queues;
6997 for (i=0; i<*count; i++) {
6998 result = fill_job_info1(info,
6999 &info[i].info1,
7000 &queue[i],
7002 snum,
7003 pinfo2);
7004 if (!W_ERROR_IS_OK(result)) {
7005 goto out;
7009 out:
7010 if (!W_ERROR_IS_OK(result)) {
7011 TALLOC_FREE(info);
7012 *count = 0;
7013 return result;
7016 *info_p = info;
7018 return WERR_OK;
7021 /****************************************************************************
7022 Enumjobs at level 2.
7023 ****************************************************************************/
7025 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7026 const print_queue_struct *queue,
7027 uint32_t num_queues, int snum,
7028 struct spoolss_PrinterInfo2 *pinfo2,
7029 union spoolss_JobInfo **info_p,
7030 uint32_t *count)
7032 union spoolss_JobInfo *info;
7033 int i;
7034 WERROR result = WERR_OK;
7036 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7037 W_ERROR_HAVE_NO_MEMORY(info);
7039 *count = num_queues;
7041 for (i=0; i<*count; i++) {
7042 struct spoolss_DeviceMode *devmode;
7044 result = spoolss_create_default_devmode(info,
7045 pinfo2->printername,
7046 &devmode);
7047 if (!W_ERROR_IS_OK(result)) {
7048 DEBUG(3, ("Can't proceed w/o a devmode!"));
7049 goto out;
7052 result = fill_job_info2(info,
7053 &info[i].info2,
7054 &queue[i],
7056 snum,
7057 pinfo2,
7058 devmode);
7059 if (!W_ERROR_IS_OK(result)) {
7060 goto out;
7064 out:
7065 if (!W_ERROR_IS_OK(result)) {
7066 TALLOC_FREE(info);
7067 *count = 0;
7068 return result;
7071 *info_p = info;
7073 return WERR_OK;
7076 /****************************************************************************
7077 Enumjobs at level 3.
7078 ****************************************************************************/
7080 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7081 const print_queue_struct *queue,
7082 uint32_t num_queues, int snum,
7083 struct spoolss_PrinterInfo2 *pinfo2,
7084 union spoolss_JobInfo **info_p,
7085 uint32_t *count)
7087 union spoolss_JobInfo *info;
7088 int i;
7089 WERROR result = WERR_OK;
7091 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7092 W_ERROR_HAVE_NO_MEMORY(info);
7094 *count = num_queues;
7096 for (i=0; i<*count; i++) {
7097 const print_queue_struct *next_queue = NULL;
7099 if (i+1 < *count) {
7100 next_queue = &queue[i+1];
7103 result = fill_job_info3(info,
7104 &info[i].info3,
7105 &queue[i],
7106 next_queue,
7108 snum,
7109 pinfo2);
7110 if (!W_ERROR_IS_OK(result)) {
7111 goto out;
7115 out:
7116 if (!W_ERROR_IS_OK(result)) {
7117 TALLOC_FREE(info);
7118 *count = 0;
7119 return result;
7122 *info_p = info;
7124 return WERR_OK;
7127 /****************************************************************
7128 _spoolss_EnumJobs
7129 ****************************************************************/
7131 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7132 struct spoolss_EnumJobs *r)
7134 WERROR result;
7135 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7136 int snum;
7137 print_status_struct prt_status;
7138 print_queue_struct *queue = NULL;
7139 uint32_t count;
7141 /* that's an [in out] buffer */
7143 if (!r->in.buffer && (r->in.offered != 0)) {
7144 return WERR_INVALID_PARAM;
7147 DEBUG(4,("_spoolss_EnumJobs\n"));
7149 *r->out.needed = 0;
7150 *r->out.count = 0;
7151 *r->out.info = NULL;
7153 /* lookup the printer snum and tdb entry */
7155 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7156 return WERR_BADFID;
7159 result = winreg_get_printer_internal(p->mem_ctx,
7160 get_session_info_system(),
7161 p->msg_ctx,
7162 lp_const_servicename(snum),
7163 &pinfo2);
7164 if (!W_ERROR_IS_OK(result)) {
7165 return result;
7168 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7169 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7170 count, prt_status.status, prt_status.message));
7172 if (count == 0) {
7173 SAFE_FREE(queue);
7174 TALLOC_FREE(pinfo2);
7175 return WERR_OK;
7178 switch (r->in.level) {
7179 case 1:
7180 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7181 pinfo2, r->out.info, r->out.count);
7182 break;
7183 case 2:
7184 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7185 pinfo2, r->out.info, r->out.count);
7186 break;
7187 case 3:
7188 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7189 pinfo2, r->out.info, r->out.count);
7190 break;
7191 default:
7192 result = WERR_UNKNOWN_LEVEL;
7193 break;
7196 SAFE_FREE(queue);
7197 TALLOC_FREE(pinfo2);
7199 if (!W_ERROR_IS_OK(result)) {
7200 return result;
7203 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7204 spoolss_EnumJobs,
7205 *r->out.info, r->in.level,
7206 *r->out.count);
7207 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7208 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7210 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7213 /****************************************************************
7214 _spoolss_ScheduleJob
7215 ****************************************************************/
7217 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7218 struct spoolss_ScheduleJob *r)
7220 return WERR_OK;
7223 /****************************************************************
7224 ****************************************************************/
7226 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7227 struct messaging_context *msg_ctx,
7228 const char *printer_name,
7229 uint32_t job_id,
7230 struct spoolss_SetJobInfo1 *r)
7232 char *old_doc_name;
7234 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7235 return WERR_BADFID;
7238 if (strequal(old_doc_name, r->document_name)) {
7239 return WERR_OK;
7242 if (!print_job_set_name(server_event_context(), msg_ctx,
7243 printer_name, job_id, r->document_name)) {
7244 return WERR_BADFID;
7247 return WERR_OK;
7250 /****************************************************************
7251 _spoolss_SetJob
7252 ****************************************************************/
7254 WERROR _spoolss_SetJob(struct pipes_struct *p,
7255 struct spoolss_SetJob *r)
7257 const struct auth_session_info *session_info = p->session_info;
7258 int snum;
7259 WERROR errcode = WERR_BADFUNC;
7261 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7262 return WERR_BADFID;
7265 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7266 return WERR_INVALID_PRINTER_NAME;
7269 switch (r->in.command) {
7270 case SPOOLSS_JOB_CONTROL_CANCEL:
7271 case SPOOLSS_JOB_CONTROL_DELETE:
7272 errcode = print_job_delete(session_info, p->msg_ctx,
7273 snum, r->in.job_id);
7274 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7275 errcode = WERR_OK;
7277 break;
7278 case SPOOLSS_JOB_CONTROL_PAUSE:
7279 if (print_job_pause(session_info, p->msg_ctx,
7280 snum, r->in.job_id, &errcode)) {
7281 errcode = WERR_OK;
7283 break;
7284 case SPOOLSS_JOB_CONTROL_RESTART:
7285 case SPOOLSS_JOB_CONTROL_RESUME:
7286 if (print_job_resume(session_info, p->msg_ctx,
7287 snum, r->in.job_id, &errcode)) {
7288 errcode = WERR_OK;
7290 break;
7291 case 0:
7292 errcode = WERR_OK;
7293 break;
7294 default:
7295 return WERR_UNKNOWN_LEVEL;
7298 if (!W_ERROR_IS_OK(errcode)) {
7299 return errcode;
7302 if (r->in.ctr == NULL) {
7303 return errcode;
7306 switch (r->in.ctr->level) {
7307 case 1:
7308 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7309 lp_const_servicename(snum),
7310 r->in.job_id,
7311 r->in.ctr->info.info1);
7312 break;
7313 case 2:
7314 case 3:
7315 case 4:
7316 default:
7317 return WERR_UNKNOWN_LEVEL;
7320 return errcode;
7323 /****************************************************************************
7324 Enumerates all printer drivers by level and architecture.
7325 ****************************************************************************/
7327 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7328 const struct auth_session_info *session_info,
7329 struct messaging_context *msg_ctx,
7330 const char *servername,
7331 const char *architecture,
7332 uint32_t level,
7333 union spoolss_DriverInfo **info_p,
7334 uint32_t *count_p)
7336 int i;
7337 uint32_t version;
7338 struct spoolss_DriverInfo8 *driver;
7339 union spoolss_DriverInfo *info = NULL;
7340 uint32_t count = 0;
7341 WERROR result = WERR_OK;
7342 uint32_t num_drivers;
7343 const char **drivers;
7344 struct dcerpc_binding_handle *b;
7345 TALLOC_CTX *tmp_ctx = NULL;
7347 *count_p = 0;
7348 *info_p = NULL;
7350 tmp_ctx = talloc_new(mem_ctx);
7351 if (!tmp_ctx) {
7352 return WERR_NOMEM;
7355 result = winreg_printer_binding_handle(tmp_ctx,
7356 session_info,
7357 msg_ctx,
7358 &b);
7359 if (!W_ERROR_IS_OK(result)) {
7360 goto out;
7363 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7364 result = winreg_get_driver_list(tmp_ctx, b,
7365 architecture, version,
7366 &num_drivers, &drivers);
7367 if (!W_ERROR_IS_OK(result)) {
7368 goto out;
7370 DEBUG(4, ("we have:[%d] drivers in environment"
7371 " [%s] and version [%d]\n",
7372 num_drivers, architecture, version));
7374 if (num_drivers != 0) {
7375 info = talloc_realloc(tmp_ctx, info,
7376 union spoolss_DriverInfo,
7377 count + num_drivers);
7378 if (!info) {
7379 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7380 "failed to enlarge driver info buffer!\n"));
7381 result = WERR_NOMEM;
7382 goto out;
7386 for (i = 0; i < num_drivers; i++) {
7387 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7389 result = winreg_get_driver(tmp_ctx, b,
7390 architecture, drivers[i],
7391 version, &driver);
7392 if (!W_ERROR_IS_OK(result)) {
7393 goto out;
7396 switch (level) {
7397 case 1:
7398 result = fill_printer_driver_info1(info, &info[count+i].info1,
7399 driver, servername);
7400 break;
7401 case 2:
7402 result = fill_printer_driver_info2(info, &info[count+i].info2,
7403 driver, servername);
7404 break;
7405 case 3:
7406 result = fill_printer_driver_info3(info, &info[count+i].info3,
7407 driver, servername);
7408 break;
7409 case 4:
7410 result = fill_printer_driver_info4(info, &info[count+i].info4,
7411 driver, servername);
7412 break;
7413 case 5:
7414 result = fill_printer_driver_info5(info, &info[count+i].info5,
7415 driver, servername);
7416 break;
7417 case 6:
7418 result = fill_printer_driver_info6(info, &info[count+i].info6,
7419 driver, servername);
7420 break;
7421 case 8:
7422 result = fill_printer_driver_info8(info, &info[count+i].info8,
7423 driver, servername);
7424 break;
7425 default:
7426 result = WERR_UNKNOWN_LEVEL;
7427 break;
7430 TALLOC_FREE(driver);
7432 if (!W_ERROR_IS_OK(result)) {
7433 goto out;
7437 count += num_drivers;
7438 TALLOC_FREE(drivers);
7441 out:
7442 if (W_ERROR_IS_OK(result)) {
7443 *info_p = talloc_move(mem_ctx, &info);
7444 *count_p = count;
7447 talloc_free(tmp_ctx);
7448 return result;
7451 /****************************************************************************
7452 Enumerates all printer drivers by level.
7453 ****************************************************************************/
7455 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7456 const struct auth_session_info *session_info,
7457 struct messaging_context *msg_ctx,
7458 const char *servername,
7459 const char *architecture,
7460 uint32_t level,
7461 union spoolss_DriverInfo **info_p,
7462 uint32_t *count_p)
7464 uint32_t a,i;
7465 WERROR result = WERR_OK;
7467 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7469 for (a=0; archi_table[a].long_archi != NULL; a++) {
7471 union spoolss_DriverInfo *info = NULL;
7472 uint32_t count = 0;
7474 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7475 session_info,
7476 msg_ctx,
7477 servername,
7478 archi_table[a].long_archi,
7479 level,
7480 &info,
7481 &count);
7482 if (!W_ERROR_IS_OK(result)) {
7483 continue;
7486 for (i=0; i < count; i++) {
7487 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7488 info[i], info_p, count_p);
7492 return result;
7495 return enumprinterdrivers_level_by_architecture(mem_ctx,
7496 session_info,
7497 msg_ctx,
7498 servername,
7499 architecture,
7500 level,
7501 info_p,
7502 count_p);
7505 /****************************************************************
7506 _spoolss_EnumPrinterDrivers
7507 ****************************************************************/
7509 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7510 struct spoolss_EnumPrinterDrivers *r)
7512 const char *cservername;
7513 WERROR result;
7515 /* that's an [in out] buffer */
7517 if (!r->in.buffer && (r->in.offered != 0)) {
7518 return WERR_INVALID_PARAM;
7521 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7523 *r->out.needed = 0;
7524 *r->out.count = 0;
7525 *r->out.info = NULL;
7527 cservername = canon_servername(r->in.server);
7529 if (!is_myname_or_ipaddr(cservername)) {
7530 return WERR_UNKNOWN_PRINTER_DRIVER;
7533 result = enumprinterdrivers_level(p->mem_ctx,
7534 get_session_info_system(),
7535 p->msg_ctx,
7536 cservername,
7537 r->in.environment,
7538 r->in.level,
7539 r->out.info,
7540 r->out.count);
7541 if (!W_ERROR_IS_OK(result)) {
7542 return result;
7545 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7546 spoolss_EnumPrinterDrivers,
7547 *r->out.info, r->in.level,
7548 *r->out.count);
7549 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7550 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7552 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7555 /****************************************************************
7556 _spoolss_EnumForms
7557 ****************************************************************/
7559 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7560 struct spoolss_EnumForms *r)
7562 WERROR result;
7564 *r->out.count = 0;
7565 *r->out.needed = 0;
7566 *r->out.info = NULL;
7568 /* that's an [in out] buffer */
7570 if (!r->in.buffer && (r->in.offered != 0) ) {
7571 return WERR_INVALID_PARAM;
7574 DEBUG(4,("_spoolss_EnumForms\n"));
7575 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7576 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7578 switch (r->in.level) {
7579 case 1:
7580 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7581 get_session_info_system(),
7582 p->msg_ctx,
7583 r->out.count,
7584 r->out.info);
7585 break;
7586 default:
7587 result = WERR_UNKNOWN_LEVEL;
7588 break;
7591 if (!W_ERROR_IS_OK(result)) {
7592 return result;
7595 if (*r->out.count == 0) {
7596 return WERR_NO_MORE_ITEMS;
7599 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7600 spoolss_EnumForms,
7601 *r->out.info, r->in.level,
7602 *r->out.count);
7603 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7604 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7606 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7609 /****************************************************************
7610 _spoolss_GetForm
7611 ****************************************************************/
7613 WERROR _spoolss_GetForm(struct pipes_struct *p,
7614 struct spoolss_GetForm *r)
7616 WERROR result;
7618 /* that's an [in out] buffer */
7620 if (!r->in.buffer && (r->in.offered != 0)) {
7621 return WERR_INVALID_PARAM;
7624 DEBUG(4,("_spoolss_GetForm\n"));
7625 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7626 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7628 switch (r->in.level) {
7629 case 1:
7630 result = winreg_printer_getform1_internal(p->mem_ctx,
7631 get_session_info_system(),
7632 p->msg_ctx,
7633 r->in.form_name,
7634 &r->out.info->info1);
7635 break;
7636 default:
7637 result = WERR_UNKNOWN_LEVEL;
7638 break;
7641 if (!W_ERROR_IS_OK(result)) {
7642 TALLOC_FREE(r->out.info);
7643 return result;
7646 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7647 r->out.info, r->in.level);
7648 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7650 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7653 /****************************************************************************
7654 ****************************************************************************/
7656 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7657 struct spoolss_PortInfo1 *r,
7658 const char *name)
7660 r->port_name = talloc_strdup(mem_ctx, name);
7661 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7663 return WERR_OK;
7666 /****************************************************************************
7667 TODO: This probably needs distinguish between TCP/IP and Local ports
7668 somehow.
7669 ****************************************************************************/
7671 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7672 struct spoolss_PortInfo2 *r,
7673 const char *name)
7675 r->port_name = talloc_strdup(mem_ctx, name);
7676 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7678 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7679 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7681 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7682 W_ERROR_HAVE_NO_MEMORY(r->description);
7684 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7685 r->reserved = 0;
7687 return WERR_OK;
7691 /****************************************************************************
7692 wrapper around the enumer ports command
7693 ****************************************************************************/
7695 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7697 char *cmd = lp_enumports_cmd();
7698 char **qlines = NULL;
7699 char *command = NULL;
7700 int numlines;
7701 int ret;
7702 int fd;
7704 *count = 0;
7705 *lines = NULL;
7707 /* if no hook then just fill in the default port */
7709 if ( !*cmd ) {
7710 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7711 return WERR_NOMEM;
7713 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7714 TALLOC_FREE(qlines);
7715 return WERR_NOMEM;
7717 qlines[1] = NULL;
7718 numlines = 1;
7720 else {
7721 /* we have a valid enumport command */
7723 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7724 if (!command) {
7725 return WERR_NOMEM;
7728 DEBUG(10,("Running [%s]\n", command));
7729 ret = smbrun(command, &fd);
7730 DEBUG(10,("Returned [%d]\n", ret));
7731 TALLOC_FREE(command);
7732 if (ret != 0) {
7733 if (fd != -1) {
7734 close(fd);
7736 return WERR_ACCESS_DENIED;
7739 numlines = 0;
7740 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7741 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7742 close(fd);
7745 *count = numlines;
7746 *lines = qlines;
7748 return WERR_OK;
7751 /****************************************************************************
7752 enumports level 1.
7753 ****************************************************************************/
7755 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7756 union spoolss_PortInfo **info_p,
7757 uint32_t *count)
7759 union spoolss_PortInfo *info = NULL;
7760 int i=0;
7761 WERROR result = WERR_OK;
7762 char **qlines = NULL;
7763 int numlines = 0;
7765 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7766 if (!W_ERROR_IS_OK(result)) {
7767 goto out;
7770 if (numlines) {
7771 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7772 if (!info) {
7773 DEBUG(10,("Returning WERR_NOMEM\n"));
7774 result = WERR_NOMEM;
7775 goto out;
7778 for (i=0; i<numlines; i++) {
7779 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7780 result = fill_port_1(info, &info[i].info1, qlines[i]);
7781 if (!W_ERROR_IS_OK(result)) {
7782 goto out;
7786 TALLOC_FREE(qlines);
7788 out:
7789 if (!W_ERROR_IS_OK(result)) {
7790 TALLOC_FREE(info);
7791 TALLOC_FREE(qlines);
7792 *count = 0;
7793 *info_p = NULL;
7794 return result;
7797 *info_p = info;
7798 *count = numlines;
7800 return WERR_OK;
7803 /****************************************************************************
7804 enumports level 2.
7805 ****************************************************************************/
7807 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7808 union spoolss_PortInfo **info_p,
7809 uint32_t *count)
7811 union spoolss_PortInfo *info = NULL;
7812 int i=0;
7813 WERROR result = WERR_OK;
7814 char **qlines = NULL;
7815 int numlines = 0;
7817 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7818 if (!W_ERROR_IS_OK(result)) {
7819 goto out;
7822 if (numlines) {
7823 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7824 if (!info) {
7825 DEBUG(10,("Returning WERR_NOMEM\n"));
7826 result = WERR_NOMEM;
7827 goto out;
7830 for (i=0; i<numlines; i++) {
7831 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7832 result = fill_port_2(info, &info[i].info2, qlines[i]);
7833 if (!W_ERROR_IS_OK(result)) {
7834 goto out;
7838 TALLOC_FREE(qlines);
7840 out:
7841 if (!W_ERROR_IS_OK(result)) {
7842 TALLOC_FREE(info);
7843 TALLOC_FREE(qlines);
7844 *count = 0;
7845 *info_p = NULL;
7846 return result;
7849 *info_p = info;
7850 *count = numlines;
7852 return WERR_OK;
7855 /****************************************************************
7856 _spoolss_EnumPorts
7857 ****************************************************************/
7859 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7860 struct spoolss_EnumPorts *r)
7862 WERROR result;
7864 /* that's an [in out] buffer */
7866 if (!r->in.buffer && (r->in.offered != 0)) {
7867 return WERR_INVALID_PARAM;
7870 DEBUG(4,("_spoolss_EnumPorts\n"));
7872 *r->out.count = 0;
7873 *r->out.needed = 0;
7874 *r->out.info = NULL;
7876 switch (r->in.level) {
7877 case 1:
7878 result = enumports_level_1(p->mem_ctx, r->out.info,
7879 r->out.count);
7880 break;
7881 case 2:
7882 result = enumports_level_2(p->mem_ctx, r->out.info,
7883 r->out.count);
7884 break;
7885 default:
7886 return WERR_UNKNOWN_LEVEL;
7889 if (!W_ERROR_IS_OK(result)) {
7890 return result;
7893 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7894 spoolss_EnumPorts,
7895 *r->out.info, r->in.level,
7896 *r->out.count);
7897 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7898 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7900 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7903 /****************************************************************************
7904 ****************************************************************************/
7906 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7907 const char *server,
7908 struct spoolss_SetPrinterInfoCtr *info_ctr,
7909 struct spoolss_DeviceMode *devmode,
7910 struct security_descriptor *secdesc,
7911 struct spoolss_UserLevelCtr *user_ctr,
7912 struct policy_handle *handle)
7914 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7915 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7916 int snum;
7917 WERROR err = WERR_OK;
7919 /* samba does not have a concept of local, non-shared printers yet, so
7920 * make sure we always setup sharename - gd */
7921 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7922 (info2->printername != NULL && info2->printername[0] != '\0')) {
7923 DEBUG(5, ("spoolss_addprinterex_level_2: "
7924 "no sharename has been set, setting printername %s as sharename\n",
7925 info2->printername));
7926 info2->sharename = info2->printername;
7929 /* check to see if the printer already exists */
7930 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7931 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7932 info2->sharename));
7933 return WERR_PRINTER_ALREADY_EXISTS;
7936 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7937 if ((snum = print_queue_snum(info2->printername)) != -1) {
7938 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7939 info2->printername));
7940 return WERR_PRINTER_ALREADY_EXISTS;
7944 /* validate printer info struct */
7945 if (!info2->printername || strlen(info2->printername) == 0) {
7946 return WERR_INVALID_PRINTER_NAME;
7948 if (!info2->portname || strlen(info2->portname) == 0) {
7949 return WERR_UNKNOWN_PORT;
7951 if (!info2->drivername || strlen(info2->drivername) == 0) {
7952 return WERR_UNKNOWN_PRINTER_DRIVER;
7954 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7955 return WERR_UNKNOWN_PRINTPROCESSOR;
7958 /* FIXME!!! smbd should check to see if the driver is installed before
7959 trying to add a printer like this --jerry */
7961 if (*lp_addprinter_cmd() ) {
7962 char *raddr;
7964 raddr = tsocket_address_inet_addr_string(p->remote_address,
7965 p->mem_ctx);
7966 if (raddr == NULL) {
7967 return WERR_NOMEM;
7970 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7971 info2, raddr,
7972 p->msg_ctx) ) {
7973 return WERR_ACCESS_DENIED;
7975 } else {
7976 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7977 "smb.conf parameter \"addprinter command\" is defined. This "
7978 "parameter must exist for this call to succeed\n",
7979 info2->sharename ));
7982 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7983 return WERR_ACCESS_DENIED;
7986 /* you must be a printer admin to add a new printer */
7987 if (!print_access_check(p->session_info,
7988 p->msg_ctx,
7989 snum,
7990 PRINTER_ACCESS_ADMINISTER)) {
7991 return WERR_ACCESS_DENIED;
7995 * Do sanity check on the requested changes for Samba.
7998 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7999 return WERR_INVALID_PARAM;
8002 if (devmode == NULL) {
8003 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8006 update_dsspooler(p->mem_ctx,
8007 get_session_info_system(),
8008 p->msg_ctx,
8010 info2,
8011 NULL);
8013 err = winreg_update_printer_internal(p->mem_ctx,
8014 get_session_info_system(),
8015 p->msg_ctx,
8016 info2->sharename,
8017 info2_mask,
8018 info2,
8019 devmode,
8020 secdesc);
8021 if (!W_ERROR_IS_OK(err)) {
8022 return err;
8025 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8026 if (!W_ERROR_IS_OK(err)) {
8027 /* Handle open failed - remove addition. */
8028 ZERO_STRUCTP(handle);
8029 return err;
8032 return WERR_OK;
8035 /****************************************************************
8036 _spoolss_AddPrinterEx
8037 ****************************************************************/
8039 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8040 struct spoolss_AddPrinterEx *r)
8042 switch (r->in.info_ctr->level) {
8043 case 1:
8044 /* we don't handle yet */
8045 /* but I know what to do ... */
8046 return WERR_UNKNOWN_LEVEL;
8047 case 2:
8048 return spoolss_addprinterex_level_2(p, r->in.server,
8049 r->in.info_ctr,
8050 r->in.devmode_ctr->devmode,
8051 r->in.secdesc_ctr->sd,
8052 r->in.userlevel_ctr,
8053 r->out.handle);
8054 default:
8055 return WERR_UNKNOWN_LEVEL;
8059 /****************************************************************
8060 _spoolss_AddPrinter
8061 ****************************************************************/
8063 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8064 struct spoolss_AddPrinter *r)
8066 struct spoolss_AddPrinterEx a;
8067 struct spoolss_UserLevelCtr userlevel_ctr;
8069 ZERO_STRUCT(userlevel_ctr);
8071 userlevel_ctr.level = 1;
8073 a.in.server = r->in.server;
8074 a.in.info_ctr = r->in.info_ctr;
8075 a.in.devmode_ctr = r->in.devmode_ctr;
8076 a.in.secdesc_ctr = r->in.secdesc_ctr;
8077 a.in.userlevel_ctr = &userlevel_ctr;
8078 a.out.handle = r->out.handle;
8080 return _spoolss_AddPrinterEx(p, &a);
8083 /****************************************************************
8084 _spoolss_AddPrinterDriverEx
8085 ****************************************************************/
8087 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8088 struct spoolss_AddPrinterDriverEx *r)
8090 WERROR err = WERR_OK;
8091 const char *driver_name = NULL;
8092 uint32_t version;
8093 const char *fn;
8095 switch (p->opnum) {
8096 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8097 fn = "_spoolss_AddPrinterDriver";
8098 break;
8099 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8100 fn = "_spoolss_AddPrinterDriverEx";
8101 break;
8102 default:
8103 return WERR_INVALID_PARAM;
8107 * we only support the semantics of AddPrinterDriver()
8108 * i.e. only copy files that are newer than existing ones
8111 if (r->in.flags == 0) {
8112 return WERR_INVALID_PARAM;
8115 if (r->in.flags != APD_COPY_NEW_FILES) {
8116 return WERR_ACCESS_DENIED;
8119 /* FIXME */
8120 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8121 /* Clever hack from Martin Zielinski <mz@seh.de>
8122 * to allow downgrade from level 8 (Vista).
8124 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8125 r->in.info_ctr->level));
8126 return WERR_UNKNOWN_LEVEL;
8129 DEBUG(5,("Cleaning driver's information\n"));
8130 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8131 if (!W_ERROR_IS_OK(err))
8132 goto done;
8134 DEBUG(5,("Moving driver to final destination\n"));
8135 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8136 if (!W_ERROR_IS_OK(err)) {
8137 goto done;
8140 err = winreg_add_driver_internal(p->mem_ctx,
8141 get_session_info_system(),
8142 p->msg_ctx,
8143 r->in.info_ctr,
8144 &driver_name,
8145 &version);
8146 if (!W_ERROR_IS_OK(err)) {
8147 goto done;
8151 * I think this is where he DrvUpgradePrinter() hook would be
8152 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8153 * server. Right now, we just need to send ourselves a message
8154 * to update each printer bound to this driver. --jerry
8157 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8158 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8159 fn, driver_name));
8162 done:
8163 return err;
8166 /****************************************************************
8167 _spoolss_AddPrinterDriver
8168 ****************************************************************/
8170 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8171 struct spoolss_AddPrinterDriver *r)
8173 struct spoolss_AddPrinterDriverEx a;
8175 switch (r->in.info_ctr->level) {
8176 case 2:
8177 case 3:
8178 case 4:
8179 case 5:
8180 break;
8181 default:
8182 return WERR_UNKNOWN_LEVEL;
8185 a.in.servername = r->in.servername;
8186 a.in.info_ctr = r->in.info_ctr;
8187 a.in.flags = APD_COPY_NEW_FILES;
8189 return _spoolss_AddPrinterDriverEx(p, &a);
8192 /****************************************************************************
8193 ****************************************************************************/
8195 struct _spoolss_paths {
8196 int type;
8197 const char *share;
8198 const char *dir;
8201 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8203 static const struct _spoolss_paths spoolss_paths[]= {
8204 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8205 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8208 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8209 const char *servername,
8210 const char *environment,
8211 int component,
8212 char **path)
8214 const char *pservername = NULL;
8215 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8216 const char *short_archi;
8218 *path = NULL;
8220 /* environment may be empty */
8221 if (environment && strlen(environment)) {
8222 long_archi = environment;
8225 /* servername may be empty */
8226 if (servername && strlen(servername)) {
8227 pservername = canon_servername(servername);
8229 if (!is_myname_or_ipaddr(pservername)) {
8230 return WERR_INVALID_PARAM;
8234 if (!(short_archi = get_short_archi(long_archi))) {
8235 return WERR_INVALID_ENVIRONMENT;
8238 switch (component) {
8239 case SPOOLSS_PRTPROCS_PATH:
8240 case SPOOLSS_DRIVER_PATH:
8241 if (pservername) {
8242 *path = talloc_asprintf(mem_ctx,
8243 "\\\\%s\\%s\\%s",
8244 pservername,
8245 spoolss_paths[component].share,
8246 short_archi);
8247 } else {
8248 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8249 SPOOLSS_DEFAULT_SERVER_PATH,
8250 spoolss_paths[component].dir,
8251 short_archi);
8253 break;
8254 default:
8255 return WERR_INVALID_PARAM;
8258 if (!*path) {
8259 return WERR_NOMEM;
8262 return WERR_OK;
8265 /****************************************************************************
8266 ****************************************************************************/
8268 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8269 const char *servername,
8270 const char *environment,
8271 struct spoolss_DriverDirectoryInfo1 *r)
8273 WERROR werr;
8274 char *path = NULL;
8276 werr = compose_spoolss_server_path(mem_ctx,
8277 servername,
8278 environment,
8279 SPOOLSS_DRIVER_PATH,
8280 &path);
8281 if (!W_ERROR_IS_OK(werr)) {
8282 return werr;
8285 DEBUG(4,("printer driver directory: [%s]\n", path));
8287 r->directory_name = path;
8289 return WERR_OK;
8292 /****************************************************************
8293 _spoolss_GetPrinterDriverDirectory
8294 ****************************************************************/
8296 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8297 struct spoolss_GetPrinterDriverDirectory *r)
8299 WERROR werror;
8301 /* that's an [in out] buffer */
8303 if (!r->in.buffer && (r->in.offered != 0)) {
8304 return WERR_INVALID_PARAM;
8307 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8308 r->in.level));
8310 *r->out.needed = 0;
8312 /* r->in.level is ignored */
8314 werror = getprinterdriverdir_level_1(p->mem_ctx,
8315 r->in.server,
8316 r->in.environment,
8317 &r->out.info->info1);
8318 if (!W_ERROR_IS_OK(werror)) {
8319 TALLOC_FREE(r->out.info);
8320 return werror;
8323 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8324 r->out.info, r->in.level);
8325 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8327 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8330 /****************************************************************
8331 _spoolss_EnumPrinterData
8332 ****************************************************************/
8334 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8335 struct spoolss_EnumPrinterData *r)
8337 WERROR result;
8338 struct spoolss_EnumPrinterDataEx r2;
8339 uint32_t count;
8340 struct spoolss_PrinterEnumValues *info, *val = NULL;
8341 uint32_t needed;
8343 r2.in.handle = r->in.handle;
8344 r2.in.key_name = "PrinterDriverData";
8345 r2.in.offered = 0;
8346 r2.out.count = &count;
8347 r2.out.info = &info;
8348 r2.out.needed = &needed;
8350 result = _spoolss_EnumPrinterDataEx(p, &r2);
8351 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8352 r2.in.offered = needed;
8353 result = _spoolss_EnumPrinterDataEx(p, &r2);
8355 if (!W_ERROR_IS_OK(result)) {
8356 return result;
8360 * The NT machine wants to know the biggest size of value and data
8362 * cf: MSDN EnumPrinterData remark section
8365 if (!r->in.value_offered && !r->in.data_offered) {
8366 uint32_t biggest_valuesize = 0;
8367 uint32_t biggest_datasize = 0;
8368 int i, name_length;
8370 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8372 for (i=0; i<count; i++) {
8374 name_length = strlen(info[i].value_name);
8375 if (strlen(info[i].value_name) > biggest_valuesize) {
8376 biggest_valuesize = name_length;
8379 if (info[i].data_length > biggest_datasize) {
8380 biggest_datasize = info[i].data_length;
8383 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8384 biggest_datasize));
8387 /* the value is an UNICODE string but real_value_size is the length
8388 in bytes including the trailing 0 */
8390 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8391 *r->out.data_needed = biggest_datasize;
8393 DEBUG(6,("final values: [%d], [%d]\n",
8394 *r->out.value_needed, *r->out.data_needed));
8396 return WERR_OK;
8399 if (r->in.enum_index < count) {
8400 val = &info[r->in.enum_index];
8403 if (val == NULL) {
8404 /* out_value should default to "" or else NT4 has
8405 problems unmarshalling the response */
8407 if (r->in.value_offered) {
8408 *r->out.value_needed = 1;
8409 r->out.value_name = talloc_strdup(r, "");
8410 if (!r->out.value_name) {
8411 return WERR_NOMEM;
8413 } else {
8414 r->out.value_name = NULL;
8415 *r->out.value_needed = 0;
8418 /* the data is counted in bytes */
8420 *r->out.data_needed = r->in.data_offered;
8422 result = WERR_NO_MORE_ITEMS;
8423 } else {
8425 * the value is:
8426 * - counted in bytes in the request
8427 * - counted in UNICODE chars in the max reply
8428 * - counted in bytes in the real size
8430 * take a pause *before* coding not *during* coding
8433 /* name */
8434 if (r->in.value_offered) {
8435 r->out.value_name = talloc_strdup(r, val->value_name);
8436 if (!r->out.value_name) {
8437 return WERR_NOMEM;
8439 *r->out.value_needed = val->value_name_len;
8440 } else {
8441 r->out.value_name = NULL;
8442 *r->out.value_needed = 0;
8445 /* type */
8447 *r->out.type = val->type;
8449 /* data - counted in bytes */
8452 * See the section "Dynamically Typed Query Parameters"
8453 * in MS-RPRN.
8456 if (r->out.data && val->data && val->data->data &&
8457 val->data_length && r->in.data_offered) {
8458 memcpy(r->out.data, val->data->data,
8459 MIN(val->data_length,r->in.data_offered));
8462 *r->out.data_needed = val->data_length;
8464 result = WERR_OK;
8467 return result;
8470 /****************************************************************
8471 _spoolss_SetPrinterData
8472 ****************************************************************/
8474 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8475 struct spoolss_SetPrinterData *r)
8477 struct spoolss_SetPrinterDataEx r2;
8479 r2.in.handle = r->in.handle;
8480 r2.in.key_name = "PrinterDriverData";
8481 r2.in.value_name = r->in.value_name;
8482 r2.in.type = r->in.type;
8483 r2.in.data = r->in.data;
8484 r2.in.offered = r->in.offered;
8486 return _spoolss_SetPrinterDataEx(p, &r2);
8489 /****************************************************************
8490 _spoolss_ResetPrinter
8491 ****************************************************************/
8493 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8494 struct spoolss_ResetPrinter *r)
8496 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8497 int snum;
8499 DEBUG(5,("_spoolss_ResetPrinter\n"));
8502 * All we do is to check to see if the handle and queue is valid.
8503 * This call really doesn't mean anything to us because we only
8504 * support RAW printing. --jerry
8507 if (!Printer) {
8508 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8509 OUR_HANDLE(r->in.handle)));
8510 return WERR_BADFID;
8513 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8514 return WERR_BADFID;
8517 /* blindly return success */
8518 return WERR_OK;
8521 /****************************************************************
8522 _spoolss_DeletePrinterData
8523 ****************************************************************/
8525 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8526 struct spoolss_DeletePrinterData *r)
8528 struct spoolss_DeletePrinterDataEx r2;
8530 r2.in.handle = r->in.handle;
8531 r2.in.key_name = "PrinterDriverData";
8532 r2.in.value_name = r->in.value_name;
8534 return _spoolss_DeletePrinterDataEx(p, &r2);
8537 /****************************************************************
8538 _spoolss_AddForm
8539 ****************************************************************/
8541 WERROR _spoolss_AddForm(struct pipes_struct *p,
8542 struct spoolss_AddForm *r)
8544 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8545 int snum = -1;
8546 WERROR status = WERR_OK;
8547 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8548 struct dcerpc_binding_handle *b;
8549 TALLOC_CTX *tmp_ctx = NULL;
8551 DEBUG(5,("_spoolss_AddForm\n"));
8553 if (!Printer) {
8554 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8555 OUR_HANDLE(r->in.handle)));
8556 return WERR_BADFID;
8559 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8560 and not a printer admin, then fail */
8562 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8563 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8564 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8565 p->session_info->info->domain_name,
8566 NULL,
8567 p->session_info->security_token,
8568 lp_printer_admin(snum))) {
8569 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8570 return WERR_ACCESS_DENIED;
8573 switch (form->flags) {
8574 case SPOOLSS_FORM_USER:
8575 case SPOOLSS_FORM_BUILTIN:
8576 case SPOOLSS_FORM_PRINTER:
8577 break;
8578 default:
8579 return WERR_INVALID_PARAM;
8582 tmp_ctx = talloc_new(p->mem_ctx);
8583 if (!tmp_ctx) {
8584 return WERR_NOMEM;
8587 status = winreg_printer_binding_handle(tmp_ctx,
8588 get_session_info_system(),
8589 p->msg_ctx,
8590 &b);
8591 if (!W_ERROR_IS_OK(status)) {
8592 goto done;
8595 status = winreg_printer_addform1(tmp_ctx, b, form);
8596 if (!W_ERROR_IS_OK(status)) {
8597 goto done;
8601 * ChangeID must always be set if this is a printer
8603 if (Printer->printer_type == SPLHND_PRINTER) {
8604 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8605 status = WERR_BADFID;
8606 goto done;
8609 status = winreg_printer_update_changeid(tmp_ctx, b,
8610 lp_const_servicename(snum));
8613 done:
8614 talloc_free(tmp_ctx);
8615 return status;
8618 /****************************************************************
8619 _spoolss_DeleteForm
8620 ****************************************************************/
8622 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8623 struct spoolss_DeleteForm *r)
8625 const char *form_name = r->in.form_name;
8626 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8627 int snum = -1;
8628 WERROR status = WERR_OK;
8629 struct dcerpc_binding_handle *b;
8630 TALLOC_CTX *tmp_ctx = NULL;
8632 DEBUG(5,("_spoolss_DeleteForm\n"));
8634 if (!Printer) {
8635 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8636 OUR_HANDLE(r->in.handle)));
8637 return WERR_BADFID;
8640 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8641 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8642 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8643 p->session_info->info->domain_name,
8644 NULL,
8645 p->session_info->security_token,
8646 lp_printer_admin(snum))) {
8647 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8648 return WERR_ACCESS_DENIED;
8651 tmp_ctx = talloc_new(p->mem_ctx);
8652 if (!tmp_ctx) {
8653 return WERR_NOMEM;
8656 status = winreg_printer_binding_handle(tmp_ctx,
8657 get_session_info_system(),
8658 p->msg_ctx,
8659 &b);
8660 if (!W_ERROR_IS_OK(status)) {
8661 goto done;
8664 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8665 if (!W_ERROR_IS_OK(status)) {
8666 goto done;
8670 * ChangeID must always be set if this is a printer
8672 if (Printer->printer_type == SPLHND_PRINTER) {
8673 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8674 status = WERR_BADFID;
8675 goto done;
8678 status = winreg_printer_update_changeid(tmp_ctx, b,
8679 lp_const_servicename(snum));
8682 done:
8683 talloc_free(tmp_ctx);
8684 return status;
8687 /****************************************************************
8688 _spoolss_SetForm
8689 ****************************************************************/
8691 WERROR _spoolss_SetForm(struct pipes_struct *p,
8692 struct spoolss_SetForm *r)
8694 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8695 const char *form_name = r->in.form_name;
8696 int snum = -1;
8697 WERROR status = WERR_OK;
8698 struct dcerpc_binding_handle *b;
8699 TALLOC_CTX *tmp_ctx = NULL;
8701 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8703 DEBUG(5,("_spoolss_SetForm\n"));
8705 if (!Printer) {
8706 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8707 OUR_HANDLE(r->in.handle)));
8708 return WERR_BADFID;
8711 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8712 and not a printer admin, then fail */
8714 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8715 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8716 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8717 p->session_info->info->domain_name,
8718 NULL,
8719 p->session_info->security_token,
8720 lp_printer_admin(snum))) {
8721 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8722 return WERR_ACCESS_DENIED;
8725 tmp_ctx = talloc_new(p->mem_ctx);
8726 if (!tmp_ctx) {
8727 return WERR_NOMEM;
8730 status = winreg_printer_binding_handle(tmp_ctx,
8731 get_session_info_system(),
8732 p->msg_ctx,
8733 &b);
8734 if (!W_ERROR_IS_OK(status)) {
8735 goto done;
8738 status = winreg_printer_setform1(tmp_ctx, b,
8739 form_name,
8740 form);
8741 if (!W_ERROR_IS_OK(status)) {
8742 goto done;
8746 * ChangeID must always be set if this is a printer
8748 if (Printer->printer_type == SPLHND_PRINTER) {
8749 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8750 status = WERR_BADFID;
8751 goto done;
8754 status = winreg_printer_update_changeid(tmp_ctx, b,
8755 lp_const_servicename(snum));
8758 done:
8759 talloc_free(tmp_ctx);
8760 return status;
8763 /****************************************************************************
8764 fill_print_processor1
8765 ****************************************************************************/
8767 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8768 struct spoolss_PrintProcessorInfo1 *r,
8769 const char *print_processor_name)
8771 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8772 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8774 return WERR_OK;
8777 /****************************************************************************
8778 enumprintprocessors level 1.
8779 ****************************************************************************/
8781 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8782 union spoolss_PrintProcessorInfo **info_p,
8783 uint32_t *count)
8785 union spoolss_PrintProcessorInfo *info;
8786 WERROR result;
8788 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8789 W_ERROR_HAVE_NO_MEMORY(info);
8791 *count = 1;
8793 result = fill_print_processor1(info, &info[0].info1, "winprint");
8794 if (!W_ERROR_IS_OK(result)) {
8795 goto out;
8798 out:
8799 if (!W_ERROR_IS_OK(result)) {
8800 TALLOC_FREE(info);
8801 *count = 0;
8802 return result;
8805 *info_p = info;
8807 return WERR_OK;
8810 /****************************************************************
8811 _spoolss_EnumPrintProcessors
8812 ****************************************************************/
8814 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8815 struct spoolss_EnumPrintProcessors *r)
8817 WERROR result;
8819 /* that's an [in out] buffer */
8821 if (!r->in.buffer && (r->in.offered != 0)) {
8822 return WERR_INVALID_PARAM;
8825 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8828 * Enumerate the print processors ...
8830 * Just reply with "winprint", to keep NT happy
8831 * and I can use my nice printer checker.
8834 *r->out.count = 0;
8835 *r->out.needed = 0;
8836 *r->out.info = NULL;
8838 if (!get_short_archi(r->in.environment)) {
8839 return WERR_INVALID_ENVIRONMENT;
8842 switch (r->in.level) {
8843 case 1:
8844 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8845 r->out.count);
8846 break;
8847 default:
8848 return WERR_UNKNOWN_LEVEL;
8851 if (!W_ERROR_IS_OK(result)) {
8852 return result;
8855 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8856 spoolss_EnumPrintProcessors,
8857 *r->out.info, r->in.level,
8858 *r->out.count);
8859 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8860 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8862 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8865 /****************************************************************************
8866 fill_printprocdatatype1
8867 ****************************************************************************/
8869 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8870 struct spoolss_PrintProcDataTypesInfo1 *r,
8871 const char *name_array)
8873 r->name_array = talloc_strdup(mem_ctx, name_array);
8874 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8876 return WERR_OK;
8879 /****************************************************************************
8880 enumprintprocdatatypes level 1.
8881 ****************************************************************************/
8883 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8884 union spoolss_PrintProcDataTypesInfo **info_p,
8885 uint32_t *count)
8887 WERROR result;
8888 union spoolss_PrintProcDataTypesInfo *info;
8890 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8891 W_ERROR_HAVE_NO_MEMORY(info);
8893 *count = 1;
8895 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8896 if (!W_ERROR_IS_OK(result)) {
8897 goto out;
8900 out:
8901 if (!W_ERROR_IS_OK(result)) {
8902 TALLOC_FREE(info);
8903 *count = 0;
8904 return result;
8907 *info_p = info;
8909 return WERR_OK;
8912 /****************************************************************
8913 _spoolss_EnumPrintProcDataTypes
8914 ****************************************************************/
8916 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8917 struct spoolss_EnumPrintProcDataTypes *r)
8919 WERROR result;
8921 /* that's an [in out] buffer */
8923 if (!r->in.buffer && (r->in.offered != 0)) {
8924 return WERR_INVALID_PARAM;
8927 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8929 *r->out.count = 0;
8930 *r->out.needed = 0;
8931 *r->out.info = NULL;
8933 if (r->in.print_processor_name == NULL ||
8934 !strequal(r->in.print_processor_name, "winprint")) {
8935 return WERR_UNKNOWN_PRINTPROCESSOR;
8938 switch (r->in.level) {
8939 case 1:
8940 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8941 r->out.count);
8942 break;
8943 default:
8944 return WERR_UNKNOWN_LEVEL;
8947 if (!W_ERROR_IS_OK(result)) {
8948 return result;
8951 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8952 spoolss_EnumPrintProcDataTypes,
8953 *r->out.info, r->in.level,
8954 *r->out.count);
8955 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8956 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8958 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8961 /****************************************************************************
8962 fill_monitor_1
8963 ****************************************************************************/
8965 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8966 struct spoolss_MonitorInfo1 *r,
8967 const char *monitor_name)
8969 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8970 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8972 return WERR_OK;
8975 /****************************************************************************
8976 fill_monitor_2
8977 ****************************************************************************/
8979 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8980 struct spoolss_MonitorInfo2 *r,
8981 const char *monitor_name,
8982 const char *environment,
8983 const char *dll_name)
8985 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8986 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8987 r->environment = talloc_strdup(mem_ctx, environment);
8988 W_ERROR_HAVE_NO_MEMORY(r->environment);
8989 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8990 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8992 return WERR_OK;
8995 /****************************************************************************
8996 enumprintmonitors level 1.
8997 ****************************************************************************/
8999 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9000 union spoolss_MonitorInfo **info_p,
9001 uint32_t *count)
9003 union spoolss_MonitorInfo *info;
9004 WERROR result = WERR_OK;
9006 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9007 W_ERROR_HAVE_NO_MEMORY(info);
9009 *count = 2;
9011 result = fill_monitor_1(info, &info[0].info1,
9012 SPL_LOCAL_PORT);
9013 if (!W_ERROR_IS_OK(result)) {
9014 goto out;
9017 result = fill_monitor_1(info, &info[1].info1,
9018 SPL_TCPIP_PORT);
9019 if (!W_ERROR_IS_OK(result)) {
9020 goto out;
9023 out:
9024 if (!W_ERROR_IS_OK(result)) {
9025 TALLOC_FREE(info);
9026 *count = 0;
9027 return result;
9030 *info_p = info;
9032 return WERR_OK;
9035 /****************************************************************************
9036 enumprintmonitors level 2.
9037 ****************************************************************************/
9039 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9040 union spoolss_MonitorInfo **info_p,
9041 uint32_t *count)
9043 union spoolss_MonitorInfo *info;
9044 WERROR result = WERR_OK;
9046 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9047 W_ERROR_HAVE_NO_MEMORY(info);
9049 *count = 2;
9051 result = fill_monitor_2(info, &info[0].info2,
9052 SPL_LOCAL_PORT,
9053 "Windows NT X86", /* FIXME */
9054 "localmon.dll");
9055 if (!W_ERROR_IS_OK(result)) {
9056 goto out;
9059 result = fill_monitor_2(info, &info[1].info2,
9060 SPL_TCPIP_PORT,
9061 "Windows NT X86", /* FIXME */
9062 "tcpmon.dll");
9063 if (!W_ERROR_IS_OK(result)) {
9064 goto out;
9067 out:
9068 if (!W_ERROR_IS_OK(result)) {
9069 TALLOC_FREE(info);
9070 *count = 0;
9071 return result;
9074 *info_p = info;
9076 return WERR_OK;
9079 /****************************************************************
9080 _spoolss_EnumMonitors
9081 ****************************************************************/
9083 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9084 struct spoolss_EnumMonitors *r)
9086 WERROR result;
9088 /* that's an [in out] buffer */
9090 if (!r->in.buffer && (r->in.offered != 0)) {
9091 return WERR_INVALID_PARAM;
9094 DEBUG(5,("_spoolss_EnumMonitors\n"));
9097 * Enumerate the print monitors ...
9099 * Just reply with "Local Port", to keep NT happy
9100 * and I can use my nice printer checker.
9103 *r->out.count = 0;
9104 *r->out.needed = 0;
9105 *r->out.info = NULL;
9107 switch (r->in.level) {
9108 case 1:
9109 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9110 r->out.count);
9111 break;
9112 case 2:
9113 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9114 r->out.count);
9115 break;
9116 default:
9117 return WERR_UNKNOWN_LEVEL;
9120 if (!W_ERROR_IS_OK(result)) {
9121 return result;
9124 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9125 spoolss_EnumMonitors,
9126 *r->out.info, r->in.level,
9127 *r->out.count);
9128 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9129 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9131 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9134 /****************************************************************************
9135 ****************************************************************************/
9137 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9138 const print_queue_struct *queue,
9139 int count, int snum,
9140 struct spoolss_PrinterInfo2 *pinfo2,
9141 uint32_t jobid,
9142 struct spoolss_JobInfo1 *r)
9144 int i = 0;
9145 bool found = false;
9147 for (i=0; i<count; i++) {
9148 if (queue[i].job == (int)jobid) {
9149 found = true;
9150 break;
9154 if (found == false) {
9155 /* NT treats not found as bad param... yet another bad choice */
9156 return WERR_INVALID_PARAM;
9159 return fill_job_info1(mem_ctx,
9161 &queue[i],
9163 snum,
9164 pinfo2);
9167 /****************************************************************************
9168 ****************************************************************************/
9170 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9171 const print_queue_struct *queue,
9172 int count, int snum,
9173 struct spoolss_PrinterInfo2 *pinfo2,
9174 uint32_t jobid,
9175 struct spoolss_JobInfo2 *r)
9177 int i = 0;
9178 bool found = false;
9179 struct spoolss_DeviceMode *devmode;
9180 WERROR result;
9182 for (i=0; i<count; i++) {
9183 if (queue[i].job == (int)jobid) {
9184 found = true;
9185 break;
9189 if (found == false) {
9190 /* NT treats not found as bad param... yet another bad
9191 choice */
9192 return WERR_INVALID_PARAM;
9196 * if the print job does not have a DEVMODE associated with it,
9197 * just use the one for the printer. A NULL devicemode is not
9198 * a failure condition
9201 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9202 if (!devmode) {
9203 result = spoolss_create_default_devmode(mem_ctx,
9204 pinfo2->printername,
9205 &devmode);
9206 if (!W_ERROR_IS_OK(result)) {
9207 DEBUG(3, ("Can't proceed w/o a devmode!"));
9208 return result;
9212 return fill_job_info2(mem_ctx,
9214 &queue[i],
9216 snum,
9217 pinfo2,
9218 devmode);
9221 /****************************************************************
9222 _spoolss_GetJob
9223 ****************************************************************/
9225 WERROR _spoolss_GetJob(struct pipes_struct *p,
9226 struct spoolss_GetJob *r)
9228 WERROR result = WERR_OK;
9229 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9230 int snum;
9231 int count;
9232 print_queue_struct *queue = NULL;
9233 print_status_struct prt_status;
9235 /* that's an [in out] buffer */
9237 if (!r->in.buffer && (r->in.offered != 0)) {
9238 return WERR_INVALID_PARAM;
9241 DEBUG(5,("_spoolss_GetJob\n"));
9243 *r->out.needed = 0;
9245 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9246 return WERR_BADFID;
9249 result = winreg_get_printer_internal(p->mem_ctx,
9250 get_session_info_system(),
9251 p->msg_ctx,
9252 lp_const_servicename(snum),
9253 &pinfo2);
9254 if (!W_ERROR_IS_OK(result)) {
9255 return result;
9258 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9260 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9261 count, prt_status.status, prt_status.message));
9263 switch (r->in.level) {
9264 case 1:
9265 result = getjob_level_1(p->mem_ctx,
9266 queue, count, snum, pinfo2,
9267 r->in.job_id, &r->out.info->info1);
9268 break;
9269 case 2:
9270 result = getjob_level_2(p->mem_ctx,
9271 queue, count, snum, pinfo2,
9272 r->in.job_id, &r->out.info->info2);
9273 break;
9274 default:
9275 result = WERR_UNKNOWN_LEVEL;
9276 break;
9279 SAFE_FREE(queue);
9280 TALLOC_FREE(pinfo2);
9282 if (!W_ERROR_IS_OK(result)) {
9283 TALLOC_FREE(r->out.info);
9284 return result;
9287 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9288 r->in.level);
9289 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9291 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9294 /****************************************************************
9295 _spoolss_GetPrinterDataEx
9296 ****************************************************************/
9298 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9299 struct spoolss_GetPrinterDataEx *r)
9302 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9303 const char *printer;
9304 int snum = 0;
9305 WERROR result = WERR_OK;
9306 DATA_BLOB blob;
9307 enum winreg_Type val_type = REG_NONE;
9308 uint8_t *val_data = NULL;
9309 uint32_t val_size = 0;
9310 struct dcerpc_binding_handle *b;
9311 TALLOC_CTX *tmp_ctx;
9313 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9315 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9316 r->in.key_name, r->in.value_name));
9318 /* in case of problem, return some default values */
9320 *r->out.needed = 0;
9321 *r->out.type = REG_NONE;
9323 tmp_ctx = talloc_new(p->mem_ctx);
9324 if (!tmp_ctx) {
9325 return WERR_NOMEM;
9328 if (!Printer) {
9329 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9330 OUR_HANDLE(r->in.handle)));
9331 result = WERR_BADFID;
9332 goto done;
9335 /* check to see if the keyname is valid */
9336 if (!strlen(r->in.key_name)) {
9337 result = WERR_INVALID_PARAM;
9338 goto done;
9341 /* Is the handle to a printer or to the server? */
9343 if (Printer->printer_type == SPLHND_SERVER) {
9345 union spoolss_PrinterData data;
9347 result = getprinterdata_printer_server(tmp_ctx,
9348 r->in.value_name,
9349 r->out.type,
9350 &data);
9351 if (!W_ERROR_IS_OK(result)) {
9352 goto done;
9355 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9356 *r->out.type, &data);
9357 if (!W_ERROR_IS_OK(result)) {
9358 goto done;
9361 *r->out.needed = blob.length;
9363 if (r->in.offered >= *r->out.needed) {
9364 memcpy(r->out.data, blob.data, blob.length);
9367 result = WERR_OK;
9368 goto done;
9371 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9372 result = WERR_BADFID;
9373 goto done;
9375 printer = lp_const_servicename(snum);
9377 result = winreg_printer_binding_handle(tmp_ctx,
9378 get_session_info_system(),
9379 p->msg_ctx,
9380 &b);
9381 if (!W_ERROR_IS_OK(result)) {
9382 goto done;
9385 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9386 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9387 strequal(r->in.value_name, "ChangeId")) {
9388 *r->out.type = REG_DWORD;
9389 *r->out.needed = 4;
9390 if (r->in.offered >= *r->out.needed) {
9391 uint32_t changeid = 0;
9393 result = winreg_printer_get_changeid(tmp_ctx, b,
9394 printer,
9395 &changeid);
9396 if (!W_ERROR_IS_OK(result)) {
9397 goto done;
9400 SIVAL(r->out.data, 0, changeid);
9401 result = WERR_OK;
9403 goto done;
9406 result = winreg_get_printer_dataex(tmp_ctx, b,
9407 printer,
9408 r->in.key_name,
9409 r->in.value_name,
9410 &val_type,
9411 &val_data,
9412 &val_size);
9413 if (!W_ERROR_IS_OK(result)) {
9414 goto done;
9417 *r->out.needed = val_size;
9418 *r->out.type = val_type;
9420 if (r->in.offered >= *r->out.needed) {
9421 memcpy(r->out.data, val_data, val_size);
9424 done:
9425 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9427 if (W_ERROR_IS_OK(result)) {
9428 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9431 talloc_free(tmp_ctx);
9432 return result;
9435 /****************************************************************
9436 _spoolss_SetPrinterDataEx
9437 ****************************************************************/
9439 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9440 struct spoolss_SetPrinterDataEx *r)
9442 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9443 int snum = 0;
9444 WERROR result = WERR_OK;
9445 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9446 char *oid_string;
9447 struct dcerpc_binding_handle *b;
9448 TALLOC_CTX *tmp_ctx;
9450 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9452 /* From MSDN documentation of SetPrinterDataEx: pass request to
9453 SetPrinterData if key is "PrinterDriverData" */
9455 if (!Printer) {
9456 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9457 OUR_HANDLE(r->in.handle)));
9458 return WERR_BADFID;
9461 if (Printer->printer_type == SPLHND_SERVER) {
9462 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9463 "Not implemented for server handles yet\n"));
9464 return WERR_INVALID_PARAM;
9467 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9468 return WERR_BADFID;
9472 * Access check : NT returns "access denied" if you make a
9473 * SetPrinterData call without the necessary privildge.
9474 * we were originally returning OK if nothing changed
9475 * which made Win2k issue **a lot** of SetPrinterData
9476 * when connecting to a printer --jerry
9479 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9480 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9481 "change denied by handle access permissions\n"));
9482 return WERR_ACCESS_DENIED;
9485 tmp_ctx = talloc_new(p->mem_ctx);
9486 if (!tmp_ctx) {
9487 return WERR_NOMEM;
9490 result = winreg_printer_binding_handle(tmp_ctx,
9491 get_session_info_system(),
9492 p->msg_ctx,
9493 &b);
9494 if (!W_ERROR_IS_OK(result)) {
9495 goto done;
9498 result = winreg_get_printer(tmp_ctx, b,
9499 lp_servicename(snum),
9500 &pinfo2);
9501 if (!W_ERROR_IS_OK(result)) {
9502 goto done;
9505 /* check for OID in valuename */
9507 oid_string = strchr(r->in.value_name, ',');
9508 if (oid_string) {
9509 *oid_string = '\0';
9510 oid_string++;
9513 /* save the registry data */
9515 result = winreg_set_printer_dataex(tmp_ctx, b,
9516 pinfo2->sharename,
9517 r->in.key_name,
9518 r->in.value_name,
9519 r->in.type,
9520 r->in.data,
9521 r->in.offered);
9523 if (W_ERROR_IS_OK(result)) {
9524 /* save the OID if one was specified */
9525 if (oid_string) {
9526 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9527 r->in.key_name, SPOOL_OID_KEY);
9528 if (!str) {
9529 result = WERR_NOMEM;
9530 goto done;
9534 * I'm not checking the status here on purpose. Don't know
9535 * if this is right, but I'm returning the status from the
9536 * previous set_printer_dataex() call. I have no idea if
9537 * this is right. --jerry
9539 winreg_set_printer_dataex(tmp_ctx, b,
9540 pinfo2->sharename,
9541 str,
9542 r->in.value_name,
9543 REG_SZ,
9544 (uint8_t *) oid_string,
9545 strlen(oid_string) + 1);
9548 result = winreg_printer_update_changeid(tmp_ctx, b,
9549 lp_const_servicename(snum));
9553 done:
9554 talloc_free(tmp_ctx);
9555 return result;
9558 /****************************************************************
9559 _spoolss_DeletePrinterDataEx
9560 ****************************************************************/
9562 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9563 struct spoolss_DeletePrinterDataEx *r)
9565 const char *printer;
9566 int snum=0;
9567 WERROR status = WERR_OK;
9568 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9570 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9572 if (!Printer) {
9573 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9574 "Invalid handle (%s:%u:%u).\n",
9575 OUR_HANDLE(r->in.handle)));
9576 return WERR_BADFID;
9579 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9580 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9581 "printer properties change denied by handle\n"));
9582 return WERR_ACCESS_DENIED;
9585 if (!r->in.value_name || !r->in.key_name) {
9586 return WERR_NOMEM;
9589 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9590 return WERR_BADFID;
9592 printer = lp_const_servicename(snum);
9594 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9595 get_session_info_system(),
9596 p->msg_ctx,
9597 printer,
9598 r->in.key_name,
9599 r->in.value_name);
9600 if (W_ERROR_IS_OK(status)) {
9601 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9602 get_session_info_system(),
9603 p->msg_ctx,
9604 printer);
9607 return status;
9610 /****************************************************************
9611 _spoolss_EnumPrinterKey
9612 ****************************************************************/
9614 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9615 struct spoolss_EnumPrinterKey *r)
9617 uint32_t num_keys;
9618 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9619 int snum = 0;
9620 WERROR result = WERR_BADFILE;
9621 const char **array = NULL;
9622 DATA_BLOB blob;
9624 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9626 if (!Printer) {
9627 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9628 OUR_HANDLE(r->in.handle)));
9629 return WERR_BADFID;
9632 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9633 return WERR_BADFID;
9636 result = winreg_enum_printer_key_internal(p->mem_ctx,
9637 get_session_info_system(),
9638 p->msg_ctx,
9639 lp_const_servicename(snum),
9640 r->in.key_name,
9641 &num_keys,
9642 &array);
9643 if (!W_ERROR_IS_OK(result)) {
9644 goto done;
9647 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9648 result = WERR_NOMEM;
9649 goto done;
9652 *r->out._ndr_size = r->in.offered / 2;
9653 *r->out.needed = blob.length;
9655 if (r->in.offered < *r->out.needed) {
9656 result = WERR_MORE_DATA;
9657 } else {
9658 result = WERR_OK;
9659 r->out.key_buffer->string_array = array;
9662 done:
9663 if (!W_ERROR_IS_OK(result)) {
9664 TALLOC_FREE(array);
9665 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9666 *r->out.needed = 0;
9670 return result;
9673 /****************************************************************
9674 _spoolss_DeletePrinterKey
9675 ****************************************************************/
9677 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9678 struct spoolss_DeletePrinterKey *r)
9680 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9681 int snum=0;
9682 WERROR status;
9683 const char *printer;
9684 struct dcerpc_binding_handle *b;
9685 TALLOC_CTX *tmp_ctx;
9687 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9689 if (!Printer) {
9690 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9691 OUR_HANDLE(r->in.handle)));
9692 return WERR_BADFID;
9695 /* if keyname == NULL, return error */
9696 if ( !r->in.key_name )
9697 return WERR_INVALID_PARAM;
9699 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9700 return WERR_BADFID;
9703 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9704 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9705 "printer properties change denied by handle\n"));
9706 return WERR_ACCESS_DENIED;
9709 printer = lp_const_servicename(snum);
9711 tmp_ctx = talloc_new(p->mem_ctx);
9712 if (!tmp_ctx) {
9713 return WERR_NOMEM;
9716 status = winreg_printer_binding_handle(tmp_ctx,
9717 get_session_info_system(),
9718 p->msg_ctx,
9719 &b);
9720 if (!W_ERROR_IS_OK(status)) {
9721 goto done;
9724 /* delete the key and all subkeys */
9725 status = winreg_delete_printer_key(tmp_ctx, b,
9726 printer,
9727 r->in.key_name);
9728 if (W_ERROR_IS_OK(status)) {
9729 status = winreg_printer_update_changeid(tmp_ctx, b,
9730 printer);
9733 done:
9734 talloc_free(tmp_ctx);
9735 return status;
9738 /****************************************************************
9739 _spoolss_EnumPrinterDataEx
9740 ****************************************************************/
9742 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9743 struct spoolss_EnumPrinterDataEx *r)
9745 uint32_t count = 0;
9746 struct spoolss_PrinterEnumValues *info = NULL;
9747 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9748 int snum;
9749 WERROR result;
9751 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9753 *r->out.count = 0;
9754 *r->out.needed = 0;
9755 *r->out.info = NULL;
9757 if (!Printer) {
9758 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9759 OUR_HANDLE(r->in.handle)));
9760 return WERR_BADFID;
9764 * first check for a keyname of NULL or "". Win2k seems to send
9765 * this a lot and we should send back WERR_INVALID_PARAM
9766 * no need to spend time looking up the printer in this case.
9767 * --jerry
9770 if (!strlen(r->in.key_name)) {
9771 result = WERR_INVALID_PARAM;
9772 goto done;
9775 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9776 return WERR_BADFID;
9779 /* now look for a match on the key name */
9780 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9781 get_session_info_system(),
9782 p->msg_ctx,
9783 lp_const_servicename(snum),
9784 r->in.key_name,
9785 &count,
9786 &info);
9787 if (!W_ERROR_IS_OK(result)) {
9788 goto done;
9791 #if 0 /* FIXME - gd */
9792 /* housekeeping information in the reply */
9794 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9795 * the hand marshalled container size is a multiple
9796 * of 4 bytes for RPC alignment.
9799 if (needed % 4) {
9800 needed += 4-(needed % 4);
9802 #endif
9803 *r->out.count = count;
9804 *r->out.info = info;
9806 done:
9807 if (!W_ERROR_IS_OK(result)) {
9808 return result;
9811 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9812 spoolss_EnumPrinterDataEx,
9813 *r->out.info,
9814 *r->out.count);
9815 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9816 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9818 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9821 /****************************************************************************
9822 ****************************************************************************/
9824 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9825 const char *servername,
9826 const char *environment,
9827 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9829 WERROR werr;
9830 char *path = NULL;
9832 werr = compose_spoolss_server_path(mem_ctx,
9833 servername,
9834 environment,
9835 SPOOLSS_PRTPROCS_PATH,
9836 &path);
9837 if (!W_ERROR_IS_OK(werr)) {
9838 return werr;
9841 DEBUG(4,("print processor directory: [%s]\n", path));
9843 r->directory_name = path;
9845 return WERR_OK;
9848 /****************************************************************
9849 _spoolss_GetPrintProcessorDirectory
9850 ****************************************************************/
9852 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9853 struct spoolss_GetPrintProcessorDirectory *r)
9855 WERROR result;
9856 char *prnproc_share = NULL;
9857 bool prnproc_share_exists = false;
9858 int snum;
9860 /* that's an [in out] buffer */
9862 if (!r->in.buffer && (r->in.offered != 0)) {
9863 return WERR_INVALID_PARAM;
9866 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9867 r->in.level));
9869 *r->out.needed = 0;
9871 /* r->in.level is ignored */
9873 /* We always should reply with a local print processor directory so that
9874 * users are not forced to have a [prnproc$] share on the Samba spoolss
9875 * server, if users decide to do so, lets announce it though - Guenther */
9877 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9878 if (!prnproc_share) {
9879 return WERR_NOMEM;
9881 if (snum != -1) {
9882 prnproc_share_exists = true;
9885 result = getprintprocessordirectory_level_1(p->mem_ctx,
9886 prnproc_share_exists ? r->in.server : NULL,
9887 r->in.environment,
9888 &r->out.info->info1);
9889 if (!W_ERROR_IS_OK(result)) {
9890 TALLOC_FREE(r->out.info);
9891 return result;
9894 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9895 r->out.info, r->in.level);
9896 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9898 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9901 /*******************************************************************
9902 ********************************************************************/
9904 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9905 const char *dllname)
9907 enum ndr_err_code ndr_err;
9908 struct spoolss_MonitorUi ui;
9910 ui.dll_name = dllname;
9912 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9913 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9914 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9915 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9917 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9920 /*******************************************************************
9921 Streams the monitor UI DLL name in UNICODE
9922 *******************************************************************/
9924 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9925 struct security_token *token, DATA_BLOB *in,
9926 DATA_BLOB *out, uint32_t *needed)
9928 const char *dllname = "tcpmonui.dll";
9930 *needed = (strlen(dllname)+1) * 2;
9932 if (out->length < *needed) {
9933 return WERR_INSUFFICIENT_BUFFER;
9936 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9937 return WERR_NOMEM;
9940 return WERR_OK;
9943 /*******************************************************************
9944 ********************************************************************/
9946 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9947 struct spoolss_PortData1 *port1,
9948 const DATA_BLOB *buf)
9950 enum ndr_err_code ndr_err;
9951 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9952 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9953 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9954 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9956 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9959 /*******************************************************************
9960 ********************************************************************/
9962 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9963 struct spoolss_PortData2 *port2,
9964 const DATA_BLOB *buf)
9966 enum ndr_err_code ndr_err;
9967 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9968 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9969 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9970 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9972 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9975 /*******************************************************************
9976 Create a new TCP/IP port
9977 *******************************************************************/
9979 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9980 struct security_token *token, DATA_BLOB *in,
9981 DATA_BLOB *out, uint32_t *needed)
9983 struct spoolss_PortData1 port1;
9984 struct spoolss_PortData2 port2;
9985 char *device_uri = NULL;
9986 uint32_t version;
9988 const char *portname;
9989 const char *hostaddress;
9990 const char *queue;
9991 uint32_t port_number;
9992 uint32_t protocol;
9994 /* peek for spoolss_PortData version */
9996 if (!in || (in->length < (128 + 4))) {
9997 return WERR_GENERAL_FAILURE;
10000 version = IVAL(in->data, 128);
10002 switch (version) {
10003 case 1:
10004 ZERO_STRUCT(port1);
10006 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10007 return WERR_NOMEM;
10010 portname = port1.portname;
10011 hostaddress = port1.hostaddress;
10012 queue = port1.queue;
10013 protocol = port1.protocol;
10014 port_number = port1.port_number;
10016 break;
10017 case 2:
10018 ZERO_STRUCT(port2);
10020 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10021 return WERR_NOMEM;
10024 portname = port2.portname;
10025 hostaddress = port2.hostaddress;
10026 queue = port2.queue;
10027 protocol = port2.protocol;
10028 port_number = port2.port_number;
10030 break;
10031 default:
10032 DEBUG(1,("xcvtcp_addport: "
10033 "unknown version of port_data: %d\n", version));
10034 return WERR_UNKNOWN_PORT;
10037 /* create the device URI and call the add_port_hook() */
10039 switch (protocol) {
10040 case PROTOCOL_RAWTCP_TYPE:
10041 device_uri = talloc_asprintf(mem_ctx,
10042 "socket://%s:%d/", hostaddress,
10043 port_number);
10044 break;
10046 case PROTOCOL_LPR_TYPE:
10047 device_uri = talloc_asprintf(mem_ctx,
10048 "lpr://%s/%s", hostaddress, queue );
10049 break;
10051 default:
10052 return WERR_UNKNOWN_PORT;
10055 if (!device_uri) {
10056 return WERR_NOMEM;
10059 return add_port_hook(mem_ctx, token, portname, device_uri);
10062 /*******************************************************************
10063 *******************************************************************/
10065 struct xcv_api_table xcvtcp_cmds[] = {
10066 { "MonitorUI", xcvtcp_monitorui },
10067 { "AddPort", xcvtcp_addport},
10068 { NULL, NULL }
10071 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10072 struct security_token *token, const char *command,
10073 DATA_BLOB *inbuf,
10074 DATA_BLOB *outbuf,
10075 uint32_t *needed )
10077 int i;
10079 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10081 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10082 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10083 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10086 return WERR_BADFUNC;
10089 /*******************************************************************
10090 *******************************************************************/
10091 #if 0 /* don't support management using the "Local Port" monitor */
10093 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10094 struct security_token *token, DATA_BLOB *in,
10095 DATA_BLOB *out, uint32_t *needed)
10097 const char *dllname = "localui.dll";
10099 *needed = (strlen(dllname)+1) * 2;
10101 if (out->length < *needed) {
10102 return WERR_INSUFFICIENT_BUFFER;
10105 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10106 return WERR_NOMEM;
10109 return WERR_OK;
10112 /*******************************************************************
10113 *******************************************************************/
10115 struct xcv_api_table xcvlocal_cmds[] = {
10116 { "MonitorUI", xcvlocal_monitorui },
10117 { NULL, NULL }
10119 #else
10120 struct xcv_api_table xcvlocal_cmds[] = {
10121 { NULL, NULL }
10123 #endif
10127 /*******************************************************************
10128 *******************************************************************/
10130 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10131 struct security_token *token, const char *command,
10132 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10133 uint32_t *needed)
10135 int i;
10137 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10139 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10140 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10141 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10143 return WERR_BADFUNC;
10146 /****************************************************************
10147 _spoolss_XcvData
10148 ****************************************************************/
10150 WERROR _spoolss_XcvData(struct pipes_struct *p,
10151 struct spoolss_XcvData *r)
10153 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10154 DATA_BLOB out_data = data_blob_null;
10155 WERROR werror;
10157 if (!Printer) {
10158 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10159 OUR_HANDLE(r->in.handle)));
10160 return WERR_BADFID;
10163 /* Has to be a handle to the TCP/IP port monitor */
10165 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10166 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10167 return WERR_BADFID;
10170 /* requires administrative access to the server */
10172 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10173 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10174 return WERR_ACCESS_DENIED;
10177 /* Allocate the outgoing buffer */
10179 if (r->in.out_data_size) {
10180 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10181 if (out_data.data == NULL) {
10182 return WERR_NOMEM;
10186 switch ( Printer->printer_type ) {
10187 case SPLHND_PORTMON_TCP:
10188 werror = process_xcvtcp_command(p->mem_ctx,
10189 p->session_info->security_token,
10190 r->in.function_name,
10191 &r->in.in_data, &out_data,
10192 r->out.needed);
10193 break;
10194 case SPLHND_PORTMON_LOCAL:
10195 werror = process_xcvlocal_command(p->mem_ctx,
10196 p->session_info->security_token,
10197 r->in.function_name,
10198 &r->in.in_data, &out_data,
10199 r->out.needed);
10200 break;
10201 default:
10202 werror = WERR_INVALID_PRINT_MONITOR;
10205 if (!W_ERROR_IS_OK(werror)) {
10206 return werror;
10209 *r->out.status_code = 0;
10211 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10212 memcpy(r->out.out_data, out_data.data,
10213 MIN(r->in.out_data_size, out_data.length));
10216 return WERR_OK;
10219 /****************************************************************
10220 _spoolss_AddPrintProcessor
10221 ****************************************************************/
10223 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10224 struct spoolss_AddPrintProcessor *r)
10226 /* for now, just indicate success and ignore the add. We'll
10227 automatically set the winprint processor for printer
10228 entries later. Used to debug the LexMark Optra S 1855 PCL
10229 driver --jerry */
10231 return WERR_OK;
10234 /****************************************************************
10235 _spoolss_AddPort
10236 ****************************************************************/
10238 WERROR _spoolss_AddPort(struct pipes_struct *p,
10239 struct spoolss_AddPort *r)
10241 /* do what w2k3 does */
10243 return WERR_NOT_SUPPORTED;
10246 /****************************************************************
10247 _spoolss_GetPrinterDriver
10248 ****************************************************************/
10250 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10251 struct spoolss_GetPrinterDriver *r)
10253 p->rng_fault_state = true;
10254 return WERR_NOT_SUPPORTED;
10257 /****************************************************************
10258 _spoolss_ReadPrinter
10259 ****************************************************************/
10261 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10262 struct spoolss_ReadPrinter *r)
10264 p->rng_fault_state = true;
10265 return WERR_NOT_SUPPORTED;
10268 /****************************************************************
10269 _spoolss_WaitForPrinterChange
10270 ****************************************************************/
10272 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10273 struct spoolss_WaitForPrinterChange *r)
10275 p->rng_fault_state = true;
10276 return WERR_NOT_SUPPORTED;
10279 /****************************************************************
10280 _spoolss_ConfigurePort
10281 ****************************************************************/
10283 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10284 struct spoolss_ConfigurePort *r)
10286 p->rng_fault_state = true;
10287 return WERR_NOT_SUPPORTED;
10290 /****************************************************************
10291 _spoolss_DeletePort
10292 ****************************************************************/
10294 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10295 struct spoolss_DeletePort *r)
10297 p->rng_fault_state = true;
10298 return WERR_NOT_SUPPORTED;
10301 /****************************************************************
10302 _spoolss_CreatePrinterIC
10303 ****************************************************************/
10305 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10306 struct spoolss_CreatePrinterIC *r)
10308 p->rng_fault_state = true;
10309 return WERR_NOT_SUPPORTED;
10312 /****************************************************************
10313 _spoolss_PlayGDIScriptOnPrinterIC
10314 ****************************************************************/
10316 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10317 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10319 p->rng_fault_state = true;
10320 return WERR_NOT_SUPPORTED;
10323 /****************************************************************
10324 _spoolss_DeletePrinterIC
10325 ****************************************************************/
10327 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10328 struct spoolss_DeletePrinterIC *r)
10330 p->rng_fault_state = true;
10331 return WERR_NOT_SUPPORTED;
10334 /****************************************************************
10335 _spoolss_AddPrinterConnection
10336 ****************************************************************/
10338 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10339 struct spoolss_AddPrinterConnection *r)
10341 p->rng_fault_state = true;
10342 return WERR_NOT_SUPPORTED;
10345 /****************************************************************
10346 _spoolss_DeletePrinterConnection
10347 ****************************************************************/
10349 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10350 struct spoolss_DeletePrinterConnection *r)
10352 p->rng_fault_state = true;
10353 return WERR_NOT_SUPPORTED;
10356 /****************************************************************
10357 _spoolss_PrinterMessageBox
10358 ****************************************************************/
10360 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10361 struct spoolss_PrinterMessageBox *r)
10363 p->rng_fault_state = true;
10364 return WERR_NOT_SUPPORTED;
10367 /****************************************************************
10368 _spoolss_AddMonitor
10369 ****************************************************************/
10371 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10372 struct spoolss_AddMonitor *r)
10374 p->rng_fault_state = true;
10375 return WERR_NOT_SUPPORTED;
10378 /****************************************************************
10379 _spoolss_DeleteMonitor
10380 ****************************************************************/
10382 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10383 struct spoolss_DeleteMonitor *r)
10385 p->rng_fault_state = true;
10386 return WERR_NOT_SUPPORTED;
10389 /****************************************************************
10390 _spoolss_DeletePrintProcessor
10391 ****************************************************************/
10393 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10394 struct spoolss_DeletePrintProcessor *r)
10396 p->rng_fault_state = true;
10397 return WERR_NOT_SUPPORTED;
10400 /****************************************************************
10401 _spoolss_AddPrintProvidor
10402 ****************************************************************/
10404 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10405 struct spoolss_AddPrintProvidor *r)
10407 p->rng_fault_state = true;
10408 return WERR_NOT_SUPPORTED;
10411 /****************************************************************
10412 _spoolss_DeletePrintProvidor
10413 ****************************************************************/
10415 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10416 struct spoolss_DeletePrintProvidor *r)
10418 p->rng_fault_state = true;
10419 return WERR_NOT_SUPPORTED;
10422 /****************************************************************
10423 _spoolss_FindFirstPrinterChangeNotification
10424 ****************************************************************/
10426 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10427 struct spoolss_FindFirstPrinterChangeNotification *r)
10429 p->rng_fault_state = true;
10430 return WERR_NOT_SUPPORTED;
10433 /****************************************************************
10434 _spoolss_FindNextPrinterChangeNotification
10435 ****************************************************************/
10437 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10438 struct spoolss_FindNextPrinterChangeNotification *r)
10440 p->rng_fault_state = true;
10441 return WERR_NOT_SUPPORTED;
10444 /****************************************************************
10445 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10446 ****************************************************************/
10448 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10449 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10451 p->rng_fault_state = true;
10452 return WERR_NOT_SUPPORTED;
10455 /****************************************************************
10456 _spoolss_ReplyOpenPrinter
10457 ****************************************************************/
10459 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10460 struct spoolss_ReplyOpenPrinter *r)
10462 p->rng_fault_state = true;
10463 return WERR_NOT_SUPPORTED;
10466 /****************************************************************
10467 _spoolss_RouterReplyPrinter
10468 ****************************************************************/
10470 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10471 struct spoolss_RouterReplyPrinter *r)
10473 p->rng_fault_state = true;
10474 return WERR_NOT_SUPPORTED;
10477 /****************************************************************
10478 _spoolss_ReplyClosePrinter
10479 ****************************************************************/
10481 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10482 struct spoolss_ReplyClosePrinter *r)
10484 p->rng_fault_state = true;
10485 return WERR_NOT_SUPPORTED;
10488 /****************************************************************
10489 _spoolss_AddPortEx
10490 ****************************************************************/
10492 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10493 struct spoolss_AddPortEx *r)
10495 p->rng_fault_state = true;
10496 return WERR_NOT_SUPPORTED;
10499 /****************************************************************
10500 _spoolss_RouterFindFirstPrinterChangeNotification
10501 ****************************************************************/
10503 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10504 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10506 p->rng_fault_state = true;
10507 return WERR_NOT_SUPPORTED;
10510 /****************************************************************
10511 _spoolss_SpoolerInit
10512 ****************************************************************/
10514 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10515 struct spoolss_SpoolerInit *r)
10517 p->rng_fault_state = true;
10518 return WERR_NOT_SUPPORTED;
10521 /****************************************************************
10522 _spoolss_ResetPrinterEx
10523 ****************************************************************/
10525 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10526 struct spoolss_ResetPrinterEx *r)
10528 p->rng_fault_state = true;
10529 return WERR_NOT_SUPPORTED;
10532 /****************************************************************
10533 _spoolss_RouterReplyPrinterEx
10534 ****************************************************************/
10536 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10537 struct spoolss_RouterReplyPrinterEx *r)
10539 p->rng_fault_state = true;
10540 return WERR_NOT_SUPPORTED;
10543 /****************************************************************
10544 _spoolss_44
10545 ****************************************************************/
10547 WERROR _spoolss_44(struct pipes_struct *p,
10548 struct spoolss_44 *r)
10550 p->rng_fault_state = true;
10551 return WERR_NOT_SUPPORTED;
10554 /****************************************************************
10555 _spoolss_SetPort
10556 ****************************************************************/
10558 WERROR _spoolss_SetPort(struct pipes_struct *p,
10559 struct spoolss_SetPort *r)
10561 p->rng_fault_state = true;
10562 return WERR_NOT_SUPPORTED;
10565 /****************************************************************
10566 _spoolss_4a
10567 ****************************************************************/
10569 WERROR _spoolss_4a(struct pipes_struct *p,
10570 struct spoolss_4a *r)
10572 p->rng_fault_state = true;
10573 return WERR_NOT_SUPPORTED;
10576 /****************************************************************
10577 _spoolss_4b
10578 ****************************************************************/
10580 WERROR _spoolss_4b(struct pipes_struct *p,
10581 struct spoolss_4b *r)
10583 p->rng_fault_state = true;
10584 return WERR_NOT_SUPPORTED;
10587 /****************************************************************
10588 _spoolss_4c
10589 ****************************************************************/
10591 WERROR _spoolss_4c(struct pipes_struct *p,
10592 struct spoolss_4c *r)
10594 p->rng_fault_state = true;
10595 return WERR_NOT_SUPPORTED;
10598 /****************************************************************
10599 _spoolss_53
10600 ****************************************************************/
10602 WERROR _spoolss_53(struct pipes_struct *p,
10603 struct spoolss_53 *r)
10605 p->rng_fault_state = true;
10606 return WERR_NOT_SUPPORTED;
10609 /****************************************************************
10610 _spoolss_AddPerMachineConnection
10611 ****************************************************************/
10613 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10614 struct spoolss_AddPerMachineConnection *r)
10616 p->rng_fault_state = true;
10617 return WERR_NOT_SUPPORTED;
10620 /****************************************************************
10621 _spoolss_DeletePerMachineConnection
10622 ****************************************************************/
10624 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10625 struct spoolss_DeletePerMachineConnection *r)
10627 p->rng_fault_state = true;
10628 return WERR_NOT_SUPPORTED;
10631 /****************************************************************
10632 _spoolss_EnumPerMachineConnections
10633 ****************************************************************/
10635 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10636 struct spoolss_EnumPerMachineConnections *r)
10638 p->rng_fault_state = true;
10639 return WERR_NOT_SUPPORTED;
10642 /****************************************************************
10643 _spoolss_5a
10644 ****************************************************************/
10646 WERROR _spoolss_5a(struct pipes_struct *p,
10647 struct spoolss_5a *r)
10649 p->rng_fault_state = true;
10650 return WERR_NOT_SUPPORTED;
10653 /****************************************************************
10654 _spoolss_5b
10655 ****************************************************************/
10657 WERROR _spoolss_5b(struct pipes_struct *p,
10658 struct spoolss_5b *r)
10660 p->rng_fault_state = true;
10661 return WERR_NOT_SUPPORTED;
10664 /****************************************************************
10665 _spoolss_5c
10666 ****************************************************************/
10668 WERROR _spoolss_5c(struct pipes_struct *p,
10669 struct spoolss_5c *r)
10671 p->rng_fault_state = true;
10672 return WERR_NOT_SUPPORTED;
10675 /****************************************************************
10676 _spoolss_5d
10677 ****************************************************************/
10679 WERROR _spoolss_5d(struct pipes_struct *p,
10680 struct spoolss_5d *r)
10682 p->rng_fault_state = true;
10683 return WERR_NOT_SUPPORTED;
10686 /****************************************************************
10687 _spoolss_5e
10688 ****************************************************************/
10690 WERROR _spoolss_5e(struct pipes_struct *p,
10691 struct spoolss_5e *r)
10693 p->rng_fault_state = true;
10694 return WERR_NOT_SUPPORTED;
10697 /****************************************************************
10698 _spoolss_5f
10699 ****************************************************************/
10701 WERROR _spoolss_5f(struct pipes_struct *p,
10702 struct spoolss_5f *r)
10704 p->rng_fault_state = true;
10705 return WERR_NOT_SUPPORTED;
10708 /****************************************************************
10709 _spoolss_60
10710 ****************************************************************/
10712 WERROR _spoolss_60(struct pipes_struct *p,
10713 struct spoolss_60 *r)
10715 p->rng_fault_state = true;
10716 return WERR_NOT_SUPPORTED;
10719 /****************************************************************
10720 _spoolss_61
10721 ****************************************************************/
10723 WERROR _spoolss_61(struct pipes_struct *p,
10724 struct spoolss_61 *r)
10726 p->rng_fault_state = true;
10727 return WERR_NOT_SUPPORTED;
10730 /****************************************************************
10731 _spoolss_62
10732 ****************************************************************/
10734 WERROR _spoolss_62(struct pipes_struct *p,
10735 struct spoolss_62 *r)
10737 p->rng_fault_state = true;
10738 return WERR_NOT_SUPPORTED;
10741 /****************************************************************
10742 _spoolss_63
10743 ****************************************************************/
10745 WERROR _spoolss_63(struct pipes_struct *p,
10746 struct spoolss_63 *r)
10748 p->rng_fault_state = true;
10749 return WERR_NOT_SUPPORTED;
10752 /****************************************************************
10753 _spoolss_64
10754 ****************************************************************/
10756 WERROR _spoolss_64(struct pipes_struct *p,
10757 struct spoolss_64 *r)
10759 p->rng_fault_state = true;
10760 return WERR_NOT_SUPPORTED;
10763 /****************************************************************
10764 _spoolss_65
10765 ****************************************************************/
10767 WERROR _spoolss_65(struct pipes_struct *p,
10768 struct spoolss_65 *r)
10770 p->rng_fault_state = true;
10771 return WERR_NOT_SUPPORTED;
10774 /****************************************************************
10775 _spoolss_GetCorePrinterDrivers
10776 ****************************************************************/
10778 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10779 struct spoolss_GetCorePrinterDrivers *r)
10781 p->rng_fault_state = true;
10782 return WERR_NOT_SUPPORTED;
10785 /****************************************************************
10786 _spoolss_67
10787 ****************************************************************/
10789 WERROR _spoolss_67(struct pipes_struct *p,
10790 struct spoolss_67 *r)
10792 p->rng_fault_state = true;
10793 return WERR_NOT_SUPPORTED;
10796 /****************************************************************
10797 _spoolss_GetPrinterDriverPackagePath
10798 ****************************************************************/
10800 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10801 struct spoolss_GetPrinterDriverPackagePath *r)
10803 p->rng_fault_state = true;
10804 return WERR_NOT_SUPPORTED;
10807 /****************************************************************
10808 _spoolss_69
10809 ****************************************************************/
10811 WERROR _spoolss_69(struct pipes_struct *p,
10812 struct spoolss_69 *r)
10814 p->rng_fault_state = true;
10815 return WERR_NOT_SUPPORTED;
10818 /****************************************************************
10819 _spoolss_6a
10820 ****************************************************************/
10822 WERROR _spoolss_6a(struct pipes_struct *p,
10823 struct spoolss_6a *r)
10825 p->rng_fault_state = true;
10826 return WERR_NOT_SUPPORTED;
10829 /****************************************************************
10830 _spoolss_6b
10831 ****************************************************************/
10833 WERROR _spoolss_6b(struct pipes_struct *p,
10834 struct spoolss_6b *r)
10836 p->rng_fault_state = true;
10837 return WERR_NOT_SUPPORTED;
10840 /****************************************************************
10841 _spoolss_6c
10842 ****************************************************************/
10844 WERROR _spoolss_6c(struct pipes_struct *p,
10845 struct spoolss_6c *r)
10847 p->rng_fault_state = true;
10848 return WERR_NOT_SUPPORTED;
10851 /****************************************************************
10852 _spoolss_6d
10853 ****************************************************************/
10855 WERROR _spoolss_6d(struct pipes_struct *p,
10856 struct spoolss_6d *r)
10858 p->rng_fault_state = true;
10859 return WERR_NOT_SUPPORTED;