BUG 9474: Downgrade v4 printer driver requests to v3.
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blobc511fd031fd753d820a946e5fabbb03fe2cbf8bb
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 "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "rpc_client/cli_winreg_spoolss.h"
58 /* macros stolen from s4 spoolss server */
59 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
60 ((info)?ndr_size_##fn(info, level, 0):0)
62 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
63 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
65 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
66 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
68 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
70 #undef DBGC_CLASS
71 #define DBGC_CLASS DBGC_RPC_SRV
73 #ifndef MAX_OPEN_PRINTER_EXS
74 #define MAX_OPEN_PRINTER_EXS 50
75 #endif
77 struct notify_back_channel;
79 /* structure to store the printer handles */
80 /* and a reference to what it's pointing to */
81 /* and the notify info asked about */
82 /* that's the central struct */
83 struct printer_handle {
84 struct printer_handle *prev, *next;
85 bool document_started;
86 bool page_started;
87 uint32 jobid; /* jobid in printing backend */
88 int printer_type;
89 const char *servername;
90 fstring sharename;
91 uint32 type;
92 uint32 access_granted;
93 struct {
94 uint32 flags;
95 uint32 options;
96 fstring localmachine;
97 uint32 printerlocal;
98 struct spoolss_NotifyOption *option;
99 struct policy_handle cli_hnd;
100 struct notify_back_channel *cli_chan;
101 uint32 change;
102 /* are we in a FindNextPrinterChangeNotify() call? */
103 bool fnpcn;
104 struct messaging_context *msg_ctx;
105 } notify;
106 struct {
107 fstring machine;
108 fstring user;
109 } client;
111 /* devmode sent in the OpenPrinter() call */
112 struct spoolss_DeviceMode *devmode;
114 /* TODO cache the printer info2 structure */
115 struct spoolss_PrinterInfo2 *info2;
119 static struct printer_handle *printers_list;
121 struct printer_session_counter {
122 struct printer_session_counter *next;
123 struct printer_session_counter *prev;
125 int snum;
126 uint32_t counter;
129 static struct printer_session_counter *counter_list;
131 struct notify_back_channel {
132 struct notify_back_channel *prev, *next;
134 /* associated client */
135 struct sockaddr_storage client_address;
137 /* print notify back-channel pipe handle*/
138 struct rpc_pipe_client *cli_pipe;
139 struct dcerpc_binding_handle *binding_handle;
140 uint32_t active_connections;
143 static struct notify_back_channel *back_channels;
145 /* Map generic permissions to printer object specific permissions */
147 const struct standard_mapping printer_std_mapping = {
148 PRINTER_READ,
149 PRINTER_WRITE,
150 PRINTER_EXECUTE,
151 PRINTER_ALL_ACCESS
154 /* Map generic permissions to print server object specific permissions */
156 const struct standard_mapping printserver_std_mapping = {
157 SERVER_READ,
158 SERVER_WRITE,
159 SERVER_EXECUTE,
160 SERVER_ALL_ACCESS
163 /* API table for Xcv Monitor functions */
165 struct xcv_api_table {
166 const char *name;
167 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 static void prune_printername_cache(void);
172 /********************************************************************
173 * Canonicalize servername.
174 ********************************************************************/
176 static const char *canon_servername(const char *servername)
178 const char *pservername = servername;
179 while (*pservername == '\\') {
180 pservername++;
182 return pservername;
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
188 switch (v) {
189 case LPQ_QUEUED:
190 return 0;
191 case LPQ_PAUSED:
192 return JOB_STATUS_PAUSED;
193 case LPQ_SPOOLING:
194 return JOB_STATUS_SPOOLING;
195 case LPQ_PRINTING:
196 return JOB_STATUS_PRINTING;
197 case LPQ_ERROR:
198 return JOB_STATUS_ERROR;
199 case LPQ_DELETING:
200 return JOB_STATUS_DELETING;
201 case LPQ_OFFLINE:
202 return JOB_STATUS_OFFLINE;
203 case LPQ_PAPEROUT:
204 return JOB_STATUS_PAPEROUT;
205 case LPQ_PRINTED:
206 return JOB_STATUS_PRINTED;
207 case LPQ_DELETED:
208 return JOB_STATUS_DELETED;
209 case LPQ_BLOCKED:
210 return JOB_STATUS_BLOCKED_DEVQ;
211 case LPQ_USER_INTERVENTION:
212 return JOB_STATUS_USER_INTERVENTION;
214 return 0;
217 static int nt_printq_status(int v)
219 switch (v) {
220 case LPQ_PAUSED:
221 return PRINTER_STATUS_PAUSED;
222 case LPQ_QUEUED:
223 case LPQ_SPOOLING:
224 case LPQ_PRINTING:
225 return 0;
227 return 0;
230 /***************************************************************************
231 Disconnect from the client
232 ****************************************************************************/
234 static void srv_spoolss_replycloseprinter(int snum,
235 struct printer_handle *prn_hnd)
237 WERROR result;
238 NTSTATUS status;
241 * Tell the specific printing tdb we no longer want messages for this printer
242 * by deregistering our PID.
245 if (!print_notify_deregister_pid(snum)) {
246 DEBUG(0, ("Failed to register our pid for printer %s\n",
247 lp_const_servicename(snum)));
250 /* weird if the test succeeds !!! */
251 if (prn_hnd->notify.cli_chan == NULL ||
252 prn_hnd->notify.cli_chan->active_connections == 0) {
253 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
254 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
255 TALLOC_FREE(prn_hnd->notify.cli_chan);
256 return;
259 status = dcerpc_spoolss_ReplyClosePrinter(
260 prn_hnd->notify.cli_chan->binding_handle,
261 talloc_tos(),
262 &prn_hnd->notify.cli_hnd,
263 &result);
264 if (!NT_STATUS_IS_OK(status)) {
265 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
266 nt_errstr(status)));
267 result = ntstatus_to_werror(status);
268 } else if (!W_ERROR_IS_OK(result)) {
269 DEBUG(0, ("reply_close_printer failed [%s].\n",
270 win_errstr(result)));
273 /* if it's the last connection, deconnect the IPC$ share */
274 if (prn_hnd->notify.cli_chan->active_connections == 1) {
276 prn_hnd->notify.cli_chan->binding_handle = NULL;
277 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
278 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
279 TALLOC_FREE(prn_hnd->notify.cli_chan);
281 if (prn_hnd->notify.msg_ctx != NULL) {
282 messaging_deregister(prn_hnd->notify.msg_ctx,
283 MSG_PRINTER_NOTIFY2, NULL);
286 * Tell the serverid.tdb we're no longer
287 * interested in printer notify messages.
290 serverid_register_msg_flags(
291 messaging_server_id(prn_hnd->notify.msg_ctx),
292 false, FLAG_MSG_PRINT_NOTIFY);
296 if (prn_hnd->notify.cli_chan) {
297 prn_hnd->notify.cli_chan->active_connections--;
298 prn_hnd->notify.cli_chan = NULL;
302 /****************************************************************************
303 Functions to free a printer entry datastruct.
304 ****************************************************************************/
306 static int printer_entry_destructor(struct printer_handle *Printer)
308 if (Printer->notify.cli_chan != NULL &&
309 Printer->notify.cli_chan->active_connections > 0) {
310 int snum = -1;
312 switch(Printer->printer_type) {
313 case SPLHND_SERVER:
314 srv_spoolss_replycloseprinter(snum, Printer);
315 break;
317 case SPLHND_PRINTER:
318 snum = print_queue_snum(Printer->sharename);
319 if (snum != -1) {
320 srv_spoolss_replycloseprinter(snum, Printer);
322 break;
323 default:
324 break;
328 Printer->notify.flags=0;
329 Printer->notify.options=0;
330 Printer->notify.localmachine[0]='\0';
331 Printer->notify.printerlocal=0;
332 TALLOC_FREE(Printer->notify.option);
333 TALLOC_FREE(Printer->devmode);
335 /* Remove from the internal list. */
336 DLIST_REMOVE(printers_list, Printer);
337 return 0;
340 /****************************************************************************
341 find printer index by handle
342 ****************************************************************************/
344 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
345 struct policy_handle *hnd)
347 struct printer_handle *find_printer = NULL;
349 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
350 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
351 return NULL;
354 return find_printer;
357 /****************************************************************************
358 Close printer index by handle.
359 ****************************************************************************/
361 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
363 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
365 if (!Printer) {
366 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
367 OUR_HANDLE(hnd)));
368 return false;
371 close_policy_hnd(p, hnd);
373 return true;
376 /****************************************************************************
377 Delete a printer given a handle.
378 ****************************************************************************/
380 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
381 const char *sharename,
382 struct messaging_context *msg_ctx)
384 char *cmd = lp_deleteprinter_cmd();
385 char *command = NULL;
386 int ret;
387 bool is_print_op = false;
389 /* can't fail if we don't try */
391 if ( !*cmd )
392 return WERR_OK;
394 command = talloc_asprintf(ctx,
395 "%s \"%s\"",
396 cmd, sharename);
397 if (!command) {
398 return WERR_NOMEM;
400 if ( token )
401 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
403 DEBUG(10,("Running [%s]\n", command));
405 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
407 if ( is_print_op )
408 become_root();
410 if ( (ret = smbrun(command, NULL)) == 0 ) {
411 /* Tell everyone we updated smb.conf. */
412 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
415 if ( is_print_op )
416 unbecome_root();
418 /********** END SePrintOperatorPrivlege BLOCK **********/
420 DEBUGADD(10,("returned [%d]\n", ret));
422 TALLOC_FREE(command);
424 if (ret != 0)
425 return WERR_BADFID; /* What to return here? */
427 /* go ahead and re-read the services immediately */
428 become_root();
429 reload_services(msg_ctx, -1, false);
430 unbecome_root();
432 if ( lp_servicenumber( sharename ) >= 0 )
433 return WERR_ACCESS_DENIED;
435 return WERR_OK;
438 /****************************************************************************
439 Delete a printer given a handle.
440 ****************************************************************************/
442 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
444 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
445 WERROR result;
447 if (!Printer) {
448 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
449 OUR_HANDLE(hnd)));
450 return WERR_BADFID;
454 * It turns out that Windows allows delete printer on a handle
455 * opened by an admin user, then used on a pipe handle created
456 * by an anonymous user..... but they're working on security.... riiight !
457 * JRA.
460 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
461 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
462 return WERR_ACCESS_DENIED;
465 /* this does not need a become root since the access check has been
466 done on the handle already */
468 result = winreg_delete_printer_key_internal(p->mem_ctx,
469 get_session_info_system(),
470 p->msg_ctx,
471 Printer->sharename,
472 "");
473 if (!W_ERROR_IS_OK(result)) {
474 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
475 return WERR_BADFID;
478 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
479 Printer->sharename, p->msg_ctx);
480 if (!W_ERROR_IS_OK(result)) {
481 return result;
483 prune_printername_cache();
484 return WERR_OK;
487 /****************************************************************************
488 Return the snum of a printer corresponding to an handle.
489 ****************************************************************************/
491 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
492 int *number, struct share_params **params)
494 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
496 if (!Printer) {
497 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
498 OUR_HANDLE(hnd)));
499 return false;
502 switch (Printer->printer_type) {
503 case SPLHND_PRINTER:
504 DEBUG(4,("short name:%s\n", Printer->sharename));
505 *number = print_queue_snum(Printer->sharename);
506 return (*number != -1);
507 case SPLHND_SERVER:
508 return false;
509 default:
510 return false;
514 /****************************************************************************
515 Set printer handle type.
516 Check if it's \\server or \\server\printer
517 ****************************************************************************/
519 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
521 DEBUG(3,("Setting printer type=%s\n", handlename));
523 /* it's a print server */
524 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
525 DEBUGADD(4,("Printer is a print server\n"));
526 Printer->printer_type = SPLHND_SERVER;
528 /* it's a printer (set_printer_hnd_name() will handle port monitors */
529 else {
530 DEBUGADD(4,("Printer is a printer\n"));
531 Printer->printer_type = SPLHND_PRINTER;
534 return true;
537 static void prune_printername_cache_fn(const char *key, const char *value,
538 time_t timeout, void *private_data)
540 gencache_del(key);
543 static void prune_printername_cache(void)
545 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
548 /****************************************************************************
549 Set printer handle name.. Accept names like \\server, \\server\printer,
550 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
551 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
552 XcvDataPort() interface.
553 ****************************************************************************/
555 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
556 const struct auth_serversupplied_info *session_info,
557 struct messaging_context *msg_ctx,
558 struct printer_handle *Printer,
559 const char *handlename)
561 int snum;
562 int n_services=lp_numservices();
563 char *aprinter;
564 const char *printername;
565 const char *servername = NULL;
566 fstring sname;
567 bool found = false;
568 struct spoolss_PrinterInfo2 *info2 = NULL;
569 WERROR result;
570 char *p;
573 * Hopefully nobody names his printers like this. Maybe \ or ,
574 * are illegal in printer names even?
576 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
577 char *cache_key;
578 char *tmp;
580 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
581 (unsigned long)strlen(handlename)));
583 aprinter = CONST_DISCARD(char *, handlename);
584 if ( *handlename == '\\' ) {
585 servername = canon_servername(handlename);
586 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
587 *aprinter = '\0';
588 aprinter++;
590 if (!is_myname_or_ipaddr(servername)) {
591 return WERR_INVALID_PRINTER_NAME;
593 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
594 if (Printer->servername == NULL) {
595 return WERR_NOMEM;
599 if (Printer->printer_type == SPLHND_SERVER) {
600 return WERR_OK;
603 if (Printer->printer_type != SPLHND_PRINTER) {
604 return WERR_INVALID_HANDLE;
607 DEBUGADD(5, ("searching for [%s]\n", aprinter));
609 p = strchr(aprinter, ',');
610 if (p != NULL) {
611 char *p2 = p;
612 p++;
613 if (*p == ' ') {
614 p++;
616 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
617 *p2 = '\0';
618 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
619 *p2 = '\0';
623 if (p) {
624 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
627 /* check for the Port Monitor Interface */
628 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
629 Printer->printer_type = SPLHND_PORTMON_TCP;
630 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
631 found = true;
633 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
634 Printer->printer_type = SPLHND_PORTMON_LOCAL;
635 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
636 found = true;
640 * With hundreds of printers, the "for" loop iterating all
641 * shares can be quite expensive, as it is done on every
642 * OpenPrinter. The loop maps "aprinter" to "sname", the
643 * result of which we cache in gencache.
646 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
647 aprinter);
648 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
650 found = (strcmp(tmp, printer_not_found) != 0);
651 if (!found) {
652 DEBUG(4, ("Printer %s not found\n", aprinter));
653 SAFE_FREE(tmp);
654 return WERR_INVALID_PRINTER_NAME;
656 fstrcpy(sname, tmp);
657 SAFE_FREE(tmp);
660 /* Search all sharenames first as this is easier than pulling
661 the printer_info_2 off of disk. Don't use find_service() since
662 that calls out to map_username() */
664 /* do another loop to look for printernames */
665 for (snum = 0; !found && snum < n_services; snum++) {
666 const char *printer = lp_const_servicename(snum);
668 /* no point going on if this is not a printer */
669 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
670 continue;
673 /* ignore [printers] share */
674 if (strequal(printer, "printers")) {
675 continue;
678 fstrcpy(sname, printer);
679 if (strequal(aprinter, printer)) {
680 found = true;
681 break;
684 /* no point looking up the printer object if
685 we aren't allowing printername != sharename */
686 if (lp_force_printername(snum)) {
687 continue;
690 result = winreg_get_printer_internal(mem_ctx,
691 session_info,
692 msg_ctx,
693 sname,
694 &info2);
695 if ( !W_ERROR_IS_OK(result) ) {
696 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
697 sname, win_errstr(result)));
698 continue;
701 printername = strrchr(info2->printername, '\\');
702 if (printername == NULL) {
703 printername = info2->printername;
704 } else {
705 printername++;
708 if (strequal(printername, aprinter)) {
709 found = true;
710 break;
713 DEBUGADD(10, ("printername: %s\n", printername));
715 TALLOC_FREE(info2);
718 if ( !found ) {
719 if (cache_key != NULL) {
720 gencache_set(cache_key, printer_not_found,
721 time(NULL)+300);
722 TALLOC_FREE(cache_key);
724 DEBUGADD(4,("Printer not found\n"));
725 return WERR_INVALID_PRINTER_NAME;
728 if (cache_key != NULL) {
729 gencache_set(cache_key, sname, time(NULL)+300);
730 TALLOC_FREE(cache_key);
733 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
735 fstrcpy(Printer->sharename, sname);
737 return WERR_OK;
740 /****************************************************************************
741 Find first available printer slot. creates a printer handle for you.
742 ****************************************************************************/
744 static WERROR open_printer_hnd(struct pipes_struct *p,
745 struct policy_handle *hnd,
746 const char *name,
747 uint32_t access_granted)
749 struct printer_handle *new_printer;
750 WERROR result;
752 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
754 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
755 if (new_printer == NULL) {
756 return WERR_NOMEM;
758 talloc_set_destructor(new_printer, printer_entry_destructor);
760 /* This also steals the printer_handle on the policy_handle */
761 if (!create_policy_hnd(p, hnd, new_printer)) {
762 TALLOC_FREE(new_printer);
763 return WERR_INVALID_HANDLE;
766 /* Add to the internal list. */
767 DLIST_ADD(printers_list, new_printer);
769 new_printer->notify.option=NULL;
771 if (!set_printer_hnd_printertype(new_printer, name)) {
772 close_printer_handle(p, hnd);
773 return WERR_INVALID_HANDLE;
776 result = set_printer_hnd_name(p->mem_ctx,
777 get_session_info_system(),
778 p->msg_ctx,
779 new_printer, name);
780 if (!W_ERROR_IS_OK(result)) {
781 close_printer_handle(p, hnd);
782 return result;
785 new_printer->access_granted = access_granted;
787 DEBUG(5, ("%d printer handles active\n",
788 (int)num_pipe_handles(p)));
790 return WERR_OK;
793 /***************************************************************************
794 check to see if the client motify handle is monitoring the notification
795 given by (notify_type, notify_field).
796 **************************************************************************/
798 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
799 uint16_t notify_field)
801 return true;
804 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
805 uint16_t notify_field)
807 struct spoolss_NotifyOption *option = p->notify.option;
808 uint32_t i, j;
811 * Flags should always be zero when the change notify
812 * is registered by the client's spooler. A user Win32 app
813 * might use the flags though instead of the NOTIFY_OPTION_INFO
814 * --jerry
817 if (!option) {
818 return false;
821 if (p->notify.flags)
822 return is_monitoring_event_flags(
823 p->notify.flags, notify_type, notify_field);
825 for (i = 0; i < option->count; i++) {
827 /* Check match for notify_type */
829 if (option->types[i].type != notify_type)
830 continue;
832 /* Check match for field */
834 for (j = 0; j < option->types[i].count; j++) {
835 if (option->types[i].fields[j].field == notify_field) {
836 return true;
841 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
842 p->servername, p->sharename, notify_type, notify_field));
844 return false;
847 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
848 _data->data.integer[0] = _integer; \
849 _data->data.integer[1] = 0;
852 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
853 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
854 if (!_data->data.string.string) {\
855 _data->data.string.size = 0; \
857 _data->data.string.size = strlen_m_term(_p) * 2;
859 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
860 _data->data.devmode.devmode = _devmode;
862 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
863 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
864 if (!_data->data.sd.sd) { \
865 _data->data.sd.sd_size = 0; \
867 _data->data.sd.sd_size = \
868 ndr_size_security_descriptor(_data->data.sd.sd, 0);
870 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
871 struct tm *t,
872 const char **pp,
873 uint32_t *plen)
875 struct spoolss_Time st;
876 uint32_t len = 16;
877 char *p;
879 if (!init_systemtime(&st, t)) {
880 return;
883 p = talloc_array(mem_ctx, char, len);
884 if (!p) {
885 return;
889 * Systemtime must be linearized as a set of UINT16's.
890 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
893 SSVAL(p, 0, st.year);
894 SSVAL(p, 2, st.month);
895 SSVAL(p, 4, st.day_of_week);
896 SSVAL(p, 6, st.day);
897 SSVAL(p, 8, st.hour);
898 SSVAL(p, 10, st.minute);
899 SSVAL(p, 12, st.second);
900 SSVAL(p, 14, st.millisecond);
902 *pp = p;
903 *plen = len;
906 /* Convert a notification message to a struct spoolss_Notify */
908 static void notify_one_value(struct spoolss_notify_msg *msg,
909 struct spoolss_Notify *data,
910 TALLOC_CTX *mem_ctx)
912 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
915 static void notify_string(struct spoolss_notify_msg *msg,
916 struct spoolss_Notify *data,
917 TALLOC_CTX *mem_ctx)
919 /* The length of the message includes the trailing \0 */
921 data->data.string.size = msg->len * 2;
922 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
923 if (!data->data.string.string) {
924 data->data.string.size = 0;
925 return;
929 static void notify_system_time(struct spoolss_notify_msg *msg,
930 struct spoolss_Notify *data,
931 TALLOC_CTX *mem_ctx)
933 data->data.string.string = NULL;
934 data->data.string.size = 0;
936 if (msg->len != sizeof(time_t)) {
937 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
938 msg->len));
939 return;
942 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
943 &data->data.string.string,
944 &data->data.string.size);
947 struct notify2_message_table {
948 const char *name;
949 void (*fn)(struct spoolss_notify_msg *msg,
950 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
953 static struct notify2_message_table printer_notify_table[] = {
954 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
955 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
956 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
957 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
958 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
959 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
960 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
961 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
962 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
963 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
964 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
965 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
966 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
967 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
968 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
969 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
970 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
971 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
972 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
975 static struct notify2_message_table job_notify_table[] = {
976 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
977 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
978 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
979 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
980 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
981 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
982 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
983 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
984 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
985 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
986 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
987 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
988 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
989 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
990 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
991 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
992 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
993 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
994 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
995 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
996 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
997 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
998 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
999 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1003 /***********************************************************************
1004 Allocate talloc context for container object
1005 **********************************************************************/
1007 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 if ( !ctr )
1010 return;
1012 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1014 return;
1017 /***********************************************************************
1018 release all allocated memory and zero out structure
1019 **********************************************************************/
1021 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 if ( !ctr )
1024 return;
1026 if ( ctr->ctx )
1027 talloc_destroy(ctr->ctx);
1029 ZERO_STRUCTP(ctr);
1031 return;
1034 /***********************************************************************
1035 **********************************************************************/
1037 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1039 if ( !ctr )
1040 return NULL;
1042 return ctr->ctx;
1045 /***********************************************************************
1046 **********************************************************************/
1048 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1050 if ( !ctr || !ctr->msg_groups )
1051 return NULL;
1053 if ( idx >= ctr->num_groups )
1054 return NULL;
1056 return &ctr->msg_groups[idx];
1060 /***********************************************************************
1061 How many groups of change messages do we have ?
1062 **********************************************************************/
1064 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1066 if ( !ctr )
1067 return 0;
1069 return ctr->num_groups;
1072 /***********************************************************************
1073 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1074 **********************************************************************/
1076 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1078 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1079 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1080 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1081 int i, new_slot;
1083 if ( !ctr || !msg )
1084 return 0;
1086 /* loop over all groups looking for a matching printer name */
1088 for ( i=0; i<ctr->num_groups; i++ ) {
1089 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1090 break;
1093 /* add a new group? */
1095 if ( i == ctr->num_groups ) {
1096 ctr->num_groups++;
1098 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1099 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1100 return 0;
1102 ctr->msg_groups = groups;
1104 /* clear the new entry and set the printer name */
1106 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1107 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1110 /* add the change messages; 'i' is the correct index now regardless */
1112 msg_grp = &ctr->msg_groups[i];
1114 msg_grp->num_msgs++;
1116 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1117 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1118 return 0;
1120 msg_grp->msgs = msg_list;
1122 new_slot = msg_grp->num_msgs-1;
1123 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1125 /* need to allocate own copy of data */
1127 if ( msg->len != 0 )
1128 msg_grp->msgs[new_slot].notify.data = (char *)
1129 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1131 return ctr->num_groups;
1134 static void construct_info_data(struct spoolss_Notify *info_data,
1135 enum spoolss_NotifyType type,
1136 uint16_t field, int id);
1138 /***********************************************************************
1139 Send a change notication message on all handles which have a call
1140 back registered
1141 **********************************************************************/
1143 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1144 struct printer_handle *prn_hnd,
1145 SPOOLSS_NOTIFY_MSG *messages,
1146 uint32_t num_msgs,
1147 struct spoolss_Notify **_notifies,
1148 int *_count)
1150 struct spoolss_Notify *notifies;
1151 SPOOLSS_NOTIFY_MSG *msg;
1152 int count = 0;
1153 uint32_t id;
1154 int i;
1156 notifies = talloc_zero_array(mem_ctx,
1157 struct spoolss_Notify, num_msgs);
1158 if (!notifies) {
1159 return ENOMEM;
1162 for (i = 0; i < num_msgs; i++) {
1164 msg = &messages[i];
1166 /* Are we monitoring this event? */
1168 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1169 continue;
1172 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1173 "for printer [%s]\n",
1174 msg->type, msg->field, prn_hnd->sharename));
1177 * if the is a printer notification handle and not a job
1178 * notification type, then set the id to 0.
1179 * Otherwise just use what was specified in the message.
1181 * When registering change notification on a print server
1182 * handle we always need to send back the id (snum) matching
1183 * the printer for which the change took place.
1184 * For change notify registered on a printer handle,
1185 * this does not matter and the id should be 0.
1187 * --jerry
1190 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1191 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1192 id = 0;
1193 } else {
1194 id = msg->id;
1197 /* Convert unix jobid to smb jobid */
1199 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1200 id = sysjob_to_jobid(msg->id);
1202 if (id == -1) {
1203 DEBUG(3, ("no such unix jobid %d\n",
1204 msg->id));
1205 continue;
1209 construct_info_data(&notifies[count],
1210 msg->type, msg->field, id);
1212 switch(msg->type) {
1213 case PRINTER_NOTIFY_TYPE:
1214 if (printer_notify_table[msg->field].fn) {
1215 printer_notify_table[msg->field].fn(msg,
1216 &notifies[count], mem_ctx);
1218 break;
1220 case JOB_NOTIFY_TYPE:
1221 if (job_notify_table[msg->field].fn) {
1222 job_notify_table[msg->field].fn(msg,
1223 &notifies[count], mem_ctx);
1225 break;
1227 default:
1228 DEBUG(5, ("Unknown notification type %d\n",
1229 msg->type));
1230 continue;
1233 count++;
1236 *_notifies = notifies;
1237 *_count = count;
1239 return 0;
1242 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1243 struct printer_handle *prn_hnd,
1244 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1246 struct spoolss_Notify *notifies;
1247 int count = 0;
1248 union spoolss_ReplyPrinterInfo info;
1249 struct spoolss_NotifyInfo info0;
1250 uint32_t reply_result;
1251 NTSTATUS status;
1252 WERROR werr;
1253 int ret;
1255 /* Is there notification on this handle? */
1256 if (prn_hnd->notify.cli_chan == NULL ||
1257 prn_hnd->notify.cli_chan->active_connections == 0) {
1258 return 0;
1261 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1262 prn_hnd->servername, prn_hnd->sharename));
1264 /* For this printer? Print servers always receive notifications. */
1265 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1266 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1267 return 0;
1270 DEBUG(10,("Our printer\n"));
1272 /* build the array of change notifications */
1273 ret = build_notify2_messages(mem_ctx, prn_hnd,
1274 msg_group->msgs,
1275 msg_group->num_msgs,
1276 &notifies, &count);
1277 if (ret) {
1278 return ret;
1281 info0.version = 0x2;
1282 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1283 info0.count = count;
1284 info0.notifies = notifies;
1286 info.info0 = &info0;
1288 status = dcerpc_spoolss_RouterReplyPrinterEx(
1289 prn_hnd->notify.cli_chan->binding_handle,
1290 mem_ctx,
1291 &prn_hnd->notify.cli_hnd,
1292 prn_hnd->notify.change, /* color */
1293 prn_hnd->notify.flags,
1294 &reply_result,
1295 0, /* reply_type, must be 0 */
1296 info, &werr);
1297 if (!NT_STATUS_IS_OK(status)) {
1298 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1299 "failed: %s\n",
1300 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301 nt_errstr(status)));
1302 werr = ntstatus_to_werror(status);
1303 } else if (!W_ERROR_IS_OK(werr)) {
1304 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1305 "failed: %s\n",
1306 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1307 win_errstr(werr)));
1309 switch (reply_result) {
1310 case 0:
1311 break;
1312 case PRINTER_NOTIFY_INFO_DISCARDED:
1313 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1314 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1315 break;
1316 default:
1317 break;
1320 return 0;
1323 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1325 struct printer_handle *p;
1326 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1327 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1328 int ret;
1330 if ( !msg_group ) {
1331 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1332 return;
1335 if (!msg_group->msgs) {
1336 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1337 return;
1340 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1342 /* loop over all printers */
1344 for (p = printers_list; p; p = p->next) {
1345 ret = send_notify2_printer(mem_ctx, p, msg_group);
1346 if (ret) {
1347 goto done;
1351 done:
1352 DEBUG(8,("send_notify2_changes: Exit...\n"));
1353 return;
1356 /***********************************************************************
1357 **********************************************************************/
1359 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1362 uint32_t tv_sec, tv_usec;
1363 size_t offset = 0;
1365 /* Unpack message */
1367 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1368 msg->printer);
1370 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1371 &tv_sec, &tv_usec,
1372 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1374 if (msg->len == 0)
1375 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1376 &msg->notify.value[0], &msg->notify.value[1]);
1377 else
1378 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1379 &msg->len, &msg->notify.data);
1381 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1382 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1384 tv->tv_sec = tv_sec;
1385 tv->tv_usec = tv_usec;
1387 if (msg->len == 0)
1388 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1389 msg->notify.value[1]));
1390 else
1391 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1393 return true;
1396 /********************************************************************
1397 Receive a notify2 message list
1398 ********************************************************************/
1400 static void receive_notify2_message_list(struct messaging_context *msg,
1401 void *private_data,
1402 uint32_t msg_type,
1403 struct server_id server_id,
1404 DATA_BLOB *data)
1406 size_t msg_count, i;
1407 char *buf = (char *)data->data;
1408 char *msg_ptr;
1409 size_t msg_len;
1410 SPOOLSS_NOTIFY_MSG notify;
1411 SPOOLSS_NOTIFY_MSG_CTR messages;
1412 int num_groups;
1414 if (data->length < 4) {
1415 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1416 return;
1419 msg_count = IVAL(buf, 0);
1420 msg_ptr = buf + 4;
1422 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1424 if (msg_count == 0) {
1425 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1426 return;
1429 /* initialize the container */
1431 ZERO_STRUCT( messages );
1432 notify_msg_ctr_init( &messages );
1435 * build message groups for each printer identified
1436 * in a change_notify msg. Remember that a PCN message
1437 * includes the handle returned for the srv_spoolss_replyopenprinter()
1438 * call. Therefore messages are grouped according to printer handle.
1441 for ( i=0; i<msg_count; i++ ) {
1442 struct timeval msg_tv;
1444 if (msg_ptr + 4 - buf > data->length) {
1445 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1446 return;
1449 msg_len = IVAL(msg_ptr,0);
1450 msg_ptr += 4;
1452 if (msg_ptr + msg_len - buf > data->length) {
1453 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1454 return;
1457 /* unpack messages */
1459 ZERO_STRUCT( notify );
1460 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1461 msg_ptr += msg_len;
1463 /* add to correct list in container */
1465 notify_msg_ctr_addmsg( &messages, &notify );
1467 /* free memory that might have been allocated by notify2_unpack_msg() */
1469 if ( notify.len != 0 )
1470 SAFE_FREE( notify.notify.data );
1473 /* process each group of messages */
1475 num_groups = notify_msg_ctr_numgroups( &messages );
1476 for ( i=0; i<num_groups; i++ )
1477 send_notify2_changes( &messages, i );
1480 /* cleanup */
1482 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1483 (uint32_t)msg_count ));
1485 notify_msg_ctr_destroy( &messages );
1487 return;
1490 /********************************************************************
1491 Send a message to ourself about new driver being installed
1492 so we can upgrade the information for each printer bound to this
1493 driver
1494 ********************************************************************/
1496 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1497 struct messaging_context *msg_ctx)
1499 int len = strlen(drivername);
1501 if (!len)
1502 return false;
1504 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1505 drivername));
1507 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1508 MSG_PRINTER_DRVUPGRADE,
1509 (uint8_t *)drivername, len+1);
1511 return true;
1514 void srv_spoolss_cleanup(void)
1516 struct printer_session_counter *session_counter;
1518 for (session_counter = counter_list;
1519 session_counter != NULL;
1520 session_counter = counter_list) {
1521 DLIST_REMOVE(counter_list, session_counter);
1522 TALLOC_FREE(session_counter);
1526 /**********************************************************************
1527 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1528 over all printers, upgrading ones as necessary
1529 **********************************************************************/
1531 void do_drv_upgrade_printer(struct messaging_context *msg,
1532 void *private_data,
1533 uint32_t msg_type,
1534 struct server_id server_id,
1535 DATA_BLOB *data)
1537 TALLOC_CTX *tmp_ctx;
1538 struct auth_serversupplied_info *session_info = NULL;
1539 struct spoolss_PrinterInfo2 *pinfo2;
1540 NTSTATUS status;
1541 WERROR result;
1542 const char *drivername;
1543 int snum;
1544 int n_services = lp_numservices();
1545 struct dcerpc_binding_handle *b = NULL;
1547 tmp_ctx = talloc_new(NULL);
1548 if (!tmp_ctx) return;
1550 status = make_session_info_system(tmp_ctx, &session_info);
1551 if (!NT_STATUS_IS_OK(status)) {
1552 DEBUG(0, ("do_drv_upgrade_printer: "
1553 "Could not create system session_info\n"));
1554 goto done;
1557 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1558 if (!drivername) {
1559 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1560 goto done;
1563 DEBUG(10, ("do_drv_upgrade_printer: "
1564 "Got message for new driver [%s]\n", drivername));
1566 /* Iterate the printer list */
1568 for (snum = 0; snum < n_services; snum++) {
1569 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1570 continue;
1573 /* ignore [printers] share */
1574 if (strequal(lp_const_servicename(snum), "printers")) {
1575 continue;
1578 if (b == NULL) {
1579 result = winreg_printer_binding_handle(tmp_ctx,
1580 session_info,
1581 msg,
1582 &b);
1583 if (!W_ERROR_IS_OK(result)) {
1584 break;
1588 result = winreg_get_printer(tmp_ctx, b,
1589 lp_const_servicename(snum),
1590 &pinfo2);
1592 if (!W_ERROR_IS_OK(result)) {
1593 continue;
1596 if (!pinfo2->drivername) {
1597 continue;
1600 if (strcmp(drivername, pinfo2->drivername) != 0) {
1601 continue;
1604 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1606 /* all we care about currently is the change_id */
1607 result = winreg_printer_update_changeid(tmp_ctx, b,
1608 pinfo2->printername);
1610 if (!W_ERROR_IS_OK(result)) {
1611 DEBUG(3, ("do_drv_upgrade_printer: "
1612 "Failed to update changeid [%s]\n",
1613 win_errstr(result)));
1617 /* all done */
1618 done:
1619 talloc_free(tmp_ctx);
1622 /********************************************************************
1623 Update the cache for all printq's with a registered client
1624 connection
1625 ********************************************************************/
1627 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1629 struct printer_handle *printer = printers_list;
1630 int snum;
1632 /* loop through all printers and update the cache where
1633 a client is connected */
1634 while (printer) {
1635 if ((printer->printer_type == SPLHND_PRINTER) &&
1636 ((printer->notify.cli_chan != NULL) &&
1637 (printer->notify.cli_chan->active_connections > 0))) {
1638 snum = print_queue_snum(printer->sharename);
1639 print_queue_status(msg_ctx, snum, NULL, NULL);
1642 printer = printer->next;
1645 return;
1648 /****************************************************************
1649 _spoolss_OpenPrinter
1650 ****************************************************************/
1652 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1653 struct spoolss_OpenPrinter *r)
1655 struct spoolss_OpenPrinterEx e;
1656 WERROR werr;
1658 ZERO_STRUCT(e.in.userlevel);
1660 e.in.printername = r->in.printername;
1661 e.in.datatype = r->in.datatype;
1662 e.in.devmode_ctr = r->in.devmode_ctr;
1663 e.in.access_mask = r->in.access_mask;
1664 e.in.level = 0;
1666 e.out.handle = r->out.handle;
1668 werr = _spoolss_OpenPrinterEx(p, &e);
1670 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1671 /* OpenPrinterEx returns this for a bad
1672 * printer name. We must return WERR_INVALID_PRINTER_NAME
1673 * instead.
1675 werr = WERR_INVALID_PRINTER_NAME;
1678 return werr;
1681 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1682 struct spoolss_DeviceMode *orig,
1683 struct spoolss_DeviceMode **dest)
1685 struct spoolss_DeviceMode *dm;
1687 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1688 if (!dm) {
1689 return WERR_NOMEM;
1692 /* copy all values, then duplicate strings and structs */
1693 *dm = *orig;
1695 dm->devicename = talloc_strdup(dm, orig->devicename);
1696 if (!dm->devicename) {
1697 return WERR_NOMEM;
1699 dm->formname = talloc_strdup(dm, orig->formname);
1700 if (!dm->formname) {
1701 return WERR_NOMEM;
1703 if (orig->driverextra_data.data) {
1704 dm->driverextra_data.data =
1705 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1706 orig->driverextra_data.length);
1707 if (!dm->driverextra_data.data) {
1708 return WERR_NOMEM;
1712 *dest = dm;
1713 return WERR_OK;
1716 /****************************************************************
1717 _spoolss_OpenPrinterEx
1718 ****************************************************************/
1720 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1721 struct spoolss_OpenPrinterEx *r)
1723 int snum;
1724 struct printer_handle *Printer=NULL;
1725 WERROR result;
1727 if (!r->in.printername) {
1728 return WERR_INVALID_PARAM;
1731 if (r->in.level > 3) {
1732 return WERR_INVALID_PARAM;
1734 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1735 (r->in.level == 2 && !r->in.userlevel.level2) ||
1736 (r->in.level == 3 && !r->in.userlevel.level3)) {
1737 return WERR_INVALID_PARAM;
1740 /* some sanity check because you can open a printer or a print server */
1741 /* aka: \\server\printer or \\server */
1743 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1745 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1746 if (!W_ERROR_IS_OK(result)) {
1747 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1748 "for printer %s\n", r->in.printername));
1749 ZERO_STRUCTP(r->out.handle);
1750 return result;
1753 Printer = find_printer_index_by_hnd(p, r->out.handle);
1754 if ( !Printer ) {
1755 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1756 "handle we created for printer %s\n", r->in.printername));
1757 close_printer_handle(p, r->out.handle);
1758 ZERO_STRUCTP(r->out.handle);
1759 return WERR_INVALID_PARAM;
1763 * First case: the user is opening the print server:
1765 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1766 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1768 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1769 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1770 * or if the user is listed in the smb.conf printer admin parameter.
1772 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1773 * client view printer folder, but does not show the MSAPW.
1775 * Note: this test needs code to check access rights here too. Jeremy
1776 * could you look at this?
1778 * Second case: the user is opening a printer:
1779 * NT doesn't let us connect to a printer if the connecting user
1780 * doesn't have print permission.
1782 * Third case: user is opening a Port Monitor
1783 * access checks same as opening a handle to the print server.
1786 switch (Printer->printer_type )
1788 case SPLHND_SERVER:
1789 case SPLHND_PORTMON_TCP:
1790 case SPLHND_PORTMON_LOCAL:
1791 /* Printserver handles use global struct... */
1793 snum = -1;
1795 /* Map standard access rights to object specific access rights */
1797 se_map_standard(&r->in.access_mask,
1798 &printserver_std_mapping);
1800 /* Deny any object specific bits that don't apply to print
1801 servers (i.e printer and job specific bits) */
1803 r->in.access_mask &= SEC_MASK_SPECIFIC;
1805 if (r->in.access_mask &
1806 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1807 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1808 close_printer_handle(p, r->out.handle);
1809 ZERO_STRUCTP(r->out.handle);
1810 return WERR_ACCESS_DENIED;
1813 /* Allow admin access */
1815 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1817 if (!lp_ms_add_printer_wizard()) {
1818 close_printer_handle(p, r->out.handle);
1819 ZERO_STRUCTP(r->out.handle);
1820 return WERR_ACCESS_DENIED;
1823 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1824 and not a printer admin, then fail */
1826 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1827 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1828 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1829 !token_contains_name_in_list(
1830 uidtoname(p->session_info->utok.uid),
1831 p->session_info->info3->base.domain.string,
1832 NULL,
1833 p->session_info->security_token,
1834 lp_printer_admin(snum))) {
1835 close_printer_handle(p, r->out.handle);
1836 ZERO_STRUCTP(r->out.handle);
1837 DEBUG(3,("access DENIED as user is not root, "
1838 "has no printoperator privilege, "
1839 "not a member of the printoperator builtin group and "
1840 "is not in printer admin list"));
1841 return WERR_ACCESS_DENIED;
1844 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1846 else
1848 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1851 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1852 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1854 /* We fall through to return WERR_OK */
1855 break;
1857 case SPLHND_PRINTER:
1858 /* NT doesn't let us connect to a printer if the connecting user
1859 doesn't have print permission. */
1861 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1862 close_printer_handle(p, r->out.handle);
1863 ZERO_STRUCTP(r->out.handle);
1864 return WERR_BADFID;
1867 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1868 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1871 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1873 /* map an empty access mask to the minimum access mask */
1874 if (r->in.access_mask == 0x0)
1875 r->in.access_mask = PRINTER_ACCESS_USE;
1878 * If we are not serving the printer driver for this printer,
1879 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1880 * will keep NT clients happy --jerry
1883 if (lp_use_client_driver(snum)
1884 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1886 r->in.access_mask = PRINTER_ACCESS_USE;
1889 /* check smb.conf parameters and the the sec_desc */
1891 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1892 p->client_id->name, p->client_id->addr)) {
1893 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894 ZERO_STRUCTP(r->out.handle);
1895 return WERR_ACCESS_DENIED;
1898 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1899 p->session_info->security_token, snum) ||
1900 !print_access_check(p->session_info,
1901 p->msg_ctx,
1902 snum,
1903 r->in.access_mask)) {
1904 DEBUG(3, ("access DENIED for printer open\n"));
1905 close_printer_handle(p, r->out.handle);
1906 ZERO_STRUCTP(r->out.handle);
1907 return WERR_ACCESS_DENIED;
1910 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 close_printer_handle(p, r->out.handle);
1913 ZERO_STRUCTP(r->out.handle);
1914 return WERR_ACCESS_DENIED;
1917 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919 else
1920 r->in.access_mask = PRINTER_ACCESS_USE;
1922 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1925 winreg_create_printer_internal(p->mem_ctx,
1926 get_session_info_system(),
1927 p->msg_ctx,
1928 lp_const_servicename(snum));
1930 break;
1932 default:
1933 /* sanity check to prevent programmer error */
1934 ZERO_STRUCTP(r->out.handle);
1935 return WERR_BADFID;
1938 Printer->access_granted = r->in.access_mask;
1941 * If the client sent a devmode in the OpenPrinter() call, then
1942 * save it here in case we get a job submission on this handle
1945 if ((Printer->printer_type != SPLHND_SERVER)
1946 && (r->in.devmode_ctr.devmode != NULL)) {
1947 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948 &Printer->devmode);
1951 return WERR_OK;
1954 /****************************************************************
1955 _spoolss_ClosePrinter
1956 ****************************************************************/
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959 struct spoolss_ClosePrinter *r)
1961 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1963 if (Printer && Printer->document_started) {
1964 struct spoolss_EndDocPrinter e;
1966 e.in.handle = r->in.handle;
1968 _spoolss_EndDocPrinter(p, &e);
1971 if (!close_printer_handle(p, r->in.handle))
1972 return WERR_BADFID;
1974 /* clear the returned printer handle. Observed behavior
1975 from Win2k server. Don't think this really matters.
1976 Previous code just copied the value of the closed
1977 handle. --jerry */
1979 ZERO_STRUCTP(r->out.handle);
1981 return WERR_OK;
1984 /****************************************************************
1985 _spoolss_DeletePrinter
1986 ****************************************************************/
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989 struct spoolss_DeletePrinter *r)
1991 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992 WERROR result;
1993 int snum;
1995 if (Printer && Printer->document_started) {
1996 struct spoolss_EndDocPrinter e;
1998 e.in.handle = r->in.handle;
2000 _spoolss_EndDocPrinter(p, &e);
2003 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004 winreg_delete_printer_key_internal(p->mem_ctx,
2005 get_session_info_system(),
2006 p->msg_ctx,
2007 lp_const_servicename(snum),
2008 "");
2011 result = delete_printer_handle(p, r->in.handle);
2013 return result;
2016 /*******************************************************************
2017 * static function to lookup the version id corresponding to an
2018 * long architecture string
2019 ******************************************************************/
2021 static const struct print_architecture_table_node archi_table[]= {
2023 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2024 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2025 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2026 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2027 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2028 {"Windows IA64", SPL_ARCH_IA64, 3 },
2029 {"Windows x64", SPL_ARCH_X64, 3 },
2030 {NULL, "", -1 }
2033 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2034 SPOOLSS_DRIVER_VERSION_NT35,
2035 SPOOLSS_DRIVER_VERSION_NT4,
2036 SPOOLSS_DRIVER_VERSION_200X,
2037 -1};
2039 static int get_version_id(const char *arch)
2041 int i;
2043 for (i=0; archi_table[i].long_archi != NULL; i++)
2045 if (strcmp(arch, archi_table[i].long_archi) == 0)
2046 return (archi_table[i].version);
2049 return -1;
2052 /****************************************************************
2053 _spoolss_DeletePrinterDriver
2054 ****************************************************************/
2056 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2057 struct spoolss_DeletePrinterDriver *r)
2060 struct spoolss_DriverInfo8 *info = NULL;
2061 int version;
2062 WERROR status;
2063 struct dcerpc_binding_handle *b;
2064 TALLOC_CTX *tmp_ctx = NULL;
2065 int i;
2066 bool found;
2068 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2069 and not a printer admin, then fail */
2071 if ( (p->session_info->utok.uid != sec_initial_uid())
2072 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2073 && !token_contains_name_in_list(
2074 uidtoname(p->session_info->utok.uid),
2075 p->session_info->info3->base.domain.string,
2076 NULL,
2077 p->session_info->security_token,
2078 lp_printer_admin(-1)) )
2080 return WERR_ACCESS_DENIED;
2083 /* check that we have a valid driver name first */
2085 if ((version = get_version_id(r->in.architecture)) == -1)
2086 return WERR_INVALID_ENVIRONMENT;
2088 tmp_ctx = talloc_new(p->mem_ctx);
2089 if (!tmp_ctx) {
2090 return WERR_NOMEM;
2093 status = winreg_printer_binding_handle(tmp_ctx,
2094 get_session_info_system(),
2095 p->msg_ctx,
2096 &b);
2097 if (!W_ERROR_IS_OK(status)) {
2098 goto done;
2101 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2102 status = winreg_get_driver(tmp_ctx, b,
2103 r->in.architecture, r->in.driver,
2104 drv_cversion[i], &info);
2105 if (!W_ERROR_IS_OK(status)) {
2106 DEBUG(5, ("skipping del of driver with version %d\n",
2107 drv_cversion[i]));
2108 continue;
2110 found = true;
2112 if (printer_driver_in_use(tmp_ctx, get_session_info_system(),
2113 p->msg_ctx, info)) {
2114 status = WERR_PRINTER_DRIVER_IN_USE;
2115 goto done;
2118 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2119 if (!W_ERROR_IS_OK(status)) {
2120 DEBUG(0, ("failed del of driver with version %d\n",
2121 drv_cversion[i]));
2122 goto done;
2125 if (found == false) {
2126 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2127 status = WERR_UNKNOWN_PRINTER_DRIVER;
2128 } else {
2129 status = WERR_OK;
2132 done:
2133 talloc_free(tmp_ctx);
2134 return status;
2137 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2138 struct pipes_struct *p,
2139 struct spoolss_DeletePrinterDriverEx *r,
2140 struct dcerpc_binding_handle *b,
2141 struct spoolss_DriverInfo8 *info)
2143 WERROR status;
2144 bool delete_files;
2146 if (printer_driver_in_use(mem_ctx, get_session_info_system(),
2147 p->msg_ctx, info)) {
2148 status = WERR_PRINTER_DRIVER_IN_USE;
2149 goto done;
2153 * we have a couple of cases to consider.
2154 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2155 * then the delete should fail if **any** files overlap with
2156 * other drivers
2157 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2158 * non-overlapping files
2159 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2160 * is set, then do not delete any files
2161 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2164 delete_files = r->in.delete_flags
2165 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2167 if (delete_files) {
2168 bool in_use = printer_driver_files_in_use(mem_ctx,
2169 get_session_info_system(),
2170 p->msg_ctx,
2171 info);
2172 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2173 status = WERR_PRINTER_DRIVER_IN_USE;
2174 goto done;
2177 * printer_driver_files_in_use() has trimmed overlapping files
2178 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2182 status = winreg_del_driver(mem_ctx, b, info, info->version);
2183 if (!W_ERROR_IS_OK(status)) {
2184 goto done;
2188 * now delete any associated files if delete_files is
2189 * true. Even if this part failes, we return succes
2190 * because the driver doesn not exist any more
2192 if (delete_files) {
2193 delete_driver_files(get_session_info_system(), info);
2196 done:
2197 return status;
2200 /****************************************************************
2201 _spoolss_DeletePrinterDriverEx
2202 ****************************************************************/
2204 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2205 struct spoolss_DeletePrinterDriverEx *r)
2207 struct spoolss_DriverInfo8 *info = NULL;
2208 WERROR status;
2209 struct dcerpc_binding_handle *b;
2210 TALLOC_CTX *tmp_ctx = NULL;
2211 int i;
2212 bool found;
2214 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2215 and not a printer admin, then fail */
2217 if ( (p->session_info->utok.uid != sec_initial_uid())
2218 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2219 && !token_contains_name_in_list(
2220 uidtoname(p->session_info->utok.uid),
2221 p->session_info->info3->base.domain.string,
2222 NULL,
2223 p->session_info->security_token, lp_printer_admin(-1)) )
2225 return WERR_ACCESS_DENIED;
2228 /* check that we have a valid driver name first */
2229 if (get_version_id(r->in.architecture) == -1) {
2230 /* this is what NT returns */
2231 return WERR_INVALID_ENVIRONMENT;
2234 tmp_ctx = talloc_new(p->mem_ctx);
2235 if (!tmp_ctx) {
2236 return WERR_NOMEM;
2239 status = winreg_printer_binding_handle(tmp_ctx,
2240 get_session_info_system(),
2241 p->msg_ctx,
2242 &b);
2243 if (!W_ERROR_IS_OK(status)) {
2244 goto done;
2247 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2248 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2249 && (drv_cversion[i] != r->in.version)) {
2250 continue;
2253 /* check if a driver with this version exists before delete */
2254 status = winreg_get_driver(tmp_ctx, b,
2255 r->in.architecture, r->in.driver,
2256 drv_cversion[i], &info);
2257 if (!W_ERROR_IS_OK(status)) {
2258 DEBUG(5, ("skipping del of driver with version %d\n",
2259 drv_cversion[i]));
2260 continue;
2262 found = true;
2264 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2265 if (!W_ERROR_IS_OK(status)) {
2266 DEBUG(0, ("failed to delete driver with version %d\n",
2267 drv_cversion[i]));
2268 goto done;
2271 if (found == false) {
2272 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2273 status = WERR_UNKNOWN_PRINTER_DRIVER;
2274 } else {
2275 status = WERR_OK;
2278 done:
2279 talloc_free(tmp_ctx);
2280 return status;
2284 /********************************************************************
2285 GetPrinterData on a printer server Handle.
2286 ********************************************************************/
2288 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2289 const char *value,
2290 enum winreg_Type *type,
2291 union spoolss_PrinterData *data)
2293 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2295 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2296 *type = REG_DWORD;
2297 data->value = 0x00;
2298 return WERR_OK;
2301 if (!StrCaseCmp(value, "BeepEnabled")) {
2302 *type = REG_DWORD;
2303 data->value = 0x00;
2304 return WERR_OK;
2307 if (!StrCaseCmp(value, "EventLog")) {
2308 *type = REG_DWORD;
2309 /* formally was 0x1b */
2310 data->value = 0x00;
2311 return WERR_OK;
2314 if (!StrCaseCmp(value, "NetPopup")) {
2315 *type = REG_DWORD;
2316 data->value = 0x00;
2317 return WERR_OK;
2320 if (!StrCaseCmp(value, "MajorVersion")) {
2321 *type = REG_DWORD;
2323 /* Windows NT 4.0 seems to not allow uploading of drivers
2324 to a server that reports 0x3 as the MajorVersion.
2325 need to investigate more how Win2k gets around this .
2326 -- jerry */
2328 if (RA_WINNT == get_remote_arch()) {
2329 data->value = 0x02;
2330 } else {
2331 data->value = 0x03;
2334 return WERR_OK;
2337 if (!StrCaseCmp(value, "MinorVersion")) {
2338 *type = REG_DWORD;
2339 data->value = 0x00;
2340 return WERR_OK;
2343 /* REG_BINARY
2344 * uint32_t size = 0x114
2345 * uint32_t major = 5
2346 * uint32_t minor = [0|1]
2347 * uint32_t build = [2195|2600]
2348 * extra unicode string = e.g. "Service Pack 3"
2350 if (!StrCaseCmp(value, "OSVersion")) {
2351 DATA_BLOB blob;
2352 enum ndr_err_code ndr_err;
2353 struct spoolss_OSVersion os;
2355 os.major = 5; /* Windows 2000 == 5.0 */
2356 os.minor = 0;
2357 os.build = 2195; /* build */
2358 os.extra_string = ""; /* leave extra string empty */
2360 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2361 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2362 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2363 return WERR_GENERAL_FAILURE;
2366 *type = REG_BINARY;
2367 data->binary = blob;
2369 return WERR_OK;
2373 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2374 *type = REG_SZ;
2376 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2377 W_ERROR_HAVE_NO_MEMORY(data->string);
2379 return WERR_OK;
2382 if (!StrCaseCmp(value, "Architecture")) {
2383 *type = REG_SZ;
2384 data->string = talloc_strdup(mem_ctx,
2385 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2386 W_ERROR_HAVE_NO_MEMORY(data->string);
2388 return WERR_OK;
2391 if (!StrCaseCmp(value, "DsPresent")) {
2392 *type = REG_DWORD;
2394 /* only show the publish check box if we are a
2395 member of a AD domain */
2397 if (lp_security() == SEC_ADS) {
2398 data->value = 0x01;
2399 } else {
2400 data->value = 0x00;
2402 return WERR_OK;
2405 if (!StrCaseCmp(value, "DNSMachineName")) {
2406 const char *hostname = get_mydnsfullname();
2408 if (!hostname) {
2409 return WERR_BADFILE;
2412 *type = REG_SZ;
2413 data->string = talloc_strdup(mem_ctx, hostname);
2414 W_ERROR_HAVE_NO_MEMORY(data->string);
2416 return WERR_OK;
2419 *type = REG_NONE;
2421 return WERR_INVALID_PARAM;
2424 /****************************************************************
2425 _spoolss_GetPrinterData
2426 ****************************************************************/
2428 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2429 struct spoolss_GetPrinterData *r)
2431 struct spoolss_GetPrinterDataEx r2;
2433 r2.in.handle = r->in.handle;
2434 r2.in.key_name = "PrinterDriverData";
2435 r2.in.value_name = r->in.value_name;
2436 r2.in.offered = r->in.offered;
2437 r2.out.type = r->out.type;
2438 r2.out.data = r->out.data;
2439 r2.out.needed = r->out.needed;
2441 return _spoolss_GetPrinterDataEx(p, &r2);
2444 /*********************************************************
2445 Connect to the client machine.
2446 **********************************************************/
2448 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2449 struct sockaddr_storage *client_ss, const char *remote_machine)
2451 NTSTATUS ret;
2452 struct cli_state *the_cli;
2453 struct sockaddr_storage rm_addr;
2454 char addr[INET6_ADDRSTRLEN];
2456 if ( is_zero_addr(client_ss) ) {
2457 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2458 remote_machine));
2459 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2460 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2461 return false;
2463 print_sockaddr(addr, sizeof(addr), &rm_addr);
2464 } else {
2465 rm_addr = *client_ss;
2466 print_sockaddr(addr, sizeof(addr), &rm_addr);
2467 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2468 addr));
2471 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2472 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2473 addr));
2474 return false;
2477 /* setup the connection */
2478 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2479 &rm_addr, 0, "IPC$", "IPC",
2480 "", /* username */
2481 "", /* domain */
2482 "", /* password */
2483 0, lp_client_signing());
2485 if ( !NT_STATUS_IS_OK( ret ) ) {
2486 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2487 remote_machine ));
2488 return false;
2491 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2492 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2493 cli_shutdown(the_cli);
2494 return false;
2498 * Ok - we have an anonymous connection to the IPC$ share.
2499 * Now start the NT Domain stuff :-).
2502 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2503 if (!NT_STATUS_IS_OK(ret)) {
2504 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2505 remote_machine, nt_errstr(ret)));
2506 cli_shutdown(the_cli);
2507 return false;
2510 return true;
2513 /***************************************************************************
2514 Connect to the client.
2515 ****************************************************************************/
2517 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2518 uint32_t localprinter,
2519 enum winreg_Type type,
2520 struct policy_handle *handle,
2521 struct notify_back_channel **_chan,
2522 struct sockaddr_storage *client_ss,
2523 struct messaging_context *msg_ctx)
2525 WERROR result;
2526 NTSTATUS status;
2527 struct notify_back_channel *chan;
2529 for (chan = back_channels; chan; chan = chan->next) {
2530 if (memcmp(&chan->client_address, client_ss,
2531 sizeof(struct sockaddr_storage)) == 0) {
2532 break;
2537 * If it's the first connection, contact the client
2538 * and connect to the IPC$ share anonymously
2540 if (!chan) {
2541 fstring unix_printer;
2543 /* the +2 is to strip the leading 2 backslashs */
2544 fstrcpy(unix_printer, printer + 2);
2546 chan = talloc_zero(back_channels, struct notify_back_channel);
2547 if (!chan) {
2548 return false;
2550 chan->client_address = *client_ss;
2552 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2553 TALLOC_FREE(chan);
2554 return false;
2556 chan->binding_handle = chan->cli_pipe->binding_handle;
2558 DLIST_ADD(back_channels, chan);
2560 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2561 receive_notify2_message_list);
2562 /* Tell the connections db we're now interested in printer
2563 * notify messages. */
2564 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2565 true, FLAG_MSG_PRINT_NOTIFY);
2569 * Tell the specific printing tdb we want messages for this printer
2570 * by registering our PID.
2573 if (!print_notify_register_pid(snum)) {
2574 DEBUG(0, ("Failed to register our pid for printer %s\n",
2575 printer));
2578 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2579 talloc_tos(),
2580 printer,
2581 localprinter,
2582 type,
2584 NULL,
2585 handle,
2586 &result);
2587 if (!NT_STATUS_IS_OK(status)) {
2588 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2589 result = ntstatus_to_werror(status);
2590 } else if (!W_ERROR_IS_OK(result)) {
2591 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2594 chan->active_connections++;
2595 *_chan = chan;
2597 return (W_ERROR_IS_OK(result));
2600 /****************************************************************
2601 ****************************************************************/
2603 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2604 const struct spoolss_NotifyOption *r)
2606 struct spoolss_NotifyOption *option;
2607 uint32_t i,k;
2609 if (!r) {
2610 return NULL;
2613 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2614 if (!option) {
2615 return NULL;
2618 *option = *r;
2620 if (!option->count) {
2621 return option;
2624 option->types = talloc_zero_array(option,
2625 struct spoolss_NotifyOptionType, option->count);
2626 if (!option->types) {
2627 talloc_free(option);
2628 return NULL;
2631 for (i=0; i < option->count; i++) {
2632 option->types[i] = r->types[i];
2634 if (option->types[i].count) {
2635 option->types[i].fields = talloc_zero_array(option,
2636 union spoolss_Field, option->types[i].count);
2637 if (!option->types[i].fields) {
2638 talloc_free(option);
2639 return NULL;
2641 for (k=0; k<option->types[i].count; k++) {
2642 option->types[i].fields[k] =
2643 r->types[i].fields[k];
2648 return option;
2651 /****************************************************************
2652 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2654 * before replying OK: status=0 a rpc call is made to the workstation
2655 * asking ReplyOpenPrinter
2657 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2658 * called from api_spoolss_rffpcnex
2659 ****************************************************************/
2661 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2662 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2664 int snum = -1;
2665 struct spoolss_NotifyOption *option = r->in.notify_options;
2666 struct sockaddr_storage client_ss;
2668 /* store the notify value in the printer struct */
2670 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2672 if (!Printer) {
2673 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2674 "Invalid handle (%s:%u:%u).\n",
2675 OUR_HANDLE(r->in.handle)));
2676 return WERR_BADFID;
2679 Printer->notify.flags = r->in.flags;
2680 Printer->notify.options = r->in.options;
2681 Printer->notify.printerlocal = r->in.printer_local;
2682 Printer->notify.msg_ctx = p->msg_ctx;
2684 TALLOC_FREE(Printer->notify.option);
2685 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2687 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2689 /* Connect to the client machine and send a ReplyOpenPrinter */
2691 if ( Printer->printer_type == SPLHND_SERVER)
2692 snum = -1;
2693 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2694 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2695 return WERR_BADFID;
2697 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698 "client_address is %s\n", p->client_id->addr));
2700 if (!lp_print_notify_backchannel(snum)) {
2701 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2702 "backchannel disabled\n"));
2703 return WERR_SERVER_UNAVAILABLE;
2706 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2707 AI_NUMERICHOST)) {
2708 return WERR_SERVER_UNAVAILABLE;
2711 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2712 Printer->notify.printerlocal, REG_SZ,
2713 &Printer->notify.cli_hnd,
2714 &Printer->notify.cli_chan,
2715 &client_ss, p->msg_ctx)) {
2716 return WERR_SERVER_UNAVAILABLE;
2719 return WERR_OK;
2722 /*******************************************************************
2723 * fill a notify_info_data with the servername
2724 ********************************************************************/
2726 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2727 int snum,
2728 struct spoolss_Notify *data,
2729 print_queue_struct *queue,
2730 struct spoolss_PrinterInfo2 *pinfo2,
2731 TALLOC_CTX *mem_ctx)
2733 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2736 /*******************************************************************
2737 * fill a notify_info_data with the printername (not including the servername).
2738 ********************************************************************/
2740 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2741 int snum,
2742 struct spoolss_Notify *data,
2743 print_queue_struct *queue,
2744 struct spoolss_PrinterInfo2 *pinfo2,
2745 TALLOC_CTX *mem_ctx)
2747 /* the notify name should not contain the \\server\ part */
2748 const char *p = strrchr(pinfo2->printername, '\\');
2750 if (!p) {
2751 p = pinfo2->printername;
2752 } else {
2753 p++;
2756 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2759 /*******************************************************************
2760 * fill a notify_info_data with the servicename
2761 ********************************************************************/
2763 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2764 int snum,
2765 struct spoolss_Notify *data,
2766 print_queue_struct *queue,
2767 struct spoolss_PrinterInfo2 *pinfo2,
2768 TALLOC_CTX *mem_ctx)
2770 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2773 /*******************************************************************
2774 * fill a notify_info_data with the port name
2775 ********************************************************************/
2777 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2778 int snum,
2779 struct spoolss_Notify *data,
2780 print_queue_struct *queue,
2781 struct spoolss_PrinterInfo2 *pinfo2,
2782 TALLOC_CTX *mem_ctx)
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2787 /*******************************************************************
2788 * fill a notify_info_data with the printername
2789 * but it doesn't exist, have to see what to do
2790 ********************************************************************/
2792 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2793 int snum,
2794 struct spoolss_Notify *data,
2795 print_queue_struct *queue,
2796 struct spoolss_PrinterInfo2 *pinfo2,
2797 TALLOC_CTX *mem_ctx)
2799 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2802 /*******************************************************************
2803 * fill a notify_info_data with the comment
2804 ********************************************************************/
2806 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2807 int snum,
2808 struct spoolss_Notify *data,
2809 print_queue_struct *queue,
2810 struct spoolss_PrinterInfo2 *pinfo2,
2811 TALLOC_CTX *mem_ctx)
2813 const char *p;
2815 if (*pinfo2->comment == '\0') {
2816 p = lp_comment(snum);
2817 } else {
2818 p = pinfo2->comment;
2821 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2824 /*******************************************************************
2825 * fill a notify_info_data with the comment
2826 * location = "Room 1, floor 2, building 3"
2827 ********************************************************************/
2829 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2830 int snum,
2831 struct spoolss_Notify *data,
2832 print_queue_struct *queue,
2833 struct spoolss_PrinterInfo2 *pinfo2,
2834 TALLOC_CTX *mem_ctx)
2836 const char *loc = pinfo2->location;
2837 NTSTATUS status;
2839 status = printer_list_get_printer(mem_ctx,
2840 pinfo2->sharename,
2841 NULL,
2842 &loc,
2843 NULL);
2844 if (NT_STATUS_IS_OK(status)) {
2845 if (loc == NULL) {
2846 loc = pinfo2->location;
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2853 /*******************************************************************
2854 * fill a notify_info_data with the device mode
2855 * jfm:xxxx don't to it for know but that's a real problem !!!
2856 ********************************************************************/
2858 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2859 int snum,
2860 struct spoolss_Notify *data,
2861 print_queue_struct *queue,
2862 struct spoolss_PrinterInfo2 *pinfo2,
2863 TALLOC_CTX *mem_ctx)
2865 /* for a dummy implementation we have to zero the fields */
2866 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2869 /*******************************************************************
2870 * fill a notify_info_data with the separator file name
2871 ********************************************************************/
2873 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2874 int snum,
2875 struct spoolss_Notify *data,
2876 print_queue_struct *queue,
2877 struct spoolss_PrinterInfo2 *pinfo2,
2878 TALLOC_CTX *mem_ctx)
2880 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2883 /*******************************************************************
2884 * fill a notify_info_data with the print processor
2885 * jfm:xxxx return always winprint to indicate we don't do anything to it
2886 ********************************************************************/
2888 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2889 int snum,
2890 struct spoolss_Notify *data,
2891 print_queue_struct *queue,
2892 struct spoolss_PrinterInfo2 *pinfo2,
2893 TALLOC_CTX *mem_ctx)
2895 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2898 /*******************************************************************
2899 * fill a notify_info_data with the print processor options
2900 * jfm:xxxx send an empty string
2901 ********************************************************************/
2903 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2904 int snum,
2905 struct spoolss_Notify *data,
2906 print_queue_struct *queue,
2907 struct spoolss_PrinterInfo2 *pinfo2,
2908 TALLOC_CTX *mem_ctx)
2910 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2913 /*******************************************************************
2914 * fill a notify_info_data with the data type
2915 * jfm:xxxx always send RAW as data type
2916 ********************************************************************/
2918 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2919 int snum,
2920 struct spoolss_Notify *data,
2921 print_queue_struct *queue,
2922 struct spoolss_PrinterInfo2 *pinfo2,
2923 TALLOC_CTX *mem_ctx)
2925 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2928 /*******************************************************************
2929 * fill a notify_info_data with the security descriptor
2930 * jfm:xxxx send an null pointer to say no security desc
2931 * have to implement security before !
2932 ********************************************************************/
2934 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2935 int snum,
2936 struct spoolss_Notify *data,
2937 print_queue_struct *queue,
2938 struct spoolss_PrinterInfo2 *pinfo2,
2939 TALLOC_CTX *mem_ctx)
2941 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2944 /*******************************************************************
2945 * fill a notify_info_data with the attributes
2946 * jfm:xxxx a samba printer is always shared
2947 ********************************************************************/
2949 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2950 int snum,
2951 struct spoolss_Notify *data,
2952 print_queue_struct *queue,
2953 struct spoolss_PrinterInfo2 *pinfo2,
2954 TALLOC_CTX *mem_ctx)
2956 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2959 /*******************************************************************
2960 * fill a notify_info_data with the priority
2961 ********************************************************************/
2963 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2964 int snum,
2965 struct spoolss_Notify *data,
2966 print_queue_struct *queue,
2967 struct spoolss_PrinterInfo2 *pinfo2,
2968 TALLOC_CTX *mem_ctx)
2970 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2973 /*******************************************************************
2974 * fill a notify_info_data with the default priority
2975 ********************************************************************/
2977 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2978 int snum,
2979 struct spoolss_Notify *data,
2980 print_queue_struct *queue,
2981 struct spoolss_PrinterInfo2 *pinfo2,
2982 TALLOC_CTX *mem_ctx)
2984 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2987 /*******************************************************************
2988 * fill a notify_info_data with the start time
2989 ********************************************************************/
2991 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2992 int snum,
2993 struct spoolss_Notify *data,
2994 print_queue_struct *queue,
2995 struct spoolss_PrinterInfo2 *pinfo2,
2996 TALLOC_CTX *mem_ctx)
2998 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3001 /*******************************************************************
3002 * fill a notify_info_data with the until time
3003 ********************************************************************/
3005 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3006 int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 struct spoolss_PrinterInfo2 *pinfo2,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3015 /*******************************************************************
3016 * fill a notify_info_data with the status
3017 ********************************************************************/
3019 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3020 int snum,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 struct spoolss_PrinterInfo2 *pinfo2,
3024 TALLOC_CTX *mem_ctx)
3026 print_status_struct status;
3028 print_queue_length(msg_ctx, snum, &status);
3029 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3032 /*******************************************************************
3033 * fill a notify_info_data with the number of jobs queued
3034 ********************************************************************/
3036 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3037 int snum,
3038 struct spoolss_Notify *data,
3039 print_queue_struct *queue,
3040 struct spoolss_PrinterInfo2 *pinfo2,
3041 TALLOC_CTX *mem_ctx)
3043 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3044 data, print_queue_length(msg_ctx, snum, NULL));
3047 /*******************************************************************
3048 * fill a notify_info_data with the average ppm
3049 ********************************************************************/
3051 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3052 int snum,
3053 struct spoolss_Notify *data,
3054 print_queue_struct *queue,
3055 struct spoolss_PrinterInfo2 *pinfo2,
3056 TALLOC_CTX *mem_ctx)
3058 /* always respond 8 pages per minutes */
3059 /* a little hard ! */
3060 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3063 /*******************************************************************
3064 * fill a notify_info_data with username
3065 ********************************************************************/
3067 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3068 int snum,
3069 struct spoolss_Notify *data,
3070 print_queue_struct *queue,
3071 struct spoolss_PrinterInfo2 *pinfo2,
3072 TALLOC_CTX *mem_ctx)
3074 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3082 int snum,
3083 struct spoolss_Notify *data,
3084 print_queue_struct *queue,
3085 struct spoolss_PrinterInfo2 *pinfo2,
3086 TALLOC_CTX *mem_ctx)
3088 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3091 /*******************************************************************
3092 * fill a notify_info_data with job name
3093 ********************************************************************/
3095 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3096 int snum,
3097 struct spoolss_Notify *data,
3098 print_queue_struct *queue,
3099 struct spoolss_PrinterInfo2 *pinfo2,
3100 TALLOC_CTX *mem_ctx)
3102 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3105 /*******************************************************************
3106 * fill a notify_info_data with job status
3107 ********************************************************************/
3109 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3110 int snum,
3111 struct spoolss_Notify *data,
3112 print_queue_struct *queue,
3113 struct spoolss_PrinterInfo2 *pinfo2,
3114 TALLOC_CTX *mem_ctx)
3117 * Now we're returning job status codes we just return a "" here. JRA.
3120 const char *p = "";
3122 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3123 p = "unknown";
3125 switch (queue->status) {
3126 case LPQ_QUEUED:
3127 p = "Queued";
3128 break;
3129 case LPQ_PAUSED:
3130 p = ""; /* NT provides the paused string */
3131 break;
3132 case LPQ_SPOOLING:
3133 p = "Spooling";
3134 break;
3135 case LPQ_PRINTING:
3136 p = "Printing";
3137 break;
3139 #endif /* NO LONGER NEEDED. */
3141 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3144 /*******************************************************************
3145 * fill a notify_info_data with job time
3146 ********************************************************************/
3148 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3149 int snum,
3150 struct spoolss_Notify *data,
3151 print_queue_struct *queue,
3152 struct spoolss_PrinterInfo2 *pinfo2,
3153 TALLOC_CTX *mem_ctx)
3155 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3158 /*******************************************************************
3159 * fill a notify_info_data with job size
3160 ********************************************************************/
3162 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3163 int snum,
3164 struct spoolss_Notify *data,
3165 print_queue_struct *queue,
3166 struct spoolss_PrinterInfo2 *pinfo2,
3167 TALLOC_CTX *mem_ctx)
3169 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3172 /*******************************************************************
3173 * fill a notify_info_data with page info
3174 ********************************************************************/
3175 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3176 int snum,
3177 struct spoolss_Notify *data,
3178 print_queue_struct *queue,
3179 struct spoolss_PrinterInfo2 *pinfo2,
3180 TALLOC_CTX *mem_ctx)
3182 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3185 /*******************************************************************
3186 * fill a notify_info_data with pages printed info.
3187 ********************************************************************/
3188 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3189 int snum,
3190 struct spoolss_Notify *data,
3191 print_queue_struct *queue,
3192 struct spoolss_PrinterInfo2 *pinfo2,
3193 TALLOC_CTX *mem_ctx)
3195 /* Add code when back-end tracks this */
3196 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3199 /*******************************************************************
3200 Fill a notify_info_data with job position.
3201 ********************************************************************/
3203 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3204 int snum,
3205 struct spoolss_Notify *data,
3206 print_queue_struct *queue,
3207 struct spoolss_PrinterInfo2 *pinfo2,
3208 TALLOC_CTX *mem_ctx)
3210 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3213 /*******************************************************************
3214 Fill a notify_info_data with submitted time.
3215 ********************************************************************/
3217 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3218 int snum,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 struct spoolss_PrinterInfo2 *pinfo2,
3222 TALLOC_CTX *mem_ctx)
3224 data->data.string.string = NULL;
3225 data->data.string.size = 0;
3227 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3228 &data->data.string.string,
3229 &data->data.string.size);
3233 struct s_notify_info_data_table
3235 enum spoolss_NotifyType type;
3236 uint16_t field;
3237 const char *name;
3238 enum spoolss_NotifyTable variable_type;
3239 void (*fn) (struct messaging_context *msg_ctx,
3240 int snum, struct spoolss_Notify *data,
3241 print_queue_struct *queue,
3242 struct spoolss_PrinterInfo2 *pinfo2,
3243 TALLOC_CTX *mem_ctx);
3246 /* A table describing the various print notification constants and
3247 whether the notification data is a pointer to a variable sized
3248 buffer, a one value uint32_t or a two value uint32_t. */
3250 static const struct s_notify_info_data_table notify_info_data_table[] =
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3303 /*******************************************************************
3304 Return the variable_type of info_data structure.
3305 ********************************************************************/
3307 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3308 uint16_t field)
3310 int i=0;
3312 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3313 if ( (notify_info_data_table[i].type == type) &&
3314 (notify_info_data_table[i].field == field) ) {
3315 return notify_info_data_table[i].variable_type;
3319 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3321 return (enum spoolss_NotifyTable) 0;
3324 /****************************************************************************
3325 ****************************************************************************/
3327 static bool search_notify(enum spoolss_NotifyType type,
3328 uint16_t field,
3329 int *value)
3331 int i;
3333 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3334 if (notify_info_data_table[i].type == type &&
3335 notify_info_data_table[i].field == field &&
3336 notify_info_data_table[i].fn != NULL) {
3337 *value = i;
3338 return true;
3342 return false;
3345 /****************************************************************************
3346 ****************************************************************************/
3348 static void construct_info_data(struct spoolss_Notify *info_data,
3349 enum spoolss_NotifyType type,
3350 uint16_t field, int id)
3352 info_data->type = type;
3353 info_data->field.field = field;
3354 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3355 info_data->job_id = id;
3358 /*******************************************************************
3360 * fill a notify_info struct with info asked
3362 ********************************************************************/
3364 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3365 struct printer_handle *print_hnd,
3366 struct spoolss_NotifyInfo *info,
3367 struct spoolss_PrinterInfo2 *pinfo2,
3368 int snum,
3369 const struct spoolss_NotifyOptionType *option_type,
3370 uint32_t id,
3371 TALLOC_CTX *mem_ctx)
3373 int field_num,j;
3374 enum spoolss_NotifyType type;
3375 uint16_t field;
3377 struct spoolss_Notify *current_data;
3379 type = option_type->type;
3381 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3382 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3383 option_type->count, lp_servicename(snum)));
3385 for(field_num=0; field_num < option_type->count; field_num++) {
3386 field = option_type->fields[field_num].field;
3388 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3390 if (!search_notify(type, field, &j) )
3391 continue;
3393 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3394 struct spoolss_Notify,
3395 info->count + 1);
3396 if (info->notifies == NULL) {
3397 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3398 return false;
3401 current_data = &info->notifies[info->count];
3403 construct_info_data(current_data, type, field, id);
3405 DEBUG(10, ("construct_notify_printer_info: "
3406 "calling [%s] snum=%d printername=[%s])\n",
3407 notify_info_data_table[j].name, snum,
3408 pinfo2->printername));
3410 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3411 NULL, pinfo2, mem_ctx);
3413 info->count++;
3416 return true;
3419 /*******************************************************************
3421 * fill a notify_info struct with info asked
3423 ********************************************************************/
3425 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3426 print_queue_struct *queue,
3427 struct spoolss_NotifyInfo *info,
3428 struct spoolss_PrinterInfo2 *pinfo2,
3429 int snum,
3430 const struct spoolss_NotifyOptionType *option_type,
3431 uint32_t id,
3432 TALLOC_CTX *mem_ctx)
3434 int field_num,j;
3435 enum spoolss_NotifyType type;
3436 uint16_t field;
3437 struct spoolss_Notify *current_data;
3439 DEBUG(4,("construct_notify_jobs_info\n"));
3441 type = option_type->type;
3443 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3444 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3445 option_type->count));
3447 for(field_num=0; field_num<option_type->count; field_num++) {
3448 field = option_type->fields[field_num].field;
3450 if (!search_notify(type, field, &j) )
3451 continue;
3453 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3454 struct spoolss_Notify,
3455 info->count + 1);
3456 if (info->notifies == NULL) {
3457 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3458 return false;
3461 current_data=&(info->notifies[info->count]);
3463 construct_info_data(current_data, type, field, id);
3464 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3465 queue, pinfo2, mem_ctx);
3466 info->count++;
3469 return true;
3473 * JFM: The enumeration is not that simple, it's even non obvious.
3475 * let's take an example: I want to monitor the PRINTER SERVER for
3476 * the printer's name and the number of jobs currently queued.
3477 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3478 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3480 * I have 3 printers on the back of my server.
3482 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3483 * structures.
3484 * Number Data Id
3485 * 1 printer 1 name 1
3486 * 2 printer 1 cjob 1
3487 * 3 printer 2 name 2
3488 * 4 printer 2 cjob 2
3489 * 5 printer 3 name 3
3490 * 6 printer 3 name 3
3492 * that's the print server case, the printer case is even worse.
3495 /*******************************************************************
3497 * enumerate all printers on the printserver
3498 * fill a notify_info struct with info asked
3500 ********************************************************************/
3502 static WERROR printserver_notify_info(struct pipes_struct *p,
3503 struct policy_handle *hnd,
3504 struct spoolss_NotifyInfo *info,
3505 TALLOC_CTX *mem_ctx)
3507 int snum;
3508 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3509 int n_services=lp_numservices();
3510 int i;
3511 struct spoolss_NotifyOption *option;
3512 struct spoolss_NotifyOptionType option_type;
3513 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3514 WERROR result;
3516 DEBUG(4,("printserver_notify_info\n"));
3518 if (!Printer)
3519 return WERR_BADFID;
3521 option = Printer->notify.option;
3523 info->version = 2;
3524 info->notifies = NULL;
3525 info->count = 0;
3527 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3528 sending a ffpcn() request first */
3530 if ( !option )
3531 return WERR_BADFID;
3533 for (i=0; i<option->count; i++) {
3534 option_type = option->types[i];
3536 if (option_type.type != PRINTER_NOTIFY_TYPE)
3537 continue;
3539 for (snum = 0; snum < n_services; snum++) {
3540 if (!lp_browseable(snum) ||
3541 !lp_snum_ok(snum) ||
3542 !lp_print_ok(snum)) {
3543 continue; /* skip */
3546 /* Maybe we should use the SYSTEM session_info here... */
3547 result = winreg_get_printer_internal(mem_ctx,
3548 get_session_info_system(),
3549 p->msg_ctx,
3550 lp_servicename(snum),
3551 &pinfo2);
3552 if (!W_ERROR_IS_OK(result)) {
3553 DEBUG(4, ("printserver_notify_info: "
3554 "Failed to get printer [%s]\n",
3555 lp_servicename(snum)));
3556 continue;
3560 construct_notify_printer_info(p->msg_ctx,
3561 Printer, info,
3562 pinfo2, snum,
3563 &option_type, snum,
3564 mem_ctx);
3566 TALLOC_FREE(pinfo2);
3570 #if 0
3572 * Debugging information, don't delete.
3575 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3576 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3577 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3579 for (i=0; i<info->count; i++) {
3580 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3581 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3582 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3584 #endif
3586 return WERR_OK;
3589 /*******************************************************************
3591 * fill a notify_info struct with info asked
3593 ********************************************************************/
3595 static WERROR printer_notify_info(struct pipes_struct *p,
3596 struct policy_handle *hnd,
3597 struct spoolss_NotifyInfo *info,
3598 TALLOC_CTX *mem_ctx)
3600 int snum;
3601 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3602 int i;
3603 uint32_t id;
3604 struct spoolss_NotifyOption *option;
3605 struct spoolss_NotifyOptionType option_type;
3606 int count,j;
3607 print_queue_struct *queue=NULL;
3608 print_status_struct status;
3609 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3610 WERROR result;
3612 DEBUG(4,("printer_notify_info\n"));
3614 if (!Printer)
3615 return WERR_BADFID;
3617 option = Printer->notify.option;
3618 id = 0x0;
3620 info->version = 2;
3621 info->notifies = NULL;
3622 info->count = 0;
3624 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3625 sending a ffpcn() request first */
3627 if ( !option )
3628 return WERR_BADFID;
3630 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3631 return WERR_BADFID;
3634 /* Maybe we should use the SYSTEM session_info here... */
3635 result = winreg_get_printer_internal(mem_ctx,
3636 get_session_info_system(),
3637 p->msg_ctx,
3638 lp_servicename(snum), &pinfo2);
3639 if (!W_ERROR_IS_OK(result)) {
3640 return WERR_BADFID;
3644 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3645 * correct servername.
3647 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3648 if (pinfo2->servername == NULL) {
3649 return WERR_NOMEM;
3652 for (i=0; i<option->count; i++) {
3653 option_type = option->types[i];
3655 switch (option_type.type) {
3656 case PRINTER_NOTIFY_TYPE:
3657 if (construct_notify_printer_info(p->msg_ctx,
3658 Printer, info,
3659 pinfo2, snum,
3660 &option_type, id,
3661 mem_ctx)) {
3662 id--;
3664 break;
3666 case JOB_NOTIFY_TYPE:
3668 count = print_queue_status(p->msg_ctx, snum, &queue,
3669 &status);
3671 for (j=0; j<count; j++) {
3672 construct_notify_jobs_info(p->msg_ctx,
3673 &queue[j], info,
3674 pinfo2, snum,
3675 &option_type,
3676 queue[j].sysjob,
3677 mem_ctx);
3680 SAFE_FREE(queue);
3681 break;
3686 * Debugging information, don't delete.
3689 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3690 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3691 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3693 for (i=0; i<info->count; i++) {
3694 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3695 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3696 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3700 talloc_free(pinfo2);
3701 return WERR_OK;
3704 /****************************************************************
3705 _spoolss_RouterRefreshPrinterChangeNotify
3706 ****************************************************************/
3708 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3709 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3711 struct spoolss_NotifyInfo *info;
3713 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3714 WERROR result = WERR_BADFID;
3716 /* we always have a spoolss_NotifyInfo struct */
3717 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3718 if (!info) {
3719 result = WERR_NOMEM;
3720 goto done;
3723 *r->out.info = info;
3725 if (!Printer) {
3726 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3727 "Invalid handle (%s:%u:%u).\n",
3728 OUR_HANDLE(r->in.handle)));
3729 goto done;
3732 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3735 * We are now using the change value, and
3736 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3737 * I don't have a global notification system, I'm sending back all the
3738 * information even when _NOTHING_ has changed.
3741 /* We need to keep track of the change value to send back in
3742 RRPCN replies otherwise our updates are ignored. */
3744 Printer->notify.fnpcn = true;
3746 if (Printer->notify.cli_chan != NULL &&
3747 Printer->notify.cli_chan->active_connections > 0) {
3748 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3749 "Saving change value in request [%x]\n",
3750 r->in.change_low));
3751 Printer->notify.change = r->in.change_low;
3754 /* just ignore the spoolss_NotifyOption */
3756 switch (Printer->printer_type) {
3757 case SPLHND_SERVER:
3758 result = printserver_notify_info(p, r->in.handle,
3759 info, p->mem_ctx);
3760 break;
3762 case SPLHND_PRINTER:
3763 result = printer_notify_info(p, r->in.handle,
3764 info, p->mem_ctx);
3765 break;
3768 Printer->notify.fnpcn = false;
3770 done:
3771 return result;
3774 /********************************************************************
3775 ********************************************************************/
3777 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3778 const char *servername,
3779 const char *printername,
3780 const char **printername_p)
3782 /* FIXME: add lp_force_printername() */
3784 if (servername == NULL) {
3785 *printername_p = talloc_strdup(mem_ctx, printername);
3786 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3787 return WERR_OK;
3790 if (servername[0] == '\\' && servername[1] == '\\') {
3791 servername += 2;
3794 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3795 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3797 return WERR_OK;
3800 /********************************************************************
3801 ********************************************************************/
3803 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3804 const char *printername)
3806 if (dm == NULL) {
3807 return;
3810 dm->devicename = talloc_strndup(dm, printername,
3811 MIN(strlen(printername), 31));
3814 /********************************************************************
3815 * construct_printer_info_0
3816 * fill a printer_info_0 struct
3817 ********************************************************************/
3819 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3820 const struct auth_serversupplied_info *session_info,
3821 struct messaging_context *msg_ctx,
3822 struct spoolss_PrinterInfo2 *info2,
3823 const char *servername,
3824 struct spoolss_PrinterInfo0 *r,
3825 int snum)
3827 int count;
3828 struct printer_session_counter *session_counter;
3829 struct timeval setuptime;
3830 print_status_struct status;
3831 WERROR result;
3833 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3834 if (!W_ERROR_IS_OK(result)) {
3835 return result;
3838 if (servername) {
3839 r->servername = talloc_strdup(mem_ctx, servername);
3840 W_ERROR_HAVE_NO_MEMORY(r->servername);
3841 } else {
3842 r->servername = NULL;
3845 count = print_queue_length(msg_ctx, snum, &status);
3847 /* check if we already have a counter for this printer */
3848 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3849 if (session_counter->snum == snum)
3850 break;
3853 /* it's the first time, add it to the list */
3854 if (session_counter == NULL) {
3855 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3856 W_ERROR_HAVE_NO_MEMORY(session_counter);
3857 session_counter->snum = snum;
3858 session_counter->counter = 0;
3859 DLIST_ADD(counter_list, session_counter);
3862 /* increment it */
3863 session_counter->counter++;
3865 r->cjobs = count;
3866 r->total_jobs = 0;
3867 r->total_bytes = 0;
3869 get_startup_time(&setuptime);
3870 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3872 /* JFM:
3873 * the global_counter should be stored in a TDB as it's common to all the clients
3874 * and should be zeroed on samba startup
3876 r->global_counter = session_counter->counter;
3877 r->total_pages = 0;
3878 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3879 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3880 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3881 r->free_build = SPOOLSS_RELEASE_BUILD;
3882 r->spooling = 0;
3883 r->max_spooling = 0;
3884 r->session_counter = session_counter->counter;
3885 r->num_error_out_of_paper = 0x0;
3886 r->num_error_not_ready = 0x0; /* number of print failure */
3887 r->job_error = 0x0;
3888 r->number_of_processors = 0x1;
3889 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3890 r->high_part_total_bytes = 0x0;
3892 /* ChangeID in milliseconds*/
3893 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3894 info2->sharename, &r->change_id);
3896 r->last_error = WERR_OK;
3897 r->status = nt_printq_status(status.status);
3898 r->enumerate_network_printers = 0x0;
3899 r->c_setprinter = 0x0;
3900 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3901 r->processor_level = 0x6; /* 6 ???*/
3902 r->ref_ic = 0;
3903 r->reserved2 = 0;
3904 r->reserved3 = 0;
3906 return WERR_OK;
3910 /********************************************************************
3911 * construct_printer_info1
3912 * fill a spoolss_PrinterInfo1 struct
3913 ********************************************************************/
3915 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3916 const struct spoolss_PrinterInfo2 *info2,
3917 uint32_t flags,
3918 const char *servername,
3919 struct spoolss_PrinterInfo1 *r,
3920 int snum)
3922 WERROR result;
3924 r->flags = flags;
3926 if (info2->comment == NULL || info2->comment[0] == '\0') {
3927 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3928 } else {
3929 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3931 W_ERROR_HAVE_NO_MEMORY(r->comment);
3933 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3934 if (!W_ERROR_IS_OK(result)) {
3935 return result;
3938 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3939 r->name,
3940 info2->drivername,
3941 r->comment);
3942 W_ERROR_HAVE_NO_MEMORY(r->description);
3944 return WERR_OK;
3947 /********************************************************************
3948 * construct_printer_info2
3949 * fill a spoolss_PrinterInfo2 struct
3950 ********************************************************************/
3952 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3953 struct messaging_context *msg_ctx,
3954 const struct spoolss_PrinterInfo2 *info2,
3955 const char *servername,
3956 struct spoolss_PrinterInfo2 *r,
3957 int snum)
3959 int count;
3960 print_status_struct status;
3961 WERROR result;
3963 count = print_queue_length(msg_ctx, snum, &status);
3965 if (servername) {
3966 r->servername = talloc_strdup(mem_ctx, servername);
3967 W_ERROR_HAVE_NO_MEMORY(r->servername);
3968 } else {
3969 r->servername = NULL;
3972 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3973 if (!W_ERROR_IS_OK(result)) {
3974 return result;
3977 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3978 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3979 r->portname = talloc_strdup(mem_ctx, info2->portname);
3980 W_ERROR_HAVE_NO_MEMORY(r->portname);
3981 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3982 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3984 if (info2->comment[0] == '\0') {
3985 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3986 } else {
3987 r->comment = talloc_strdup(mem_ctx, info2->comment);
3989 W_ERROR_HAVE_NO_MEMORY(r->comment);
3991 r->location = talloc_strdup(mem_ctx, info2->location);
3992 if (info2->location[0] == '\0') {
3993 const char *loc = NULL;
3994 NTSTATUS nt_status;
3996 nt_status = printer_list_get_printer(mem_ctx,
3997 info2->sharename,
3998 NULL,
3999 &loc,
4000 NULL);
4001 if (NT_STATUS_IS_OK(nt_status)) {
4002 if (loc != NULL) {
4003 r->location = talloc_strdup(mem_ctx, loc);
4007 W_ERROR_HAVE_NO_MEMORY(r->location);
4009 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4010 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4011 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4012 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4013 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4014 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4015 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4016 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4018 r->attributes = info2->attributes;
4020 r->priority = info2->priority;
4021 r->defaultpriority = info2->defaultpriority;
4022 r->starttime = info2->starttime;
4023 r->untiltime = info2->untiltime;
4024 r->status = nt_printq_status(status.status);
4025 r->cjobs = count;
4026 r->averageppm = info2->averageppm;
4028 if (info2->devmode != NULL) {
4029 result = copy_devicemode(mem_ctx,
4030 info2->devmode,
4031 &r->devmode);
4032 if (!W_ERROR_IS_OK(result)) {
4033 return result;
4035 } else if (lp_default_devmode(snum)) {
4036 result = spoolss_create_default_devmode(mem_ctx,
4037 info2->printername,
4038 &r->devmode);
4039 if (!W_ERROR_IS_OK(result)) {
4040 return result;
4042 } else {
4043 r->devmode = NULL;
4044 DEBUG(8,("Returning NULL Devicemode!\n"));
4047 compose_devicemode_devicename(r->devmode, r->printername);
4049 r->secdesc = NULL;
4051 if (info2->secdesc != NULL) {
4052 /* don't use talloc_steal() here unless you do a deep steal of all
4053 the SEC_DESC members */
4055 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4058 return WERR_OK;
4061 /********************************************************************
4062 * construct_printer_info3
4063 * fill a spoolss_PrinterInfo3 struct
4064 ********************************************************************/
4066 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4067 const struct spoolss_PrinterInfo2 *info2,
4068 const char *servername,
4069 struct spoolss_PrinterInfo3 *r,
4070 int snum)
4072 /* These are the components of the SD we are returning. */
4074 if (info2->secdesc != NULL) {
4075 /* don't use talloc_steal() here unless you do a deep steal of all
4076 the SEC_DESC members */
4078 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4079 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4082 return WERR_OK;
4085 /********************************************************************
4086 * construct_printer_info4
4087 * fill a spoolss_PrinterInfo4 struct
4088 ********************************************************************/
4090 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4091 const struct spoolss_PrinterInfo2 *info2,
4092 const char *servername,
4093 struct spoolss_PrinterInfo4 *r,
4094 int snum)
4096 WERROR result;
4098 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4099 if (!W_ERROR_IS_OK(result)) {
4100 return result;
4103 if (servername) {
4104 r->servername = talloc_strdup(mem_ctx, servername);
4105 W_ERROR_HAVE_NO_MEMORY(r->servername);
4106 } else {
4107 r->servername = NULL;
4110 r->attributes = info2->attributes;
4112 return WERR_OK;
4115 /********************************************************************
4116 * construct_printer_info5
4117 * fill a spoolss_PrinterInfo5 struct
4118 ********************************************************************/
4120 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4121 const struct spoolss_PrinterInfo2 *info2,
4122 const char *servername,
4123 struct spoolss_PrinterInfo5 *r,
4124 int snum)
4126 WERROR result;
4128 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4129 if (!W_ERROR_IS_OK(result)) {
4130 return result;
4133 r->portname = talloc_strdup(mem_ctx, info2->portname);
4134 W_ERROR_HAVE_NO_MEMORY(r->portname);
4136 r->attributes = info2->attributes;
4138 /* these two are not used by NT+ according to MSDN */
4139 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4140 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4142 return WERR_OK;
4145 /********************************************************************
4146 * construct_printer_info_6
4147 * fill a spoolss_PrinterInfo6 struct
4148 ********************************************************************/
4150 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4151 struct messaging_context *msg_ctx,
4152 const struct spoolss_PrinterInfo2 *info2,
4153 const char *servername,
4154 struct spoolss_PrinterInfo6 *r,
4155 int snum)
4157 int count;
4158 print_status_struct status;
4160 count = print_queue_length(msg_ctx, snum, &status);
4162 r->status = nt_printq_status(status.status);
4164 return WERR_OK;
4167 /********************************************************************
4168 * construct_printer_info7
4169 * fill a spoolss_PrinterInfo7 struct
4170 ********************************************************************/
4172 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4173 struct messaging_context *msg_ctx,
4174 const char *servername,
4175 struct spoolss_PrinterInfo7 *r,
4176 int snum)
4178 struct auth_serversupplied_info *session_info;
4179 struct GUID guid;
4180 NTSTATUS status;
4182 status = make_session_info_system(mem_ctx, &session_info);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 DEBUG(0, ("construct_printer_info7: "
4185 "Could not create system session_info\n"));
4186 return WERR_NOMEM;
4189 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4190 servername,
4191 lp_servicename(snum), &guid, NULL)) {
4192 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4193 r->action = DSPRINT_PUBLISH;
4194 } else {
4195 r->guid = talloc_strdup(mem_ctx, "");
4196 r->action = DSPRINT_UNPUBLISH;
4198 W_ERROR_HAVE_NO_MEMORY(r->guid);
4200 TALLOC_FREE(session_info);
4201 return WERR_OK;
4204 /********************************************************************
4205 * construct_printer_info8
4206 * fill a spoolss_PrinterInfo8 struct
4207 ********************************************************************/
4209 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4210 const struct spoolss_PrinterInfo2 *info2,
4211 const char *servername,
4212 struct spoolss_DeviceModeInfo *r,
4213 int snum)
4215 WERROR result;
4216 const char *printername;
4218 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4219 if (!W_ERROR_IS_OK(result)) {
4220 return result;
4223 if (info2->devmode != NULL) {
4224 result = copy_devicemode(mem_ctx,
4225 info2->devmode,
4226 &r->devmode);
4227 if (!W_ERROR_IS_OK(result)) {
4228 return result;
4230 } else if (lp_default_devmode(snum)) {
4231 result = spoolss_create_default_devmode(mem_ctx,
4232 info2->printername,
4233 &r->devmode);
4234 if (!W_ERROR_IS_OK(result)) {
4235 return result;
4237 } else {
4238 r->devmode = NULL;
4239 DEBUG(8,("Returning NULL Devicemode!\n"));
4242 compose_devicemode_devicename(r->devmode, printername);
4244 return WERR_OK;
4248 /********************************************************************
4249 ********************************************************************/
4251 static bool snum_is_shared_printer(int snum)
4253 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4256 /********************************************************************
4257 Spoolss_enumprinters.
4258 ********************************************************************/
4260 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4261 const struct auth_serversupplied_info *session_info,
4262 struct messaging_context *msg_ctx,
4263 const char *servername,
4264 uint32_t level,
4265 uint32_t flags,
4266 union spoolss_PrinterInfo **info_p,
4267 uint32_t *count_p)
4269 int snum;
4270 int n_services = lp_numservices();
4271 union spoolss_PrinterInfo *info = NULL;
4272 uint32_t count = 0;
4273 WERROR result = WERR_OK;
4274 struct dcerpc_binding_handle *b = NULL;
4276 *count_p = 0;
4277 *info_p = NULL;
4279 for (snum = 0; snum < n_services; snum++) {
4281 const char *printer;
4282 struct spoolss_PrinterInfo2 *info2;
4284 if (!snum_is_shared_printer(snum)) {
4285 continue;
4288 printer = lp_const_servicename(snum);
4290 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4291 printer, snum));
4293 if (b == NULL) {
4294 result = winreg_printer_binding_handle(mem_ctx,
4295 session_info,
4296 msg_ctx,
4297 &b);
4298 if (!W_ERROR_IS_OK(result)) {
4299 goto out;
4303 result = winreg_create_printer(mem_ctx, b,
4304 printer);
4305 if (!W_ERROR_IS_OK(result)) {
4306 goto out;
4309 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4310 union spoolss_PrinterInfo,
4311 count + 1);
4312 if (!info) {
4313 result = WERR_NOMEM;
4314 goto out;
4317 result = winreg_get_printer(mem_ctx, b,
4318 printer, &info2);
4319 if (!W_ERROR_IS_OK(result)) {
4320 goto out;
4323 switch (level) {
4324 case 0:
4325 result = construct_printer_info0(info, session_info,
4326 msg_ctx, info2,
4327 servername,
4328 &info[count].info0, snum);
4329 break;
4330 case 1:
4331 result = construct_printer_info1(info, info2, flags,
4332 servername,
4333 &info[count].info1, snum);
4334 break;
4335 case 2:
4336 result = construct_printer_info2(info, msg_ctx, info2,
4337 servername,
4338 &info[count].info2, snum);
4339 break;
4340 case 4:
4341 result = construct_printer_info4(info, info2,
4342 servername,
4343 &info[count].info4, snum);
4344 break;
4345 case 5:
4346 result = construct_printer_info5(info, info2,
4347 servername,
4348 &info[count].info5, snum);
4349 break;
4351 default:
4352 result = WERR_UNKNOWN_LEVEL;
4353 goto out;
4356 if (!W_ERROR_IS_OK(result)) {
4357 goto out;
4360 count++;
4363 *count_p = count;
4364 *info_p = info;
4366 out:
4367 if (!W_ERROR_IS_OK(result)) {
4368 TALLOC_FREE(info);
4369 return result;
4372 *info_p = info;
4374 return WERR_OK;
4377 /********************************************************************
4378 * handle enumeration of printers at level 0
4379 ********************************************************************/
4381 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4382 const struct auth_serversupplied_info *session_info,
4383 struct messaging_context *msg_ctx,
4384 uint32_t flags,
4385 const char *servername,
4386 union spoolss_PrinterInfo **info,
4387 uint32_t *count)
4389 DEBUG(4,("enum_all_printers_info_0\n"));
4391 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4392 servername, 0, flags, info, count);
4396 /********************************************************************
4397 ********************************************************************/
4399 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4400 const struct auth_serversupplied_info *session_info,
4401 struct messaging_context *msg_ctx,
4402 const char *servername,
4403 uint32_t flags,
4404 union spoolss_PrinterInfo **info,
4405 uint32_t *count)
4407 DEBUG(4,("enum_all_printers_info_1\n"));
4409 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4410 servername, 1, flags, info, count);
4413 /********************************************************************
4414 enum_all_printers_info_1_local.
4415 *********************************************************************/
4417 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4418 const struct auth_serversupplied_info *session_info,
4419 struct messaging_context *msg_ctx,
4420 const char *servername,
4421 union spoolss_PrinterInfo **info,
4422 uint32_t *count)
4424 DEBUG(4,("enum_all_printers_info_1_local\n"));
4426 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4427 servername, PRINTER_ENUM_ICON8, info, count);
4430 /********************************************************************
4431 enum_all_printers_info_1_name.
4432 *********************************************************************/
4434 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4435 const struct auth_serversupplied_info *session_info,
4436 struct messaging_context *msg_ctx,
4437 const char *servername,
4438 union spoolss_PrinterInfo **info,
4439 uint32_t *count)
4441 const char *s = servername;
4443 DEBUG(4,("enum_all_printers_info_1_name\n"));
4445 if (servername != NULL &&
4446 (servername[0] == '\\') && (servername[1] == '\\')) {
4447 s = servername + 2;
4450 if (!is_myname_or_ipaddr(s)) {
4451 return WERR_INVALID_NAME;
4454 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4455 servername, PRINTER_ENUM_ICON8, info, count);
4458 /********************************************************************
4459 enum_all_printers_info_1_network.
4460 *********************************************************************/
4462 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4463 const struct auth_serversupplied_info *session_info,
4464 struct messaging_context *msg_ctx,
4465 const char *servername,
4466 union spoolss_PrinterInfo **info,
4467 uint32_t *count)
4469 const char *s = servername;
4471 DEBUG(4,("enum_all_printers_info_1_network\n"));
4473 /* If we respond to a enum_printers level 1 on our name with flags
4474 set to PRINTER_ENUM_REMOTE with a list of printers then these
4475 printers incorrectly appear in the APW browse list.
4476 Specifically the printers for the server appear at the workgroup
4477 level where all the other servers in the domain are
4478 listed. Windows responds to this call with a
4479 WERR_CAN_NOT_COMPLETE so we should do the same. */
4481 if (servername != NULL &&
4482 (servername[0] == '\\') && (servername[1] == '\\')) {
4483 s = servername + 2;
4486 if (is_myname_or_ipaddr(s)) {
4487 return WERR_CAN_NOT_COMPLETE;
4490 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4491 servername, PRINTER_ENUM_NAME, info, count);
4494 /********************************************************************
4495 * api_spoolss_enumprinters
4497 * called from api_spoolss_enumprinters (see this to understand)
4498 ********************************************************************/
4500 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4501 const struct auth_serversupplied_info *session_info,
4502 struct messaging_context *msg_ctx,
4503 const char *servername,
4504 union spoolss_PrinterInfo **info,
4505 uint32_t *count)
4507 DEBUG(4,("enum_all_printers_info_2\n"));
4509 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4510 servername, 2, 0, info, count);
4513 /********************************************************************
4514 * handle enumeration of printers at level 1
4515 ********************************************************************/
4517 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4518 const struct auth_serversupplied_info *session_info,
4519 struct messaging_context *msg_ctx,
4520 uint32_t flags,
4521 const char *servername,
4522 union spoolss_PrinterInfo **info,
4523 uint32_t *count)
4525 /* Not all the flags are equals */
4527 if (flags & PRINTER_ENUM_LOCAL) {
4528 return enum_all_printers_info_1_local(mem_ctx, session_info,
4529 msg_ctx, servername, info, count);
4532 if (flags & PRINTER_ENUM_NAME) {
4533 return enum_all_printers_info_1_name(mem_ctx, session_info,
4534 msg_ctx, servername, info,
4535 count);
4538 if (flags & PRINTER_ENUM_NETWORK) {
4539 return enum_all_printers_info_1_network(mem_ctx, session_info,
4540 msg_ctx, servername, info,
4541 count);
4544 return WERR_OK; /* NT4sp5 does that */
4547 /********************************************************************
4548 * handle enumeration of printers at level 2
4549 ********************************************************************/
4551 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4552 const struct auth_serversupplied_info *session_info,
4553 struct messaging_context *msg_ctx,
4554 uint32_t flags,
4555 const char *servername,
4556 union spoolss_PrinterInfo **info,
4557 uint32_t *count)
4559 if (flags & PRINTER_ENUM_LOCAL) {
4561 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4562 servername,
4563 info, count);
4566 if (flags & PRINTER_ENUM_NAME) {
4567 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4568 return WERR_INVALID_NAME;
4571 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4572 servername,
4573 info, count);
4576 if (flags & PRINTER_ENUM_REMOTE) {
4577 return WERR_UNKNOWN_LEVEL;
4580 return WERR_OK;
4583 /********************************************************************
4584 * handle enumeration of printers at level 4
4585 ********************************************************************/
4587 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4588 const struct auth_serversupplied_info *session_info,
4589 struct messaging_context *msg_ctx,
4590 uint32_t flags,
4591 const char *servername,
4592 union spoolss_PrinterInfo **info,
4593 uint32_t *count)
4595 DEBUG(4,("enum_all_printers_info_4\n"));
4597 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4598 servername, 4, flags, info, count);
4602 /********************************************************************
4603 * handle enumeration of printers at level 5
4604 ********************************************************************/
4606 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4607 const struct auth_serversupplied_info *session_info,
4608 struct messaging_context *msg_ctx,
4609 uint32_t flags,
4610 const char *servername,
4611 union spoolss_PrinterInfo **info,
4612 uint32_t *count)
4614 DEBUG(4,("enum_all_printers_info_5\n"));
4616 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4617 servername, 5, flags, info, count);
4620 /****************************************************************
4621 _spoolss_EnumPrinters
4622 ****************************************************************/
4624 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4625 struct spoolss_EnumPrinters *r)
4627 const struct auth_serversupplied_info *session_info = get_session_info_system();
4628 WERROR result;
4630 /* that's an [in out] buffer */
4632 if (!r->in.buffer && (r->in.offered != 0)) {
4633 return WERR_INVALID_PARAM;
4636 DEBUG(4,("_spoolss_EnumPrinters\n"));
4638 *r->out.needed = 0;
4639 *r->out.count = 0;
4640 *r->out.info = NULL;
4643 * Level 1:
4644 * flags==PRINTER_ENUM_NAME
4645 * if name=="" then enumerates all printers
4646 * if name!="" then enumerate the printer
4647 * flags==PRINTER_ENUM_REMOTE
4648 * name is NULL, enumerate printers
4649 * Level 2: name!="" enumerates printers, name can't be NULL
4650 * Level 3: doesn't exist
4651 * Level 4: does a local registry lookup
4652 * Level 5: same as Level 2
4655 if (r->in.server && r->in.server[0] == '\0') {
4656 r->in.server = NULL;
4659 switch (r->in.level) {
4660 case 0:
4661 result = enumprinters_level0(p->mem_ctx, session_info,
4662 p->msg_ctx, r->in.flags,
4663 r->in.server,
4664 r->out.info, r->out.count);
4665 break;
4666 case 1:
4667 result = enumprinters_level1(p->mem_ctx, session_info,
4668 p->msg_ctx, r->in.flags,
4669 r->in.server,
4670 r->out.info, r->out.count);
4671 break;
4672 case 2:
4673 result = enumprinters_level2(p->mem_ctx, session_info,
4674 p->msg_ctx, r->in.flags,
4675 r->in.server,
4676 r->out.info, r->out.count);
4677 break;
4678 case 4:
4679 result = enumprinters_level4(p->mem_ctx, session_info,
4680 p->msg_ctx, r->in.flags,
4681 r->in.server,
4682 r->out.info, r->out.count);
4683 break;
4684 case 5:
4685 result = enumprinters_level5(p->mem_ctx, session_info,
4686 p->msg_ctx, r->in.flags,
4687 r->in.server,
4688 r->out.info, r->out.count);
4689 break;
4690 default:
4691 return WERR_UNKNOWN_LEVEL;
4694 if (!W_ERROR_IS_OK(result)) {
4695 return result;
4698 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4699 spoolss_EnumPrinters,
4700 *r->out.info, r->in.level,
4701 *r->out.count);
4702 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4703 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4705 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4708 /****************************************************************
4709 _spoolss_GetPrinter
4710 ****************************************************************/
4712 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4713 struct spoolss_GetPrinter *r)
4715 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4716 struct spoolss_PrinterInfo2 *info2 = NULL;
4717 WERROR result = WERR_OK;
4718 int snum;
4720 /* that's an [in out] buffer */
4722 if (!r->in.buffer && (r->in.offered != 0)) {
4723 return WERR_INVALID_PARAM;
4726 *r->out.needed = 0;
4728 if (Printer == NULL) {
4729 return WERR_BADFID;
4732 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4733 return WERR_BADFID;
4736 result = winreg_get_printer_internal(p->mem_ctx,
4737 get_session_info_system(),
4738 p->msg_ctx,
4739 lp_const_servicename(snum),
4740 &info2);
4741 if (!W_ERROR_IS_OK(result)) {
4742 goto out;
4745 switch (r->in.level) {
4746 case 0:
4747 result = construct_printer_info0(p->mem_ctx,
4748 get_session_info_system(),
4749 p->msg_ctx,
4750 info2,
4751 Printer->servername,
4752 &r->out.info->info0,
4753 snum);
4754 break;
4755 case 1:
4756 result = construct_printer_info1(p->mem_ctx, info2,
4757 PRINTER_ENUM_ICON8,
4758 Printer->servername,
4759 &r->out.info->info1, snum);
4760 break;
4761 case 2:
4762 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4763 Printer->servername,
4764 &r->out.info->info2, snum);
4765 break;
4766 case 3:
4767 result = construct_printer_info3(p->mem_ctx, info2,
4768 Printer->servername,
4769 &r->out.info->info3, snum);
4770 break;
4771 case 4:
4772 result = construct_printer_info4(p->mem_ctx, info2,
4773 Printer->servername,
4774 &r->out.info->info4, snum);
4775 break;
4776 case 5:
4777 result = construct_printer_info5(p->mem_ctx, info2,
4778 Printer->servername,
4779 &r->out.info->info5, snum);
4780 break;
4781 case 6:
4782 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4783 Printer->servername,
4784 &r->out.info->info6, snum);
4785 break;
4786 case 7:
4787 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4788 Printer->servername,
4789 &r->out.info->info7, snum);
4790 break;
4791 case 8:
4792 result = construct_printer_info8(p->mem_ctx, info2,
4793 Printer->servername,
4794 &r->out.info->info8, snum);
4795 break;
4796 default:
4797 result = WERR_UNKNOWN_LEVEL;
4798 break;
4801 out:
4802 if (!W_ERROR_IS_OK(result)) {
4803 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4804 r->in.level, win_errstr(result)));
4805 TALLOC_FREE(r->out.info);
4806 return result;
4809 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4810 r->out.info, r->in.level);
4811 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4813 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4816 /********************************************************************
4817 ********************************************************************/
4819 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4820 do { \
4821 if (in && strlen(in)) { \
4822 out = talloc_strdup(mem_ctx, in); \
4823 } else { \
4824 out = talloc_strdup(mem_ctx, ""); \
4826 W_ERROR_HAVE_NO_MEMORY(out); \
4827 } while (0);
4829 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4830 do { \
4831 if (in && strlen(in)) { \
4832 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4833 } else { \
4834 out = talloc_strdup(mem_ctx, ""); \
4836 W_ERROR_HAVE_NO_MEMORY(out); \
4837 } while (0);
4839 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4840 const char **string_array,
4841 const char ***presult,
4842 const char *cservername,
4843 const char *arch,
4844 int version)
4846 int i, num_strings = 0;
4847 const char **array = NULL;
4849 if (string_array == NULL) {
4850 return WERR_INVALID_PARAMETER;
4853 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4854 const char *str = NULL;
4856 if (cservername == NULL || arch == NULL) {
4857 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4858 } else {
4859 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4862 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4863 TALLOC_FREE(array);
4864 return WERR_NOMEM;
4868 if (i > 0) {
4869 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4870 &array, &num_strings);
4873 if (presult) {
4874 *presult = array;
4877 return WERR_OK;
4880 /********************************************************************
4881 * fill a spoolss_DriverInfo1 struct
4882 ********************************************************************/
4884 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4885 struct spoolss_DriverInfo1 *r,
4886 const struct spoolss_DriverInfo8 *driver,
4887 const char *servername)
4889 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4890 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4892 return WERR_OK;
4895 /********************************************************************
4896 * fill a spoolss_DriverInfo2 struct
4897 ********************************************************************/
4899 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4900 struct spoolss_DriverInfo2 *r,
4901 const struct spoolss_DriverInfo8 *driver,
4902 const char *servername)
4905 const char *cservername = canon_servername(servername);
4907 r->version = driver->version;
4909 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4910 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4911 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4912 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4914 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4915 driver->architecture,
4916 driver->version,
4917 driver->driver_path,
4918 r->driver_path);
4920 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4921 driver->architecture,
4922 driver->version,
4923 driver->data_file,
4924 r->data_file);
4926 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4927 driver->architecture,
4928 driver->version,
4929 driver->config_file,
4930 r->config_file);
4932 return WERR_OK;
4935 /********************************************************************
4936 * fill a spoolss_DriverInfo3 struct
4937 ********************************************************************/
4939 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4940 struct spoolss_DriverInfo3 *r,
4941 const struct spoolss_DriverInfo8 *driver,
4942 const char *servername)
4944 const char *cservername = canon_servername(servername);
4946 r->version = driver->version;
4948 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4949 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4950 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4951 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4953 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954 driver->architecture,
4955 driver->version,
4956 driver->driver_path,
4957 r->driver_path);
4959 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4960 driver->architecture,
4961 driver->version,
4962 driver->data_file,
4963 r->data_file);
4965 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4966 driver->architecture,
4967 driver->version,
4968 driver->config_file,
4969 r->config_file);
4971 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4972 driver->architecture,
4973 driver->version,
4974 driver->help_file,
4975 r->help_file);
4977 FILL_DRIVER_STRING(mem_ctx,
4978 driver->monitor_name,
4979 r->monitor_name);
4981 FILL_DRIVER_STRING(mem_ctx,
4982 driver->default_datatype,
4983 r->default_datatype);
4985 return string_array_from_driver_info(mem_ctx,
4986 driver->dependent_files,
4987 &r->dependent_files,
4988 cservername,
4989 driver->architecture,
4990 driver->version);
4993 /********************************************************************
4994 * fill a spoolss_DriverInfo4 struct
4995 ********************************************************************/
4997 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4998 struct spoolss_DriverInfo4 *r,
4999 const struct spoolss_DriverInfo8 *driver,
5000 const char *servername)
5002 const char *cservername = canon_servername(servername);
5003 WERROR result;
5005 r->version = driver->version;
5007 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5008 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5009 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5010 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5012 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013 driver->architecture,
5014 driver->version,
5015 driver->driver_path,
5016 r->driver_path);
5018 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5019 driver->architecture,
5020 driver->version,
5021 driver->data_file,
5022 r->data_file);
5024 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5025 driver->architecture,
5026 driver->version,
5027 driver->config_file,
5028 r->config_file);
5030 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5031 driver->architecture,
5032 driver->version,
5033 driver->help_file,
5034 r->help_file);
5036 result = string_array_from_driver_info(mem_ctx,
5037 driver->dependent_files,
5038 &r->dependent_files,
5039 cservername,
5040 driver->architecture,
5041 driver->version);
5042 if (!W_ERROR_IS_OK(result)) {
5043 return result;
5046 FILL_DRIVER_STRING(mem_ctx,
5047 driver->monitor_name,
5048 r->monitor_name);
5050 FILL_DRIVER_STRING(mem_ctx,
5051 driver->default_datatype,
5052 r->default_datatype);
5055 result = string_array_from_driver_info(mem_ctx,
5056 driver->previous_names,
5057 &r->previous_names,
5058 NULL, NULL, 0);
5060 return result;
5063 /********************************************************************
5064 * fill a spoolss_DriverInfo5 struct
5065 ********************************************************************/
5067 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5068 struct spoolss_DriverInfo5 *r,
5069 const struct spoolss_DriverInfo8 *driver,
5070 const char *servername)
5072 const char *cservername = canon_servername(servername);
5074 r->version = driver->version;
5076 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5077 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5078 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5079 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5081 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5082 driver->architecture,
5083 driver->version,
5084 driver->driver_path,
5085 r->driver_path);
5087 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5088 driver->architecture,
5089 driver->version,
5090 driver->data_file,
5091 r->data_file);
5093 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094 driver->architecture,
5095 driver->version,
5096 driver->config_file,
5097 r->config_file);
5099 r->driver_attributes = 0;
5100 r->config_version = 0;
5101 r->driver_version = 0;
5103 return WERR_OK;
5105 /********************************************************************
5106 * fill a spoolss_DriverInfo6 struct
5107 ********************************************************************/
5109 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5110 struct spoolss_DriverInfo6 *r,
5111 const struct spoolss_DriverInfo8 *driver,
5112 const char *servername)
5114 const char *cservername = canon_servername(servername);
5115 WERROR result;
5117 r->version = driver->version;
5119 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5120 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5121 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5122 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5124 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125 driver->architecture,
5126 driver->version,
5127 driver->driver_path,
5128 r->driver_path);
5130 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5131 driver->architecture,
5132 driver->version,
5133 driver->data_file,
5134 r->data_file);
5136 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5137 driver->architecture,
5138 driver->version,
5139 driver->config_file,
5140 r->config_file);
5142 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5143 driver->architecture,
5144 driver->version,
5145 driver->help_file,
5146 r->help_file);
5148 FILL_DRIVER_STRING(mem_ctx,
5149 driver->monitor_name,
5150 r->monitor_name);
5152 FILL_DRIVER_STRING(mem_ctx,
5153 driver->default_datatype,
5154 r->default_datatype);
5156 result = string_array_from_driver_info(mem_ctx,
5157 driver->dependent_files,
5158 &r->dependent_files,
5159 cservername,
5160 driver->architecture,
5161 driver->version);
5162 if (!W_ERROR_IS_OK(result)) {
5163 return result;
5166 result = string_array_from_driver_info(mem_ctx,
5167 driver->previous_names,
5168 &r->previous_names,
5169 NULL, NULL, 0);
5170 if (!W_ERROR_IS_OK(result)) {
5171 return result;
5174 r->driver_date = driver->driver_date;
5175 r->driver_version = driver->driver_version;
5177 FILL_DRIVER_STRING(mem_ctx,
5178 driver->manufacturer_name,
5179 r->manufacturer_name);
5180 FILL_DRIVER_STRING(mem_ctx,
5181 driver->manufacturer_url,
5182 r->manufacturer_url);
5183 FILL_DRIVER_STRING(mem_ctx,
5184 driver->hardware_id,
5185 r->hardware_id);
5186 FILL_DRIVER_STRING(mem_ctx,
5187 driver->provider,
5188 r->provider);
5190 return WERR_OK;
5193 /********************************************************************
5194 * fill a spoolss_DriverInfo8 struct
5195 ********************************************************************/
5197 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5198 struct spoolss_DriverInfo8 *r,
5199 const struct spoolss_DriverInfo8 *driver,
5200 const char *servername)
5202 const char *cservername = canon_servername(servername);
5203 WERROR result;
5205 r->version = driver->version;
5207 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5208 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5209 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5210 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5212 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213 driver->architecture,
5214 driver->version,
5215 driver->driver_path,
5216 r->driver_path);
5218 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5219 driver->architecture,
5220 driver->version,
5221 driver->data_file,
5222 r->data_file);
5224 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5225 driver->architecture,
5226 driver->version,
5227 driver->config_file,
5228 r->config_file);
5230 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5231 driver->architecture,
5232 driver->version,
5233 driver->help_file,
5234 r->help_file);
5236 FILL_DRIVER_STRING(mem_ctx,
5237 driver->monitor_name,
5238 r->monitor_name);
5240 FILL_DRIVER_STRING(mem_ctx,
5241 driver->default_datatype,
5242 r->default_datatype);
5244 result = string_array_from_driver_info(mem_ctx,
5245 driver->dependent_files,
5246 &r->dependent_files,
5247 cservername,
5248 driver->architecture,
5249 driver->version);
5250 if (!W_ERROR_IS_OK(result)) {
5251 return result;
5254 result = string_array_from_driver_info(mem_ctx,
5255 driver->previous_names,
5256 &r->previous_names,
5257 NULL, NULL, 0);
5258 if (!W_ERROR_IS_OK(result)) {
5259 return result;
5262 r->driver_date = driver->driver_date;
5263 r->driver_version = driver->driver_version;
5265 FILL_DRIVER_STRING(mem_ctx,
5266 driver->manufacturer_name,
5267 r->manufacturer_name);
5268 FILL_DRIVER_STRING(mem_ctx,
5269 driver->manufacturer_url,
5270 r->manufacturer_url);
5271 FILL_DRIVER_STRING(mem_ctx,
5272 driver->hardware_id,
5273 r->hardware_id);
5274 FILL_DRIVER_STRING(mem_ctx,
5275 driver->provider,
5276 r->provider);
5278 FILL_DRIVER_STRING(mem_ctx,
5279 driver->print_processor,
5280 r->print_processor);
5281 FILL_DRIVER_STRING(mem_ctx,
5282 driver->vendor_setup,
5283 r->vendor_setup);
5285 result = string_array_from_driver_info(mem_ctx,
5286 driver->color_profiles,
5287 &r->color_profiles,
5288 NULL, NULL, 0);
5289 if (!W_ERROR_IS_OK(result)) {
5290 return result;
5293 FILL_DRIVER_STRING(mem_ctx,
5294 driver->inf_path,
5295 r->inf_path);
5297 r->printer_driver_attributes = driver->printer_driver_attributes;
5299 result = string_array_from_driver_info(mem_ctx,
5300 driver->core_driver_dependencies,
5301 &r->core_driver_dependencies,
5302 NULL, NULL, 0);
5303 if (!W_ERROR_IS_OK(result)) {
5304 return result;
5307 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5308 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5310 return WERR_OK;
5313 #if 0 /* disabled until marshalling issues are resolved - gd */
5314 /********************************************************************
5315 ********************************************************************/
5317 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5318 struct spoolss_DriverFileInfo *r,
5319 const char *cservername,
5320 const char *file_name,
5321 enum spoolss_DriverFileType file_type,
5322 uint32_t file_version)
5324 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5325 cservername, file_name);
5326 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5327 r->file_type = file_type;
5328 r->file_version = file_version;
5330 return WERR_OK;
5333 /********************************************************************
5334 ********************************************************************/
5336 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5337 const struct spoolss_DriverInfo8 *driver,
5338 const char *cservername,
5339 struct spoolss_DriverFileInfo **info_p,
5340 uint32_t *count_p)
5342 struct spoolss_DriverFileInfo *info = NULL;
5343 uint32_t count = 0;
5344 WERROR result;
5345 uint32_t i;
5347 *info_p = NULL;
5348 *count_p = 0;
5350 if (strlen(driver->driver_path)) {
5351 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5352 struct spoolss_DriverFileInfo,
5353 count + 1);
5354 W_ERROR_HAVE_NO_MEMORY(info);
5355 result = fill_spoolss_DriverFileInfo(info,
5356 &info[count],
5357 cservername,
5358 driver->driver_path,
5359 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5361 W_ERROR_NOT_OK_RETURN(result);
5362 count++;
5365 if (strlen(driver->config_file)) {
5366 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5367 struct spoolss_DriverFileInfo,
5368 count + 1);
5369 W_ERROR_HAVE_NO_MEMORY(info);
5370 result = fill_spoolss_DriverFileInfo(info,
5371 &info[count],
5372 cservername,
5373 driver->config_file,
5374 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5376 W_ERROR_NOT_OK_RETURN(result);
5377 count++;
5380 if (strlen(driver->data_file)) {
5381 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5382 struct spoolss_DriverFileInfo,
5383 count + 1);
5384 W_ERROR_HAVE_NO_MEMORY(info);
5385 result = fill_spoolss_DriverFileInfo(info,
5386 &info[count],
5387 cservername,
5388 driver->data_file,
5389 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5391 W_ERROR_NOT_OK_RETURN(result);
5392 count++;
5395 if (strlen(driver->help_file)) {
5396 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5397 struct spoolss_DriverFileInfo,
5398 count + 1);
5399 W_ERROR_HAVE_NO_MEMORY(info);
5400 result = fill_spoolss_DriverFileInfo(info,
5401 &info[count],
5402 cservername,
5403 driver->help_file,
5404 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5406 W_ERROR_NOT_OK_RETURN(result);
5407 count++;
5410 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5411 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5412 struct spoolss_DriverFileInfo,
5413 count + 1);
5414 W_ERROR_HAVE_NO_MEMORY(info);
5415 result = fill_spoolss_DriverFileInfo(info,
5416 &info[count],
5417 cservername,
5418 driver->dependent_files[i],
5419 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5421 W_ERROR_NOT_OK_RETURN(result);
5422 count++;
5425 *info_p = info;
5426 *count_p = count;
5428 return WERR_OK;
5431 /********************************************************************
5432 * fill a spoolss_DriverInfo101 struct
5433 ********************************************************************/
5435 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5436 struct spoolss_DriverInfo101 *r,
5437 const struct spoolss_DriverInfo8 *driver,
5438 const char *servername)
5440 const char *cservername = canon_servername(servername);
5441 WERROR result;
5443 r->version = driver->version;
5445 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5446 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5447 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5448 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5450 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5451 cservername,
5452 &r->file_info,
5453 &r->file_count);
5454 if (!W_ERROR_IS_OK(result)) {
5455 return result;
5458 FILL_DRIVER_STRING(mem_ctx,
5459 driver->monitor_name,
5460 r->monitor_name);
5462 FILL_DRIVER_STRING(mem_ctx,
5463 driver->default_datatype,
5464 r->default_datatype);
5466 result = string_array_from_driver_info(mem_ctx,
5467 driver->previous_names,
5468 &r->previous_names,
5469 NULL, NULL, 0);
5470 if (!W_ERROR_IS_OK(result)) {
5471 return result;
5474 r->driver_date = driver->driver_date;
5475 r->driver_version = driver->driver_version;
5477 FILL_DRIVER_STRING(mem_ctx,
5478 driver->manufacturer_name,
5479 r->manufacturer_name);
5480 FILL_DRIVER_STRING(mem_ctx,
5481 driver->manufacturer_url,
5482 r->manufacturer_url);
5483 FILL_DRIVER_STRING(mem_ctx,
5484 driver->hardware_id,
5485 r->hardware_id);
5486 FILL_DRIVER_STRING(mem_ctx,
5487 driver->provider,
5488 r->provider);
5490 return WERR_OK;
5492 #endif
5493 /********************************************************************
5494 ********************************************************************/
5496 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5497 const struct auth_serversupplied_info *session_info,
5498 struct messaging_context *msg_ctx,
5499 uint32_t level,
5500 union spoolss_DriverInfo *r,
5501 int snum,
5502 const char *servername,
5503 const char *architecture,
5504 uint32_t version)
5506 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5507 struct spoolss_DriverInfo8 *driver;
5508 WERROR result;
5509 struct dcerpc_binding_handle *b;
5511 if (level == 101) {
5512 return WERR_UNKNOWN_LEVEL;
5515 result = winreg_printer_binding_handle(mem_ctx,
5516 session_info,
5517 msg_ctx,
5518 &b);
5519 if (!W_ERROR_IS_OK(result)) {
5520 return result;
5523 result = winreg_get_printer(mem_ctx, b,
5524 lp_const_servicename(snum),
5525 &pinfo2);
5527 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5528 win_errstr(result)));
5530 if (!W_ERROR_IS_OK(result)) {
5531 return WERR_INVALID_PRINTER_NAME;
5534 result = winreg_get_driver(mem_ctx, b,
5535 architecture,
5536 pinfo2->drivername, version, &driver);
5538 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5539 win_errstr(result)));
5541 if (!W_ERROR_IS_OK(result)) {
5543 * Is this a W2k client ?
5546 if (version < 3) {
5547 talloc_free(pinfo2);
5548 return WERR_UNKNOWN_PRINTER_DRIVER;
5551 /* Yes - try again with a WinNT driver. */
5552 version = 2;
5553 result = winreg_get_driver(mem_ctx, b,
5554 architecture,
5555 pinfo2->drivername,
5556 version, &driver);
5557 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5558 win_errstr(result)));
5559 if (!W_ERROR_IS_OK(result)) {
5560 talloc_free(pinfo2);
5561 return WERR_UNKNOWN_PRINTER_DRIVER;
5565 switch (level) {
5566 case 1:
5567 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5568 break;
5569 case 2:
5570 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5571 break;
5572 case 3:
5573 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5574 break;
5575 case 4:
5576 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5577 break;
5578 case 5:
5579 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5580 break;
5581 case 6:
5582 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5583 break;
5584 case 8:
5585 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5586 break;
5587 #if 0 /* disabled until marshalling issues are resolved - gd */
5588 case 101:
5589 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5590 break;
5591 #endif
5592 default:
5593 result = WERR_UNKNOWN_LEVEL;
5594 break;
5597 talloc_free(pinfo2);
5598 talloc_free(driver);
5600 return result;
5603 /****************************************************************
5604 _spoolss_GetPrinterDriver2
5605 ****************************************************************/
5607 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5608 struct spoolss_GetPrinterDriver2 *r)
5610 struct printer_handle *printer;
5611 WERROR result;
5612 uint32_t version = r->in.client_major_version;
5614 int snum;
5616 /* that's an [in out] buffer */
5618 if (!r->in.buffer && (r->in.offered != 0)) {
5619 return WERR_INVALID_PARAM;
5622 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5624 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5625 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5626 return WERR_INVALID_PRINTER_NAME;
5629 *r->out.needed = 0;
5630 *r->out.server_major_version = 0;
5631 *r->out.server_minor_version = 0;
5633 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5634 return WERR_BADFID;
5637 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5638 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5639 "downgrading to v3\n"));
5640 version = SPOOLSS_DRIVER_VERSION_200X;
5643 result = construct_printer_driver_info_level(p->mem_ctx,
5644 get_session_info_system(),
5645 p->msg_ctx,
5646 r->in.level, r->out.info,
5647 snum, printer->servername,
5648 r->in.architecture,
5649 version);
5650 if (!W_ERROR_IS_OK(result)) {
5651 TALLOC_FREE(r->out.info);
5652 return result;
5655 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5656 r->out.info, r->in.level);
5657 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5659 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5663 /****************************************************************
5664 _spoolss_StartPagePrinter
5665 ****************************************************************/
5667 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5668 struct spoolss_StartPagePrinter *r)
5670 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5672 if (!Printer) {
5673 DEBUG(3,("_spoolss_StartPagePrinter: "
5674 "Error in startpageprinter printer handle\n"));
5675 return WERR_BADFID;
5678 Printer->page_started = true;
5679 return WERR_OK;
5682 /****************************************************************
5683 _spoolss_EndPagePrinter
5684 ****************************************************************/
5686 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5687 struct spoolss_EndPagePrinter *r)
5689 int snum;
5691 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5693 if (!Printer) {
5694 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5695 OUR_HANDLE(r->in.handle)));
5696 return WERR_BADFID;
5699 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5700 return WERR_BADFID;
5702 Printer->page_started = false;
5703 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5705 return WERR_OK;
5708 /****************************************************************
5709 _spoolss_StartDocPrinter
5710 ****************************************************************/
5712 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5713 struct spoolss_StartDocPrinter *r)
5715 struct spoolss_DocumentInfo1 *info_1;
5716 int snum;
5717 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5718 WERROR werr;
5720 if (!Printer) {
5721 DEBUG(2,("_spoolss_StartDocPrinter: "
5722 "Invalid handle (%s:%u:%u)\n",
5723 OUR_HANDLE(r->in.handle)));
5724 return WERR_BADFID;
5727 if (Printer->jobid) {
5728 DEBUG(2, ("_spoolss_StartDocPrinter: "
5729 "StartDocPrinter called twice! "
5730 "(existing jobid = %d)\n", Printer->jobid));
5731 return WERR_INVALID_HANDLE;
5734 if (r->in.level != 1) {
5735 return WERR_UNKNOWN_LEVEL;
5738 info_1 = r->in.info.info1;
5741 * a nice thing with NT is it doesn't listen to what you tell it.
5742 * when asked to send _only_ RAW datas, it tries to send datas
5743 * in EMF format.
5745 * So I add checks like in NT Server ...
5748 if (info_1->datatype) {
5749 if (strcmp(info_1->datatype, "RAW") != 0) {
5750 *r->out.job_id = 0;
5751 return WERR_INVALID_DATATYPE;
5755 /* get the share number of the printer */
5756 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5757 return WERR_BADFID;
5760 werr = print_job_start(p->session_info,
5761 p->msg_ctx,
5762 p->client_id->name,
5763 snum,
5764 info_1->document_name,
5765 info_1->output_file,
5766 Printer->devmode,
5767 &Printer->jobid);
5769 /* An error occured in print_job_start() so return an appropriate
5770 NT error code. */
5772 if (!W_ERROR_IS_OK(werr)) {
5773 return werr;
5776 Printer->document_started = true;
5777 *r->out.job_id = Printer->jobid;
5779 return WERR_OK;
5782 /****************************************************************
5783 _spoolss_EndDocPrinter
5784 ****************************************************************/
5786 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5787 struct spoolss_EndDocPrinter *r)
5789 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5790 NTSTATUS status;
5791 int snum;
5793 if (!Printer) {
5794 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5795 OUR_HANDLE(r->in.handle)));
5796 return WERR_BADFID;
5799 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5800 return WERR_BADFID;
5803 Printer->document_started = false;
5804 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5805 if (!NT_STATUS_IS_OK(status)) {
5806 DEBUG(2, ("_spoolss_EndDocPrinter: "
5807 "print_job_end failed [%s]\n",
5808 nt_errstr(status)));
5811 Printer->jobid = 0;
5812 return ntstatus_to_werror(status);
5815 /****************************************************************
5816 _spoolss_WritePrinter
5817 ****************************************************************/
5819 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5820 struct spoolss_WritePrinter *r)
5822 ssize_t buffer_written;
5823 int snum;
5824 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5826 if (!Printer) {
5827 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5828 OUR_HANDLE(r->in.handle)));
5829 *r->out.num_written = r->in._data_size;
5830 return WERR_BADFID;
5833 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5834 return WERR_BADFID;
5836 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5837 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5838 snum, Printer->jobid,
5839 (const char *)r->in.data.data,
5840 (size_t)r->in._data_size);
5841 if (buffer_written == (ssize_t)-1) {
5842 *r->out.num_written = 0;
5843 if (errno == ENOSPC)
5844 return WERR_NO_SPOOL_SPACE;
5845 else
5846 return WERR_ACCESS_DENIED;
5849 *r->out.num_written = r->in._data_size;
5851 return WERR_OK;
5854 /********************************************************************
5855 * api_spoolss_getprinter
5856 * called from the spoolss dispatcher
5858 ********************************************************************/
5860 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5861 struct pipes_struct *p)
5863 const struct auth_serversupplied_info *session_info = p->session_info;
5864 int snum;
5865 WERROR errcode = WERR_BADFUNC;
5866 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5868 if (!Printer) {
5869 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5870 OUR_HANDLE(handle)));
5871 return WERR_BADFID;
5874 if (!get_printer_snum(p, handle, &snum, NULL))
5875 return WERR_BADFID;
5877 switch (command) {
5878 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5879 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5880 break;
5881 case SPOOLSS_PRINTER_CONTROL_RESUME:
5882 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5883 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5884 break;
5885 case SPOOLSS_PRINTER_CONTROL_PURGE:
5886 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5887 break;
5888 default:
5889 return WERR_UNKNOWN_LEVEL;
5892 return errcode;
5896 /****************************************************************
5897 _spoolss_AbortPrinter
5898 * From MSDN: "Deletes printer's spool file if printer is configured
5899 * for spooling"
5900 ****************************************************************/
5902 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5903 struct spoolss_AbortPrinter *r)
5905 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5906 int snum;
5907 WERROR errcode = WERR_OK;
5909 if (!Printer) {
5910 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5911 OUR_HANDLE(r->in.handle)));
5912 return WERR_BADFID;
5915 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5916 return WERR_BADFID;
5918 if (!Printer->document_started) {
5919 return WERR_SPL_NO_STARTDOC;
5922 errcode = print_job_delete(p->session_info,
5923 p->msg_ctx,
5924 snum,
5925 Printer->jobid);
5927 return errcode;
5930 /********************************************************************
5931 * called by spoolss_api_setprinter
5932 * when updating a printer description
5933 ********************************************************************/
5935 static WERROR update_printer_sec(struct policy_handle *handle,
5936 struct pipes_struct *p,
5937 struct sec_desc_buf *secdesc_ctr)
5939 struct spoolss_security_descriptor *new_secdesc = NULL;
5940 struct spoolss_security_descriptor *old_secdesc = NULL;
5941 const char *printer;
5942 WERROR result;
5943 int snum;
5944 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5945 struct dcerpc_binding_handle *b;
5947 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5948 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5949 OUR_HANDLE(handle)));
5951 result = WERR_BADFID;
5952 goto done;
5955 if (secdesc_ctr == NULL) {
5956 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5957 result = WERR_INVALID_PARAM;
5958 goto done;
5960 printer = lp_const_servicename(snum);
5962 /* Check the user has permissions to change the security
5963 descriptor. By experimentation with two NT machines, the user
5964 requires Full Access to the printer to change security
5965 information. */
5967 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5968 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5969 result = WERR_ACCESS_DENIED;
5970 goto done;
5973 result = winreg_printer_binding_handle(p->mem_ctx,
5974 get_session_info_system(),
5975 p->msg_ctx,
5976 &b);
5977 if (!W_ERROR_IS_OK(result)) {
5978 goto done;
5981 /* NT seems to like setting the security descriptor even though
5982 nothing may have actually changed. */
5983 result = winreg_get_printer_secdesc(p->mem_ctx, b,
5984 printer,
5985 &old_secdesc);
5986 if (!W_ERROR_IS_OK(result)) {
5987 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5988 result = WERR_BADFID;
5989 goto done;
5992 if (DEBUGLEVEL >= 10) {
5993 struct security_acl *the_acl;
5994 int i;
5996 the_acl = old_secdesc->dacl;
5997 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5998 printer, the_acl->num_aces));
6000 for (i = 0; i < the_acl->num_aces; i++) {
6001 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6002 &the_acl->aces[i].trustee),
6003 the_acl->aces[i].access_mask));
6006 the_acl = secdesc_ctr->sd->dacl;
6008 if (the_acl) {
6009 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6010 printer, the_acl->num_aces));
6012 for (i = 0; i < the_acl->num_aces; i++) {
6013 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6014 &the_acl->aces[i].trustee),
6015 the_acl->aces[i].access_mask));
6017 } else {
6018 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6022 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
6023 if (new_secdesc == NULL) {
6024 result = WERR_NOMEM;
6025 goto done;
6028 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6029 result = WERR_OK;
6030 goto done;
6033 result = winreg_set_printer_secdesc(p->mem_ctx, b,
6034 printer,
6035 new_secdesc);
6037 done:
6038 return result;
6041 /********************************************************************
6042 Canonicalize printer info from a client
6043 ********************************************************************/
6045 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6046 struct spoolss_SetPrinterInfo2 *info2,
6047 int snum)
6049 fstring printername;
6050 const char *p;
6052 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6053 "portname=%s drivername=%s comment=%s location=%s\n",
6054 info2->servername, info2->printername, info2->sharename,
6055 info2->portname, info2->drivername, info2->comment,
6056 info2->location));
6058 /* we force some elements to "correct" values */
6059 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6060 if (info2->servername == NULL) {
6061 return false;
6063 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6064 if (info2->sharename == NULL) {
6065 return false;
6068 /* check to see if we allow printername != sharename */
6069 if (lp_force_printername(snum)) {
6070 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6071 global_myname(), info2->sharename);
6072 } else {
6073 /* make sure printername is in \\server\printername format */
6074 fstrcpy(printername, info2->printername);
6075 p = printername;
6076 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6077 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6078 p++;
6081 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6082 global_myname(), p);
6084 if (info2->printername == NULL) {
6085 return false;
6088 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6089 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6091 return true;
6094 /****************************************************************************
6095 ****************************************************************************/
6097 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6099 char *cmd = lp_addport_cmd();
6100 char *command = NULL;
6101 int ret;
6102 bool is_print_op = false;
6104 if ( !*cmd ) {
6105 return WERR_ACCESS_DENIED;
6108 command = talloc_asprintf(ctx,
6109 "%s \"%s\" \"%s\"", cmd, portname, uri );
6110 if (!command) {
6111 return WERR_NOMEM;
6114 if ( token )
6115 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6117 DEBUG(10,("Running [%s]\n", command));
6119 /********* BEGIN SePrintOperatorPrivilege **********/
6121 if ( is_print_op )
6122 become_root();
6124 ret = smbrun(command, NULL);
6126 if ( is_print_op )
6127 unbecome_root();
6129 /********* END SePrintOperatorPrivilege **********/
6131 DEBUGADD(10,("returned [%d]\n", ret));
6133 TALLOC_FREE(command);
6135 if ( ret != 0 ) {
6136 return WERR_ACCESS_DENIED;
6139 return WERR_OK;
6142 /****************************************************************************
6143 ****************************************************************************/
6145 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6146 struct spoolss_SetPrinterInfo2 *info2,
6147 const char *remote_machine,
6148 struct messaging_context *msg_ctx)
6150 char *cmd = lp_addprinter_cmd();
6151 char **qlines;
6152 char *command = NULL;
6153 int numlines;
6154 int ret;
6155 int fd;
6156 bool is_print_op = false;
6158 if (!remote_machine) {
6159 return false;
6162 command = talloc_asprintf(ctx,
6163 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6164 cmd, info2->printername, info2->sharename,
6165 info2->portname, info2->drivername,
6166 info2->location, info2->comment, remote_machine);
6167 if (!command) {
6168 return false;
6171 if ( token )
6172 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6174 DEBUG(10,("Running [%s]\n", command));
6176 /********* BEGIN SePrintOperatorPrivilege **********/
6178 if ( is_print_op )
6179 become_root();
6181 if ( (ret = smbrun(command, &fd)) == 0 ) {
6182 /* Tell everyone we updated smb.conf. */
6183 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6186 if ( is_print_op )
6187 unbecome_root();
6189 /********* END SePrintOperatorPrivilege **********/
6191 DEBUGADD(10,("returned [%d]\n", ret));
6193 TALLOC_FREE(command);
6195 if ( ret != 0 ) {
6196 if (fd != -1)
6197 close(fd);
6198 return false;
6201 /* reload our services immediately */
6202 become_root();
6203 reload_services(msg_ctx, -1, false);
6204 unbecome_root();
6206 numlines = 0;
6207 /* Get lines and convert them back to dos-codepage */
6208 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6209 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6210 close(fd);
6212 /* Set the portname to what the script says the portname should be. */
6213 /* but don't require anything to be return from the script exit a good error code */
6215 if (numlines) {
6216 /* Set the portname to what the script says the portname should be. */
6217 info2->portname = talloc_strdup(ctx, qlines[0]);
6218 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6221 TALLOC_FREE(qlines);
6222 return true;
6225 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6226 const struct auth_serversupplied_info *session_info,
6227 struct messaging_context *msg_ctx,
6228 int snum,
6229 struct spoolss_SetPrinterInfo2 *printer,
6230 struct spoolss_PrinterInfo2 *old_printer)
6232 bool force_update = (old_printer == NULL);
6233 const char *dnsdomname;
6234 const char *longname;
6235 const char *uncname;
6236 const char *spooling;
6237 DATA_BLOB buffer;
6238 WERROR result = WERR_OK;
6239 struct dcerpc_binding_handle *b;
6241 result = winreg_printer_binding_handle(mem_ctx,
6242 session_info,
6243 msg_ctx,
6244 &b);
6245 if (!W_ERROR_IS_OK(result)) {
6246 return result;
6249 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6250 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6251 winreg_set_printer_dataex(mem_ctx, b,
6252 printer->sharename,
6253 SPOOL_DSSPOOLER_KEY,
6254 SPOOL_REG_DRIVERNAME,
6255 REG_SZ,
6256 buffer.data,
6257 buffer.length);
6259 if (!force_update) {
6260 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6261 printer->drivername));
6263 notify_printer_driver(server_event_context(), msg_ctx,
6264 snum, printer->drivername ?
6265 printer->drivername : "");
6269 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6270 push_reg_sz(mem_ctx, &buffer, printer->comment);
6271 winreg_set_printer_dataex(mem_ctx, b,
6272 printer->sharename,
6273 SPOOL_DSSPOOLER_KEY,
6274 SPOOL_REG_DESCRIPTION,
6275 REG_SZ,
6276 buffer.data,
6277 buffer.length);
6279 if (!force_update) {
6280 notify_printer_comment(server_event_context(), msg_ctx,
6281 snum, printer->comment ?
6282 printer->comment : "");
6286 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6287 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6288 winreg_set_printer_dataex(mem_ctx, b,
6289 printer->sharename,
6290 SPOOL_DSSPOOLER_KEY,
6291 SPOOL_REG_PRINTSHARENAME,
6292 REG_SZ,
6293 buffer.data,
6294 buffer.length);
6296 if (!force_update) {
6297 notify_printer_sharename(server_event_context(),
6298 msg_ctx,
6299 snum, printer->sharename ?
6300 printer->sharename : "");
6304 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6305 const char *p;
6307 p = strrchr(printer->printername, '\\' );
6308 if (p != NULL) {
6309 p++;
6310 } else {
6311 p = printer->printername;
6314 push_reg_sz(mem_ctx, &buffer, p);
6315 winreg_set_printer_dataex(mem_ctx, b,
6316 printer->sharename,
6317 SPOOL_DSSPOOLER_KEY,
6318 SPOOL_REG_PRINTERNAME,
6319 REG_SZ,
6320 buffer.data,
6321 buffer.length);
6323 if (!force_update) {
6324 notify_printer_printername(server_event_context(),
6325 msg_ctx, snum, p ? p : "");
6329 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6330 push_reg_sz(mem_ctx, &buffer, printer->portname);
6331 winreg_set_printer_dataex(mem_ctx, b,
6332 printer->sharename,
6333 SPOOL_DSSPOOLER_KEY,
6334 SPOOL_REG_PORTNAME,
6335 REG_SZ,
6336 buffer.data,
6337 buffer.length);
6339 if (!force_update) {
6340 notify_printer_port(server_event_context(),
6341 msg_ctx, snum, printer->portname ?
6342 printer->portname : "");
6346 if (force_update || !strequal(printer->location, old_printer->location)) {
6347 push_reg_sz(mem_ctx, &buffer, printer->location);
6348 winreg_set_printer_dataex(mem_ctx, b,
6349 printer->sharename,
6350 SPOOL_DSSPOOLER_KEY,
6351 SPOOL_REG_LOCATION,
6352 REG_SZ,
6353 buffer.data,
6354 buffer.length);
6356 if (!force_update) {
6357 notify_printer_location(server_event_context(),
6358 msg_ctx, snum,
6359 printer->location ?
6360 printer->location : "");
6364 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6365 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6366 winreg_set_printer_dataex(mem_ctx, b,
6367 printer->sharename,
6368 SPOOL_DSSPOOLER_KEY,
6369 SPOOL_REG_PRINTSEPARATORFILE,
6370 REG_SZ,
6371 buffer.data,
6372 buffer.length);
6374 if (!force_update) {
6375 notify_printer_sepfile(server_event_context(),
6376 msg_ctx, snum,
6377 printer->sepfile ?
6378 printer->sepfile : "");
6382 if (force_update || printer->starttime != old_printer->starttime) {
6383 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6384 SIVAL(buffer.data, 0, printer->starttime);
6385 winreg_set_printer_dataex(mem_ctx, b,
6386 printer->sharename,
6387 SPOOL_DSSPOOLER_KEY,
6388 SPOOL_REG_PRINTSTARTTIME,
6389 REG_DWORD,
6390 buffer.data,
6391 buffer.length);
6394 if (force_update || printer->untiltime != old_printer->untiltime) {
6395 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6396 SIVAL(buffer.data, 0, printer->untiltime);
6397 winreg_set_printer_dataex(mem_ctx, b,
6398 printer->sharename,
6399 SPOOL_DSSPOOLER_KEY,
6400 SPOOL_REG_PRINTENDTIME,
6401 REG_DWORD,
6402 buffer.data,
6403 buffer.length);
6406 if (force_update || printer->priority != old_printer->priority) {
6407 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6408 SIVAL(buffer.data, 0, printer->priority);
6409 winreg_set_printer_dataex(mem_ctx, b,
6410 printer->sharename,
6411 SPOOL_DSSPOOLER_KEY,
6412 SPOOL_REG_PRIORITY,
6413 REG_DWORD,
6414 buffer.data,
6415 buffer.length);
6418 if (force_update || printer->attributes != old_printer->attributes) {
6419 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6420 SIVAL(buffer.data, 0, (printer->attributes &
6421 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6422 winreg_set_printer_dataex(mem_ctx, b,
6423 printer->sharename,
6424 SPOOL_DSSPOOLER_KEY,
6425 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6426 REG_DWORD,
6427 buffer.data,
6428 buffer.length);
6430 switch (printer->attributes & 0x3) {
6431 case 0:
6432 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6433 break;
6434 case 1:
6435 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6436 break;
6437 case 2:
6438 spooling = SPOOL_REGVAL_PRINTDIRECT;
6439 break;
6440 default:
6441 spooling = "unknown";
6443 push_reg_sz(mem_ctx, &buffer, spooling);
6444 winreg_set_printer_dataex(mem_ctx, b,
6445 printer->sharename,
6446 SPOOL_DSSPOOLER_KEY,
6447 SPOOL_REG_PRINTSPOOLING,
6448 REG_SZ,
6449 buffer.data,
6450 buffer.length);
6453 push_reg_sz(mem_ctx, &buffer, global_myname());
6454 winreg_set_printer_dataex(mem_ctx, b,
6455 printer->sharename,
6456 SPOOL_DSSPOOLER_KEY,
6457 SPOOL_REG_SHORTSERVERNAME,
6458 REG_SZ,
6459 buffer.data,
6460 buffer.length);
6462 dnsdomname = get_mydnsfullname();
6463 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6464 longname = talloc_strdup(mem_ctx, dnsdomname);
6465 } else {
6466 longname = talloc_strdup(mem_ctx, global_myname());
6468 if (longname == NULL) {
6469 result = WERR_NOMEM;
6470 goto done;
6473 push_reg_sz(mem_ctx, &buffer, longname);
6474 winreg_set_printer_dataex(mem_ctx, b,
6475 printer->sharename,
6476 SPOOL_DSSPOOLER_KEY,
6477 SPOOL_REG_SERVERNAME,
6478 REG_SZ,
6479 buffer.data,
6480 buffer.length);
6482 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6483 global_myname(), printer->sharename);
6484 push_reg_sz(mem_ctx, &buffer, uncname);
6485 winreg_set_printer_dataex(mem_ctx, b,
6486 printer->sharename,
6487 SPOOL_DSSPOOLER_KEY,
6488 SPOOL_REG_UNCNAME,
6489 REG_SZ,
6490 buffer.data,
6491 buffer.length);
6493 done:
6494 return result;
6497 /********************************************************************
6498 * Called by spoolss_api_setprinter
6499 * when updating a printer description.
6500 ********************************************************************/
6502 static WERROR update_printer(struct pipes_struct *p,
6503 struct policy_handle *handle,
6504 struct spoolss_SetPrinterInfoCtr *info_ctr,
6505 struct spoolss_DeviceMode *devmode)
6507 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6508 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6509 struct spoolss_PrinterInfo2 *old_printer;
6510 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6511 int snum;
6512 WERROR result = WERR_OK;
6513 TALLOC_CTX *tmp_ctx;
6514 struct dcerpc_binding_handle *b;
6516 DEBUG(8,("update_printer\n"));
6518 tmp_ctx = talloc_new(p->mem_ctx);
6519 if (tmp_ctx == NULL) {
6520 return WERR_NOMEM;
6523 if (!Printer) {
6524 result = WERR_BADFID;
6525 goto done;
6528 if (!get_printer_snum(p, handle, &snum, NULL)) {
6529 result = WERR_BADFID;
6530 goto done;
6533 result = winreg_printer_binding_handle(tmp_ctx,
6534 get_session_info_system(),
6535 p->msg_ctx,
6536 &b);
6537 if (!W_ERROR_IS_OK(result)) {
6538 goto done;
6541 result = winreg_get_printer(tmp_ctx, b,
6542 lp_const_servicename(snum),
6543 &old_printer);
6544 if (!W_ERROR_IS_OK(result)) {
6545 result = WERR_BADFID;
6546 goto done;
6549 /* Do sanity check on the requested changes for Samba */
6550 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6551 result = WERR_INVALID_PARAM;
6552 goto done;
6555 /* FIXME!!! If the driver has changed we really should verify that
6556 it is installed before doing much else --jerry */
6558 /* Check calling user has permission to update printer description */
6559 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6560 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6561 result = WERR_ACCESS_DENIED;
6562 goto done;
6565 /* Call addprinter hook */
6566 /* Check changes to see if this is really needed */
6568 if (*lp_addprinter_cmd() &&
6569 (!strequal(printer->drivername, old_printer->drivername) ||
6570 !strequal(printer->comment, old_printer->comment) ||
6571 !strequal(printer->portname, old_printer->portname) ||
6572 !strequal(printer->location, old_printer->location)) )
6574 /* add_printer_hook() will call reload_services() */
6575 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6576 printer, p->client_id->addr,
6577 p->msg_ctx)) {
6578 result = WERR_ACCESS_DENIED;
6579 goto done;
6583 update_dsspooler(tmp_ctx,
6584 get_session_info_system(),
6585 p->msg_ctx,
6586 snum,
6587 printer,
6588 old_printer);
6590 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6592 if (devmode == NULL) {
6593 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6595 result = winreg_update_printer(tmp_ctx, b,
6596 printer->sharename,
6597 printer_mask,
6598 printer,
6599 devmode,
6600 NULL);
6602 done:
6603 talloc_free(tmp_ctx);
6605 return result;
6608 /****************************************************************************
6609 ****************************************************************************/
6610 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6611 struct policy_handle *handle,
6612 struct spoolss_SetPrinterInfo7 *info7)
6614 #ifdef HAVE_ADS
6615 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6616 WERROR result;
6617 int snum;
6618 struct printer_handle *Printer;
6620 if ( lp_security() != SEC_ADS ) {
6621 return WERR_UNKNOWN_LEVEL;
6624 Printer = find_printer_index_by_hnd(p, handle);
6626 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6628 if (!Printer)
6629 return WERR_BADFID;
6631 if (!get_printer_snum(p, handle, &snum, NULL))
6632 return WERR_BADFID;
6634 result = winreg_get_printer_internal(p->mem_ctx,
6635 get_session_info_system(),
6636 p->msg_ctx,
6637 lp_servicename(snum),
6638 &pinfo2);
6639 if (!W_ERROR_IS_OK(result)) {
6640 return WERR_BADFID;
6643 nt_printer_publish(pinfo2,
6644 get_session_info_system(),
6645 p->msg_ctx,
6646 pinfo2,
6647 info7->action);
6649 TALLOC_FREE(pinfo2);
6650 return WERR_OK;
6651 #else
6652 return WERR_UNKNOWN_LEVEL;
6653 #endif
6656 /********************************************************************
6657 ********************************************************************/
6659 static WERROR update_printer_devmode(struct pipes_struct *p,
6660 struct policy_handle *handle,
6661 struct spoolss_DeviceMode *devmode)
6663 int snum;
6664 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6665 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6667 DEBUG(8,("update_printer_devmode\n"));
6669 if (!Printer) {
6670 return WERR_BADFID;
6673 if (!get_printer_snum(p, handle, &snum, NULL)) {
6674 return WERR_BADFID;
6677 /* Check calling user has permission to update printer description */
6678 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6679 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6680 return WERR_ACCESS_DENIED;
6683 return winreg_update_printer_internal(p->mem_ctx,
6684 get_session_info_system(),
6685 p->msg_ctx,
6686 lp_const_servicename(snum),
6687 info2_mask,
6688 NULL,
6689 devmode,
6690 NULL);
6694 /****************************************************************
6695 _spoolss_SetPrinter
6696 ****************************************************************/
6698 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6699 struct spoolss_SetPrinter *r)
6701 WERROR result;
6703 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6705 if (!Printer) {
6706 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6707 OUR_HANDLE(r->in.handle)));
6708 return WERR_BADFID;
6711 /* check the level */
6712 switch (r->in.info_ctr->level) {
6713 case 0:
6714 return control_printer(r->in.handle, r->in.command, p);
6715 case 2:
6716 result = update_printer(p, r->in.handle,
6717 r->in.info_ctr,
6718 r->in.devmode_ctr->devmode);
6719 if (!W_ERROR_IS_OK(result))
6720 return result;
6721 if (r->in.secdesc_ctr->sd)
6722 result = update_printer_sec(r->in.handle, p,
6723 r->in.secdesc_ctr);
6724 return result;
6725 case 3:
6726 return update_printer_sec(r->in.handle, p,
6727 r->in.secdesc_ctr);
6728 case 7:
6729 return publish_or_unpublish_printer(p, r->in.handle,
6730 r->in.info_ctr->info.info7);
6731 case 8:
6732 return update_printer_devmode(p, r->in.handle,
6733 r->in.devmode_ctr->devmode);
6734 default:
6735 return WERR_UNKNOWN_LEVEL;
6739 /****************************************************************
6740 _spoolss_FindClosePrinterNotify
6741 ****************************************************************/
6743 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6744 struct spoolss_FindClosePrinterNotify *r)
6746 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6748 if (!Printer) {
6749 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6750 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6751 return WERR_BADFID;
6754 if (Printer->notify.cli_chan != NULL &&
6755 Printer->notify.cli_chan->active_connections > 0) {
6756 int snum = -1;
6758 if (Printer->printer_type == SPLHND_PRINTER) {
6759 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6760 return WERR_BADFID;
6764 srv_spoolss_replycloseprinter(snum, Printer);
6767 Printer->notify.flags=0;
6768 Printer->notify.options=0;
6769 Printer->notify.localmachine[0]='\0';
6770 Printer->notify.printerlocal=0;
6771 TALLOC_FREE(Printer->notify.option);
6773 return WERR_OK;
6776 /****************************************************************
6777 _spoolss_AddJob
6778 ****************************************************************/
6780 WERROR _spoolss_AddJob(struct pipes_struct *p,
6781 struct spoolss_AddJob *r)
6783 if (!r->in.buffer && (r->in.offered != 0)) {
6784 return WERR_INVALID_PARAM;
6787 /* this is what a NT server returns for AddJob. AddJob must fail on
6788 * non-local printers */
6790 if (r->in.level != 1) {
6791 return WERR_UNKNOWN_LEVEL;
6794 return WERR_INVALID_PARAM;
6797 /****************************************************************************
6798 fill_job_info1
6799 ****************************************************************************/
6801 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6802 struct spoolss_JobInfo1 *r,
6803 const print_queue_struct *queue,
6804 int position, int snum,
6805 struct spoolss_PrinterInfo2 *pinfo2)
6807 struct tm *t;
6809 t = gmtime(&queue->time);
6811 r->job_id = queue->sysjob;
6813 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6814 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6815 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6816 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6817 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6818 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6819 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6820 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6821 r->data_type = talloc_strdup(mem_ctx, "RAW");
6822 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6823 r->text_status = talloc_strdup(mem_ctx, "");
6824 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6826 r->status = nt_printj_status(queue->status);
6827 r->priority = queue->priority;
6828 r->position = position;
6829 r->total_pages = queue->page_count;
6830 r->pages_printed = 0; /* ??? */
6832 init_systemtime(&r->submitted, t);
6834 return WERR_OK;
6837 /****************************************************************************
6838 fill_job_info2
6839 ****************************************************************************/
6841 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6842 struct spoolss_JobInfo2 *r,
6843 const print_queue_struct *queue,
6844 int position, int snum,
6845 struct spoolss_PrinterInfo2 *pinfo2,
6846 struct spoolss_DeviceMode *devmode)
6848 struct tm *t;
6850 t = gmtime(&queue->time);
6852 r->job_id = queue->sysjob;
6854 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6855 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6856 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6857 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6858 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6859 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6860 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6861 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6862 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6863 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6864 r->data_type = talloc_strdup(mem_ctx, "RAW");
6865 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6866 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6867 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6868 r->parameters = talloc_strdup(mem_ctx, "");
6869 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6870 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6871 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6873 r->devmode = devmode;
6875 r->text_status = talloc_strdup(mem_ctx, "");
6876 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6878 r->secdesc = NULL;
6880 r->status = nt_printj_status(queue->status);
6881 r->priority = queue->priority;
6882 r->position = position;
6883 r->start_time = 0;
6884 r->until_time = 0;
6885 r->total_pages = queue->page_count;
6886 r->size = queue->size;
6887 init_systemtime(&r->submitted, t);
6888 r->time = 0;
6889 r->pages_printed = 0; /* ??? */
6891 return WERR_OK;
6894 /****************************************************************************
6895 fill_job_info3
6896 ****************************************************************************/
6898 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6899 struct spoolss_JobInfo3 *r,
6900 const print_queue_struct *queue,
6901 const print_queue_struct *next_queue,
6902 int position, int snum,
6903 struct spoolss_PrinterInfo2 *pinfo2)
6905 r->job_id = queue->sysjob;
6906 r->next_job_id = 0;
6907 if (next_queue) {
6908 r->next_job_id = next_queue->sysjob;
6910 r->reserved = 0;
6912 return WERR_OK;
6915 /****************************************************************************
6916 Enumjobs at level 1.
6917 ****************************************************************************/
6919 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6920 const print_queue_struct *queue,
6921 uint32_t num_queues, int snum,
6922 struct spoolss_PrinterInfo2 *pinfo2,
6923 union spoolss_JobInfo **info_p,
6924 uint32_t *count)
6926 union spoolss_JobInfo *info;
6927 int i;
6928 WERROR result = WERR_OK;
6930 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6931 W_ERROR_HAVE_NO_MEMORY(info);
6933 *count = num_queues;
6935 for (i=0; i<*count; i++) {
6936 result = fill_job_info1(info,
6937 &info[i].info1,
6938 &queue[i],
6940 snum,
6941 pinfo2);
6942 if (!W_ERROR_IS_OK(result)) {
6943 goto out;
6947 out:
6948 if (!W_ERROR_IS_OK(result)) {
6949 TALLOC_FREE(info);
6950 *count = 0;
6951 return result;
6954 *info_p = info;
6956 return WERR_OK;
6959 /****************************************************************************
6960 Enumjobs at level 2.
6961 ****************************************************************************/
6963 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6964 const print_queue_struct *queue,
6965 uint32_t num_queues, int snum,
6966 struct spoolss_PrinterInfo2 *pinfo2,
6967 union spoolss_JobInfo **info_p,
6968 uint32_t *count)
6970 union spoolss_JobInfo *info;
6971 int i;
6972 WERROR result = WERR_OK;
6974 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6975 W_ERROR_HAVE_NO_MEMORY(info);
6977 *count = num_queues;
6979 for (i=0; i<*count; i++) {
6980 struct spoolss_DeviceMode *devmode;
6982 result = spoolss_create_default_devmode(info,
6983 pinfo2->printername,
6984 &devmode);
6985 if (!W_ERROR_IS_OK(result)) {
6986 DEBUG(3, ("Can't proceed w/o a devmode!"));
6987 goto out;
6990 result = fill_job_info2(info,
6991 &info[i].info2,
6992 &queue[i],
6994 snum,
6995 pinfo2,
6996 devmode);
6997 if (!W_ERROR_IS_OK(result)) {
6998 goto out;
7002 out:
7003 if (!W_ERROR_IS_OK(result)) {
7004 TALLOC_FREE(info);
7005 *count = 0;
7006 return result;
7009 *info_p = info;
7011 return WERR_OK;
7014 /****************************************************************************
7015 Enumjobs at level 3.
7016 ****************************************************************************/
7018 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7019 const print_queue_struct *queue,
7020 uint32_t num_queues, int snum,
7021 struct spoolss_PrinterInfo2 *pinfo2,
7022 union spoolss_JobInfo **info_p,
7023 uint32_t *count)
7025 union spoolss_JobInfo *info;
7026 int i;
7027 WERROR result = WERR_OK;
7029 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7030 W_ERROR_HAVE_NO_MEMORY(info);
7032 *count = num_queues;
7034 for (i=0; i<*count; i++) {
7035 const print_queue_struct *next_queue = NULL;
7037 if (i+1 < *count) {
7038 next_queue = &queue[i+1];
7041 result = fill_job_info3(info,
7042 &info[i].info3,
7043 &queue[i],
7044 next_queue,
7046 snum,
7047 pinfo2);
7048 if (!W_ERROR_IS_OK(result)) {
7049 goto out;
7053 out:
7054 if (!W_ERROR_IS_OK(result)) {
7055 TALLOC_FREE(info);
7056 *count = 0;
7057 return result;
7060 *info_p = info;
7062 return WERR_OK;
7065 /****************************************************************
7066 _spoolss_EnumJobs
7067 ****************************************************************/
7069 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7070 struct spoolss_EnumJobs *r)
7072 WERROR result;
7073 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7074 int snum;
7075 print_status_struct prt_status;
7076 print_queue_struct *queue = NULL;
7077 uint32_t count;
7079 /* that's an [in out] buffer */
7081 if (!r->in.buffer && (r->in.offered != 0)) {
7082 return WERR_INVALID_PARAM;
7085 DEBUG(4,("_spoolss_EnumJobs\n"));
7087 *r->out.needed = 0;
7088 *r->out.count = 0;
7089 *r->out.info = NULL;
7091 /* lookup the printer snum and tdb entry */
7093 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7094 return WERR_BADFID;
7097 result = winreg_get_printer_internal(p->mem_ctx,
7098 get_session_info_system(),
7099 p->msg_ctx,
7100 lp_const_servicename(snum),
7101 &pinfo2);
7102 if (!W_ERROR_IS_OK(result)) {
7103 return result;
7106 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7107 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7108 count, prt_status.status, prt_status.message));
7110 if (count == 0) {
7111 SAFE_FREE(queue);
7112 TALLOC_FREE(pinfo2);
7113 return WERR_OK;
7116 switch (r->in.level) {
7117 case 1:
7118 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7119 pinfo2, r->out.info, r->out.count);
7120 break;
7121 case 2:
7122 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7123 pinfo2, r->out.info, r->out.count);
7124 break;
7125 case 3:
7126 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7127 pinfo2, r->out.info, r->out.count);
7128 break;
7129 default:
7130 result = WERR_UNKNOWN_LEVEL;
7131 break;
7134 SAFE_FREE(queue);
7135 TALLOC_FREE(pinfo2);
7137 if (!W_ERROR_IS_OK(result)) {
7138 return result;
7141 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7142 spoolss_EnumJobs,
7143 *r->out.info, r->in.level,
7144 *r->out.count);
7145 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7146 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7148 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7151 /****************************************************************
7152 _spoolss_ScheduleJob
7153 ****************************************************************/
7155 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7156 struct spoolss_ScheduleJob *r)
7158 return WERR_OK;
7161 /****************************************************************
7162 ****************************************************************/
7164 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7165 struct messaging_context *msg_ctx,
7166 const char *printer_name,
7167 uint32_t job_id,
7168 struct spoolss_SetJobInfo1 *r)
7170 char *old_doc_name;
7172 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7173 return WERR_BADFID;
7176 if (strequal(old_doc_name, r->document_name)) {
7177 return WERR_OK;
7180 if (!print_job_set_name(server_event_context(), msg_ctx,
7181 printer_name, job_id, r->document_name)) {
7182 return WERR_BADFID;
7185 return WERR_OK;
7188 /****************************************************************
7189 _spoolss_SetJob
7190 ****************************************************************/
7192 WERROR _spoolss_SetJob(struct pipes_struct *p,
7193 struct spoolss_SetJob *r)
7195 const struct auth_serversupplied_info *session_info = p->session_info;
7196 int snum;
7197 WERROR errcode = WERR_BADFUNC;
7199 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7200 return WERR_BADFID;
7203 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7204 return WERR_INVALID_PRINTER_NAME;
7207 switch (r->in.command) {
7208 case SPOOLSS_JOB_CONTROL_CANCEL:
7209 case SPOOLSS_JOB_CONTROL_DELETE:
7210 errcode = print_job_delete(session_info, p->msg_ctx,
7211 snum, r->in.job_id);
7212 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7213 errcode = WERR_OK;
7215 break;
7216 case SPOOLSS_JOB_CONTROL_PAUSE:
7217 errcode = print_job_pause(session_info, p->msg_ctx,
7218 snum, r->in.job_id);
7219 break;
7220 case SPOOLSS_JOB_CONTROL_RESTART:
7221 case SPOOLSS_JOB_CONTROL_RESUME:
7222 errcode = print_job_resume(session_info, p->msg_ctx,
7223 snum, r->in.job_id);
7224 break;
7225 case 0:
7226 errcode = WERR_OK;
7227 break;
7228 default:
7229 return WERR_UNKNOWN_LEVEL;
7232 if (!W_ERROR_IS_OK(errcode)) {
7233 return errcode;
7236 if (r->in.ctr == NULL) {
7237 return errcode;
7240 switch (r->in.ctr->level) {
7241 case 1:
7242 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7243 lp_const_servicename(snum),
7244 r->in.job_id,
7245 r->in.ctr->info.info1);
7246 break;
7247 case 2:
7248 case 3:
7249 case 4:
7250 default:
7251 return WERR_UNKNOWN_LEVEL;
7254 return errcode;
7257 /****************************************************************************
7258 Enumerates all printer drivers by level and architecture.
7259 ****************************************************************************/
7261 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7262 const struct auth_serversupplied_info *session_info,
7263 struct messaging_context *msg_ctx,
7264 const char *servername,
7265 const char *architecture,
7266 uint32_t level,
7267 union spoolss_DriverInfo **info_p,
7268 uint32_t *count_p)
7270 int i;
7271 uint32_t version;
7272 struct spoolss_DriverInfo8 *driver;
7273 union spoolss_DriverInfo *info = NULL;
7274 uint32_t count = 0;
7275 WERROR result = WERR_OK;
7276 uint32_t num_drivers;
7277 const char **drivers;
7278 struct dcerpc_binding_handle *b;
7280 *count_p = 0;
7281 *info_p = NULL;
7283 result = winreg_printer_binding_handle(mem_ctx,
7284 session_info,
7285 msg_ctx,
7286 &b);
7287 if (!W_ERROR_IS_OK(result)) {
7288 goto out;
7291 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7292 result = winreg_get_driver_list(mem_ctx, b,
7293 architecture, version,
7294 &num_drivers, &drivers);
7295 if (!W_ERROR_IS_OK(result)) {
7296 goto out;
7298 DEBUG(4, ("we have:[%d] drivers in environment"
7299 " [%s] and version [%d]\n",
7300 num_drivers, architecture, version));
7302 if (num_drivers != 0) {
7303 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7304 union spoolss_DriverInfo,
7305 count + num_drivers);
7306 if (!info) {
7307 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7308 "failed to enlarge driver info buffer!\n"));
7309 result = WERR_NOMEM;
7310 goto out;
7314 for (i = 0; i < num_drivers; i++) {
7315 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7317 result = winreg_get_driver(mem_ctx, b,
7318 architecture, drivers[i],
7319 version, &driver);
7320 if (!W_ERROR_IS_OK(result)) {
7321 goto out;
7324 switch (level) {
7325 case 1:
7326 result = fill_printer_driver_info1(info, &info[count+i].info1,
7327 driver, servername);
7328 break;
7329 case 2:
7330 result = fill_printer_driver_info2(info, &info[count+i].info2,
7331 driver, servername);
7332 break;
7333 case 3:
7334 result = fill_printer_driver_info3(info, &info[count+i].info3,
7335 driver, servername);
7336 break;
7337 case 4:
7338 result = fill_printer_driver_info4(info, &info[count+i].info4,
7339 driver, servername);
7340 break;
7341 case 5:
7342 result = fill_printer_driver_info5(info, &info[count+i].info5,
7343 driver, servername);
7344 break;
7345 case 6:
7346 result = fill_printer_driver_info6(info, &info[count+i].info6,
7347 driver, servername);
7348 break;
7349 case 8:
7350 result = fill_printer_driver_info8(info, &info[count+i].info8,
7351 driver, servername);
7352 break;
7353 default:
7354 result = WERR_UNKNOWN_LEVEL;
7355 break;
7358 TALLOC_FREE(driver);
7360 if (!W_ERROR_IS_OK(result)) {
7361 goto out;
7365 count += num_drivers;
7366 TALLOC_FREE(drivers);
7369 out:
7370 TALLOC_FREE(drivers);
7372 if (!W_ERROR_IS_OK(result)) {
7373 TALLOC_FREE(info);
7374 return result;
7377 *info_p = info;
7378 *count_p = count;
7380 return WERR_OK;
7383 /****************************************************************************
7384 Enumerates all printer drivers by level.
7385 ****************************************************************************/
7387 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7388 const struct auth_serversupplied_info *session_info,
7389 struct messaging_context *msg_ctx,
7390 const char *servername,
7391 const char *architecture,
7392 uint32_t level,
7393 union spoolss_DriverInfo **info_p,
7394 uint32_t *count_p)
7396 uint32_t a,i;
7397 WERROR result = WERR_OK;
7399 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7401 for (a=0; archi_table[a].long_archi != NULL; a++) {
7403 union spoolss_DriverInfo *info = NULL;
7404 uint32_t count = 0;
7406 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7407 session_info,
7408 msg_ctx,
7409 servername,
7410 archi_table[a].long_archi,
7411 level,
7412 &info,
7413 &count);
7414 if (!W_ERROR_IS_OK(result)) {
7415 continue;
7418 for (i=0; i < count; i++) {
7419 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7420 info[i], info_p, count_p);
7424 return result;
7427 return enumprinterdrivers_level_by_architecture(mem_ctx,
7428 session_info,
7429 msg_ctx,
7430 servername,
7431 architecture,
7432 level,
7433 info_p,
7434 count_p);
7437 /****************************************************************
7438 _spoolss_EnumPrinterDrivers
7439 ****************************************************************/
7441 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7442 struct spoolss_EnumPrinterDrivers *r)
7444 const char *cservername;
7445 WERROR result;
7447 /* that's an [in out] buffer */
7449 if (!r->in.buffer && (r->in.offered != 0)) {
7450 return WERR_INVALID_PARAM;
7453 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7455 *r->out.needed = 0;
7456 *r->out.count = 0;
7457 *r->out.info = NULL;
7459 cservername = canon_servername(r->in.server);
7461 if (!is_myname_or_ipaddr(cservername)) {
7462 return WERR_UNKNOWN_PRINTER_DRIVER;
7465 result = enumprinterdrivers_level(p->mem_ctx,
7466 get_session_info_system(),
7467 p->msg_ctx,
7468 cservername,
7469 r->in.environment,
7470 r->in.level,
7471 r->out.info,
7472 r->out.count);
7473 if (!W_ERROR_IS_OK(result)) {
7474 return result;
7477 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7478 spoolss_EnumPrinterDrivers,
7479 *r->out.info, r->in.level,
7480 *r->out.count);
7481 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7482 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7484 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7487 /****************************************************************
7488 _spoolss_EnumForms
7489 ****************************************************************/
7491 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7492 struct spoolss_EnumForms *r)
7494 WERROR result;
7496 *r->out.count = 0;
7497 *r->out.needed = 0;
7498 *r->out.info = NULL;
7500 /* that's an [in out] buffer */
7502 if (!r->in.buffer && (r->in.offered != 0) ) {
7503 return WERR_INVALID_PARAM;
7506 DEBUG(4,("_spoolss_EnumForms\n"));
7507 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7508 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7510 switch (r->in.level) {
7511 case 1:
7512 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7513 get_session_info_system(),
7514 p->msg_ctx,
7515 r->out.count,
7516 r->out.info);
7517 break;
7518 default:
7519 result = WERR_UNKNOWN_LEVEL;
7520 break;
7523 if (!W_ERROR_IS_OK(result)) {
7524 return result;
7527 if (*r->out.count == 0) {
7528 return WERR_NO_MORE_ITEMS;
7531 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7532 spoolss_EnumForms,
7533 *r->out.info, r->in.level,
7534 *r->out.count);
7535 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7536 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7538 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7541 /****************************************************************
7542 _spoolss_GetForm
7543 ****************************************************************/
7545 WERROR _spoolss_GetForm(struct pipes_struct *p,
7546 struct spoolss_GetForm *r)
7548 WERROR result;
7550 /* that's an [in out] buffer */
7552 if (!r->in.buffer && (r->in.offered != 0)) {
7553 return WERR_INVALID_PARAM;
7556 DEBUG(4,("_spoolss_GetForm\n"));
7557 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7558 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7560 switch (r->in.level) {
7561 case 1:
7562 result = winreg_printer_getform1_internal(p->mem_ctx,
7563 get_session_info_system(),
7564 p->msg_ctx,
7565 r->in.form_name,
7566 &r->out.info->info1);
7567 break;
7568 default:
7569 result = WERR_UNKNOWN_LEVEL;
7570 break;
7573 if (!W_ERROR_IS_OK(result)) {
7574 TALLOC_FREE(r->out.info);
7575 return result;
7578 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7579 r->out.info, r->in.level);
7580 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7582 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7585 /****************************************************************************
7586 ****************************************************************************/
7588 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7589 struct spoolss_PortInfo1 *r,
7590 const char *name)
7592 r->port_name = talloc_strdup(mem_ctx, name);
7593 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7595 return WERR_OK;
7598 /****************************************************************************
7599 TODO: This probably needs distinguish between TCP/IP and Local ports
7600 somehow.
7601 ****************************************************************************/
7603 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7604 struct spoolss_PortInfo2 *r,
7605 const char *name)
7607 r->port_name = talloc_strdup(mem_ctx, name);
7608 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7610 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7611 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7613 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7614 W_ERROR_HAVE_NO_MEMORY(r->description);
7616 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7617 r->reserved = 0;
7619 return WERR_OK;
7623 /****************************************************************************
7624 wrapper around the enumer ports command
7625 ****************************************************************************/
7627 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7629 char *cmd = lp_enumports_cmd();
7630 char **qlines = NULL;
7631 char *command = NULL;
7632 int numlines;
7633 int ret;
7634 int fd;
7636 *count = 0;
7637 *lines = NULL;
7639 /* if no hook then just fill in the default port */
7641 if ( !*cmd ) {
7642 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7643 return WERR_NOMEM;
7645 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7646 TALLOC_FREE(qlines);
7647 return WERR_NOMEM;
7649 qlines[1] = NULL;
7650 numlines = 1;
7652 else {
7653 /* we have a valid enumport command */
7655 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7656 if (!command) {
7657 return WERR_NOMEM;
7660 DEBUG(10,("Running [%s]\n", command));
7661 ret = smbrun(command, &fd);
7662 DEBUG(10,("Returned [%d]\n", ret));
7663 TALLOC_FREE(command);
7664 if (ret != 0) {
7665 if (fd != -1) {
7666 close(fd);
7668 return WERR_ACCESS_DENIED;
7671 numlines = 0;
7672 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7673 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7674 close(fd);
7677 *count = numlines;
7678 *lines = qlines;
7680 return WERR_OK;
7683 /****************************************************************************
7684 enumports level 1.
7685 ****************************************************************************/
7687 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7688 union spoolss_PortInfo **info_p,
7689 uint32_t *count)
7691 union spoolss_PortInfo *info = NULL;
7692 int i=0;
7693 WERROR result = WERR_OK;
7694 char **qlines = NULL;
7695 int numlines = 0;
7697 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7698 if (!W_ERROR_IS_OK(result)) {
7699 goto out;
7702 if (numlines) {
7703 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7704 if (!info) {
7705 DEBUG(10,("Returning WERR_NOMEM\n"));
7706 result = WERR_NOMEM;
7707 goto out;
7710 for (i=0; i<numlines; i++) {
7711 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7712 result = fill_port_1(info, &info[i].info1, qlines[i]);
7713 if (!W_ERROR_IS_OK(result)) {
7714 goto out;
7718 TALLOC_FREE(qlines);
7720 out:
7721 if (!W_ERROR_IS_OK(result)) {
7722 TALLOC_FREE(info);
7723 TALLOC_FREE(qlines);
7724 *count = 0;
7725 *info_p = NULL;
7726 return result;
7729 *info_p = info;
7730 *count = numlines;
7732 return WERR_OK;
7735 /****************************************************************************
7736 enumports level 2.
7737 ****************************************************************************/
7739 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7740 union spoolss_PortInfo **info_p,
7741 uint32_t *count)
7743 union spoolss_PortInfo *info = NULL;
7744 int i=0;
7745 WERROR result = WERR_OK;
7746 char **qlines = NULL;
7747 int numlines = 0;
7749 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7750 if (!W_ERROR_IS_OK(result)) {
7751 goto out;
7754 if (numlines) {
7755 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7756 if (!info) {
7757 DEBUG(10,("Returning WERR_NOMEM\n"));
7758 result = WERR_NOMEM;
7759 goto out;
7762 for (i=0; i<numlines; i++) {
7763 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7764 result = fill_port_2(info, &info[i].info2, qlines[i]);
7765 if (!W_ERROR_IS_OK(result)) {
7766 goto out;
7770 TALLOC_FREE(qlines);
7772 out:
7773 if (!W_ERROR_IS_OK(result)) {
7774 TALLOC_FREE(info);
7775 TALLOC_FREE(qlines);
7776 *count = 0;
7777 *info_p = NULL;
7778 return result;
7781 *info_p = info;
7782 *count = numlines;
7784 return WERR_OK;
7787 /****************************************************************
7788 _spoolss_EnumPorts
7789 ****************************************************************/
7791 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7792 struct spoolss_EnumPorts *r)
7794 WERROR result;
7796 /* that's an [in out] buffer */
7798 if (!r->in.buffer && (r->in.offered != 0)) {
7799 return WERR_INVALID_PARAM;
7802 DEBUG(4,("_spoolss_EnumPorts\n"));
7804 *r->out.count = 0;
7805 *r->out.needed = 0;
7806 *r->out.info = NULL;
7808 switch (r->in.level) {
7809 case 1:
7810 result = enumports_level_1(p->mem_ctx, r->out.info,
7811 r->out.count);
7812 break;
7813 case 2:
7814 result = enumports_level_2(p->mem_ctx, r->out.info,
7815 r->out.count);
7816 break;
7817 default:
7818 return WERR_UNKNOWN_LEVEL;
7821 if (!W_ERROR_IS_OK(result)) {
7822 return result;
7825 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7826 spoolss_EnumPorts,
7827 *r->out.info, r->in.level,
7828 *r->out.count);
7829 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7830 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7832 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7835 /****************************************************************************
7836 ****************************************************************************/
7838 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7839 const char *server,
7840 struct spoolss_SetPrinterInfoCtr *info_ctr,
7841 struct spoolss_DeviceMode *devmode,
7842 struct security_descriptor *secdesc,
7843 struct spoolss_UserLevelCtr *user_ctr,
7844 struct policy_handle *handle)
7846 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7847 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7848 int snum;
7849 WERROR err = WERR_OK;
7851 /* samba does not have a concept of local, non-shared printers yet, so
7852 * make sure we always setup sharename - gd */
7853 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7854 (info2->printername != NULL && info2->printername[0] != '\0')) {
7855 DEBUG(5, ("spoolss_addprinterex_level_2: "
7856 "no sharename has been set, setting printername %s as sharename\n",
7857 info2->printername));
7858 info2->sharename = info2->printername;
7861 /* check to see if the printer already exists */
7862 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7863 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7864 info2->sharename));
7865 return WERR_PRINTER_ALREADY_EXISTS;
7868 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7869 if ((snum = print_queue_snum(info2->printername)) != -1) {
7870 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7871 info2->printername));
7872 return WERR_PRINTER_ALREADY_EXISTS;
7876 /* validate printer info struct */
7877 if (!info2->printername || strlen(info2->printername) == 0) {
7878 return WERR_INVALID_PRINTER_NAME;
7880 if (!info2->portname || strlen(info2->portname) == 0) {
7881 return WERR_UNKNOWN_PORT;
7883 if (!info2->drivername || strlen(info2->drivername) == 0) {
7884 return WERR_UNKNOWN_PRINTER_DRIVER;
7886 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7887 return WERR_UNKNOWN_PRINTPROCESSOR;
7890 /* FIXME!!! smbd should check to see if the driver is installed before
7891 trying to add a printer like this --jerry */
7893 if (*lp_addprinter_cmd() ) {
7894 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7895 info2, p->client_id->addr,
7896 p->msg_ctx) ) {
7897 return WERR_ACCESS_DENIED;
7899 } else {
7900 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7901 "smb.conf parameter \"addprinter command\" is defined. This "
7902 "parameter must exist for this call to succeed\n",
7903 info2->sharename ));
7906 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7907 return WERR_ACCESS_DENIED;
7910 /* you must be a printer admin to add a new printer */
7911 if (!print_access_check(p->session_info,
7912 p->msg_ctx,
7913 snum,
7914 PRINTER_ACCESS_ADMINISTER)) {
7915 return WERR_ACCESS_DENIED;
7919 * Do sanity check on the requested changes for Samba.
7922 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7923 return WERR_INVALID_PARAM;
7926 if (devmode == NULL) {
7927 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7930 update_dsspooler(p->mem_ctx,
7931 get_session_info_system(),
7932 p->msg_ctx,
7934 info2,
7935 NULL);
7937 err = winreg_update_printer_internal(p->mem_ctx,
7938 get_session_info_system(),
7939 p->msg_ctx,
7940 info2->sharename,
7941 info2_mask,
7942 info2,
7943 devmode,
7944 secdesc);
7945 if (!W_ERROR_IS_OK(err)) {
7946 return err;
7949 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7950 if (!W_ERROR_IS_OK(err)) {
7951 /* Handle open failed - remove addition. */
7952 ZERO_STRUCTP(handle);
7953 return err;
7956 return WERR_OK;
7959 /****************************************************************
7960 _spoolss_AddPrinterEx
7961 ****************************************************************/
7963 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7964 struct spoolss_AddPrinterEx *r)
7966 switch (r->in.info_ctr->level) {
7967 case 1:
7968 /* we don't handle yet */
7969 /* but I know what to do ... */
7970 return WERR_UNKNOWN_LEVEL;
7971 case 2:
7972 return spoolss_addprinterex_level_2(p, r->in.server,
7973 r->in.info_ctr,
7974 r->in.devmode_ctr->devmode,
7975 r->in.secdesc_ctr->sd,
7976 r->in.userlevel_ctr,
7977 r->out.handle);
7978 default:
7979 return WERR_UNKNOWN_LEVEL;
7983 /****************************************************************
7984 _spoolss_AddPrinter
7985 ****************************************************************/
7987 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7988 struct spoolss_AddPrinter *r)
7990 struct spoolss_AddPrinterEx a;
7991 struct spoolss_UserLevelCtr userlevel_ctr;
7993 ZERO_STRUCT(userlevel_ctr);
7995 userlevel_ctr.level = 1;
7997 a.in.server = r->in.server;
7998 a.in.info_ctr = r->in.info_ctr;
7999 a.in.devmode_ctr = r->in.devmode_ctr;
8000 a.in.secdesc_ctr = r->in.secdesc_ctr;
8001 a.in.userlevel_ctr = &userlevel_ctr;
8002 a.out.handle = r->out.handle;
8004 return _spoolss_AddPrinterEx(p, &a);
8007 /****************************************************************
8008 _spoolss_AddPrinterDriverEx
8009 ****************************************************************/
8011 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8012 struct spoolss_AddPrinterDriverEx *r)
8014 WERROR err = WERR_OK;
8015 const char *driver_name = NULL;
8016 uint32_t version;
8017 const char *fn;
8019 switch (p->opnum) {
8020 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8021 fn = "_spoolss_AddPrinterDriver";
8022 break;
8023 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8024 fn = "_spoolss_AddPrinterDriverEx";
8025 break;
8026 default:
8027 return WERR_INVALID_PARAM;
8031 * we only support the semantics of AddPrinterDriver()
8032 * i.e. only copy files that are newer than existing ones
8035 if (r->in.flags == 0) {
8036 return WERR_INVALID_PARAM;
8039 if (r->in.flags != APD_COPY_NEW_FILES) {
8040 return WERR_ACCESS_DENIED;
8043 /* FIXME */
8044 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8045 /* Clever hack from Martin Zielinski <mz@seh.de>
8046 * to allow downgrade from level 8 (Vista).
8048 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8049 r->in.info_ctr->level));
8050 return WERR_UNKNOWN_LEVEL;
8053 DEBUG(5,("Cleaning driver's information\n"));
8054 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8055 if (!W_ERROR_IS_OK(err))
8056 goto done;
8058 DEBUG(5,("Moving driver to final destination\n"));
8059 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8060 if (!W_ERROR_IS_OK(err)) {
8061 goto done;
8064 err = winreg_add_driver_internal(p->mem_ctx,
8065 get_session_info_system(),
8066 p->msg_ctx,
8067 r->in.info_ctr,
8068 &driver_name,
8069 &version);
8070 if (!W_ERROR_IS_OK(err)) {
8071 goto done;
8075 * I think this is where he DrvUpgradePrinter() hook would be
8076 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8077 * server. Right now, we just need to send ourselves a message
8078 * to update each printer bound to this driver. --jerry
8081 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8082 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8083 fn, driver_name));
8086 done:
8087 return err;
8090 /****************************************************************
8091 _spoolss_AddPrinterDriver
8092 ****************************************************************/
8094 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8095 struct spoolss_AddPrinterDriver *r)
8097 struct spoolss_AddPrinterDriverEx a;
8099 switch (r->in.info_ctr->level) {
8100 case 2:
8101 case 3:
8102 case 4:
8103 case 5:
8104 break;
8105 default:
8106 return WERR_UNKNOWN_LEVEL;
8109 a.in.servername = r->in.servername;
8110 a.in.info_ctr = r->in.info_ctr;
8111 a.in.flags = APD_COPY_NEW_FILES;
8113 return _spoolss_AddPrinterDriverEx(p, &a);
8116 /****************************************************************************
8117 ****************************************************************************/
8119 struct _spoolss_paths {
8120 int type;
8121 const char *share;
8122 const char *dir;
8125 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8127 static const struct _spoolss_paths spoolss_paths[]= {
8128 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8129 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8132 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8133 const char *servername,
8134 const char *environment,
8135 int component,
8136 char **path)
8138 const char *pservername = NULL;
8139 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8140 const char *short_archi;
8142 *path = NULL;
8144 /* environment may be empty */
8145 if (environment && strlen(environment)) {
8146 long_archi = environment;
8149 /* servername may be empty */
8150 if (servername && strlen(servername)) {
8151 pservername = canon_servername(servername);
8153 if (!is_myname_or_ipaddr(pservername)) {
8154 return WERR_INVALID_PARAM;
8158 if (!(short_archi = get_short_archi(long_archi))) {
8159 return WERR_INVALID_ENVIRONMENT;
8162 switch (component) {
8163 case SPOOLSS_PRTPROCS_PATH:
8164 case SPOOLSS_DRIVER_PATH:
8165 if (pservername) {
8166 *path = talloc_asprintf(mem_ctx,
8167 "\\\\%s\\%s\\%s",
8168 pservername,
8169 spoolss_paths[component].share,
8170 short_archi);
8171 } else {
8172 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8173 SPOOLSS_DEFAULT_SERVER_PATH,
8174 spoolss_paths[component].dir,
8175 short_archi);
8177 break;
8178 default:
8179 return WERR_INVALID_PARAM;
8182 if (!*path) {
8183 return WERR_NOMEM;
8186 return WERR_OK;
8189 /****************************************************************************
8190 ****************************************************************************/
8192 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8193 const char *servername,
8194 const char *environment,
8195 struct spoolss_DriverDirectoryInfo1 *r)
8197 WERROR werr;
8198 char *path = NULL;
8200 werr = compose_spoolss_server_path(mem_ctx,
8201 servername,
8202 environment,
8203 SPOOLSS_DRIVER_PATH,
8204 &path);
8205 if (!W_ERROR_IS_OK(werr)) {
8206 return werr;
8209 DEBUG(4,("printer driver directory: [%s]\n", path));
8211 r->directory_name = path;
8213 return WERR_OK;
8216 /****************************************************************
8217 _spoolss_GetPrinterDriverDirectory
8218 ****************************************************************/
8220 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8221 struct spoolss_GetPrinterDriverDirectory *r)
8223 WERROR werror;
8225 /* that's an [in out] buffer */
8227 if (!r->in.buffer && (r->in.offered != 0)) {
8228 return WERR_INVALID_PARAM;
8231 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8232 r->in.level));
8234 *r->out.needed = 0;
8236 /* r->in.level is ignored */
8238 werror = getprinterdriverdir_level_1(p->mem_ctx,
8239 r->in.server,
8240 r->in.environment,
8241 &r->out.info->info1);
8242 if (!W_ERROR_IS_OK(werror)) {
8243 TALLOC_FREE(r->out.info);
8244 return werror;
8247 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8248 r->out.info, r->in.level);
8249 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8251 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8254 /****************************************************************
8255 _spoolss_EnumPrinterData
8256 ****************************************************************/
8258 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8259 struct spoolss_EnumPrinterData *r)
8261 WERROR result;
8262 struct spoolss_EnumPrinterDataEx r2;
8263 uint32_t count;
8264 struct spoolss_PrinterEnumValues *info, *val = NULL;
8265 uint32_t needed;
8267 r2.in.handle = r->in.handle;
8268 r2.in.key_name = "PrinterDriverData";
8269 r2.in.offered = 0;
8270 r2.out.count = &count;
8271 r2.out.info = &info;
8272 r2.out.needed = &needed;
8274 result = _spoolss_EnumPrinterDataEx(p, &r2);
8275 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8276 r2.in.offered = needed;
8277 result = _spoolss_EnumPrinterDataEx(p, &r2);
8279 if (!W_ERROR_IS_OK(result)) {
8280 return result;
8284 * The NT machine wants to know the biggest size of value and data
8286 * cf: MSDN EnumPrinterData remark section
8289 if (!r->in.value_offered && !r->in.data_offered) {
8290 uint32_t biggest_valuesize = 0;
8291 uint32_t biggest_datasize = 0;
8292 int i, name_length;
8294 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8296 for (i=0; i<count; i++) {
8298 name_length = strlen(info[i].value_name);
8299 if (strlen(info[i].value_name) > biggest_valuesize) {
8300 biggest_valuesize = name_length;
8303 if (info[i].data_length > biggest_datasize) {
8304 biggest_datasize = info[i].data_length;
8307 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8308 biggest_datasize));
8311 /* the value is an UNICODE string but real_value_size is the length
8312 in bytes including the trailing 0 */
8314 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8315 *r->out.data_needed = biggest_datasize;
8317 DEBUG(6,("final values: [%d], [%d]\n",
8318 *r->out.value_needed, *r->out.data_needed));
8320 return WERR_OK;
8323 if (r->in.enum_index < count) {
8324 val = &info[r->in.enum_index];
8327 if (val == NULL) {
8328 /* out_value should default to "" or else NT4 has
8329 problems unmarshalling the response */
8331 if (r->in.value_offered) {
8332 *r->out.value_needed = 1;
8333 r->out.value_name = talloc_strdup(r, "");
8334 if (!r->out.value_name) {
8335 return WERR_NOMEM;
8337 } else {
8338 r->out.value_name = NULL;
8339 *r->out.value_needed = 0;
8342 /* the data is counted in bytes */
8344 *r->out.data_needed = r->in.data_offered;
8346 result = WERR_NO_MORE_ITEMS;
8347 } else {
8349 * the value is:
8350 * - counted in bytes in the request
8351 * - counted in UNICODE chars in the max reply
8352 * - counted in bytes in the real size
8354 * take a pause *before* coding not *during* coding
8357 /* name */
8358 if (r->in.value_offered) {
8359 r->out.value_name = talloc_strdup(r, val->value_name);
8360 if (!r->out.value_name) {
8361 return WERR_NOMEM;
8363 *r->out.value_needed = val->value_name_len;
8364 } else {
8365 r->out.value_name = NULL;
8366 *r->out.value_needed = 0;
8369 /* type */
8371 *r->out.type = val->type;
8373 /* data - counted in bytes */
8376 * See the section "Dynamically Typed Query Parameters"
8377 * in MS-RPRN.
8380 if (r->out.data && val->data && val->data->data &&
8381 val->data_length && r->in.data_offered) {
8382 memcpy(r->out.data, val->data->data,
8383 MIN(val->data_length,r->in.data_offered));
8386 *r->out.data_needed = val->data_length;
8388 result = WERR_OK;
8391 return result;
8394 /****************************************************************
8395 _spoolss_SetPrinterData
8396 ****************************************************************/
8398 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8399 struct spoolss_SetPrinterData *r)
8401 struct spoolss_SetPrinterDataEx r2;
8403 r2.in.handle = r->in.handle;
8404 r2.in.key_name = "PrinterDriverData";
8405 r2.in.value_name = r->in.value_name;
8406 r2.in.type = r->in.type;
8407 r2.in.data = r->in.data;
8408 r2.in.offered = r->in.offered;
8410 return _spoolss_SetPrinterDataEx(p, &r2);
8413 /****************************************************************
8414 _spoolss_ResetPrinter
8415 ****************************************************************/
8417 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8418 struct spoolss_ResetPrinter *r)
8420 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8421 int snum;
8423 DEBUG(5,("_spoolss_ResetPrinter\n"));
8426 * All we do is to check to see if the handle and queue is valid.
8427 * This call really doesn't mean anything to us because we only
8428 * support RAW printing. --jerry
8431 if (!Printer) {
8432 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8433 OUR_HANDLE(r->in.handle)));
8434 return WERR_BADFID;
8437 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8438 return WERR_BADFID;
8441 /* blindly return success */
8442 return WERR_OK;
8445 /****************************************************************
8446 _spoolss_DeletePrinterData
8447 ****************************************************************/
8449 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8450 struct spoolss_DeletePrinterData *r)
8452 struct spoolss_DeletePrinterDataEx r2;
8454 r2.in.handle = r->in.handle;
8455 r2.in.key_name = "PrinterDriverData";
8456 r2.in.value_name = r->in.value_name;
8458 return _spoolss_DeletePrinterDataEx(p, &r2);
8461 /****************************************************************
8462 _spoolss_AddForm
8463 ****************************************************************/
8465 WERROR _spoolss_AddForm(struct pipes_struct *p,
8466 struct spoolss_AddForm *r)
8468 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8469 int snum = -1;
8470 WERROR status = WERR_OK;
8471 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8472 struct dcerpc_binding_handle *b;
8474 DEBUG(5,("_spoolss_AddForm\n"));
8476 if (!Printer) {
8477 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8478 OUR_HANDLE(r->in.handle)));
8479 return WERR_BADFID;
8482 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8483 and not a printer admin, then fail */
8485 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8486 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8487 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8488 p->session_info->info3->base.domain.string,
8489 NULL,
8490 p->session_info->security_token,
8491 lp_printer_admin(snum))) {
8492 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8493 return WERR_ACCESS_DENIED;
8496 switch (form->flags) {
8497 case SPOOLSS_FORM_USER:
8498 case SPOOLSS_FORM_BUILTIN:
8499 case SPOOLSS_FORM_PRINTER:
8500 break;
8501 default:
8502 return WERR_INVALID_PARAM;
8505 status = winreg_printer_binding_handle(p->mem_ctx,
8506 get_session_info_system(),
8507 p->msg_ctx,
8508 &b);
8509 if (!W_ERROR_IS_OK(status)) {
8510 return status;
8513 status = winreg_printer_addform1(p->mem_ctx, b,
8514 form);
8515 if (!W_ERROR_IS_OK(status)) {
8516 return status;
8520 * ChangeID must always be set if this is a printer
8522 if (Printer->printer_type == SPLHND_PRINTER) {
8523 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8524 return WERR_BADFID;
8527 status = winreg_printer_update_changeid(p->mem_ctx, b,
8528 lp_const_servicename(snum));
8529 if (!W_ERROR_IS_OK(status)) {
8530 return status;
8534 return status;
8537 /****************************************************************
8538 _spoolss_DeleteForm
8539 ****************************************************************/
8541 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8542 struct spoolss_DeleteForm *r)
8544 const char *form_name = r->in.form_name;
8545 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8546 int snum = -1;
8547 WERROR status = WERR_OK;
8548 struct dcerpc_binding_handle *b;
8550 DEBUG(5,("_spoolss_DeleteForm\n"));
8552 if (!Printer) {
8553 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8554 OUR_HANDLE(r->in.handle)));
8555 return WERR_BADFID;
8558 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8559 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8560 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8561 p->session_info->info3->base.domain.string,
8562 NULL,
8563 p->session_info->security_token,
8564 lp_printer_admin(snum))) {
8565 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8566 return WERR_ACCESS_DENIED;
8569 status = winreg_printer_binding_handle(p->mem_ctx,
8570 get_session_info_system(),
8571 p->msg_ctx,
8572 &b);
8573 if (!W_ERROR_IS_OK(status)) {
8574 return status;
8577 status = winreg_printer_deleteform1(p->mem_ctx, b,
8578 form_name);
8579 if (!W_ERROR_IS_OK(status)) {
8580 return status;
8584 * ChangeID must always be set if this is a printer
8586 if (Printer->printer_type == SPLHND_PRINTER) {
8587 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8588 return WERR_BADFID;
8591 status = winreg_printer_update_changeid(p->mem_ctx, b,
8592 lp_const_servicename(snum));
8593 if (!W_ERROR_IS_OK(status)) {
8594 return status;
8598 return status;
8601 /****************************************************************
8602 _spoolss_SetForm
8603 ****************************************************************/
8605 WERROR _spoolss_SetForm(struct pipes_struct *p,
8606 struct spoolss_SetForm *r)
8608 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8609 const char *form_name = r->in.form_name;
8610 int snum = -1;
8611 WERROR status = WERR_OK;
8612 struct dcerpc_binding_handle *b;
8614 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8616 DEBUG(5,("_spoolss_SetForm\n"));
8618 if (!Printer) {
8619 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8620 OUR_HANDLE(r->in.handle)));
8621 return WERR_BADFID;
8624 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8625 and not a printer admin, then fail */
8627 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8628 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8629 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8630 p->session_info->info3->base.domain.string,
8631 NULL,
8632 p->session_info->security_token,
8633 lp_printer_admin(snum))) {
8634 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8635 return WERR_ACCESS_DENIED;
8638 status = winreg_printer_binding_handle(p->mem_ctx,
8639 get_session_info_system(),
8640 p->msg_ctx,
8641 &b);
8642 if (!W_ERROR_IS_OK(status)) {
8643 return status;
8646 status = winreg_printer_setform1(p->mem_ctx, b,
8647 form_name,
8648 form);
8649 if (!W_ERROR_IS_OK(status)) {
8650 return status;
8654 * ChangeID must always be set if this is a printer
8656 if (Printer->printer_type == SPLHND_PRINTER) {
8657 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8658 return WERR_BADFID;
8661 status = winreg_printer_update_changeid(p->mem_ctx, b,
8662 lp_const_servicename(snum));
8663 if (!W_ERROR_IS_OK(status)) {
8664 return status;
8668 return status;
8671 /****************************************************************************
8672 fill_print_processor1
8673 ****************************************************************************/
8675 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8676 struct spoolss_PrintProcessorInfo1 *r,
8677 const char *print_processor_name)
8679 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8680 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8682 return WERR_OK;
8685 /****************************************************************************
8686 enumprintprocessors level 1.
8687 ****************************************************************************/
8689 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8690 union spoolss_PrintProcessorInfo **info_p,
8691 uint32_t *count)
8693 union spoolss_PrintProcessorInfo *info;
8694 WERROR result;
8696 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8697 W_ERROR_HAVE_NO_MEMORY(info);
8699 *count = 1;
8701 result = fill_print_processor1(info, &info[0].info1, "winprint");
8702 if (!W_ERROR_IS_OK(result)) {
8703 goto out;
8706 out:
8707 if (!W_ERROR_IS_OK(result)) {
8708 TALLOC_FREE(info);
8709 *count = 0;
8710 return result;
8713 *info_p = info;
8715 return WERR_OK;
8718 /****************************************************************
8719 _spoolss_EnumPrintProcessors
8720 ****************************************************************/
8722 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8723 struct spoolss_EnumPrintProcessors *r)
8725 WERROR result;
8727 /* that's an [in out] buffer */
8729 if (!r->in.buffer && (r->in.offered != 0)) {
8730 return WERR_INVALID_PARAM;
8733 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8736 * Enumerate the print processors ...
8738 * Just reply with "winprint", to keep NT happy
8739 * and I can use my nice printer checker.
8742 *r->out.count = 0;
8743 *r->out.needed = 0;
8744 *r->out.info = NULL;
8746 if (!get_short_archi(r->in.environment)) {
8747 return WERR_INVALID_ENVIRONMENT;
8750 switch (r->in.level) {
8751 case 1:
8752 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8753 r->out.count);
8754 break;
8755 default:
8756 return WERR_UNKNOWN_LEVEL;
8759 if (!W_ERROR_IS_OK(result)) {
8760 return result;
8763 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8764 spoolss_EnumPrintProcessors,
8765 *r->out.info, r->in.level,
8766 *r->out.count);
8767 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8768 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8770 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8773 /****************************************************************************
8774 fill_printprocdatatype1
8775 ****************************************************************************/
8777 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8778 struct spoolss_PrintProcDataTypesInfo1 *r,
8779 const char *name_array)
8781 r->name_array = talloc_strdup(mem_ctx, name_array);
8782 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8784 return WERR_OK;
8787 /****************************************************************************
8788 enumprintprocdatatypes level 1.
8789 ****************************************************************************/
8791 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8792 union spoolss_PrintProcDataTypesInfo **info_p,
8793 uint32_t *count)
8795 WERROR result;
8796 union spoolss_PrintProcDataTypesInfo *info;
8798 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8799 W_ERROR_HAVE_NO_MEMORY(info);
8801 *count = 1;
8803 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8804 if (!W_ERROR_IS_OK(result)) {
8805 goto out;
8808 out:
8809 if (!W_ERROR_IS_OK(result)) {
8810 TALLOC_FREE(info);
8811 *count = 0;
8812 return result;
8815 *info_p = info;
8817 return WERR_OK;
8820 /****************************************************************
8821 _spoolss_EnumPrintProcDataTypes
8822 ****************************************************************/
8824 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8825 struct spoolss_EnumPrintProcDataTypes *r)
8827 WERROR result;
8829 /* that's an [in out] buffer */
8831 if (!r->in.buffer && (r->in.offered != 0)) {
8832 return WERR_INVALID_PARAM;
8835 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8837 *r->out.count = 0;
8838 *r->out.needed = 0;
8839 *r->out.info = NULL;
8841 if (r->in.print_processor_name == NULL ||
8842 !strequal(r->in.print_processor_name, "winprint")) {
8843 return WERR_UNKNOWN_PRINTPROCESSOR;
8846 switch (r->in.level) {
8847 case 1:
8848 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8849 r->out.count);
8850 break;
8851 default:
8852 return WERR_UNKNOWN_LEVEL;
8855 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8856 spoolss_EnumPrintProcDataTypes,
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_monitor_1
8867 ****************************************************************************/
8869 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8870 struct spoolss_MonitorInfo1 *r,
8871 const char *monitor_name)
8873 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8874 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8876 return WERR_OK;
8879 /****************************************************************************
8880 fill_monitor_2
8881 ****************************************************************************/
8883 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8884 struct spoolss_MonitorInfo2 *r,
8885 const char *monitor_name,
8886 const char *environment,
8887 const char *dll_name)
8889 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8890 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8891 r->environment = talloc_strdup(mem_ctx, environment);
8892 W_ERROR_HAVE_NO_MEMORY(r->environment);
8893 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8894 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8896 return WERR_OK;
8899 /****************************************************************************
8900 enumprintmonitors level 1.
8901 ****************************************************************************/
8903 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8904 union spoolss_MonitorInfo **info_p,
8905 uint32_t *count)
8907 union spoolss_MonitorInfo *info;
8908 WERROR result = WERR_OK;
8910 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8911 W_ERROR_HAVE_NO_MEMORY(info);
8913 *count = 2;
8915 result = fill_monitor_1(info, &info[0].info1,
8916 SPL_LOCAL_PORT);
8917 if (!W_ERROR_IS_OK(result)) {
8918 goto out;
8921 result = fill_monitor_1(info, &info[1].info1,
8922 SPL_TCPIP_PORT);
8923 if (!W_ERROR_IS_OK(result)) {
8924 goto out;
8927 out:
8928 if (!W_ERROR_IS_OK(result)) {
8929 TALLOC_FREE(info);
8930 *count = 0;
8931 return result;
8934 *info_p = info;
8936 return WERR_OK;
8939 /****************************************************************************
8940 enumprintmonitors level 2.
8941 ****************************************************************************/
8943 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8944 union spoolss_MonitorInfo **info_p,
8945 uint32_t *count)
8947 union spoolss_MonitorInfo *info;
8948 WERROR result = WERR_OK;
8950 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8951 W_ERROR_HAVE_NO_MEMORY(info);
8953 *count = 2;
8955 result = fill_monitor_2(info, &info[0].info2,
8956 SPL_LOCAL_PORT,
8957 "Windows NT X86", /* FIXME */
8958 "localmon.dll");
8959 if (!W_ERROR_IS_OK(result)) {
8960 goto out;
8963 result = fill_monitor_2(info, &info[1].info2,
8964 SPL_TCPIP_PORT,
8965 "Windows NT X86", /* FIXME */
8966 "tcpmon.dll");
8967 if (!W_ERROR_IS_OK(result)) {
8968 goto out;
8971 out:
8972 if (!W_ERROR_IS_OK(result)) {
8973 TALLOC_FREE(info);
8974 *count = 0;
8975 return result;
8978 *info_p = info;
8980 return WERR_OK;
8983 /****************************************************************
8984 _spoolss_EnumMonitors
8985 ****************************************************************/
8987 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8988 struct spoolss_EnumMonitors *r)
8990 WERROR result;
8992 /* that's an [in out] buffer */
8994 if (!r->in.buffer && (r->in.offered != 0)) {
8995 return WERR_INVALID_PARAM;
8998 DEBUG(5,("_spoolss_EnumMonitors\n"));
9001 * Enumerate the print monitors ...
9003 * Just reply with "Local Port", to keep NT happy
9004 * and I can use my nice printer checker.
9007 *r->out.count = 0;
9008 *r->out.needed = 0;
9009 *r->out.info = NULL;
9011 switch (r->in.level) {
9012 case 1:
9013 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9014 r->out.count);
9015 break;
9016 case 2:
9017 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9018 r->out.count);
9019 break;
9020 default:
9021 return WERR_UNKNOWN_LEVEL;
9024 if (!W_ERROR_IS_OK(result)) {
9025 return result;
9028 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9029 spoolss_EnumMonitors,
9030 *r->out.info, r->in.level,
9031 *r->out.count);
9032 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9033 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9035 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9038 /****************************************************************************
9039 ****************************************************************************/
9041 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9042 const print_queue_struct *queue,
9043 int count, int snum,
9044 struct spoolss_PrinterInfo2 *pinfo2,
9045 uint32_t jobid,
9046 struct spoolss_JobInfo1 *r)
9048 int i = 0;
9049 bool found = false;
9051 for (i=0; i<count; i++) {
9052 if (queue[i].sysjob == (int)jobid) {
9053 found = true;
9054 break;
9058 if (found == false) {
9059 /* NT treats not found as bad param... yet another bad choice */
9060 return WERR_INVALID_PARAM;
9063 return fill_job_info1(mem_ctx,
9065 &queue[i],
9067 snum,
9068 pinfo2);
9071 /****************************************************************************
9072 ****************************************************************************/
9074 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9075 const print_queue_struct *queue,
9076 int count, int snum,
9077 struct spoolss_PrinterInfo2 *pinfo2,
9078 uint32_t jobid,
9079 struct spoolss_JobInfo2 *r)
9081 int i = 0;
9082 bool found = false;
9083 struct spoolss_DeviceMode *devmode;
9084 WERROR result;
9086 for (i=0; i<count; i++) {
9087 if (queue[i].sysjob == (int)jobid) {
9088 found = true;
9089 break;
9093 if (found == false) {
9094 /* NT treats not found as bad param... yet another bad
9095 choice */
9096 return WERR_INVALID_PARAM;
9100 * if the print job does not have a DEVMODE associated with it,
9101 * just use the one for the printer. A NULL devicemode is not
9102 * a failure condition
9105 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9106 if (!devmode) {
9107 result = spoolss_create_default_devmode(mem_ctx,
9108 pinfo2->printername,
9109 &devmode);
9110 if (!W_ERROR_IS_OK(result)) {
9111 DEBUG(3, ("Can't proceed w/o a devmode!"));
9112 return result;
9116 return fill_job_info2(mem_ctx,
9118 &queue[i],
9120 snum,
9121 pinfo2,
9122 devmode);
9125 /****************************************************************
9126 _spoolss_GetJob
9127 ****************************************************************/
9129 WERROR _spoolss_GetJob(struct pipes_struct *p,
9130 struct spoolss_GetJob *r)
9132 WERROR result = WERR_OK;
9133 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9134 int snum;
9135 int count;
9136 print_queue_struct *queue = NULL;
9137 print_status_struct prt_status;
9139 /* that's an [in out] buffer */
9141 if (!r->in.buffer && (r->in.offered != 0)) {
9142 return WERR_INVALID_PARAM;
9145 DEBUG(5,("_spoolss_GetJob\n"));
9147 *r->out.needed = 0;
9149 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9150 return WERR_BADFID;
9153 result = winreg_get_printer_internal(p->mem_ctx,
9154 get_session_info_system(),
9155 p->msg_ctx,
9156 lp_const_servicename(snum),
9157 &pinfo2);
9158 if (!W_ERROR_IS_OK(result)) {
9159 return result;
9162 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9164 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9165 count, prt_status.status, prt_status.message));
9167 switch (r->in.level) {
9168 case 1:
9169 result = getjob_level_1(p->mem_ctx,
9170 queue, count, snum, pinfo2,
9171 r->in.job_id, &r->out.info->info1);
9172 break;
9173 case 2:
9174 result = getjob_level_2(p->mem_ctx,
9175 queue, count, snum, pinfo2,
9176 r->in.job_id, &r->out.info->info2);
9177 break;
9178 default:
9179 result = WERR_UNKNOWN_LEVEL;
9180 break;
9183 SAFE_FREE(queue);
9184 TALLOC_FREE(pinfo2);
9186 if (!W_ERROR_IS_OK(result)) {
9187 TALLOC_FREE(r->out.info);
9188 return result;
9191 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9192 r->in.level);
9193 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9195 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9198 /****************************************************************
9199 _spoolss_GetPrinterDataEx
9200 ****************************************************************/
9202 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9203 struct spoolss_GetPrinterDataEx *r)
9206 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9207 const char *printer;
9208 int snum = 0;
9209 WERROR result = WERR_OK;
9210 DATA_BLOB blob;
9211 enum winreg_Type val_type = REG_NONE;
9212 uint8_t *val_data = NULL;
9213 uint32_t val_size = 0;
9214 struct dcerpc_binding_handle *b;
9216 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9218 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9219 r->in.key_name, r->in.value_name));
9221 /* in case of problem, return some default values */
9223 *r->out.needed = 0;
9224 *r->out.type = REG_NONE;
9226 if (!Printer) {
9227 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9228 OUR_HANDLE(r->in.handle)));
9229 result = WERR_BADFID;
9230 goto done;
9233 /* Is the handle to a printer or to the server? */
9235 if (Printer->printer_type == SPLHND_SERVER) {
9237 union spoolss_PrinterData data;
9239 result = getprinterdata_printer_server(p->mem_ctx,
9240 r->in.value_name,
9241 r->out.type,
9242 &data);
9243 if (!W_ERROR_IS_OK(result)) {
9244 return result;
9247 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9248 *r->out.type, &data);
9249 if (!W_ERROR_IS_OK(result)) {
9250 return result;
9253 *r->out.needed = blob.length;
9255 if (r->in.offered >= *r->out.needed) {
9256 memcpy(r->out.data, blob.data, blob.length);
9259 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9262 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9263 return WERR_BADFID;
9265 printer = lp_const_servicename(snum);
9267 /* check to see if the keyname is valid */
9268 if (!strlen(r->in.key_name)) {
9269 return WERR_INVALID_PARAM;
9272 result = winreg_printer_binding_handle(p->mem_ctx,
9273 get_session_info_system(),
9274 p->msg_ctx,
9275 &b);
9276 if (!W_ERROR_IS_OK(result)) {
9277 return result;
9280 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9281 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9282 strequal(r->in.value_name, "ChangeId")) {
9283 *r->out.type = REG_DWORD;
9284 *r->out.needed = 4;
9285 if (r->in.offered >= *r->out.needed) {
9286 uint32_t changeid = 0;
9288 result = winreg_printer_get_changeid(p->mem_ctx, b,
9289 printer,
9290 &changeid);
9291 if (!W_ERROR_IS_OK(result)) {
9292 return result;
9295 SIVAL(r->out.data, 0, changeid);
9296 result = WERR_OK;
9298 goto done;
9301 result = winreg_get_printer_dataex(p->mem_ctx, b,
9302 printer,
9303 r->in.key_name,
9304 r->in.value_name,
9305 &val_type,
9306 &val_data,
9307 &val_size);
9308 if (!W_ERROR_IS_OK(result)) {
9309 return result;
9312 *r->out.needed = val_size;
9313 *r->out.type = val_type;
9315 if (r->in.offered >= *r->out.needed) {
9316 memcpy(r->out.data, val_data, val_size);
9319 done:
9320 /* retain type when returning WERR_MORE_DATA */
9321 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9323 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9326 /****************************************************************
9327 _spoolss_SetPrinterDataEx
9328 ****************************************************************/
9330 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9331 struct spoolss_SetPrinterDataEx *r)
9333 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9334 int snum = 0;
9335 WERROR result = WERR_OK;
9336 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9337 char *oid_string;
9338 struct dcerpc_binding_handle *b;
9340 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9342 /* From MSDN documentation of SetPrinterDataEx: pass request to
9343 SetPrinterData if key is "PrinterDriverData" */
9345 if (!Printer) {
9346 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9347 OUR_HANDLE(r->in.handle)));
9348 return WERR_BADFID;
9351 if (Printer->printer_type == SPLHND_SERVER) {
9352 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9353 "Not implemented for server handles yet\n"));
9354 return WERR_INVALID_PARAM;
9357 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9358 return WERR_BADFID;
9362 * Access check : NT returns "access denied" if you make a
9363 * SetPrinterData call without the necessary privildge.
9364 * we were originally returning OK if nothing changed
9365 * which made Win2k issue **a lot** of SetPrinterData
9366 * when connecting to a printer --jerry
9369 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9370 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9371 "change denied by handle access permissions\n"));
9372 return WERR_ACCESS_DENIED;
9375 result = winreg_printer_binding_handle(p->mem_ctx,
9376 get_session_info_system(),
9377 p->msg_ctx,
9378 &b);
9379 if (!W_ERROR_IS_OK(result)) {
9380 return result;
9383 result = winreg_get_printer(Printer, b,
9384 lp_servicename(snum),
9385 &pinfo2);
9386 if (!W_ERROR_IS_OK(result)) {
9387 return result;
9390 /* check for OID in valuename */
9392 oid_string = strchr(r->in.value_name, ',');
9393 if (oid_string) {
9394 *oid_string = '\0';
9395 oid_string++;
9398 /* save the registry data */
9400 result = winreg_set_printer_dataex(p->mem_ctx, b,
9401 pinfo2->sharename,
9402 r->in.key_name,
9403 r->in.value_name,
9404 r->in.type,
9405 r->in.data,
9406 r->in.offered);
9408 if (W_ERROR_IS_OK(result)) {
9409 /* save the OID if one was specified */
9410 if (oid_string) {
9411 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9412 r->in.key_name, SPOOL_OID_KEY);
9413 if (!str) {
9414 result = WERR_NOMEM;
9415 goto done;
9419 * I'm not checking the status here on purpose. Don't know
9420 * if this is right, but I'm returning the status from the
9421 * previous set_printer_dataex() call. I have no idea if
9422 * this is right. --jerry
9424 winreg_set_printer_dataex(p->mem_ctx, b,
9425 pinfo2->sharename,
9426 str,
9427 r->in.value_name,
9428 REG_SZ,
9429 (uint8_t *) oid_string,
9430 strlen(oid_string) + 1);
9433 result = winreg_printer_update_changeid(p->mem_ctx, b,
9434 lp_const_servicename(snum));
9438 done:
9439 talloc_free(pinfo2);
9440 return result;
9443 /****************************************************************
9444 _spoolss_DeletePrinterDataEx
9445 ****************************************************************/
9447 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9448 struct spoolss_DeletePrinterDataEx *r)
9450 const char *printer;
9451 int snum=0;
9452 WERROR status = WERR_OK;
9453 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9455 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9457 if (!Printer) {
9458 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9459 "Invalid handle (%s:%u:%u).\n",
9460 OUR_HANDLE(r->in.handle)));
9461 return WERR_BADFID;
9464 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9465 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9466 "printer properties change denied by handle\n"));
9467 return WERR_ACCESS_DENIED;
9470 if (!r->in.value_name || !r->in.key_name) {
9471 return WERR_NOMEM;
9474 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9475 return WERR_BADFID;
9477 printer = lp_const_servicename(snum);
9479 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9480 get_session_info_system(),
9481 p->msg_ctx,
9482 printer,
9483 r->in.key_name,
9484 r->in.value_name);
9485 if (W_ERROR_IS_OK(status)) {
9486 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9487 get_session_info_system(),
9488 p->msg_ctx,
9489 printer);
9492 return status;
9495 /****************************************************************
9496 _spoolss_EnumPrinterKey
9497 ****************************************************************/
9499 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9500 struct spoolss_EnumPrinterKey *r)
9502 uint32_t num_keys;
9503 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9504 int snum = 0;
9505 WERROR result = WERR_BADFILE;
9506 const char **array = NULL;
9507 DATA_BLOB blob;
9509 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9511 if (!Printer) {
9512 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9513 OUR_HANDLE(r->in.handle)));
9514 return WERR_BADFID;
9517 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9518 return WERR_BADFID;
9521 result = winreg_enum_printer_key_internal(p->mem_ctx,
9522 get_session_info_system(),
9523 p->msg_ctx,
9524 lp_const_servicename(snum),
9525 r->in.key_name,
9526 &num_keys,
9527 &array);
9528 if (!W_ERROR_IS_OK(result)) {
9529 goto done;
9532 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9533 result = WERR_NOMEM;
9534 goto done;
9537 *r->out._ndr_size = r->in.offered / 2;
9538 *r->out.needed = blob.length;
9540 if (r->in.offered < *r->out.needed) {
9541 result = WERR_MORE_DATA;
9542 } else {
9543 result = WERR_OK;
9544 r->out.key_buffer->string_array = array;
9547 done:
9548 if (!W_ERROR_IS_OK(result)) {
9549 TALLOC_FREE(array);
9550 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9551 *r->out.needed = 0;
9555 return result;
9558 /****************************************************************
9559 _spoolss_DeletePrinterKey
9560 ****************************************************************/
9562 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9563 struct spoolss_DeletePrinterKey *r)
9565 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9566 int snum=0;
9567 WERROR status;
9568 const char *printer;
9569 struct dcerpc_binding_handle *b;
9571 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9573 if (!Printer) {
9574 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9575 OUR_HANDLE(r->in.handle)));
9576 return WERR_BADFID;
9579 /* if keyname == NULL, return error */
9580 if ( !r->in.key_name )
9581 return WERR_INVALID_PARAM;
9583 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9584 return WERR_BADFID;
9587 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9588 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9589 "printer properties change denied by handle\n"));
9590 return WERR_ACCESS_DENIED;
9593 printer = lp_const_servicename(snum);
9595 status = winreg_printer_binding_handle(p->mem_ctx,
9596 get_session_info_system(),
9597 p->msg_ctx,
9598 &b);
9599 if (!W_ERROR_IS_OK(status)) {
9600 return status;
9603 /* delete the key and all subkeys */
9604 status = winreg_delete_printer_key(p->mem_ctx, b,
9605 printer,
9606 r->in.key_name);
9607 if (W_ERROR_IS_OK(status)) {
9608 status = winreg_printer_update_changeid(p->mem_ctx, b,
9609 printer);
9612 return status;
9615 /****************************************************************
9616 _spoolss_EnumPrinterDataEx
9617 ****************************************************************/
9619 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9620 struct spoolss_EnumPrinterDataEx *r)
9622 uint32_t count = 0;
9623 struct spoolss_PrinterEnumValues *info = NULL;
9624 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9625 int snum;
9626 WERROR result;
9628 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9630 *r->out.count = 0;
9631 *r->out.needed = 0;
9632 *r->out.info = NULL;
9634 if (!Printer) {
9635 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9636 OUR_HANDLE(r->in.handle)));
9637 return WERR_BADFID;
9641 * first check for a keyname of NULL or "". Win2k seems to send
9642 * this a lot and we should send back WERR_INVALID_PARAM
9643 * no need to spend time looking up the printer in this case.
9644 * --jerry
9647 if (!strlen(r->in.key_name)) {
9648 result = WERR_INVALID_PARAM;
9649 goto done;
9652 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9653 return WERR_BADFID;
9656 /* now look for a match on the key name */
9657 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9658 get_session_info_system(),
9659 p->msg_ctx,
9660 lp_const_servicename(snum),
9661 r->in.key_name,
9662 &count,
9663 &info);
9664 if (!W_ERROR_IS_OK(result)) {
9665 goto done;
9668 #if 0 /* FIXME - gd */
9669 /* housekeeping information in the reply */
9671 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9672 * the hand marshalled container size is a multiple
9673 * of 4 bytes for RPC alignment.
9676 if (needed % 4) {
9677 needed += 4-(needed % 4);
9679 #endif
9680 *r->out.count = count;
9681 *r->out.info = info;
9683 done:
9684 if (!W_ERROR_IS_OK(result)) {
9685 return result;
9688 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9689 spoolss_EnumPrinterDataEx,
9690 *r->out.info,
9691 *r->out.count);
9692 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9693 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9695 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9698 /****************************************************************************
9699 ****************************************************************************/
9701 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9702 const char *servername,
9703 const char *environment,
9704 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9706 WERROR werr;
9707 char *path = NULL;
9709 werr = compose_spoolss_server_path(mem_ctx,
9710 servername,
9711 environment,
9712 SPOOLSS_PRTPROCS_PATH,
9713 &path);
9714 if (!W_ERROR_IS_OK(werr)) {
9715 return werr;
9718 DEBUG(4,("print processor directory: [%s]\n", path));
9720 r->directory_name = path;
9722 return WERR_OK;
9725 /****************************************************************
9726 _spoolss_GetPrintProcessorDirectory
9727 ****************************************************************/
9729 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9730 struct spoolss_GetPrintProcessorDirectory *r)
9732 WERROR result;
9733 char *prnproc_share = NULL;
9734 bool prnproc_share_exists = false;
9735 int snum;
9737 /* that's an [in out] buffer */
9739 if (!r->in.buffer && (r->in.offered != 0)) {
9740 return WERR_INVALID_PARAM;
9743 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9744 r->in.level));
9746 *r->out.needed = 0;
9748 /* r->in.level is ignored */
9750 /* We always should reply with a local print processor directory so that
9751 * users are not forced to have a [prnproc$] share on the Samba spoolss
9752 * server, if users decide to do so, lets announce it though - Guenther */
9754 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9755 if (!prnproc_share) {
9756 return WERR_NOMEM;
9758 if (snum != -1) {
9759 prnproc_share_exists = true;
9762 result = getprintprocessordirectory_level_1(p->mem_ctx,
9763 prnproc_share_exists ? r->in.server : NULL,
9764 r->in.environment,
9765 &r->out.info->info1);
9766 if (!W_ERROR_IS_OK(result)) {
9767 TALLOC_FREE(r->out.info);
9768 return result;
9771 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9772 r->out.info, r->in.level);
9773 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9775 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9778 /*******************************************************************
9779 ********************************************************************/
9781 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9782 const char *dllname)
9784 enum ndr_err_code ndr_err;
9785 struct spoolss_MonitorUi ui;
9787 ui.dll_name = dllname;
9789 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9790 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9791 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9792 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9794 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9797 /*******************************************************************
9798 Streams the monitor UI DLL name in UNICODE
9799 *******************************************************************/
9801 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9802 struct security_token *token, DATA_BLOB *in,
9803 DATA_BLOB *out, uint32_t *needed)
9805 const char *dllname = "tcpmonui.dll";
9807 *needed = (strlen(dllname)+1) * 2;
9809 if (out->length < *needed) {
9810 return WERR_INSUFFICIENT_BUFFER;
9813 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9814 return WERR_NOMEM;
9817 return WERR_OK;
9820 /*******************************************************************
9821 ********************************************************************/
9823 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9824 struct spoolss_PortData1 *port1,
9825 const DATA_BLOB *buf)
9827 enum ndr_err_code ndr_err;
9828 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9829 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9830 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9831 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9833 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9836 /*******************************************************************
9837 ********************************************************************/
9839 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9840 struct spoolss_PortData2 *port2,
9841 const DATA_BLOB *buf)
9843 enum ndr_err_code ndr_err;
9844 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9845 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9846 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9847 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9849 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9852 /*******************************************************************
9853 Create a new TCP/IP port
9854 *******************************************************************/
9856 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9857 struct security_token *token, DATA_BLOB *in,
9858 DATA_BLOB *out, uint32_t *needed)
9860 struct spoolss_PortData1 port1;
9861 struct spoolss_PortData2 port2;
9862 char *device_uri = NULL;
9863 uint32_t version;
9865 const char *portname;
9866 const char *hostaddress;
9867 const char *queue;
9868 uint32_t port_number;
9869 uint32_t protocol;
9871 /* peek for spoolss_PortData version */
9873 if (!in || (in->length < (128 + 4))) {
9874 return WERR_GENERAL_FAILURE;
9877 version = IVAL(in->data, 128);
9879 switch (version) {
9880 case 1:
9881 ZERO_STRUCT(port1);
9883 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9884 return WERR_NOMEM;
9887 portname = port1.portname;
9888 hostaddress = port1.hostaddress;
9889 queue = port1.queue;
9890 protocol = port1.protocol;
9891 port_number = port1.port_number;
9893 break;
9894 case 2:
9895 ZERO_STRUCT(port2);
9897 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9898 return WERR_NOMEM;
9901 portname = port2.portname;
9902 hostaddress = port2.hostaddress;
9903 queue = port2.queue;
9904 protocol = port2.protocol;
9905 port_number = port2.port_number;
9907 break;
9908 default:
9909 DEBUG(1,("xcvtcp_addport: "
9910 "unknown version of port_data: %d\n", version));
9911 return WERR_UNKNOWN_PORT;
9914 /* create the device URI and call the add_port_hook() */
9916 switch (protocol) {
9917 case PROTOCOL_RAWTCP_TYPE:
9918 device_uri = talloc_asprintf(mem_ctx,
9919 "socket://%s:%d/", hostaddress,
9920 port_number);
9921 break;
9923 case PROTOCOL_LPR_TYPE:
9924 device_uri = talloc_asprintf(mem_ctx,
9925 "lpr://%s/%s", hostaddress, queue );
9926 break;
9928 default:
9929 return WERR_UNKNOWN_PORT;
9932 if (!device_uri) {
9933 return WERR_NOMEM;
9936 return add_port_hook(mem_ctx, token, portname, device_uri);
9939 /*******************************************************************
9940 *******************************************************************/
9942 struct xcv_api_table xcvtcp_cmds[] = {
9943 { "MonitorUI", xcvtcp_monitorui },
9944 { "AddPort", xcvtcp_addport},
9945 { NULL, NULL }
9948 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9949 struct security_token *token, const char *command,
9950 DATA_BLOB *inbuf,
9951 DATA_BLOB *outbuf,
9952 uint32_t *needed )
9954 int i;
9956 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9958 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9959 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9960 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9963 return WERR_BADFUNC;
9966 /*******************************************************************
9967 *******************************************************************/
9968 #if 0 /* don't support management using the "Local Port" monitor */
9970 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9971 struct security_token *token, DATA_BLOB *in,
9972 DATA_BLOB *out, uint32_t *needed)
9974 const char *dllname = "localui.dll";
9976 *needed = (strlen(dllname)+1) * 2;
9978 if (out->length < *needed) {
9979 return WERR_INSUFFICIENT_BUFFER;
9982 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9983 return WERR_NOMEM;
9986 return WERR_OK;
9989 /*******************************************************************
9990 *******************************************************************/
9992 struct xcv_api_table xcvlocal_cmds[] = {
9993 { "MonitorUI", xcvlocal_monitorui },
9994 { NULL, NULL }
9996 #else
9997 struct xcv_api_table xcvlocal_cmds[] = {
9998 { NULL, NULL }
10000 #endif
10004 /*******************************************************************
10005 *******************************************************************/
10007 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10008 struct security_token *token, const char *command,
10009 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10010 uint32_t *needed)
10012 int i;
10014 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10016 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10017 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10018 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10020 return WERR_BADFUNC;
10023 /****************************************************************
10024 _spoolss_XcvData
10025 ****************************************************************/
10027 WERROR _spoolss_XcvData(struct pipes_struct *p,
10028 struct spoolss_XcvData *r)
10030 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10031 DATA_BLOB out_data = data_blob_null;
10032 WERROR werror;
10034 if (!Printer) {
10035 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10036 OUR_HANDLE(r->in.handle)));
10037 return WERR_BADFID;
10040 /* Has to be a handle to the TCP/IP port monitor */
10042 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10043 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10044 return WERR_BADFID;
10047 /* requires administrative access to the server */
10049 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10050 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10051 return WERR_ACCESS_DENIED;
10054 /* Allocate the outgoing buffer */
10056 if (r->in.out_data_size) {
10057 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10058 if (out_data.data == NULL) {
10059 return WERR_NOMEM;
10063 switch ( Printer->printer_type ) {
10064 case SPLHND_PORTMON_TCP:
10065 werror = process_xcvtcp_command(p->mem_ctx,
10066 p->session_info->security_token,
10067 r->in.function_name,
10068 &r->in.in_data, &out_data,
10069 r->out.needed);
10070 break;
10071 case SPLHND_PORTMON_LOCAL:
10072 werror = process_xcvlocal_command(p->mem_ctx,
10073 p->session_info->security_token,
10074 r->in.function_name,
10075 &r->in.in_data, &out_data,
10076 r->out.needed);
10077 break;
10078 default:
10079 werror = WERR_INVALID_PRINT_MONITOR;
10082 if (!W_ERROR_IS_OK(werror)) {
10083 return werror;
10086 *r->out.status_code = 0;
10088 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10089 memcpy(r->out.out_data, out_data.data,
10090 MIN(r->in.out_data_size, out_data.length));
10093 return WERR_OK;
10096 /****************************************************************
10097 _spoolss_AddPrintProcessor
10098 ****************************************************************/
10100 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10101 struct spoolss_AddPrintProcessor *r)
10103 /* for now, just indicate success and ignore the add. We'll
10104 automatically set the winprint processor for printer
10105 entries later. Used to debug the LexMark Optra S 1855 PCL
10106 driver --jerry */
10108 return WERR_OK;
10111 /****************************************************************
10112 _spoolss_AddPort
10113 ****************************************************************/
10115 WERROR _spoolss_AddPort(struct pipes_struct *p,
10116 struct spoolss_AddPort *r)
10118 /* do what w2k3 does */
10120 return WERR_NOT_SUPPORTED;
10123 /****************************************************************
10124 _spoolss_GetPrinterDriver
10125 ****************************************************************/
10127 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10128 struct spoolss_GetPrinterDriver *r)
10130 p->rng_fault_state = true;
10131 return WERR_NOT_SUPPORTED;
10134 /****************************************************************
10135 _spoolss_ReadPrinter
10136 ****************************************************************/
10138 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10139 struct spoolss_ReadPrinter *r)
10141 p->rng_fault_state = true;
10142 return WERR_NOT_SUPPORTED;
10145 /****************************************************************
10146 _spoolss_WaitForPrinterChange
10147 ****************************************************************/
10149 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10150 struct spoolss_WaitForPrinterChange *r)
10152 p->rng_fault_state = true;
10153 return WERR_NOT_SUPPORTED;
10156 /****************************************************************
10157 _spoolss_ConfigurePort
10158 ****************************************************************/
10160 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10161 struct spoolss_ConfigurePort *r)
10163 p->rng_fault_state = true;
10164 return WERR_NOT_SUPPORTED;
10167 /****************************************************************
10168 _spoolss_DeletePort
10169 ****************************************************************/
10171 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10172 struct spoolss_DeletePort *r)
10174 p->rng_fault_state = true;
10175 return WERR_NOT_SUPPORTED;
10178 /****************************************************************
10179 _spoolss_CreatePrinterIC
10180 ****************************************************************/
10182 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10183 struct spoolss_CreatePrinterIC *r)
10185 p->rng_fault_state = true;
10186 return WERR_NOT_SUPPORTED;
10189 /****************************************************************
10190 _spoolss_PlayGDIScriptOnPrinterIC
10191 ****************************************************************/
10193 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10194 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10196 p->rng_fault_state = true;
10197 return WERR_NOT_SUPPORTED;
10200 /****************************************************************
10201 _spoolss_DeletePrinterIC
10202 ****************************************************************/
10204 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10205 struct spoolss_DeletePrinterIC *r)
10207 p->rng_fault_state = true;
10208 return WERR_NOT_SUPPORTED;
10211 /****************************************************************
10212 _spoolss_AddPrinterConnection
10213 ****************************************************************/
10215 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10216 struct spoolss_AddPrinterConnection *r)
10218 p->rng_fault_state = true;
10219 return WERR_NOT_SUPPORTED;
10222 /****************************************************************
10223 _spoolss_DeletePrinterConnection
10224 ****************************************************************/
10226 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10227 struct spoolss_DeletePrinterConnection *r)
10229 p->rng_fault_state = true;
10230 return WERR_NOT_SUPPORTED;
10233 /****************************************************************
10234 _spoolss_PrinterMessageBox
10235 ****************************************************************/
10237 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10238 struct spoolss_PrinterMessageBox *r)
10240 p->rng_fault_state = true;
10241 return WERR_NOT_SUPPORTED;
10244 /****************************************************************
10245 _spoolss_AddMonitor
10246 ****************************************************************/
10248 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10249 struct spoolss_AddMonitor *r)
10251 p->rng_fault_state = true;
10252 return WERR_NOT_SUPPORTED;
10255 /****************************************************************
10256 _spoolss_DeleteMonitor
10257 ****************************************************************/
10259 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10260 struct spoolss_DeleteMonitor *r)
10262 p->rng_fault_state = true;
10263 return WERR_NOT_SUPPORTED;
10266 /****************************************************************
10267 _spoolss_DeletePrintProcessor
10268 ****************************************************************/
10270 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10271 struct spoolss_DeletePrintProcessor *r)
10273 p->rng_fault_state = true;
10274 return WERR_NOT_SUPPORTED;
10277 /****************************************************************
10278 _spoolss_AddPrintProvidor
10279 ****************************************************************/
10281 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10282 struct spoolss_AddPrintProvidor *r)
10284 p->rng_fault_state = true;
10285 return WERR_NOT_SUPPORTED;
10288 /****************************************************************
10289 _spoolss_DeletePrintProvidor
10290 ****************************************************************/
10292 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10293 struct spoolss_DeletePrintProvidor *r)
10295 p->rng_fault_state = true;
10296 return WERR_NOT_SUPPORTED;
10299 /****************************************************************
10300 _spoolss_FindFirstPrinterChangeNotification
10301 ****************************************************************/
10303 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10304 struct spoolss_FindFirstPrinterChangeNotification *r)
10306 p->rng_fault_state = true;
10307 return WERR_NOT_SUPPORTED;
10310 /****************************************************************
10311 _spoolss_FindNextPrinterChangeNotification
10312 ****************************************************************/
10314 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10315 struct spoolss_FindNextPrinterChangeNotification *r)
10317 p->rng_fault_state = true;
10318 return WERR_NOT_SUPPORTED;
10321 /****************************************************************
10322 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10323 ****************************************************************/
10325 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10326 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10328 p->rng_fault_state = true;
10329 return WERR_NOT_SUPPORTED;
10332 /****************************************************************
10333 _spoolss_ReplyOpenPrinter
10334 ****************************************************************/
10336 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10337 struct spoolss_ReplyOpenPrinter *r)
10339 p->rng_fault_state = true;
10340 return WERR_NOT_SUPPORTED;
10343 /****************************************************************
10344 _spoolss_RouterReplyPrinter
10345 ****************************************************************/
10347 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10348 struct spoolss_RouterReplyPrinter *r)
10350 p->rng_fault_state = true;
10351 return WERR_NOT_SUPPORTED;
10354 /****************************************************************
10355 _spoolss_ReplyClosePrinter
10356 ****************************************************************/
10358 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10359 struct spoolss_ReplyClosePrinter *r)
10361 p->rng_fault_state = true;
10362 return WERR_NOT_SUPPORTED;
10365 /****************************************************************
10366 _spoolss_AddPortEx
10367 ****************************************************************/
10369 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10370 struct spoolss_AddPortEx *r)
10372 p->rng_fault_state = true;
10373 return WERR_NOT_SUPPORTED;
10376 /****************************************************************
10377 _spoolss_RouterFindFirstPrinterChangeNotification
10378 ****************************************************************/
10380 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10381 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10383 p->rng_fault_state = true;
10384 return WERR_NOT_SUPPORTED;
10387 /****************************************************************
10388 _spoolss_SpoolerInit
10389 ****************************************************************/
10391 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10392 struct spoolss_SpoolerInit *r)
10394 p->rng_fault_state = true;
10395 return WERR_NOT_SUPPORTED;
10398 /****************************************************************
10399 _spoolss_ResetPrinterEx
10400 ****************************************************************/
10402 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10403 struct spoolss_ResetPrinterEx *r)
10405 p->rng_fault_state = true;
10406 return WERR_NOT_SUPPORTED;
10409 /****************************************************************
10410 _spoolss_RouterReplyPrinterEx
10411 ****************************************************************/
10413 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10414 struct spoolss_RouterReplyPrinterEx *r)
10416 p->rng_fault_state = true;
10417 return WERR_NOT_SUPPORTED;
10420 /****************************************************************
10421 _spoolss_44
10422 ****************************************************************/
10424 WERROR _spoolss_44(struct pipes_struct *p,
10425 struct spoolss_44 *r)
10427 p->rng_fault_state = true;
10428 return WERR_NOT_SUPPORTED;
10431 /****************************************************************
10432 _spoolss_SetPort
10433 ****************************************************************/
10435 WERROR _spoolss_SetPort(struct pipes_struct *p,
10436 struct spoolss_SetPort *r)
10438 p->rng_fault_state = true;
10439 return WERR_NOT_SUPPORTED;
10442 /****************************************************************
10443 _spoolss_4a
10444 ****************************************************************/
10446 WERROR _spoolss_4a(struct pipes_struct *p,
10447 struct spoolss_4a *r)
10449 p->rng_fault_state = true;
10450 return WERR_NOT_SUPPORTED;
10453 /****************************************************************
10454 _spoolss_4b
10455 ****************************************************************/
10457 WERROR _spoolss_4b(struct pipes_struct *p,
10458 struct spoolss_4b *r)
10460 p->rng_fault_state = true;
10461 return WERR_NOT_SUPPORTED;
10464 /****************************************************************
10465 _spoolss_4c
10466 ****************************************************************/
10468 WERROR _spoolss_4c(struct pipes_struct *p,
10469 struct spoolss_4c *r)
10471 p->rng_fault_state = true;
10472 return WERR_NOT_SUPPORTED;
10475 /****************************************************************
10476 _spoolss_53
10477 ****************************************************************/
10479 WERROR _spoolss_53(struct pipes_struct *p,
10480 struct spoolss_53 *r)
10482 p->rng_fault_state = true;
10483 return WERR_NOT_SUPPORTED;
10486 /****************************************************************
10487 _spoolss_AddPerMachineConnection
10488 ****************************************************************/
10490 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10491 struct spoolss_AddPerMachineConnection *r)
10493 p->rng_fault_state = true;
10494 return WERR_NOT_SUPPORTED;
10497 /****************************************************************
10498 _spoolss_DeletePerMachineConnection
10499 ****************************************************************/
10501 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10502 struct spoolss_DeletePerMachineConnection *r)
10504 p->rng_fault_state = true;
10505 return WERR_NOT_SUPPORTED;
10508 /****************************************************************
10509 _spoolss_EnumPerMachineConnections
10510 ****************************************************************/
10512 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10513 struct spoolss_EnumPerMachineConnections *r)
10515 p->rng_fault_state = true;
10516 return WERR_NOT_SUPPORTED;
10519 /****************************************************************
10520 _spoolss_5a
10521 ****************************************************************/
10523 WERROR _spoolss_5a(struct pipes_struct *p,
10524 struct spoolss_5a *r)
10526 p->rng_fault_state = true;
10527 return WERR_NOT_SUPPORTED;
10530 /****************************************************************
10531 _spoolss_5b
10532 ****************************************************************/
10534 WERROR _spoolss_5b(struct pipes_struct *p,
10535 struct spoolss_5b *r)
10537 p->rng_fault_state = true;
10538 return WERR_NOT_SUPPORTED;
10541 /****************************************************************
10542 _spoolss_5c
10543 ****************************************************************/
10545 WERROR _spoolss_5c(struct pipes_struct *p,
10546 struct spoolss_5c *r)
10548 p->rng_fault_state = true;
10549 return WERR_NOT_SUPPORTED;
10552 /****************************************************************
10553 _spoolss_5d
10554 ****************************************************************/
10556 WERROR _spoolss_5d(struct pipes_struct *p,
10557 struct spoolss_5d *r)
10559 p->rng_fault_state = true;
10560 return WERR_NOT_SUPPORTED;
10563 /****************************************************************
10564 _spoolss_5e
10565 ****************************************************************/
10567 WERROR _spoolss_5e(struct pipes_struct *p,
10568 struct spoolss_5e *r)
10570 p->rng_fault_state = true;
10571 return WERR_NOT_SUPPORTED;
10574 /****************************************************************
10575 _spoolss_5f
10576 ****************************************************************/
10578 WERROR _spoolss_5f(struct pipes_struct *p,
10579 struct spoolss_5f *r)
10581 p->rng_fault_state = true;
10582 return WERR_NOT_SUPPORTED;
10585 /****************************************************************
10586 _spoolss_60
10587 ****************************************************************/
10589 WERROR _spoolss_60(struct pipes_struct *p,
10590 struct spoolss_60 *r)
10592 p->rng_fault_state = true;
10593 return WERR_NOT_SUPPORTED;
10596 /****************************************************************
10597 _spoolss_61
10598 ****************************************************************/
10600 WERROR _spoolss_61(struct pipes_struct *p,
10601 struct spoolss_61 *r)
10603 p->rng_fault_state = true;
10604 return WERR_NOT_SUPPORTED;
10607 /****************************************************************
10608 _spoolss_62
10609 ****************************************************************/
10611 WERROR _spoolss_62(struct pipes_struct *p,
10612 struct spoolss_62 *r)
10614 p->rng_fault_state = true;
10615 return WERR_NOT_SUPPORTED;
10618 /****************************************************************
10619 _spoolss_63
10620 ****************************************************************/
10622 WERROR _spoolss_63(struct pipes_struct *p,
10623 struct spoolss_63 *r)
10625 p->rng_fault_state = true;
10626 return WERR_NOT_SUPPORTED;
10629 /****************************************************************
10630 _spoolss_64
10631 ****************************************************************/
10633 WERROR _spoolss_64(struct pipes_struct *p,
10634 struct spoolss_64 *r)
10636 p->rng_fault_state = true;
10637 return WERR_NOT_SUPPORTED;
10640 /****************************************************************
10641 _spoolss_65
10642 ****************************************************************/
10644 WERROR _spoolss_65(struct pipes_struct *p,
10645 struct spoolss_65 *r)
10647 p->rng_fault_state = true;
10648 return WERR_NOT_SUPPORTED;
10651 /****************************************************************
10652 _spoolss_GetCorePrinterDrivers
10653 ****************************************************************/
10655 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10656 struct spoolss_GetCorePrinterDrivers *r)
10658 p->rng_fault_state = true;
10659 return WERR_NOT_SUPPORTED;
10662 /****************************************************************
10663 _spoolss_67
10664 ****************************************************************/
10666 WERROR _spoolss_67(struct pipes_struct *p,
10667 struct spoolss_67 *r)
10669 p->rng_fault_state = true;
10670 return WERR_NOT_SUPPORTED;
10673 /****************************************************************
10674 _spoolss_GetPrinterDriverPackagePath
10675 ****************************************************************/
10677 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10678 struct spoolss_GetPrinterDriverPackagePath *r)
10680 p->rng_fault_state = true;
10681 return WERR_NOT_SUPPORTED;
10684 /****************************************************************
10685 _spoolss_69
10686 ****************************************************************/
10688 WERROR _spoolss_69(struct pipes_struct *p,
10689 struct spoolss_69 *r)
10691 p->rng_fault_state = true;
10692 return WERR_NOT_SUPPORTED;
10695 /****************************************************************
10696 _spoolss_6a
10697 ****************************************************************/
10699 WERROR _spoolss_6a(struct pipes_struct *p,
10700 struct spoolss_6a *r)
10702 p->rng_fault_state = true;
10703 return WERR_NOT_SUPPORTED;
10706 /****************************************************************
10707 _spoolss_6b
10708 ****************************************************************/
10710 WERROR _spoolss_6b(struct pipes_struct *p,
10711 struct spoolss_6b *r)
10713 p->rng_fault_state = true;
10714 return WERR_NOT_SUPPORTED;
10717 /****************************************************************
10718 _spoolss_6c
10719 ****************************************************************/
10721 WERROR _spoolss_6c(struct pipes_struct *p,
10722 struct spoolss_6c *r)
10724 p->rng_fault_state = true;
10725 return WERR_NOT_SUPPORTED;
10728 /****************************************************************
10729 _spoolss_6d
10730 ****************************************************************/
10732 WERROR _spoolss_6d(struct pipes_struct *p,
10733 struct spoolss_6d *r)
10735 p->rng_fault_state = true;
10736 return WERR_NOT_SUPPORTED;