spoolss: fix DPD_DELETE_ALL_FILES error return
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob2403f32d9db81c1c8c2d64f1cfe425d0e04e32de
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) {
1947 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948 &Printer->devmode);
1951 #if 0 /* JERRY -- I'm doubtful this is really effective */
1952 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1953 optimization in Windows 2000 clients --jerry */
1955 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1956 && (RA_WIN2K == get_remote_arch()) )
1958 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1959 sys_usleep( 500000 );
1961 #endif
1963 return WERR_OK;
1966 /****************************************************************
1967 _spoolss_ClosePrinter
1968 ****************************************************************/
1970 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1971 struct spoolss_ClosePrinter *r)
1973 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1975 if (Printer && Printer->document_started) {
1976 struct spoolss_EndDocPrinter e;
1978 e.in.handle = r->in.handle;
1980 _spoolss_EndDocPrinter(p, &e);
1983 if (!close_printer_handle(p, r->in.handle))
1984 return WERR_BADFID;
1986 /* clear the returned printer handle. Observed behavior
1987 from Win2k server. Don't think this really matters.
1988 Previous code just copied the value of the closed
1989 handle. --jerry */
1991 ZERO_STRUCTP(r->out.handle);
1993 return WERR_OK;
1996 /****************************************************************
1997 _spoolss_DeletePrinter
1998 ****************************************************************/
2000 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2001 struct spoolss_DeletePrinter *r)
2003 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2004 WERROR result;
2005 int snum;
2007 if (Printer && Printer->document_started) {
2008 struct spoolss_EndDocPrinter e;
2010 e.in.handle = r->in.handle;
2012 _spoolss_EndDocPrinter(p, &e);
2015 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2016 winreg_delete_printer_key_internal(p->mem_ctx,
2017 get_session_info_system(),
2018 p->msg_ctx,
2019 lp_const_servicename(snum),
2020 "");
2023 result = delete_printer_handle(p, r->in.handle);
2025 return result;
2028 /*******************************************************************
2029 * static function to lookup the version id corresponding to an
2030 * long architecture string
2031 ******************************************************************/
2033 static const struct print_architecture_table_node archi_table[]= {
2035 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2036 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2037 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2038 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2039 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2040 {"Windows IA64", SPL_ARCH_IA64, 3 },
2041 {"Windows x64", SPL_ARCH_X64, 3 },
2042 {NULL, "", -1 }
2045 static int get_version_id(const char *arch)
2047 int i;
2049 for (i=0; archi_table[i].long_archi != NULL; i++)
2051 if (strcmp(arch, archi_table[i].long_archi) == 0)
2052 return (archi_table[i].version);
2055 return -1;
2058 /****************************************************************
2059 _spoolss_DeletePrinterDriver
2060 ****************************************************************/
2062 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2063 struct spoolss_DeletePrinterDriver *r)
2066 struct spoolss_DriverInfo8 *info = NULL;
2067 struct spoolss_DriverInfo8 *info_win2k = NULL;
2068 int version;
2069 WERROR status;
2070 struct dcerpc_binding_handle *b;
2072 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2073 and not a printer admin, then fail */
2075 if ( (p->session_info->utok.uid != sec_initial_uid())
2076 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2077 && !token_contains_name_in_list(
2078 uidtoname(p->session_info->utok.uid),
2079 p->session_info->info3->base.domain.string,
2080 NULL,
2081 p->session_info->security_token,
2082 lp_printer_admin(-1)) )
2084 return WERR_ACCESS_DENIED;
2087 /* check that we have a valid driver name first */
2089 if ((version = get_version_id(r->in.architecture)) == -1)
2090 return WERR_INVALID_ENVIRONMENT;
2092 status = winreg_printer_binding_handle(p->mem_ctx,
2093 get_session_info_system(),
2094 p->msg_ctx,
2095 &b);
2096 if (!W_ERROR_IS_OK(status)) {
2097 return status;
2100 status = winreg_get_driver(p->mem_ctx, b,
2101 r->in.architecture, r->in.driver,
2102 version, &info);
2103 if (!W_ERROR_IS_OK(status)) {
2104 /* try for Win2k driver if "Windows NT x86" */
2106 if ( version == 2 ) {
2107 version = 3;
2109 status = winreg_get_driver(p->mem_ctx, b,
2110 r->in.architecture,
2111 r->in.driver,
2112 version, &info);
2113 if (!W_ERROR_IS_OK(status)) {
2114 status = WERR_UNKNOWN_PRINTER_DRIVER;
2115 goto done;
2118 /* otherwise it was a failure */
2119 else {
2120 status = WERR_UNKNOWN_PRINTER_DRIVER;
2121 goto done;
2126 if (printer_driver_in_use(p->mem_ctx,
2127 get_session_info_system(),
2128 p->msg_ctx,
2129 info)) {
2130 status = WERR_PRINTER_DRIVER_IN_USE;
2131 goto done;
2134 if (version == 2) {
2135 status = winreg_get_driver(p->mem_ctx, b,
2136 r->in.architecture,
2137 r->in.driver, 3, &info_win2k);
2138 if (W_ERROR_IS_OK(status)) {
2139 /* if we get to here, we now have 2 driver info structures to remove */
2140 /* remove the Win2k driver first*/
2142 status = winreg_del_driver(p->mem_ctx, b,
2143 info_win2k, 3);
2144 talloc_free(info_win2k);
2146 /* this should not have failed---if it did, report to client */
2147 if (!W_ERROR_IS_OK(status)) {
2148 goto done;
2153 status = winreg_del_driver(p->mem_ctx, b,
2154 info, version);
2156 done:
2157 talloc_free(info);
2159 return status;
2162 /****************************************************************
2163 _spoolss_DeletePrinterDriverEx
2164 ****************************************************************/
2166 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2167 struct spoolss_DeletePrinterDriverEx *r)
2169 struct spoolss_DriverInfo8 *info = NULL;
2170 struct spoolss_DriverInfo8 *info_win2k = NULL;
2171 int version;
2172 bool delete_files;
2173 WERROR status;
2174 struct dcerpc_binding_handle *b;
2176 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2177 and not a printer admin, then fail */
2179 if ( (p->session_info->utok.uid != sec_initial_uid())
2180 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2181 && !token_contains_name_in_list(
2182 uidtoname(p->session_info->utok.uid),
2183 p->session_info->info3->base.domain.string,
2184 NULL,
2185 p->session_info->security_token, lp_printer_admin(-1)) )
2187 return WERR_ACCESS_DENIED;
2190 /* check that we have a valid driver name first */
2191 if ((version = get_version_id(r->in.architecture)) == -1) {
2192 /* this is what NT returns */
2193 return WERR_INVALID_ENVIRONMENT;
2196 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2197 version = r->in.version;
2199 status = winreg_printer_binding_handle(p->mem_ctx,
2200 get_session_info_system(),
2201 p->msg_ctx,
2202 &b);
2203 if (!W_ERROR_IS_OK(status)) {
2204 return status;
2207 status = winreg_get_driver(p->mem_ctx, b,
2208 r->in.architecture,
2209 r->in.driver,
2210 version,
2211 &info);
2212 if (!W_ERROR_IS_OK(status)) {
2213 status = WERR_UNKNOWN_PRINTER_DRIVER;
2216 * if the client asked for a specific version,
2217 * or this is something other than Windows NT x86,
2218 * then we've failed
2221 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2222 goto done;
2224 /* try for Win2k driver if "Windows NT x86" */
2226 version = 3;
2227 status = winreg_get_driver(info, b,
2228 r->in.architecture,
2229 r->in.driver,
2230 version, &info);
2231 if (!W_ERROR_IS_OK(status)) {
2232 status = WERR_UNKNOWN_PRINTER_DRIVER;
2233 goto done;
2237 if (printer_driver_in_use(info,
2238 get_session_info_system(),
2239 p->msg_ctx,
2240 info)) {
2241 status = WERR_PRINTER_DRIVER_IN_USE;
2242 goto done;
2246 * we have a couple of cases to consider.
2247 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2248 * then the delete should fail if **any** files overlap with
2249 * other drivers
2250 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2251 * non-overlapping files
2252 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2253 * is set, the do not delete any files
2254 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2257 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2259 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2261 if (delete_files &&
2262 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2263 printer_driver_files_in_use(info,
2264 get_session_info_system(),
2265 p->msg_ctx,
2266 info)) {
2267 status = WERR_PRINTER_DRIVER_IN_USE;
2268 goto done;
2272 /* also check for W32X86/3 if necessary; maybe we already have? */
2274 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2275 status = winreg_get_driver(info, b,
2276 r->in.architecture,
2277 r->in.driver, 3, &info_win2k);
2278 if (W_ERROR_IS_OK(status)) {
2280 if (delete_files &&
2281 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2282 printer_driver_files_in_use(info,
2283 get_session_info_system(),
2284 p->msg_ctx,
2285 info_win2k)) {
2286 /* no idea of the correct error here */
2287 talloc_free(info_win2k);
2288 status = WERR_ACCESS_DENIED;
2289 goto done;
2292 /* if we get to here, we now have 2 driver info structures to remove */
2293 /* remove the Win2k driver first*/
2295 status = winreg_del_driver(info, b,
2296 info_win2k,
2299 /* this should not have failed---if it did, report to client */
2301 if (!W_ERROR_IS_OK(status)) {
2302 goto done;
2306 * now delete any associated files if delete_files is
2307 * true. Even if this part failes, we return succes
2308 * because the driver doesn not exist any more
2310 if (delete_files) {
2311 delete_driver_files(get_session_info_system(),
2312 info_win2k);
2317 status = winreg_del_driver(info, b,
2318 info,
2319 version);
2320 if (!W_ERROR_IS_OK(status)) {
2321 goto done;
2325 * now delete any associated files if delete_files is
2326 * true. Even if this part failes, we return succes
2327 * because the driver doesn not exist any more
2329 if (delete_files) {
2330 delete_driver_files(get_session_info_system(), info);
2333 done:
2334 talloc_free(info);
2335 return status;
2339 /********************************************************************
2340 GetPrinterData on a printer server Handle.
2341 ********************************************************************/
2343 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2344 const char *value,
2345 enum winreg_Type *type,
2346 union spoolss_PrinterData *data)
2348 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2350 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2351 *type = REG_DWORD;
2352 data->value = 0x00;
2353 return WERR_OK;
2356 if (!StrCaseCmp(value, "BeepEnabled")) {
2357 *type = REG_DWORD;
2358 data->value = 0x00;
2359 return WERR_OK;
2362 if (!StrCaseCmp(value, "EventLog")) {
2363 *type = REG_DWORD;
2364 /* formally was 0x1b */
2365 data->value = 0x00;
2366 return WERR_OK;
2369 if (!StrCaseCmp(value, "NetPopup")) {
2370 *type = REG_DWORD;
2371 data->value = 0x00;
2372 return WERR_OK;
2375 if (!StrCaseCmp(value, "MajorVersion")) {
2376 *type = REG_DWORD;
2378 /* Windows NT 4.0 seems to not allow uploading of drivers
2379 to a server that reports 0x3 as the MajorVersion.
2380 need to investigate more how Win2k gets around this .
2381 -- jerry */
2383 if (RA_WINNT == get_remote_arch()) {
2384 data->value = 0x02;
2385 } else {
2386 data->value = 0x03;
2389 return WERR_OK;
2392 if (!StrCaseCmp(value, "MinorVersion")) {
2393 *type = REG_DWORD;
2394 data->value = 0x00;
2395 return WERR_OK;
2398 /* REG_BINARY
2399 * uint32_t size = 0x114
2400 * uint32_t major = 5
2401 * uint32_t minor = [0|1]
2402 * uint32_t build = [2195|2600]
2403 * extra unicode string = e.g. "Service Pack 3"
2405 if (!StrCaseCmp(value, "OSVersion")) {
2406 DATA_BLOB blob;
2407 enum ndr_err_code ndr_err;
2408 struct spoolss_OSVersion os;
2410 os.major = 5; /* Windows 2000 == 5.0 */
2411 os.minor = 0;
2412 os.build = 2195; /* build */
2413 os.extra_string = ""; /* leave extra string empty */
2415 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2416 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2417 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2418 return WERR_GENERAL_FAILURE;
2421 *type = REG_BINARY;
2422 data->binary = blob;
2424 return WERR_OK;
2428 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2429 *type = REG_SZ;
2431 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2432 W_ERROR_HAVE_NO_MEMORY(data->string);
2434 return WERR_OK;
2437 if (!StrCaseCmp(value, "Architecture")) {
2438 *type = REG_SZ;
2439 data->string = talloc_strdup(mem_ctx,
2440 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2441 W_ERROR_HAVE_NO_MEMORY(data->string);
2443 return WERR_OK;
2446 if (!StrCaseCmp(value, "DsPresent")) {
2447 *type = REG_DWORD;
2449 /* only show the publish check box if we are a
2450 member of a AD domain */
2452 if (lp_security() == SEC_ADS) {
2453 data->value = 0x01;
2454 } else {
2455 data->value = 0x00;
2457 return WERR_OK;
2460 if (!StrCaseCmp(value, "DNSMachineName")) {
2461 const char *hostname = get_mydnsfullname();
2463 if (!hostname) {
2464 return WERR_BADFILE;
2467 *type = REG_SZ;
2468 data->string = talloc_strdup(mem_ctx, hostname);
2469 W_ERROR_HAVE_NO_MEMORY(data->string);
2471 return WERR_OK;
2474 *type = REG_NONE;
2476 return WERR_INVALID_PARAM;
2479 /****************************************************************
2480 _spoolss_GetPrinterData
2481 ****************************************************************/
2483 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2484 struct spoolss_GetPrinterData *r)
2486 struct spoolss_GetPrinterDataEx r2;
2488 r2.in.handle = r->in.handle;
2489 r2.in.key_name = "PrinterDriverData";
2490 r2.in.value_name = r->in.value_name;
2491 r2.in.offered = r->in.offered;
2492 r2.out.type = r->out.type;
2493 r2.out.data = r->out.data;
2494 r2.out.needed = r->out.needed;
2496 return _spoolss_GetPrinterDataEx(p, &r2);
2499 /*********************************************************
2500 Connect to the client machine.
2501 **********************************************************/
2503 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2504 struct sockaddr_storage *client_ss, const char *remote_machine)
2506 NTSTATUS ret;
2507 struct cli_state *the_cli;
2508 struct sockaddr_storage rm_addr;
2509 char addr[INET6_ADDRSTRLEN];
2511 if ( is_zero_addr(client_ss) ) {
2512 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2513 remote_machine));
2514 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2515 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2516 return false;
2518 print_sockaddr(addr, sizeof(addr), &rm_addr);
2519 } else {
2520 rm_addr = *client_ss;
2521 print_sockaddr(addr, sizeof(addr), &rm_addr);
2522 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2523 addr));
2526 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2527 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2528 addr));
2529 return false;
2532 /* setup the connection */
2533 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2534 &rm_addr, 0, "IPC$", "IPC",
2535 "", /* username */
2536 "", /* domain */
2537 "", /* password */
2538 0, lp_client_signing());
2540 if ( !NT_STATUS_IS_OK( ret ) ) {
2541 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2542 remote_machine ));
2543 return false;
2546 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2547 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2548 cli_shutdown(the_cli);
2549 return false;
2553 * Ok - we have an anonymous connection to the IPC$ share.
2554 * Now start the NT Domain stuff :-).
2557 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2558 if (!NT_STATUS_IS_OK(ret)) {
2559 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2560 remote_machine, nt_errstr(ret)));
2561 cli_shutdown(the_cli);
2562 return false;
2565 return true;
2568 /***************************************************************************
2569 Connect to the client.
2570 ****************************************************************************/
2572 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2573 uint32_t localprinter,
2574 enum winreg_Type type,
2575 struct policy_handle *handle,
2576 struct notify_back_channel **_chan,
2577 struct sockaddr_storage *client_ss,
2578 struct messaging_context *msg_ctx)
2580 WERROR result;
2581 NTSTATUS status;
2582 struct notify_back_channel *chan;
2584 for (chan = back_channels; chan; chan = chan->next) {
2585 if (memcmp(&chan->client_address, client_ss,
2586 sizeof(struct sockaddr_storage)) == 0) {
2587 break;
2592 * If it's the first connection, contact the client
2593 * and connect to the IPC$ share anonymously
2595 if (!chan) {
2596 fstring unix_printer;
2598 /* the +2 is to strip the leading 2 backslashs */
2599 fstrcpy(unix_printer, printer + 2);
2601 chan = talloc_zero(back_channels, struct notify_back_channel);
2602 if (!chan) {
2603 return false;
2605 chan->client_address = *client_ss;
2607 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2608 TALLOC_FREE(chan);
2609 return false;
2611 chan->binding_handle = chan->cli_pipe->binding_handle;
2613 DLIST_ADD(back_channels, chan);
2615 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2616 receive_notify2_message_list);
2617 /* Tell the connections db we're now interested in printer
2618 * notify messages. */
2619 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2620 true, FLAG_MSG_PRINT_NOTIFY);
2624 * Tell the specific printing tdb we want messages for this printer
2625 * by registering our PID.
2628 if (!print_notify_register_pid(snum)) {
2629 DEBUG(0, ("Failed to register our pid for printer %s\n",
2630 printer));
2633 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2634 talloc_tos(),
2635 printer,
2636 localprinter,
2637 type,
2639 NULL,
2640 handle,
2641 &result);
2642 if (!NT_STATUS_IS_OK(status)) {
2643 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2644 result = ntstatus_to_werror(status);
2645 } else if (!W_ERROR_IS_OK(result)) {
2646 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2649 chan->active_connections++;
2650 *_chan = chan;
2652 return (W_ERROR_IS_OK(result));
2655 /****************************************************************
2656 ****************************************************************/
2658 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2659 const struct spoolss_NotifyOption *r)
2661 struct spoolss_NotifyOption *option;
2662 uint32_t i,k;
2664 if (!r) {
2665 return NULL;
2668 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2669 if (!option) {
2670 return NULL;
2673 *option = *r;
2675 if (!option->count) {
2676 return option;
2679 option->types = talloc_zero_array(option,
2680 struct spoolss_NotifyOptionType, option->count);
2681 if (!option->types) {
2682 talloc_free(option);
2683 return NULL;
2686 for (i=0; i < option->count; i++) {
2687 option->types[i] = r->types[i];
2689 if (option->types[i].count) {
2690 option->types[i].fields = talloc_zero_array(option,
2691 union spoolss_Field, option->types[i].count);
2692 if (!option->types[i].fields) {
2693 talloc_free(option);
2694 return NULL;
2696 for (k=0; k<option->types[i].count; k++) {
2697 option->types[i].fields[k] =
2698 r->types[i].fields[k];
2703 return option;
2706 /****************************************************************
2707 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2709 * before replying OK: status=0 a rpc call is made to the workstation
2710 * asking ReplyOpenPrinter
2712 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2713 * called from api_spoolss_rffpcnex
2714 ****************************************************************/
2716 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2717 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2719 int snum = -1;
2720 struct spoolss_NotifyOption *option = r->in.notify_options;
2721 struct sockaddr_storage client_ss;
2723 /* store the notify value in the printer struct */
2725 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2727 if (!Printer) {
2728 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2729 "Invalid handle (%s:%u:%u).\n",
2730 OUR_HANDLE(r->in.handle)));
2731 return WERR_BADFID;
2734 Printer->notify.flags = r->in.flags;
2735 Printer->notify.options = r->in.options;
2736 Printer->notify.printerlocal = r->in.printer_local;
2737 Printer->notify.msg_ctx = p->msg_ctx;
2739 TALLOC_FREE(Printer->notify.option);
2740 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2742 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2744 /* Connect to the client machine and send a ReplyOpenPrinter */
2746 if ( Printer->printer_type == SPLHND_SERVER)
2747 snum = -1;
2748 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2749 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2750 return WERR_BADFID;
2752 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2753 "client_address is %s\n", p->client_id->addr));
2755 if (!lp_print_notify_backchannel(snum)) {
2756 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2757 "backchannel disabled\n"));
2758 return WERR_SERVER_UNAVAILABLE;
2761 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2762 AI_NUMERICHOST)) {
2763 return WERR_SERVER_UNAVAILABLE;
2766 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2767 Printer->notify.printerlocal, REG_SZ,
2768 &Printer->notify.cli_hnd,
2769 &Printer->notify.cli_chan,
2770 &client_ss, p->msg_ctx)) {
2771 return WERR_SERVER_UNAVAILABLE;
2774 return WERR_OK;
2777 /*******************************************************************
2778 * fill a notify_info_data with the servername
2779 ********************************************************************/
2781 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2782 int snum,
2783 struct spoolss_Notify *data,
2784 print_queue_struct *queue,
2785 struct spoolss_PrinterInfo2 *pinfo2,
2786 TALLOC_CTX *mem_ctx)
2788 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2791 /*******************************************************************
2792 * fill a notify_info_data with the printername (not including the servername).
2793 ********************************************************************/
2795 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2796 int snum,
2797 struct spoolss_Notify *data,
2798 print_queue_struct *queue,
2799 struct spoolss_PrinterInfo2 *pinfo2,
2800 TALLOC_CTX *mem_ctx)
2802 /* the notify name should not contain the \\server\ part */
2803 const char *p = strrchr(pinfo2->printername, '\\');
2805 if (!p) {
2806 p = pinfo2->printername;
2807 } else {
2808 p++;
2811 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2814 /*******************************************************************
2815 * fill a notify_info_data with the servicename
2816 ********************************************************************/
2818 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2819 int snum,
2820 struct spoolss_Notify *data,
2821 print_queue_struct *queue,
2822 struct spoolss_PrinterInfo2 *pinfo2,
2823 TALLOC_CTX *mem_ctx)
2825 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2828 /*******************************************************************
2829 * fill a notify_info_data with the port name
2830 ********************************************************************/
2832 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2833 int snum,
2834 struct spoolss_Notify *data,
2835 print_queue_struct *queue,
2836 struct spoolss_PrinterInfo2 *pinfo2,
2837 TALLOC_CTX *mem_ctx)
2839 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2842 /*******************************************************************
2843 * fill a notify_info_data with the printername
2844 * but it doesn't exist, have to see what to do
2845 ********************************************************************/
2847 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2848 int snum,
2849 struct spoolss_Notify *data,
2850 print_queue_struct *queue,
2851 struct spoolss_PrinterInfo2 *pinfo2,
2852 TALLOC_CTX *mem_ctx)
2854 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2857 /*******************************************************************
2858 * fill a notify_info_data with the comment
2859 ********************************************************************/
2861 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2862 int snum,
2863 struct spoolss_Notify *data,
2864 print_queue_struct *queue,
2865 struct spoolss_PrinterInfo2 *pinfo2,
2866 TALLOC_CTX *mem_ctx)
2868 const char *p;
2870 if (*pinfo2->comment == '\0') {
2871 p = lp_comment(snum);
2872 } else {
2873 p = pinfo2->comment;
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2879 /*******************************************************************
2880 * fill a notify_info_data with the comment
2881 * location = "Room 1, floor 2, building 3"
2882 ********************************************************************/
2884 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2885 int snum,
2886 struct spoolss_Notify *data,
2887 print_queue_struct *queue,
2888 struct spoolss_PrinterInfo2 *pinfo2,
2889 TALLOC_CTX *mem_ctx)
2891 const char *loc = pinfo2->location;
2892 NTSTATUS status;
2894 status = printer_list_get_printer(mem_ctx,
2895 pinfo2->sharename,
2896 NULL,
2897 &loc,
2898 NULL);
2899 if (NT_STATUS_IS_OK(status)) {
2900 if (loc == NULL) {
2901 loc = pinfo2->location;
2905 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2908 /*******************************************************************
2909 * fill a notify_info_data with the device mode
2910 * jfm:xxxx don't to it for know but that's a real problem !!!
2911 ********************************************************************/
2913 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2914 int snum,
2915 struct spoolss_Notify *data,
2916 print_queue_struct *queue,
2917 struct spoolss_PrinterInfo2 *pinfo2,
2918 TALLOC_CTX *mem_ctx)
2920 /* for a dummy implementation we have to zero the fields */
2921 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2924 /*******************************************************************
2925 * fill a notify_info_data with the separator file name
2926 ********************************************************************/
2928 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2929 int snum,
2930 struct spoolss_Notify *data,
2931 print_queue_struct *queue,
2932 struct spoolss_PrinterInfo2 *pinfo2,
2933 TALLOC_CTX *mem_ctx)
2935 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2938 /*******************************************************************
2939 * fill a notify_info_data with the print processor
2940 * jfm:xxxx return always winprint to indicate we don't do anything to it
2941 ********************************************************************/
2943 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2944 int snum,
2945 struct spoolss_Notify *data,
2946 print_queue_struct *queue,
2947 struct spoolss_PrinterInfo2 *pinfo2,
2948 TALLOC_CTX *mem_ctx)
2950 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2953 /*******************************************************************
2954 * fill a notify_info_data with the print processor options
2955 * jfm:xxxx send an empty string
2956 ********************************************************************/
2958 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2959 int snum,
2960 struct spoolss_Notify *data,
2961 print_queue_struct *queue,
2962 struct spoolss_PrinterInfo2 *pinfo2,
2963 TALLOC_CTX *mem_ctx)
2965 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2968 /*******************************************************************
2969 * fill a notify_info_data with the data type
2970 * jfm:xxxx always send RAW as data type
2971 ********************************************************************/
2973 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2974 int snum,
2975 struct spoolss_Notify *data,
2976 print_queue_struct *queue,
2977 struct spoolss_PrinterInfo2 *pinfo2,
2978 TALLOC_CTX *mem_ctx)
2980 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2983 /*******************************************************************
2984 * fill a notify_info_data with the security descriptor
2985 * jfm:xxxx send an null pointer to say no security desc
2986 * have to implement security before !
2987 ********************************************************************/
2989 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2990 int snum,
2991 struct spoolss_Notify *data,
2992 print_queue_struct *queue,
2993 struct spoolss_PrinterInfo2 *pinfo2,
2994 TALLOC_CTX *mem_ctx)
2996 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2999 /*******************************************************************
3000 * fill a notify_info_data with the attributes
3001 * jfm:xxxx a samba printer is always shared
3002 ********************************************************************/
3004 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3005 int snum,
3006 struct spoolss_Notify *data,
3007 print_queue_struct *queue,
3008 struct spoolss_PrinterInfo2 *pinfo2,
3009 TALLOC_CTX *mem_ctx)
3011 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3014 /*******************************************************************
3015 * fill a notify_info_data with the priority
3016 ********************************************************************/
3018 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3019 int snum,
3020 struct spoolss_Notify *data,
3021 print_queue_struct *queue,
3022 struct spoolss_PrinterInfo2 *pinfo2,
3023 TALLOC_CTX *mem_ctx)
3025 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3028 /*******************************************************************
3029 * fill a notify_info_data with the default priority
3030 ********************************************************************/
3032 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3033 int snum,
3034 struct spoolss_Notify *data,
3035 print_queue_struct *queue,
3036 struct spoolss_PrinterInfo2 *pinfo2,
3037 TALLOC_CTX *mem_ctx)
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3042 /*******************************************************************
3043 * fill a notify_info_data with the start time
3044 ********************************************************************/
3046 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3047 int snum,
3048 struct spoolss_Notify *data,
3049 print_queue_struct *queue,
3050 struct spoolss_PrinterInfo2 *pinfo2,
3051 TALLOC_CTX *mem_ctx)
3053 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3056 /*******************************************************************
3057 * fill a notify_info_data with the until time
3058 ********************************************************************/
3060 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3061 int snum,
3062 struct spoolss_Notify *data,
3063 print_queue_struct *queue,
3064 struct spoolss_PrinterInfo2 *pinfo2,
3065 TALLOC_CTX *mem_ctx)
3067 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3070 /*******************************************************************
3071 * fill a notify_info_data with the status
3072 ********************************************************************/
3074 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3075 int snum,
3076 struct spoolss_Notify *data,
3077 print_queue_struct *queue,
3078 struct spoolss_PrinterInfo2 *pinfo2,
3079 TALLOC_CTX *mem_ctx)
3081 print_status_struct status;
3083 print_queue_length(msg_ctx, snum, &status);
3084 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3087 /*******************************************************************
3088 * fill a notify_info_data with the number of jobs queued
3089 ********************************************************************/
3091 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3092 int snum,
3093 struct spoolss_Notify *data,
3094 print_queue_struct *queue,
3095 struct spoolss_PrinterInfo2 *pinfo2,
3096 TALLOC_CTX *mem_ctx)
3098 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3099 data, print_queue_length(msg_ctx, snum, NULL));
3102 /*******************************************************************
3103 * fill a notify_info_data with the average ppm
3104 ********************************************************************/
3106 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3107 int snum,
3108 struct spoolss_Notify *data,
3109 print_queue_struct *queue,
3110 struct spoolss_PrinterInfo2 *pinfo2,
3111 TALLOC_CTX *mem_ctx)
3113 /* always respond 8 pages per minutes */
3114 /* a little hard ! */
3115 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3118 /*******************************************************************
3119 * fill a notify_info_data with username
3120 ********************************************************************/
3122 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3123 int snum,
3124 struct spoolss_Notify *data,
3125 print_queue_struct *queue,
3126 struct spoolss_PrinterInfo2 *pinfo2,
3127 TALLOC_CTX *mem_ctx)
3129 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3132 /*******************************************************************
3133 * fill a notify_info_data with job status
3134 ********************************************************************/
3136 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3137 int snum,
3138 struct spoolss_Notify *data,
3139 print_queue_struct *queue,
3140 struct spoolss_PrinterInfo2 *pinfo2,
3141 TALLOC_CTX *mem_ctx)
3143 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3146 /*******************************************************************
3147 * fill a notify_info_data with job name
3148 ********************************************************************/
3150 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3151 int snum,
3152 struct spoolss_Notify *data,
3153 print_queue_struct *queue,
3154 struct spoolss_PrinterInfo2 *pinfo2,
3155 TALLOC_CTX *mem_ctx)
3157 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3160 /*******************************************************************
3161 * fill a notify_info_data with job status
3162 ********************************************************************/
3164 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3165 int snum,
3166 struct spoolss_Notify *data,
3167 print_queue_struct *queue,
3168 struct spoolss_PrinterInfo2 *pinfo2,
3169 TALLOC_CTX *mem_ctx)
3172 * Now we're returning job status codes we just return a "" here. JRA.
3175 const char *p = "";
3177 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3178 p = "unknown";
3180 switch (queue->status) {
3181 case LPQ_QUEUED:
3182 p = "Queued";
3183 break;
3184 case LPQ_PAUSED:
3185 p = ""; /* NT provides the paused string */
3186 break;
3187 case LPQ_SPOOLING:
3188 p = "Spooling";
3189 break;
3190 case LPQ_PRINTING:
3191 p = "Printing";
3192 break;
3194 #endif /* NO LONGER NEEDED. */
3196 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3199 /*******************************************************************
3200 * fill a notify_info_data with job time
3201 ********************************************************************/
3203 static void spoolss_notify_job_time(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, 0);
3213 /*******************************************************************
3214 * fill a notify_info_data with job size
3215 ********************************************************************/
3217 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3218 int snum,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 struct spoolss_PrinterInfo2 *pinfo2,
3222 TALLOC_CTX *mem_ctx)
3224 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3227 /*******************************************************************
3228 * fill a notify_info_data with page info
3229 ********************************************************************/
3230 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3231 int snum,
3232 struct spoolss_Notify *data,
3233 print_queue_struct *queue,
3234 struct spoolss_PrinterInfo2 *pinfo2,
3235 TALLOC_CTX *mem_ctx)
3237 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3240 /*******************************************************************
3241 * fill a notify_info_data with pages printed info.
3242 ********************************************************************/
3243 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3244 int snum,
3245 struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 struct spoolss_PrinterInfo2 *pinfo2,
3248 TALLOC_CTX *mem_ctx)
3250 /* Add code when back-end tracks this */
3251 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3254 /*******************************************************************
3255 Fill a notify_info_data with job position.
3256 ********************************************************************/
3258 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3259 int snum,
3260 struct spoolss_Notify *data,
3261 print_queue_struct *queue,
3262 struct spoolss_PrinterInfo2 *pinfo2,
3263 TALLOC_CTX *mem_ctx)
3265 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3268 /*******************************************************************
3269 Fill a notify_info_data with submitted time.
3270 ********************************************************************/
3272 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3273 int snum,
3274 struct spoolss_Notify *data,
3275 print_queue_struct *queue,
3276 struct spoolss_PrinterInfo2 *pinfo2,
3277 TALLOC_CTX *mem_ctx)
3279 data->data.string.string = NULL;
3280 data->data.string.size = 0;
3282 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3283 &data->data.string.string,
3284 &data->data.string.size);
3288 struct s_notify_info_data_table
3290 enum spoolss_NotifyType type;
3291 uint16_t field;
3292 const char *name;
3293 enum spoolss_NotifyTable variable_type;
3294 void (*fn) (struct messaging_context *msg_ctx,
3295 int snum, struct spoolss_Notify *data,
3296 print_queue_struct *queue,
3297 struct spoolss_PrinterInfo2 *pinfo2,
3298 TALLOC_CTX *mem_ctx);
3301 /* A table describing the various print notification constants and
3302 whether the notification data is a pointer to a variable sized
3303 buffer, a one value uint32_t or a two value uint32_t. */
3305 static const struct s_notify_info_data_table notify_info_data_table[] =
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3328 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3329 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3330 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3349 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3350 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3351 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3352 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3353 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3354 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3355 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3358 /*******************************************************************
3359 Return the variable_type of info_data structure.
3360 ********************************************************************/
3362 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3363 uint16_t field)
3365 int i=0;
3367 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3368 if ( (notify_info_data_table[i].type == type) &&
3369 (notify_info_data_table[i].field == field) ) {
3370 return notify_info_data_table[i].variable_type;
3374 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3376 return (enum spoolss_NotifyTable) 0;
3379 /****************************************************************************
3380 ****************************************************************************/
3382 static bool search_notify(enum spoolss_NotifyType type,
3383 uint16_t field,
3384 int *value)
3386 int i;
3388 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3389 if (notify_info_data_table[i].type == type &&
3390 notify_info_data_table[i].field == field &&
3391 notify_info_data_table[i].fn != NULL) {
3392 *value = i;
3393 return true;
3397 return false;
3400 /****************************************************************************
3401 ****************************************************************************/
3403 static void construct_info_data(struct spoolss_Notify *info_data,
3404 enum spoolss_NotifyType type,
3405 uint16_t field, int id)
3407 info_data->type = type;
3408 info_data->field.field = field;
3409 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3410 info_data->job_id = id;
3413 /*******************************************************************
3415 * fill a notify_info struct with info asked
3417 ********************************************************************/
3419 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3420 struct printer_handle *print_hnd,
3421 struct spoolss_NotifyInfo *info,
3422 struct spoolss_PrinterInfo2 *pinfo2,
3423 int snum,
3424 const struct spoolss_NotifyOptionType *option_type,
3425 uint32_t id,
3426 TALLOC_CTX *mem_ctx)
3428 int field_num,j;
3429 enum spoolss_NotifyType type;
3430 uint16_t field;
3432 struct spoolss_Notify *current_data;
3434 type = option_type->type;
3436 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3437 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3438 option_type->count, lp_servicename(snum)));
3440 for(field_num=0; field_num < option_type->count; field_num++) {
3441 field = option_type->fields[field_num].field;
3443 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3445 if (!search_notify(type, field, &j) )
3446 continue;
3448 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3449 struct spoolss_Notify,
3450 info->count + 1);
3451 if (info->notifies == NULL) {
3452 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3453 return false;
3456 current_data = &info->notifies[info->count];
3458 construct_info_data(current_data, type, field, id);
3460 DEBUG(10, ("construct_notify_printer_info: "
3461 "calling [%s] snum=%d printername=[%s])\n",
3462 notify_info_data_table[j].name, snum,
3463 pinfo2->printername));
3465 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3466 NULL, pinfo2, mem_ctx);
3468 info->count++;
3471 return true;
3474 /*******************************************************************
3476 * fill a notify_info struct with info asked
3478 ********************************************************************/
3480 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3481 print_queue_struct *queue,
3482 struct spoolss_NotifyInfo *info,
3483 struct spoolss_PrinterInfo2 *pinfo2,
3484 int snum,
3485 const struct spoolss_NotifyOptionType *option_type,
3486 uint32_t id,
3487 TALLOC_CTX *mem_ctx)
3489 int field_num,j;
3490 enum spoolss_NotifyType type;
3491 uint16_t field;
3492 struct spoolss_Notify *current_data;
3494 DEBUG(4,("construct_notify_jobs_info\n"));
3496 type = option_type->type;
3498 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3499 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3500 option_type->count));
3502 for(field_num=0; field_num<option_type->count; field_num++) {
3503 field = option_type->fields[field_num].field;
3505 if (!search_notify(type, field, &j) )
3506 continue;
3508 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3509 struct spoolss_Notify,
3510 info->count + 1);
3511 if (info->notifies == NULL) {
3512 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3513 return false;
3516 current_data=&(info->notifies[info->count]);
3518 construct_info_data(current_data, type, field, id);
3519 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3520 queue, pinfo2, mem_ctx);
3521 info->count++;
3524 return true;
3528 * JFM: The enumeration is not that simple, it's even non obvious.
3530 * let's take an example: I want to monitor the PRINTER SERVER for
3531 * the printer's name and the number of jobs currently queued.
3532 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3533 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3535 * I have 3 printers on the back of my server.
3537 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3538 * structures.
3539 * Number Data Id
3540 * 1 printer 1 name 1
3541 * 2 printer 1 cjob 1
3542 * 3 printer 2 name 2
3543 * 4 printer 2 cjob 2
3544 * 5 printer 3 name 3
3545 * 6 printer 3 name 3
3547 * that's the print server case, the printer case is even worse.
3550 /*******************************************************************
3552 * enumerate all printers on the printserver
3553 * fill a notify_info struct with info asked
3555 ********************************************************************/
3557 static WERROR printserver_notify_info(struct pipes_struct *p,
3558 struct policy_handle *hnd,
3559 struct spoolss_NotifyInfo *info,
3560 TALLOC_CTX *mem_ctx)
3562 int snum;
3563 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3564 int n_services=lp_numservices();
3565 int i;
3566 struct spoolss_NotifyOption *option;
3567 struct spoolss_NotifyOptionType option_type;
3568 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3569 WERROR result;
3571 DEBUG(4,("printserver_notify_info\n"));
3573 if (!Printer)
3574 return WERR_BADFID;
3576 option = Printer->notify.option;
3578 info->version = 2;
3579 info->notifies = NULL;
3580 info->count = 0;
3582 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3583 sending a ffpcn() request first */
3585 if ( !option )
3586 return WERR_BADFID;
3588 for (i=0; i<option->count; i++) {
3589 option_type = option->types[i];
3591 if (option_type.type != PRINTER_NOTIFY_TYPE)
3592 continue;
3594 for (snum = 0; snum < n_services; snum++) {
3595 if (!lp_browseable(snum) ||
3596 !lp_snum_ok(snum) ||
3597 !lp_print_ok(snum)) {
3598 continue; /* skip */
3601 /* Maybe we should use the SYSTEM session_info here... */
3602 result = winreg_get_printer_internal(mem_ctx,
3603 get_session_info_system(),
3604 p->msg_ctx,
3605 lp_servicename(snum),
3606 &pinfo2);
3607 if (!W_ERROR_IS_OK(result)) {
3608 DEBUG(4, ("printserver_notify_info: "
3609 "Failed to get printer [%s]\n",
3610 lp_servicename(snum)));
3611 continue;
3615 construct_notify_printer_info(p->msg_ctx,
3616 Printer, info,
3617 pinfo2, snum,
3618 &option_type, snum,
3619 mem_ctx);
3621 TALLOC_FREE(pinfo2);
3625 #if 0
3627 * Debugging information, don't delete.
3630 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3631 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3632 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3634 for (i=0; i<info->count; i++) {
3635 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3636 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3637 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3639 #endif
3641 return WERR_OK;
3644 /*******************************************************************
3646 * fill a notify_info struct with info asked
3648 ********************************************************************/
3650 static WERROR printer_notify_info(struct pipes_struct *p,
3651 struct policy_handle *hnd,
3652 struct spoolss_NotifyInfo *info,
3653 TALLOC_CTX *mem_ctx)
3655 int snum;
3656 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3657 int i;
3658 uint32_t id;
3659 struct spoolss_NotifyOption *option;
3660 struct spoolss_NotifyOptionType option_type;
3661 int count,j;
3662 print_queue_struct *queue=NULL;
3663 print_status_struct status;
3664 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3665 WERROR result;
3667 DEBUG(4,("printer_notify_info\n"));
3669 if (!Printer)
3670 return WERR_BADFID;
3672 option = Printer->notify.option;
3673 id = 0x0;
3675 info->version = 2;
3676 info->notifies = NULL;
3677 info->count = 0;
3679 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3680 sending a ffpcn() request first */
3682 if ( !option )
3683 return WERR_BADFID;
3685 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3686 return WERR_BADFID;
3689 /* Maybe we should use the SYSTEM session_info here... */
3690 result = winreg_get_printer_internal(mem_ctx,
3691 get_session_info_system(),
3692 p->msg_ctx,
3693 lp_servicename(snum), &pinfo2);
3694 if (!W_ERROR_IS_OK(result)) {
3695 return WERR_BADFID;
3699 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3700 * correct servername.
3702 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3703 if (pinfo2->servername == NULL) {
3704 return WERR_NOMEM;
3707 for (i=0; i<option->count; i++) {
3708 option_type = option->types[i];
3710 switch (option_type.type) {
3711 case PRINTER_NOTIFY_TYPE:
3712 if (construct_notify_printer_info(p->msg_ctx,
3713 Printer, info,
3714 pinfo2, snum,
3715 &option_type, id,
3716 mem_ctx)) {
3717 id--;
3719 break;
3721 case JOB_NOTIFY_TYPE:
3723 count = print_queue_status(p->msg_ctx, snum, &queue,
3724 &status);
3726 for (j=0; j<count; j++) {
3727 construct_notify_jobs_info(p->msg_ctx,
3728 &queue[j], info,
3729 pinfo2, snum,
3730 &option_type,
3731 queue[j].job,
3732 mem_ctx);
3735 SAFE_FREE(queue);
3736 break;
3741 * Debugging information, don't delete.
3744 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3745 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3746 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3748 for (i=0; i<info->count; i++) {
3749 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3750 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3751 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3755 talloc_free(pinfo2);
3756 return WERR_OK;
3759 /****************************************************************
3760 _spoolss_RouterRefreshPrinterChangeNotify
3761 ****************************************************************/
3763 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3764 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3766 struct spoolss_NotifyInfo *info;
3768 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3769 WERROR result = WERR_BADFID;
3771 /* we always have a spoolss_NotifyInfo struct */
3772 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3773 if (!info) {
3774 result = WERR_NOMEM;
3775 goto done;
3778 *r->out.info = info;
3780 if (!Printer) {
3781 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3782 "Invalid handle (%s:%u:%u).\n",
3783 OUR_HANDLE(r->in.handle)));
3784 goto done;
3787 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3790 * We are now using the change value, and
3791 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3792 * I don't have a global notification system, I'm sending back all the
3793 * information even when _NOTHING_ has changed.
3796 /* We need to keep track of the change value to send back in
3797 RRPCN replies otherwise our updates are ignored. */
3799 Printer->notify.fnpcn = true;
3801 if (Printer->notify.cli_chan != NULL &&
3802 Printer->notify.cli_chan->active_connections > 0) {
3803 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3804 "Saving change value in request [%x]\n",
3805 r->in.change_low));
3806 Printer->notify.change = r->in.change_low;
3809 /* just ignore the spoolss_NotifyOption */
3811 switch (Printer->printer_type) {
3812 case SPLHND_SERVER:
3813 result = printserver_notify_info(p, r->in.handle,
3814 info, p->mem_ctx);
3815 break;
3817 case SPLHND_PRINTER:
3818 result = printer_notify_info(p, r->in.handle,
3819 info, p->mem_ctx);
3820 break;
3823 Printer->notify.fnpcn = false;
3825 done:
3826 return result;
3829 /********************************************************************
3830 ********************************************************************/
3832 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3833 const char *servername,
3834 const char *printername,
3835 const char **printername_p)
3837 /* FIXME: add lp_force_printername() */
3839 if (servername == NULL) {
3840 *printername_p = talloc_strdup(mem_ctx, printername);
3841 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3842 return WERR_OK;
3845 if (servername[0] == '\\' && servername[1] == '\\') {
3846 servername += 2;
3849 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3850 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3852 return WERR_OK;
3855 /********************************************************************
3856 ********************************************************************/
3858 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3859 const char *printername)
3861 if (dm == NULL) {
3862 return;
3865 dm->devicename = talloc_strndup(dm, printername,
3866 MIN(strlen(printername), 31));
3869 /********************************************************************
3870 * construct_printer_info_0
3871 * fill a printer_info_0 struct
3872 ********************************************************************/
3874 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3875 const struct auth_serversupplied_info *session_info,
3876 struct messaging_context *msg_ctx,
3877 struct spoolss_PrinterInfo2 *info2,
3878 const char *servername,
3879 struct spoolss_PrinterInfo0 *r,
3880 int snum)
3882 int count;
3883 struct printer_session_counter *session_counter;
3884 struct timeval setuptime;
3885 print_status_struct status;
3886 WERROR result;
3888 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3889 if (!W_ERROR_IS_OK(result)) {
3890 return result;
3893 if (servername) {
3894 r->servername = talloc_strdup(mem_ctx, servername);
3895 W_ERROR_HAVE_NO_MEMORY(r->servername);
3896 } else {
3897 r->servername = NULL;
3900 count = print_queue_length(msg_ctx, snum, &status);
3902 /* check if we already have a counter for this printer */
3903 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3904 if (session_counter->snum == snum)
3905 break;
3908 /* it's the first time, add it to the list */
3909 if (session_counter == NULL) {
3910 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3911 W_ERROR_HAVE_NO_MEMORY(session_counter);
3912 session_counter->snum = snum;
3913 session_counter->counter = 0;
3914 DLIST_ADD(counter_list, session_counter);
3917 /* increment it */
3918 session_counter->counter++;
3920 r->cjobs = count;
3921 r->total_jobs = 0;
3922 r->total_bytes = 0;
3924 get_startup_time(&setuptime);
3925 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3927 /* JFM:
3928 * the global_counter should be stored in a TDB as it's common to all the clients
3929 * and should be zeroed on samba startup
3931 r->global_counter = session_counter->counter;
3932 r->total_pages = 0;
3933 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3934 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3935 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3936 r->free_build = SPOOLSS_RELEASE_BUILD;
3937 r->spooling = 0;
3938 r->max_spooling = 0;
3939 r->session_counter = session_counter->counter;
3940 r->num_error_out_of_paper = 0x0;
3941 r->num_error_not_ready = 0x0; /* number of print failure */
3942 r->job_error = 0x0;
3943 r->number_of_processors = 0x1;
3944 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3945 r->high_part_total_bytes = 0x0;
3947 /* ChangeID in milliseconds*/
3948 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3949 info2->sharename, &r->change_id);
3951 r->last_error = WERR_OK;
3952 r->status = nt_printq_status(status.status);
3953 r->enumerate_network_printers = 0x0;
3954 r->c_setprinter = 0x0;
3955 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3956 r->processor_level = 0x6; /* 6 ???*/
3957 r->ref_ic = 0;
3958 r->reserved2 = 0;
3959 r->reserved3 = 0;
3961 return WERR_OK;
3965 /********************************************************************
3966 * construct_printer_info1
3967 * fill a spoolss_PrinterInfo1 struct
3968 ********************************************************************/
3970 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3971 const struct spoolss_PrinterInfo2 *info2,
3972 uint32_t flags,
3973 const char *servername,
3974 struct spoolss_PrinterInfo1 *r,
3975 int snum)
3977 WERROR result;
3979 r->flags = flags;
3981 if (info2->comment == NULL || info2->comment[0] == '\0') {
3982 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3983 } else {
3984 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3986 W_ERROR_HAVE_NO_MEMORY(r->comment);
3988 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3989 if (!W_ERROR_IS_OK(result)) {
3990 return result;
3993 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3994 r->name,
3995 info2->drivername,
3996 r->comment);
3997 W_ERROR_HAVE_NO_MEMORY(r->description);
3999 return WERR_OK;
4002 /********************************************************************
4003 * construct_printer_info2
4004 * fill a spoolss_PrinterInfo2 struct
4005 ********************************************************************/
4007 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4008 struct messaging_context *msg_ctx,
4009 const struct spoolss_PrinterInfo2 *info2,
4010 const char *servername,
4011 struct spoolss_PrinterInfo2 *r,
4012 int snum)
4014 int count;
4015 print_status_struct status;
4016 WERROR result;
4018 count = print_queue_length(msg_ctx, snum, &status);
4020 if (servername) {
4021 r->servername = talloc_strdup(mem_ctx, servername);
4022 W_ERROR_HAVE_NO_MEMORY(r->servername);
4023 } else {
4024 r->servername = NULL;
4027 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4028 if (!W_ERROR_IS_OK(result)) {
4029 return result;
4032 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4033 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4034 r->portname = talloc_strdup(mem_ctx, info2->portname);
4035 W_ERROR_HAVE_NO_MEMORY(r->portname);
4036 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4037 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4039 if (info2->comment[0] == '\0') {
4040 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4041 } else {
4042 r->comment = talloc_strdup(mem_ctx, info2->comment);
4044 W_ERROR_HAVE_NO_MEMORY(r->comment);
4046 r->location = talloc_strdup(mem_ctx, info2->location);
4047 if (info2->location[0] == '\0') {
4048 const char *loc = NULL;
4049 NTSTATUS nt_status;
4051 nt_status = printer_list_get_printer(mem_ctx,
4052 info2->sharename,
4053 NULL,
4054 &loc,
4055 NULL);
4056 if (NT_STATUS_IS_OK(nt_status)) {
4057 if (loc != NULL) {
4058 r->location = talloc_strdup(mem_ctx, loc);
4062 W_ERROR_HAVE_NO_MEMORY(r->location);
4064 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4065 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4066 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4067 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4068 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4069 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4070 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4071 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4073 r->attributes = info2->attributes;
4075 r->priority = info2->priority;
4076 r->defaultpriority = info2->defaultpriority;
4077 r->starttime = info2->starttime;
4078 r->untiltime = info2->untiltime;
4079 r->status = nt_printq_status(status.status);
4080 r->cjobs = count;
4081 r->averageppm = info2->averageppm;
4083 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4084 if (!r->devmode) {
4085 DEBUG(8,("Returning NULL Devicemode!\n"));
4088 compose_devicemode_devicename(r->devmode, r->printername);
4090 r->secdesc = NULL;
4092 if (info2->secdesc != NULL) {
4093 /* don't use talloc_steal() here unless you do a deep steal of all
4094 the SEC_DESC members */
4096 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4099 return WERR_OK;
4102 /********************************************************************
4103 * construct_printer_info3
4104 * fill a spoolss_PrinterInfo3 struct
4105 ********************************************************************/
4107 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4108 const struct spoolss_PrinterInfo2 *info2,
4109 const char *servername,
4110 struct spoolss_PrinterInfo3 *r,
4111 int snum)
4113 /* These are the components of the SD we are returning. */
4115 if (info2->secdesc != NULL) {
4116 /* don't use talloc_steal() here unless you do a deep steal of all
4117 the SEC_DESC members */
4119 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4120 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4123 return WERR_OK;
4126 /********************************************************************
4127 * construct_printer_info4
4128 * fill a spoolss_PrinterInfo4 struct
4129 ********************************************************************/
4131 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4132 const struct spoolss_PrinterInfo2 *info2,
4133 const char *servername,
4134 struct spoolss_PrinterInfo4 *r,
4135 int snum)
4137 WERROR result;
4139 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4140 if (!W_ERROR_IS_OK(result)) {
4141 return result;
4144 if (servername) {
4145 r->servername = talloc_strdup(mem_ctx, servername);
4146 W_ERROR_HAVE_NO_MEMORY(r->servername);
4147 } else {
4148 r->servername = NULL;
4151 r->attributes = info2->attributes;
4153 return WERR_OK;
4156 /********************************************************************
4157 * construct_printer_info5
4158 * fill a spoolss_PrinterInfo5 struct
4159 ********************************************************************/
4161 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4162 const struct spoolss_PrinterInfo2 *info2,
4163 const char *servername,
4164 struct spoolss_PrinterInfo5 *r,
4165 int snum)
4167 WERROR result;
4169 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4170 if (!W_ERROR_IS_OK(result)) {
4171 return result;
4174 r->portname = talloc_strdup(mem_ctx, info2->portname);
4175 W_ERROR_HAVE_NO_MEMORY(r->portname);
4177 r->attributes = info2->attributes;
4179 /* these two are not used by NT+ according to MSDN */
4180 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4181 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4183 return WERR_OK;
4186 /********************************************************************
4187 * construct_printer_info_6
4188 * fill a spoolss_PrinterInfo6 struct
4189 ********************************************************************/
4191 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4192 struct messaging_context *msg_ctx,
4193 const struct spoolss_PrinterInfo2 *info2,
4194 const char *servername,
4195 struct spoolss_PrinterInfo6 *r,
4196 int snum)
4198 int count;
4199 print_status_struct status;
4201 count = print_queue_length(msg_ctx, snum, &status);
4203 r->status = nt_printq_status(status.status);
4205 return WERR_OK;
4208 /********************************************************************
4209 * construct_printer_info7
4210 * fill a spoolss_PrinterInfo7 struct
4211 ********************************************************************/
4213 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4214 struct messaging_context *msg_ctx,
4215 const char *servername,
4216 struct spoolss_PrinterInfo7 *r,
4217 int snum)
4219 struct auth_serversupplied_info *session_info;
4220 struct GUID guid;
4221 NTSTATUS status;
4223 status = make_session_info_system(mem_ctx, &session_info);
4224 if (!NT_STATUS_IS_OK(status)) {
4225 DEBUG(0, ("construct_printer_info7: "
4226 "Could not create system session_info\n"));
4227 return WERR_NOMEM;
4230 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4231 servername,
4232 lp_servicename(snum), &guid, NULL)) {
4233 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4234 r->action = DSPRINT_PUBLISH;
4235 } else {
4236 r->guid = talloc_strdup(mem_ctx, "");
4237 r->action = DSPRINT_UNPUBLISH;
4239 W_ERROR_HAVE_NO_MEMORY(r->guid);
4241 TALLOC_FREE(session_info);
4242 return WERR_OK;
4245 /********************************************************************
4246 * construct_printer_info8
4247 * fill a spoolss_PrinterInfo8 struct
4248 ********************************************************************/
4250 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4251 const struct spoolss_PrinterInfo2 *info2,
4252 const char *servername,
4253 struct spoolss_DeviceModeInfo *r,
4254 int snum)
4256 WERROR result;
4257 const char *printername;
4259 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4260 if (!W_ERROR_IS_OK(result)) {
4261 return result;
4264 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4265 if (!r->devmode) {
4266 DEBUG(8,("Returning NULL Devicemode!\n"));
4269 compose_devicemode_devicename(r->devmode, printername);
4271 return WERR_OK;
4275 /********************************************************************
4276 ********************************************************************/
4278 static bool snum_is_shared_printer(int snum)
4280 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4283 /********************************************************************
4284 Spoolss_enumprinters.
4285 ********************************************************************/
4287 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4288 const struct auth_serversupplied_info *session_info,
4289 struct messaging_context *msg_ctx,
4290 const char *servername,
4291 uint32_t level,
4292 uint32_t flags,
4293 union spoolss_PrinterInfo **info_p,
4294 uint32_t *count_p)
4296 int snum;
4297 int n_services = lp_numservices();
4298 union spoolss_PrinterInfo *info = NULL;
4299 uint32_t count = 0;
4300 WERROR result = WERR_OK;
4301 struct dcerpc_binding_handle *b = NULL;
4303 *count_p = 0;
4304 *info_p = NULL;
4306 for (snum = 0; snum < n_services; snum++) {
4308 const char *printer;
4309 struct spoolss_PrinterInfo2 *info2;
4311 if (!snum_is_shared_printer(snum)) {
4312 continue;
4315 printer = lp_const_servicename(snum);
4317 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4318 printer, snum));
4320 if (b == NULL) {
4321 result = winreg_printer_binding_handle(mem_ctx,
4322 session_info,
4323 msg_ctx,
4324 &b);
4325 if (!W_ERROR_IS_OK(result)) {
4326 goto out;
4330 result = winreg_create_printer(mem_ctx, b,
4331 printer);
4332 if (!W_ERROR_IS_OK(result)) {
4333 goto out;
4336 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4337 union spoolss_PrinterInfo,
4338 count + 1);
4339 if (!info) {
4340 result = WERR_NOMEM;
4341 goto out;
4344 result = winreg_get_printer(mem_ctx, b,
4345 printer, &info2);
4346 if (!W_ERROR_IS_OK(result)) {
4347 goto out;
4350 switch (level) {
4351 case 0:
4352 result = construct_printer_info0(info, session_info,
4353 msg_ctx, info2,
4354 servername,
4355 &info[count].info0, snum);
4356 break;
4357 case 1:
4358 result = construct_printer_info1(info, info2, flags,
4359 servername,
4360 &info[count].info1, snum);
4361 break;
4362 case 2:
4363 result = construct_printer_info2(info, msg_ctx, info2,
4364 servername,
4365 &info[count].info2, snum);
4366 break;
4367 case 4:
4368 result = construct_printer_info4(info, info2,
4369 servername,
4370 &info[count].info4, snum);
4371 break;
4372 case 5:
4373 result = construct_printer_info5(info, info2,
4374 servername,
4375 &info[count].info5, snum);
4376 break;
4378 default:
4379 result = WERR_UNKNOWN_LEVEL;
4380 goto out;
4383 if (!W_ERROR_IS_OK(result)) {
4384 goto out;
4387 count++;
4390 *count_p = count;
4391 *info_p = info;
4393 out:
4394 if (!W_ERROR_IS_OK(result)) {
4395 TALLOC_FREE(info);
4396 return result;
4399 *info_p = info;
4401 return WERR_OK;
4404 /********************************************************************
4405 * handle enumeration of printers at level 0
4406 ********************************************************************/
4408 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4409 const struct auth_serversupplied_info *session_info,
4410 struct messaging_context *msg_ctx,
4411 uint32_t flags,
4412 const char *servername,
4413 union spoolss_PrinterInfo **info,
4414 uint32_t *count)
4416 DEBUG(4,("enum_all_printers_info_0\n"));
4418 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4419 servername, 0, flags, info, count);
4423 /********************************************************************
4424 ********************************************************************/
4426 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4427 const struct auth_serversupplied_info *session_info,
4428 struct messaging_context *msg_ctx,
4429 const char *servername,
4430 uint32_t flags,
4431 union spoolss_PrinterInfo **info,
4432 uint32_t *count)
4434 DEBUG(4,("enum_all_printers_info_1\n"));
4436 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4437 servername, 1, flags, info, count);
4440 /********************************************************************
4441 enum_all_printers_info_1_local.
4442 *********************************************************************/
4444 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4445 const struct auth_serversupplied_info *session_info,
4446 struct messaging_context *msg_ctx,
4447 const char *servername,
4448 union spoolss_PrinterInfo **info,
4449 uint32_t *count)
4451 DEBUG(4,("enum_all_printers_info_1_local\n"));
4453 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4454 servername, PRINTER_ENUM_ICON8, info, count);
4457 /********************************************************************
4458 enum_all_printers_info_1_name.
4459 *********************************************************************/
4461 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4462 const struct auth_serversupplied_info *session_info,
4463 struct messaging_context *msg_ctx,
4464 const char *servername,
4465 union spoolss_PrinterInfo **info,
4466 uint32_t *count)
4468 const char *s = servername;
4470 DEBUG(4,("enum_all_printers_info_1_name\n"));
4472 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4473 s = servername + 2;
4476 if (!is_myname_or_ipaddr(s)) {
4477 return WERR_INVALID_NAME;
4480 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4481 servername, PRINTER_ENUM_ICON8, info, count);
4484 /********************************************************************
4485 enum_all_printers_info_1_network.
4486 *********************************************************************/
4488 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4489 const struct auth_serversupplied_info *session_info,
4490 struct messaging_context *msg_ctx,
4491 const char *servername,
4492 union spoolss_PrinterInfo **info,
4493 uint32_t *count)
4495 const char *s = servername;
4497 DEBUG(4,("enum_all_printers_info_1_network\n"));
4499 /* If we respond to a enum_printers level 1 on our name with flags
4500 set to PRINTER_ENUM_REMOTE with a list of printers then these
4501 printers incorrectly appear in the APW browse list.
4502 Specifically the printers for the server appear at the workgroup
4503 level where all the other servers in the domain are
4504 listed. Windows responds to this call with a
4505 WERR_CAN_NOT_COMPLETE so we should do the same. */
4507 if (servername[0] == '\\' && servername[1] == '\\') {
4508 s = servername + 2;
4511 if (is_myname_or_ipaddr(s)) {
4512 return WERR_CAN_NOT_COMPLETE;
4515 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4516 servername, PRINTER_ENUM_NAME, info, count);
4519 /********************************************************************
4520 * api_spoolss_enumprinters
4522 * called from api_spoolss_enumprinters (see this to understand)
4523 ********************************************************************/
4525 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4526 const struct auth_serversupplied_info *session_info,
4527 struct messaging_context *msg_ctx,
4528 const char *servername,
4529 union spoolss_PrinterInfo **info,
4530 uint32_t *count)
4532 DEBUG(4,("enum_all_printers_info_2\n"));
4534 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4535 servername, 2, 0, info, count);
4538 /********************************************************************
4539 * handle enumeration of printers at level 1
4540 ********************************************************************/
4542 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4543 const struct auth_serversupplied_info *session_info,
4544 struct messaging_context *msg_ctx,
4545 uint32_t flags,
4546 const char *servername,
4547 union spoolss_PrinterInfo **info,
4548 uint32_t *count)
4550 /* Not all the flags are equals */
4552 if (flags & PRINTER_ENUM_LOCAL) {
4553 return enum_all_printers_info_1_local(mem_ctx, session_info,
4554 msg_ctx, servername, info, count);
4557 if (flags & PRINTER_ENUM_NAME) {
4558 return enum_all_printers_info_1_name(mem_ctx, session_info,
4559 msg_ctx, servername, info,
4560 count);
4563 if (flags & PRINTER_ENUM_NETWORK) {
4564 return enum_all_printers_info_1_network(mem_ctx, session_info,
4565 msg_ctx, servername, info,
4566 count);
4569 return WERR_OK; /* NT4sp5 does that */
4572 /********************************************************************
4573 * handle enumeration of printers at level 2
4574 ********************************************************************/
4576 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4577 const struct auth_serversupplied_info *session_info,
4578 struct messaging_context *msg_ctx,
4579 uint32_t flags,
4580 const char *servername,
4581 union spoolss_PrinterInfo **info,
4582 uint32_t *count)
4584 if (flags & PRINTER_ENUM_LOCAL) {
4586 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4587 servername,
4588 info, count);
4591 if (flags & PRINTER_ENUM_NAME) {
4592 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4593 return WERR_INVALID_NAME;
4596 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4597 servername,
4598 info, count);
4601 if (flags & PRINTER_ENUM_REMOTE) {
4602 return WERR_UNKNOWN_LEVEL;
4605 return WERR_OK;
4608 /********************************************************************
4609 * handle enumeration of printers at level 4
4610 ********************************************************************/
4612 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4613 const struct auth_serversupplied_info *session_info,
4614 struct messaging_context *msg_ctx,
4615 uint32_t flags,
4616 const char *servername,
4617 union spoolss_PrinterInfo **info,
4618 uint32_t *count)
4620 DEBUG(4,("enum_all_printers_info_4\n"));
4622 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4623 servername, 4, flags, info, count);
4627 /********************************************************************
4628 * handle enumeration of printers at level 5
4629 ********************************************************************/
4631 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4632 const struct auth_serversupplied_info *session_info,
4633 struct messaging_context *msg_ctx,
4634 uint32_t flags,
4635 const char *servername,
4636 union spoolss_PrinterInfo **info,
4637 uint32_t *count)
4639 DEBUG(4,("enum_all_printers_info_5\n"));
4641 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4642 servername, 5, flags, info, count);
4645 /****************************************************************
4646 _spoolss_EnumPrinters
4647 ****************************************************************/
4649 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4650 struct spoolss_EnumPrinters *r)
4652 const struct auth_serversupplied_info *session_info = get_session_info_system();
4653 WERROR result;
4655 /* that's an [in out] buffer */
4657 if (!r->in.buffer && (r->in.offered != 0)) {
4658 return WERR_INVALID_PARAM;
4661 DEBUG(4,("_spoolss_EnumPrinters\n"));
4663 *r->out.needed = 0;
4664 *r->out.count = 0;
4665 *r->out.info = NULL;
4668 * Level 1:
4669 * flags==PRINTER_ENUM_NAME
4670 * if name=="" then enumerates all printers
4671 * if name!="" then enumerate the printer
4672 * flags==PRINTER_ENUM_REMOTE
4673 * name is NULL, enumerate printers
4674 * Level 2: name!="" enumerates printers, name can't be NULL
4675 * Level 3: doesn't exist
4676 * Level 4: does a local registry lookup
4677 * Level 5: same as Level 2
4680 if (r->in.server && r->in.server[0] == '\0') {
4681 r->in.server = NULL;
4684 switch (r->in.level) {
4685 case 0:
4686 result = enumprinters_level0(p->mem_ctx, session_info,
4687 p->msg_ctx, r->in.flags,
4688 r->in.server,
4689 r->out.info, r->out.count);
4690 break;
4691 case 1:
4692 result = enumprinters_level1(p->mem_ctx, session_info,
4693 p->msg_ctx, r->in.flags,
4694 r->in.server,
4695 r->out.info, r->out.count);
4696 break;
4697 case 2:
4698 result = enumprinters_level2(p->mem_ctx, session_info,
4699 p->msg_ctx, r->in.flags,
4700 r->in.server,
4701 r->out.info, r->out.count);
4702 break;
4703 case 4:
4704 result = enumprinters_level4(p->mem_ctx, session_info,
4705 p->msg_ctx, r->in.flags,
4706 r->in.server,
4707 r->out.info, r->out.count);
4708 break;
4709 case 5:
4710 result = enumprinters_level5(p->mem_ctx, session_info,
4711 p->msg_ctx, r->in.flags,
4712 r->in.server,
4713 r->out.info, r->out.count);
4714 break;
4715 default:
4716 return WERR_UNKNOWN_LEVEL;
4719 if (!W_ERROR_IS_OK(result)) {
4720 return result;
4723 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4724 spoolss_EnumPrinters,
4725 *r->out.info, r->in.level,
4726 *r->out.count);
4727 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4728 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4730 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4733 /****************************************************************
4734 _spoolss_GetPrinter
4735 ****************************************************************/
4737 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4738 struct spoolss_GetPrinter *r)
4740 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4741 struct spoolss_PrinterInfo2 *info2 = NULL;
4742 WERROR result = WERR_OK;
4743 int snum;
4745 /* that's an [in out] buffer */
4747 if (!r->in.buffer && (r->in.offered != 0)) {
4748 return WERR_INVALID_PARAM;
4751 *r->out.needed = 0;
4753 if (Printer == NULL) {
4754 return WERR_BADFID;
4757 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4758 return WERR_BADFID;
4761 result = winreg_get_printer_internal(p->mem_ctx,
4762 get_session_info_system(),
4763 p->msg_ctx,
4764 lp_const_servicename(snum),
4765 &info2);
4766 if (!W_ERROR_IS_OK(result)) {
4767 goto out;
4770 switch (r->in.level) {
4771 case 0:
4772 result = construct_printer_info0(p->mem_ctx,
4773 get_session_info_system(),
4774 p->msg_ctx,
4775 info2,
4776 Printer->servername,
4777 &r->out.info->info0,
4778 snum);
4779 break;
4780 case 1:
4781 result = construct_printer_info1(p->mem_ctx, info2,
4782 PRINTER_ENUM_ICON8,
4783 Printer->servername,
4784 &r->out.info->info1, snum);
4785 break;
4786 case 2:
4787 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4788 Printer->servername,
4789 &r->out.info->info2, snum);
4790 break;
4791 case 3:
4792 result = construct_printer_info3(p->mem_ctx, info2,
4793 Printer->servername,
4794 &r->out.info->info3, snum);
4795 break;
4796 case 4:
4797 result = construct_printer_info4(p->mem_ctx, info2,
4798 Printer->servername,
4799 &r->out.info->info4, snum);
4800 break;
4801 case 5:
4802 result = construct_printer_info5(p->mem_ctx, info2,
4803 Printer->servername,
4804 &r->out.info->info5, snum);
4805 break;
4806 case 6:
4807 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4808 Printer->servername,
4809 &r->out.info->info6, snum);
4810 break;
4811 case 7:
4812 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4813 Printer->servername,
4814 &r->out.info->info7, snum);
4815 break;
4816 case 8:
4817 result = construct_printer_info8(p->mem_ctx, info2,
4818 Printer->servername,
4819 &r->out.info->info8, snum);
4820 break;
4821 default:
4822 result = WERR_UNKNOWN_LEVEL;
4823 break;
4826 out:
4827 if (!W_ERROR_IS_OK(result)) {
4828 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4829 r->in.level, win_errstr(result)));
4830 TALLOC_FREE(r->out.info);
4831 return result;
4834 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4835 r->out.info, r->in.level);
4836 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4838 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4841 /********************************************************************
4842 ********************************************************************/
4844 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4845 do { \
4846 if (in && strlen(in)) { \
4847 out = talloc_strdup(mem_ctx, in); \
4848 } else { \
4849 out = talloc_strdup(mem_ctx, ""); \
4851 W_ERROR_HAVE_NO_MEMORY(out); \
4852 } while (0);
4854 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4855 do { \
4856 if (in && strlen(in)) { \
4857 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4858 } else { \
4859 out = talloc_strdup(mem_ctx, ""); \
4861 W_ERROR_HAVE_NO_MEMORY(out); \
4862 } while (0);
4864 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4865 const char **string_array,
4866 const char ***presult,
4867 const char *cservername,
4868 const char *arch,
4869 int version)
4871 int i, num_strings = 0;
4872 const char **array = NULL;
4874 if (string_array == NULL) {
4875 return WERR_INVALID_PARAMETER;
4878 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4879 const char *str = NULL;
4881 if (cservername == NULL || arch == NULL) {
4882 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4883 } else {
4884 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4887 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4888 TALLOC_FREE(array);
4889 return WERR_NOMEM;
4893 if (i > 0) {
4894 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4895 &array, &num_strings);
4898 if (presult) {
4899 *presult = array;
4902 return WERR_OK;
4905 /********************************************************************
4906 * fill a spoolss_DriverInfo1 struct
4907 ********************************************************************/
4909 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4910 struct spoolss_DriverInfo1 *r,
4911 const struct spoolss_DriverInfo8 *driver,
4912 const char *servername)
4914 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4915 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4917 return WERR_OK;
4920 /********************************************************************
4921 * fill a spoolss_DriverInfo2 struct
4922 ********************************************************************/
4924 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4925 struct spoolss_DriverInfo2 *r,
4926 const struct spoolss_DriverInfo8 *driver,
4927 const char *servername)
4930 const char *cservername = canon_servername(servername);
4932 r->version = driver->version;
4934 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4935 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4936 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4937 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4939 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4940 driver->architecture,
4941 driver->version,
4942 driver->driver_path,
4943 r->driver_path);
4945 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4946 driver->architecture,
4947 driver->version,
4948 driver->data_file,
4949 r->data_file);
4951 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4952 driver->architecture,
4953 driver->version,
4954 driver->config_file,
4955 r->config_file);
4957 return WERR_OK;
4960 /********************************************************************
4961 * fill a spoolss_DriverInfo3 struct
4962 ********************************************************************/
4964 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4965 struct spoolss_DriverInfo3 *r,
4966 const struct spoolss_DriverInfo8 *driver,
4967 const char *servername)
4969 const char *cservername = canon_servername(servername);
4971 r->version = driver->version;
4973 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4974 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4975 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4976 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4978 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979 driver->architecture,
4980 driver->version,
4981 driver->driver_path,
4982 r->driver_path);
4984 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985 driver->architecture,
4986 driver->version,
4987 driver->data_file,
4988 r->data_file);
4990 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4991 driver->architecture,
4992 driver->version,
4993 driver->config_file,
4994 r->config_file);
4996 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997 driver->architecture,
4998 driver->version,
4999 driver->help_file,
5000 r->help_file);
5002 FILL_DRIVER_STRING(mem_ctx,
5003 driver->monitor_name,
5004 r->monitor_name);
5006 FILL_DRIVER_STRING(mem_ctx,
5007 driver->default_datatype,
5008 r->default_datatype);
5010 return string_array_from_driver_info(mem_ctx,
5011 driver->dependent_files,
5012 &r->dependent_files,
5013 cservername,
5014 driver->architecture,
5015 driver->version);
5018 /********************************************************************
5019 * fill a spoolss_DriverInfo4 struct
5020 ********************************************************************/
5022 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5023 struct spoolss_DriverInfo4 *r,
5024 const struct spoolss_DriverInfo8 *driver,
5025 const char *servername)
5027 const char *cservername = canon_servername(servername);
5028 WERROR result;
5030 r->version = driver->version;
5032 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5033 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5034 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5035 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5037 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5038 driver->architecture,
5039 driver->version,
5040 driver->driver_path,
5041 r->driver_path);
5043 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5044 driver->architecture,
5045 driver->version,
5046 driver->data_file,
5047 r->data_file);
5049 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050 driver->architecture,
5051 driver->version,
5052 driver->config_file,
5053 r->config_file);
5055 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056 driver->architecture,
5057 driver->version,
5058 driver->help_file,
5059 r->help_file);
5061 result = string_array_from_driver_info(mem_ctx,
5062 driver->dependent_files,
5063 &r->dependent_files,
5064 cservername,
5065 driver->architecture,
5066 driver->version);
5067 if (!W_ERROR_IS_OK(result)) {
5068 return result;
5071 FILL_DRIVER_STRING(mem_ctx,
5072 driver->monitor_name,
5073 r->monitor_name);
5075 FILL_DRIVER_STRING(mem_ctx,
5076 driver->default_datatype,
5077 r->default_datatype);
5080 result = string_array_from_driver_info(mem_ctx,
5081 driver->previous_names,
5082 &r->previous_names,
5083 NULL, NULL, 0);
5085 return result;
5088 /********************************************************************
5089 * fill a spoolss_DriverInfo5 struct
5090 ********************************************************************/
5092 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5093 struct spoolss_DriverInfo5 *r,
5094 const struct spoolss_DriverInfo8 *driver,
5095 const char *servername)
5097 const char *cservername = canon_servername(servername);
5099 r->version = driver->version;
5101 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5102 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5103 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5104 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5106 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107 driver->architecture,
5108 driver->version,
5109 driver->driver_path,
5110 r->driver_path);
5112 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113 driver->architecture,
5114 driver->version,
5115 driver->data_file,
5116 r->data_file);
5118 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119 driver->architecture,
5120 driver->version,
5121 driver->config_file,
5122 r->config_file);
5124 r->driver_attributes = 0;
5125 r->config_version = 0;
5126 r->driver_version = 0;
5128 return WERR_OK;
5130 /********************************************************************
5131 * fill a spoolss_DriverInfo6 struct
5132 ********************************************************************/
5134 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5135 struct spoolss_DriverInfo6 *r,
5136 const struct spoolss_DriverInfo8 *driver,
5137 const char *servername)
5139 const char *cservername = canon_servername(servername);
5140 WERROR result;
5142 r->version = driver->version;
5144 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5145 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5146 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5147 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5149 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5150 driver->architecture,
5151 driver->version,
5152 driver->driver_path,
5153 r->driver_path);
5155 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5156 driver->architecture,
5157 driver->version,
5158 driver->data_file,
5159 r->data_file);
5161 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5162 driver->architecture,
5163 driver->version,
5164 driver->config_file,
5165 r->config_file);
5167 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5168 driver->architecture,
5169 driver->version,
5170 driver->help_file,
5171 r->help_file);
5173 FILL_DRIVER_STRING(mem_ctx,
5174 driver->monitor_name,
5175 r->monitor_name);
5177 FILL_DRIVER_STRING(mem_ctx,
5178 driver->default_datatype,
5179 r->default_datatype);
5181 result = string_array_from_driver_info(mem_ctx,
5182 driver->dependent_files,
5183 &r->dependent_files,
5184 cservername,
5185 driver->architecture,
5186 driver->version);
5187 if (!W_ERROR_IS_OK(result)) {
5188 return result;
5191 result = string_array_from_driver_info(mem_ctx,
5192 driver->previous_names,
5193 &r->previous_names,
5194 NULL, NULL, 0);
5195 if (!W_ERROR_IS_OK(result)) {
5196 return result;
5199 r->driver_date = driver->driver_date;
5200 r->driver_version = driver->driver_version;
5202 FILL_DRIVER_STRING(mem_ctx,
5203 driver->manufacturer_name,
5204 r->manufacturer_name);
5205 FILL_DRIVER_STRING(mem_ctx,
5206 driver->manufacturer_url,
5207 r->manufacturer_url);
5208 FILL_DRIVER_STRING(mem_ctx,
5209 driver->hardware_id,
5210 r->hardware_id);
5211 FILL_DRIVER_STRING(mem_ctx,
5212 driver->provider,
5213 r->provider);
5215 return WERR_OK;
5218 /********************************************************************
5219 * fill a spoolss_DriverInfo8 struct
5220 ********************************************************************/
5222 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5223 struct spoolss_DriverInfo8 *r,
5224 const struct spoolss_DriverInfo8 *driver,
5225 const char *servername)
5227 const char *cservername = canon_servername(servername);
5228 WERROR result;
5230 r->version = driver->version;
5232 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5233 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5234 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5235 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5237 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5238 driver->architecture,
5239 driver->version,
5240 driver->driver_path,
5241 r->driver_path);
5243 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5244 driver->architecture,
5245 driver->version,
5246 driver->data_file,
5247 r->data_file);
5249 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5250 driver->architecture,
5251 driver->version,
5252 driver->config_file,
5253 r->config_file);
5255 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5256 driver->architecture,
5257 driver->version,
5258 driver->help_file,
5259 r->help_file);
5261 FILL_DRIVER_STRING(mem_ctx,
5262 driver->monitor_name,
5263 r->monitor_name);
5265 FILL_DRIVER_STRING(mem_ctx,
5266 driver->default_datatype,
5267 r->default_datatype);
5269 result = string_array_from_driver_info(mem_ctx,
5270 driver->dependent_files,
5271 &r->dependent_files,
5272 cservername,
5273 driver->architecture,
5274 driver->version);
5275 if (!W_ERROR_IS_OK(result)) {
5276 return result;
5279 result = string_array_from_driver_info(mem_ctx,
5280 driver->previous_names,
5281 &r->previous_names,
5282 NULL, NULL, 0);
5283 if (!W_ERROR_IS_OK(result)) {
5284 return result;
5287 r->driver_date = driver->driver_date;
5288 r->driver_version = driver->driver_version;
5290 FILL_DRIVER_STRING(mem_ctx,
5291 driver->manufacturer_name,
5292 r->manufacturer_name);
5293 FILL_DRIVER_STRING(mem_ctx,
5294 driver->manufacturer_url,
5295 r->manufacturer_url);
5296 FILL_DRIVER_STRING(mem_ctx,
5297 driver->hardware_id,
5298 r->hardware_id);
5299 FILL_DRIVER_STRING(mem_ctx,
5300 driver->provider,
5301 r->provider);
5303 FILL_DRIVER_STRING(mem_ctx,
5304 driver->print_processor,
5305 r->print_processor);
5306 FILL_DRIVER_STRING(mem_ctx,
5307 driver->vendor_setup,
5308 r->vendor_setup);
5310 result = string_array_from_driver_info(mem_ctx,
5311 driver->color_profiles,
5312 &r->color_profiles,
5313 NULL, NULL, 0);
5314 if (!W_ERROR_IS_OK(result)) {
5315 return result;
5318 FILL_DRIVER_STRING(mem_ctx,
5319 driver->inf_path,
5320 r->inf_path);
5322 r->printer_driver_attributes = driver->printer_driver_attributes;
5324 result = string_array_from_driver_info(mem_ctx,
5325 driver->core_driver_dependencies,
5326 &r->core_driver_dependencies,
5327 NULL, NULL, 0);
5328 if (!W_ERROR_IS_OK(result)) {
5329 return result;
5332 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5333 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5335 return WERR_OK;
5338 #if 0 /* disabled until marshalling issues are resolved - gd */
5339 /********************************************************************
5340 ********************************************************************/
5342 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5343 struct spoolss_DriverFileInfo *r,
5344 const char *cservername,
5345 const char *file_name,
5346 enum spoolss_DriverFileType file_type,
5347 uint32_t file_version)
5349 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5350 cservername, file_name);
5351 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5352 r->file_type = file_type;
5353 r->file_version = file_version;
5355 return WERR_OK;
5358 /********************************************************************
5359 ********************************************************************/
5361 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5362 const struct spoolss_DriverInfo8 *driver,
5363 const char *cservername,
5364 struct spoolss_DriverFileInfo **info_p,
5365 uint32_t *count_p)
5367 struct spoolss_DriverFileInfo *info = NULL;
5368 uint32_t count = 0;
5369 WERROR result;
5370 uint32_t i;
5372 *info_p = NULL;
5373 *count_p = 0;
5375 if (strlen(driver->driver_path)) {
5376 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5377 struct spoolss_DriverFileInfo,
5378 count + 1);
5379 W_ERROR_HAVE_NO_MEMORY(info);
5380 result = fill_spoolss_DriverFileInfo(info,
5381 &info[count],
5382 cservername,
5383 driver->driver_path,
5384 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5386 W_ERROR_NOT_OK_RETURN(result);
5387 count++;
5390 if (strlen(driver->config_file)) {
5391 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5392 struct spoolss_DriverFileInfo,
5393 count + 1);
5394 W_ERROR_HAVE_NO_MEMORY(info);
5395 result = fill_spoolss_DriverFileInfo(info,
5396 &info[count],
5397 cservername,
5398 driver->config_file,
5399 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5401 W_ERROR_NOT_OK_RETURN(result);
5402 count++;
5405 if (strlen(driver->data_file)) {
5406 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5407 struct spoolss_DriverFileInfo,
5408 count + 1);
5409 W_ERROR_HAVE_NO_MEMORY(info);
5410 result = fill_spoolss_DriverFileInfo(info,
5411 &info[count],
5412 cservername,
5413 driver->data_file,
5414 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5416 W_ERROR_NOT_OK_RETURN(result);
5417 count++;
5420 if (strlen(driver->help_file)) {
5421 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5422 struct spoolss_DriverFileInfo,
5423 count + 1);
5424 W_ERROR_HAVE_NO_MEMORY(info);
5425 result = fill_spoolss_DriverFileInfo(info,
5426 &info[count],
5427 cservername,
5428 driver->help_file,
5429 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5431 W_ERROR_NOT_OK_RETURN(result);
5432 count++;
5435 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5436 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5437 struct spoolss_DriverFileInfo,
5438 count + 1);
5439 W_ERROR_HAVE_NO_MEMORY(info);
5440 result = fill_spoolss_DriverFileInfo(info,
5441 &info[count],
5442 cservername,
5443 driver->dependent_files[i],
5444 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5446 W_ERROR_NOT_OK_RETURN(result);
5447 count++;
5450 *info_p = info;
5451 *count_p = count;
5453 return WERR_OK;
5456 /********************************************************************
5457 * fill a spoolss_DriverInfo101 struct
5458 ********************************************************************/
5460 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5461 struct spoolss_DriverInfo101 *r,
5462 const struct spoolss_DriverInfo8 *driver,
5463 const char *servername)
5465 const char *cservername = canon_servername(servername);
5466 WERROR result;
5468 r->version = driver->version;
5470 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5471 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5472 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5473 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5475 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5476 cservername,
5477 &r->file_info,
5478 &r->file_count);
5479 if (!W_ERROR_IS_OK(result)) {
5480 return result;
5483 FILL_DRIVER_STRING(mem_ctx,
5484 driver->monitor_name,
5485 r->monitor_name);
5487 FILL_DRIVER_STRING(mem_ctx,
5488 driver->default_datatype,
5489 r->default_datatype);
5491 result = string_array_from_driver_info(mem_ctx,
5492 driver->previous_names,
5493 &r->previous_names,
5494 NULL, NULL, 0);
5495 if (!W_ERROR_IS_OK(result)) {
5496 return result;
5499 r->driver_date = driver->driver_date;
5500 r->driver_version = driver->driver_version;
5502 FILL_DRIVER_STRING(mem_ctx,
5503 driver->manufacturer_name,
5504 r->manufacturer_name);
5505 FILL_DRIVER_STRING(mem_ctx,
5506 driver->manufacturer_url,
5507 r->manufacturer_url);
5508 FILL_DRIVER_STRING(mem_ctx,
5509 driver->hardware_id,
5510 r->hardware_id);
5511 FILL_DRIVER_STRING(mem_ctx,
5512 driver->provider,
5513 r->provider);
5515 return WERR_OK;
5517 #endif
5518 /********************************************************************
5519 ********************************************************************/
5521 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5522 const struct auth_serversupplied_info *session_info,
5523 struct messaging_context *msg_ctx,
5524 uint32_t level,
5525 union spoolss_DriverInfo *r,
5526 int snum,
5527 const char *servername,
5528 const char *architecture,
5529 uint32_t version)
5531 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5532 struct spoolss_DriverInfo8 *driver;
5533 WERROR result;
5534 struct dcerpc_binding_handle *b;
5536 if (level == 101) {
5537 return WERR_UNKNOWN_LEVEL;
5540 result = winreg_printer_binding_handle(mem_ctx,
5541 session_info,
5542 msg_ctx,
5543 &b);
5544 if (!W_ERROR_IS_OK(result)) {
5545 return result;
5548 result = winreg_get_printer(mem_ctx, b,
5549 lp_const_servicename(snum),
5550 &pinfo2);
5552 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5553 win_errstr(result)));
5555 if (!W_ERROR_IS_OK(result)) {
5556 return WERR_INVALID_PRINTER_NAME;
5559 result = winreg_get_driver(mem_ctx, b,
5560 architecture,
5561 pinfo2->drivername, version, &driver);
5563 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5564 win_errstr(result)));
5566 if (!W_ERROR_IS_OK(result)) {
5568 * Is this a W2k client ?
5571 if (version < 3) {
5572 talloc_free(pinfo2);
5573 return WERR_UNKNOWN_PRINTER_DRIVER;
5576 /* Yes - try again with a WinNT driver. */
5577 version = 2;
5578 result = winreg_get_driver(mem_ctx, b,
5579 architecture,
5580 pinfo2->drivername,
5581 version, &driver);
5582 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5583 win_errstr(result)));
5584 if (!W_ERROR_IS_OK(result)) {
5585 talloc_free(pinfo2);
5586 return WERR_UNKNOWN_PRINTER_DRIVER;
5590 switch (level) {
5591 case 1:
5592 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5593 break;
5594 case 2:
5595 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5596 break;
5597 case 3:
5598 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5599 break;
5600 case 4:
5601 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5602 break;
5603 case 5:
5604 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5605 break;
5606 case 6:
5607 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5608 break;
5609 case 8:
5610 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5611 break;
5612 #if 0 /* disabled until marshalling issues are resolved - gd */
5613 case 101:
5614 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5615 break;
5616 #endif
5617 default:
5618 result = WERR_UNKNOWN_LEVEL;
5619 break;
5622 talloc_free(pinfo2);
5623 talloc_free(driver);
5625 return result;
5628 /****************************************************************
5629 _spoolss_GetPrinterDriver2
5630 ****************************************************************/
5632 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5633 struct spoolss_GetPrinterDriver2 *r)
5635 struct printer_handle *printer;
5636 WERROR result;
5638 int snum;
5640 /* that's an [in out] buffer */
5642 if (!r->in.buffer && (r->in.offered != 0)) {
5643 return WERR_INVALID_PARAM;
5646 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5648 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5649 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5650 return WERR_INVALID_PRINTER_NAME;
5653 *r->out.needed = 0;
5654 *r->out.server_major_version = 0;
5655 *r->out.server_minor_version = 0;
5657 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5658 return WERR_BADFID;
5661 result = construct_printer_driver_info_level(p->mem_ctx,
5662 get_session_info_system(),
5663 p->msg_ctx,
5664 r->in.level, r->out.info,
5665 snum, printer->servername,
5666 r->in.architecture,
5667 r->in.client_major_version);
5668 if (!W_ERROR_IS_OK(result)) {
5669 TALLOC_FREE(r->out.info);
5670 return result;
5673 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5674 r->out.info, r->in.level);
5675 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5677 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5681 /****************************************************************
5682 _spoolss_StartPagePrinter
5683 ****************************************************************/
5685 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5686 struct spoolss_StartPagePrinter *r)
5688 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5690 if (!Printer) {
5691 DEBUG(3,("_spoolss_StartPagePrinter: "
5692 "Error in startpageprinter printer handle\n"));
5693 return WERR_BADFID;
5696 Printer->page_started = true;
5697 return WERR_OK;
5700 /****************************************************************
5701 _spoolss_EndPagePrinter
5702 ****************************************************************/
5704 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5705 struct spoolss_EndPagePrinter *r)
5707 int snum;
5709 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5711 if (!Printer) {
5712 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5713 OUR_HANDLE(r->in.handle)));
5714 return WERR_BADFID;
5717 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5718 return WERR_BADFID;
5720 Printer->page_started = false;
5721 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5723 return WERR_OK;
5726 /****************************************************************
5727 _spoolss_StartDocPrinter
5728 ****************************************************************/
5730 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5731 struct spoolss_StartDocPrinter *r)
5733 struct spoolss_DocumentInfo1 *info_1;
5734 int snum;
5735 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5736 WERROR werr;
5738 if (!Printer) {
5739 DEBUG(2,("_spoolss_StartDocPrinter: "
5740 "Invalid handle (%s:%u:%u)\n",
5741 OUR_HANDLE(r->in.handle)));
5742 return WERR_BADFID;
5745 if (Printer->jobid) {
5746 DEBUG(2, ("_spoolss_StartDocPrinter: "
5747 "StartDocPrinter called twice! "
5748 "(existing jobid = %d)\n", Printer->jobid));
5749 return WERR_INVALID_HANDLE;
5752 if (r->in.level != 1) {
5753 return WERR_UNKNOWN_LEVEL;
5756 info_1 = r->in.info.info1;
5759 * a nice thing with NT is it doesn't listen to what you tell it.
5760 * when asked to send _only_ RAW datas, it tries to send datas
5761 * in EMF format.
5763 * So I add checks like in NT Server ...
5766 if (info_1->datatype) {
5767 if (strcmp(info_1->datatype, "RAW") != 0) {
5768 *r->out.job_id = 0;
5769 return WERR_INVALID_DATATYPE;
5773 /* get the share number of the printer */
5774 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5775 return WERR_BADFID;
5778 werr = print_job_start(p->session_info,
5779 p->msg_ctx,
5780 p->client_id->name,
5781 snum,
5782 info_1->document_name,
5783 info_1->output_file,
5784 Printer->devmode,
5785 &Printer->jobid);
5787 /* An error occured in print_job_start() so return an appropriate
5788 NT error code. */
5790 if (!W_ERROR_IS_OK(werr)) {
5791 return werr;
5794 Printer->document_started = true;
5795 *r->out.job_id = Printer->jobid;
5797 return WERR_OK;
5800 /****************************************************************
5801 _spoolss_EndDocPrinter
5802 ****************************************************************/
5804 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5805 struct spoolss_EndDocPrinter *r)
5807 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5808 NTSTATUS status;
5809 int snum;
5811 if (!Printer) {
5812 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5813 OUR_HANDLE(r->in.handle)));
5814 return WERR_BADFID;
5817 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5818 return WERR_BADFID;
5821 Printer->document_started = false;
5822 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5823 if (!NT_STATUS_IS_OK(status)) {
5824 DEBUG(2, ("_spoolss_EndDocPrinter: "
5825 "print_job_end failed [%s]\n",
5826 nt_errstr(status)));
5829 Printer->jobid = 0;
5830 return ntstatus_to_werror(status);
5833 /****************************************************************
5834 _spoolss_WritePrinter
5835 ****************************************************************/
5837 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5838 struct spoolss_WritePrinter *r)
5840 ssize_t buffer_written;
5841 int snum;
5842 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5844 if (!Printer) {
5845 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5846 OUR_HANDLE(r->in.handle)));
5847 *r->out.num_written = r->in._data_size;
5848 return WERR_BADFID;
5851 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5852 return WERR_BADFID;
5854 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5855 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5856 snum, Printer->jobid,
5857 (const char *)r->in.data.data,
5858 (size_t)r->in._data_size);
5859 if (buffer_written == (ssize_t)-1) {
5860 *r->out.num_written = 0;
5861 if (errno == ENOSPC)
5862 return WERR_NO_SPOOL_SPACE;
5863 else
5864 return WERR_ACCESS_DENIED;
5867 *r->out.num_written = r->in._data_size;
5869 return WERR_OK;
5872 /********************************************************************
5873 * api_spoolss_getprinter
5874 * called from the spoolss dispatcher
5876 ********************************************************************/
5878 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5879 struct pipes_struct *p)
5881 const struct auth_serversupplied_info *session_info = p->session_info;
5882 int snum;
5883 WERROR errcode = WERR_BADFUNC;
5884 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5886 if (!Printer) {
5887 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5888 OUR_HANDLE(handle)));
5889 return WERR_BADFID;
5892 if (!get_printer_snum(p, handle, &snum, NULL))
5893 return WERR_BADFID;
5895 switch (command) {
5896 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5897 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5898 break;
5899 case SPOOLSS_PRINTER_CONTROL_RESUME:
5900 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5901 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5902 break;
5903 case SPOOLSS_PRINTER_CONTROL_PURGE:
5904 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5905 break;
5906 default:
5907 return WERR_UNKNOWN_LEVEL;
5910 return errcode;
5914 /****************************************************************
5915 _spoolss_AbortPrinter
5916 * From MSDN: "Deletes printer's spool file if printer is configured
5917 * for spooling"
5918 ****************************************************************/
5920 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5921 struct spoolss_AbortPrinter *r)
5923 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5924 int snum;
5925 WERROR errcode = WERR_OK;
5927 if (!Printer) {
5928 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5929 OUR_HANDLE(r->in.handle)));
5930 return WERR_BADFID;
5933 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5934 return WERR_BADFID;
5936 if (!Printer->document_started) {
5937 return WERR_SPL_NO_STARTDOC;
5940 errcode = print_job_delete(p->session_info,
5941 p->msg_ctx,
5942 snum,
5943 Printer->jobid);
5945 return errcode;
5948 /********************************************************************
5949 * called by spoolss_api_setprinter
5950 * when updating a printer description
5951 ********************************************************************/
5953 static WERROR update_printer_sec(struct policy_handle *handle,
5954 struct pipes_struct *p,
5955 struct sec_desc_buf *secdesc_ctr)
5957 struct spoolss_security_descriptor *new_secdesc = NULL;
5958 struct spoolss_security_descriptor *old_secdesc = NULL;
5959 const char *printer;
5960 WERROR result;
5961 int snum;
5962 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5963 struct dcerpc_binding_handle *b;
5965 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5966 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5967 OUR_HANDLE(handle)));
5969 result = WERR_BADFID;
5970 goto done;
5973 if (secdesc_ctr == NULL) {
5974 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5975 result = WERR_INVALID_PARAM;
5976 goto done;
5978 printer = lp_const_servicename(snum);
5980 /* Check the user has permissions to change the security
5981 descriptor. By experimentation with two NT machines, the user
5982 requires Full Access to the printer to change security
5983 information. */
5985 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5986 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5987 result = WERR_ACCESS_DENIED;
5988 goto done;
5991 result = winreg_printer_binding_handle(p->mem_ctx,
5992 get_session_info_system(),
5993 p->msg_ctx,
5994 &b);
5995 if (!W_ERROR_IS_OK(result)) {
5996 goto done;
5999 /* NT seems to like setting the security descriptor even though
6000 nothing may have actually changed. */
6001 result = winreg_get_printer_secdesc(p->mem_ctx, b,
6002 printer,
6003 &old_secdesc);
6004 if (!W_ERROR_IS_OK(result)) {
6005 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6006 result = WERR_BADFID;
6007 goto done;
6010 if (DEBUGLEVEL >= 10) {
6011 struct security_acl *the_acl;
6012 int i;
6014 the_acl = old_secdesc->dacl;
6015 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6016 printer, the_acl->num_aces));
6018 for (i = 0; i < the_acl->num_aces; i++) {
6019 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6020 &the_acl->aces[i].trustee),
6021 the_acl->aces[i].access_mask));
6024 the_acl = secdesc_ctr->sd->dacl;
6026 if (the_acl) {
6027 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6028 printer, the_acl->num_aces));
6030 for (i = 0; i < the_acl->num_aces; i++) {
6031 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6032 &the_acl->aces[i].trustee),
6033 the_acl->aces[i].access_mask));
6035 } else {
6036 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6040 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
6041 if (new_secdesc == NULL) {
6042 result = WERR_NOMEM;
6043 goto done;
6046 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6047 result = WERR_OK;
6048 goto done;
6051 result = winreg_set_printer_secdesc(p->mem_ctx, b,
6052 printer,
6053 new_secdesc);
6055 done:
6056 return result;
6059 /********************************************************************
6060 Canonicalize printer info from a client
6061 ********************************************************************/
6063 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6064 struct spoolss_SetPrinterInfo2 *info2,
6065 int snum)
6067 fstring printername;
6068 const char *p;
6070 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6071 "portname=%s drivername=%s comment=%s location=%s\n",
6072 info2->servername, info2->printername, info2->sharename,
6073 info2->portname, info2->drivername, info2->comment,
6074 info2->location));
6076 /* we force some elements to "correct" values */
6077 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6078 if (info2->servername == NULL) {
6079 return false;
6081 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6082 if (info2->sharename == NULL) {
6083 return false;
6086 /* check to see if we allow printername != sharename */
6087 if (lp_force_printername(snum)) {
6088 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6089 global_myname(), info2->sharename);
6090 } else {
6091 /* make sure printername is in \\server\printername format */
6092 fstrcpy(printername, info2->printername);
6093 p = printername;
6094 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6095 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6096 p++;
6099 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6100 global_myname(), p);
6102 if (info2->printername == NULL) {
6103 return false;
6106 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6107 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6109 return true;
6112 /****************************************************************************
6113 ****************************************************************************/
6115 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6117 char *cmd = lp_addport_cmd();
6118 char *command = NULL;
6119 int ret;
6120 bool is_print_op = false;
6122 if ( !*cmd ) {
6123 return WERR_ACCESS_DENIED;
6126 command = talloc_asprintf(ctx,
6127 "%s \"%s\" \"%s\"", cmd, portname, uri );
6128 if (!command) {
6129 return WERR_NOMEM;
6132 if ( token )
6133 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6135 DEBUG(10,("Running [%s]\n", command));
6137 /********* BEGIN SePrintOperatorPrivilege **********/
6139 if ( is_print_op )
6140 become_root();
6142 ret = smbrun(command, NULL);
6144 if ( is_print_op )
6145 unbecome_root();
6147 /********* END SePrintOperatorPrivilege **********/
6149 DEBUGADD(10,("returned [%d]\n", ret));
6151 TALLOC_FREE(command);
6153 if ( ret != 0 ) {
6154 return WERR_ACCESS_DENIED;
6157 return WERR_OK;
6160 /****************************************************************************
6161 ****************************************************************************/
6163 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6164 struct spoolss_SetPrinterInfo2 *info2,
6165 const char *remote_machine,
6166 struct messaging_context *msg_ctx)
6168 char *cmd = lp_addprinter_cmd();
6169 char **qlines;
6170 char *command = NULL;
6171 int numlines;
6172 int ret;
6173 int fd;
6174 bool is_print_op = false;
6176 if (!remote_machine) {
6177 return false;
6180 command = talloc_asprintf(ctx,
6181 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6182 cmd, info2->printername, info2->sharename,
6183 info2->portname, info2->drivername,
6184 info2->location, info2->comment, remote_machine);
6185 if (!command) {
6186 return false;
6189 if ( token )
6190 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6192 DEBUG(10,("Running [%s]\n", command));
6194 /********* BEGIN SePrintOperatorPrivilege **********/
6196 if ( is_print_op )
6197 become_root();
6199 if ( (ret = smbrun(command, &fd)) == 0 ) {
6200 /* Tell everyone we updated smb.conf. */
6201 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6204 if ( is_print_op )
6205 unbecome_root();
6207 /********* END SePrintOperatorPrivilege **********/
6209 DEBUGADD(10,("returned [%d]\n", ret));
6211 TALLOC_FREE(command);
6213 if ( ret != 0 ) {
6214 if (fd != -1)
6215 close(fd);
6216 return false;
6219 /* reload our services immediately */
6220 become_root();
6221 reload_services(msg_ctx, -1, false);
6222 unbecome_root();
6224 numlines = 0;
6225 /* Get lines and convert them back to dos-codepage */
6226 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6227 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6228 close(fd);
6230 /* Set the portname to what the script says the portname should be. */
6231 /* but don't require anything to be return from the script exit a good error code */
6233 if (numlines) {
6234 /* Set the portname to what the script says the portname should be. */
6235 info2->portname = talloc_strdup(ctx, qlines[0]);
6236 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6239 TALLOC_FREE(qlines);
6240 return true;
6243 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6244 const struct auth_serversupplied_info *session_info,
6245 struct messaging_context *msg_ctx,
6246 int snum,
6247 struct spoolss_SetPrinterInfo2 *printer,
6248 struct spoolss_PrinterInfo2 *old_printer)
6250 bool force_update = (old_printer == NULL);
6251 const char *dnsdomname;
6252 const char *longname;
6253 const char *uncname;
6254 const char *spooling;
6255 DATA_BLOB buffer;
6256 WERROR result = WERR_OK;
6257 struct dcerpc_binding_handle *b;
6259 result = winreg_printer_binding_handle(mem_ctx,
6260 session_info,
6261 msg_ctx,
6262 &b);
6263 if (!W_ERROR_IS_OK(result)) {
6264 return result;
6267 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6268 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6269 winreg_set_printer_dataex(mem_ctx, b,
6270 printer->sharename,
6271 SPOOL_DSSPOOLER_KEY,
6272 SPOOL_REG_DRIVERNAME,
6273 REG_SZ,
6274 buffer.data,
6275 buffer.length);
6277 if (!force_update) {
6278 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6279 printer->drivername));
6281 notify_printer_driver(server_event_context(), msg_ctx,
6282 snum, printer->drivername ?
6283 printer->drivername : "");
6287 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6288 push_reg_sz(mem_ctx, &buffer, printer->comment);
6289 winreg_set_printer_dataex(mem_ctx, b,
6290 printer->sharename,
6291 SPOOL_DSSPOOLER_KEY,
6292 SPOOL_REG_DESCRIPTION,
6293 REG_SZ,
6294 buffer.data,
6295 buffer.length);
6297 if (!force_update) {
6298 notify_printer_comment(server_event_context(), msg_ctx,
6299 snum, printer->comment ?
6300 printer->comment : "");
6304 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6305 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6306 winreg_set_printer_dataex(mem_ctx, b,
6307 printer->sharename,
6308 SPOOL_DSSPOOLER_KEY,
6309 SPOOL_REG_PRINTSHARENAME,
6310 REG_SZ,
6311 buffer.data,
6312 buffer.length);
6314 if (!force_update) {
6315 notify_printer_sharename(server_event_context(),
6316 msg_ctx,
6317 snum, printer->sharename ?
6318 printer->sharename : "");
6322 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6323 const char *p;
6325 p = strrchr(printer->printername, '\\' );
6326 if (p != NULL) {
6327 p++;
6328 } else {
6329 p = printer->printername;
6332 push_reg_sz(mem_ctx, &buffer, p);
6333 winreg_set_printer_dataex(mem_ctx, b,
6334 printer->sharename,
6335 SPOOL_DSSPOOLER_KEY,
6336 SPOOL_REG_PRINTERNAME,
6337 REG_SZ,
6338 buffer.data,
6339 buffer.length);
6341 if (!force_update) {
6342 notify_printer_printername(server_event_context(),
6343 msg_ctx, snum, p ? p : "");
6347 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6348 push_reg_sz(mem_ctx, &buffer, printer->portname);
6349 winreg_set_printer_dataex(mem_ctx, b,
6350 printer->sharename,
6351 SPOOL_DSSPOOLER_KEY,
6352 SPOOL_REG_PORTNAME,
6353 REG_SZ,
6354 buffer.data,
6355 buffer.length);
6357 if (!force_update) {
6358 notify_printer_port(server_event_context(),
6359 msg_ctx, snum, printer->portname ?
6360 printer->portname : "");
6364 if (force_update || !strequal(printer->location, old_printer->location)) {
6365 push_reg_sz(mem_ctx, &buffer, printer->location);
6366 winreg_set_printer_dataex(mem_ctx, b,
6367 printer->sharename,
6368 SPOOL_DSSPOOLER_KEY,
6369 SPOOL_REG_LOCATION,
6370 REG_SZ,
6371 buffer.data,
6372 buffer.length);
6374 if (!force_update) {
6375 notify_printer_location(server_event_context(),
6376 msg_ctx, snum,
6377 printer->location ?
6378 printer->location : "");
6382 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6383 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6384 winreg_set_printer_dataex(mem_ctx, b,
6385 printer->sharename,
6386 SPOOL_DSSPOOLER_KEY,
6387 SPOOL_REG_PRINTSEPARATORFILE,
6388 REG_SZ,
6389 buffer.data,
6390 buffer.length);
6392 if (!force_update) {
6393 notify_printer_sepfile(server_event_context(),
6394 msg_ctx, snum,
6395 printer->sepfile ?
6396 printer->sepfile : "");
6400 if (force_update || printer->starttime != old_printer->starttime) {
6401 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6402 SIVAL(buffer.data, 0, printer->starttime);
6403 winreg_set_printer_dataex(mem_ctx, b,
6404 printer->sharename,
6405 SPOOL_DSSPOOLER_KEY,
6406 SPOOL_REG_PRINTSTARTTIME,
6407 REG_DWORD,
6408 buffer.data,
6409 buffer.length);
6412 if (force_update || printer->untiltime != old_printer->untiltime) {
6413 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6414 SIVAL(buffer.data, 0, printer->untiltime);
6415 winreg_set_printer_dataex(mem_ctx, b,
6416 printer->sharename,
6417 SPOOL_DSSPOOLER_KEY,
6418 SPOOL_REG_PRINTENDTIME,
6419 REG_DWORD,
6420 buffer.data,
6421 buffer.length);
6424 if (force_update || printer->priority != old_printer->priority) {
6425 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6426 SIVAL(buffer.data, 0, printer->priority);
6427 winreg_set_printer_dataex(mem_ctx, b,
6428 printer->sharename,
6429 SPOOL_DSSPOOLER_KEY,
6430 SPOOL_REG_PRIORITY,
6431 REG_DWORD,
6432 buffer.data,
6433 buffer.length);
6436 if (force_update || printer->attributes != old_printer->attributes) {
6437 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6438 SIVAL(buffer.data, 0, (printer->attributes &
6439 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6440 winreg_set_printer_dataex(mem_ctx, b,
6441 printer->sharename,
6442 SPOOL_DSSPOOLER_KEY,
6443 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6444 REG_DWORD,
6445 buffer.data,
6446 buffer.length);
6448 switch (printer->attributes & 0x3) {
6449 case 0:
6450 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6451 break;
6452 case 1:
6453 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6454 break;
6455 case 2:
6456 spooling = SPOOL_REGVAL_PRINTDIRECT;
6457 break;
6458 default:
6459 spooling = "unknown";
6461 push_reg_sz(mem_ctx, &buffer, spooling);
6462 winreg_set_printer_dataex(mem_ctx, b,
6463 printer->sharename,
6464 SPOOL_DSSPOOLER_KEY,
6465 SPOOL_REG_PRINTSPOOLING,
6466 REG_SZ,
6467 buffer.data,
6468 buffer.length);
6471 push_reg_sz(mem_ctx, &buffer, global_myname());
6472 winreg_set_printer_dataex(mem_ctx, b,
6473 printer->sharename,
6474 SPOOL_DSSPOOLER_KEY,
6475 SPOOL_REG_SHORTSERVERNAME,
6476 REG_SZ,
6477 buffer.data,
6478 buffer.length);
6480 dnsdomname = get_mydnsfullname();
6481 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6482 longname = talloc_strdup(mem_ctx, dnsdomname);
6483 } else {
6484 longname = talloc_strdup(mem_ctx, global_myname());
6486 if (longname == NULL) {
6487 result = WERR_NOMEM;
6488 goto done;
6491 push_reg_sz(mem_ctx, &buffer, longname);
6492 winreg_set_printer_dataex(mem_ctx, b,
6493 printer->sharename,
6494 SPOOL_DSSPOOLER_KEY,
6495 SPOOL_REG_SERVERNAME,
6496 REG_SZ,
6497 buffer.data,
6498 buffer.length);
6500 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6501 global_myname(), printer->sharename);
6502 push_reg_sz(mem_ctx, &buffer, uncname);
6503 winreg_set_printer_dataex(mem_ctx, b,
6504 printer->sharename,
6505 SPOOL_DSSPOOLER_KEY,
6506 SPOOL_REG_UNCNAME,
6507 REG_SZ,
6508 buffer.data,
6509 buffer.length);
6511 done:
6512 return result;
6515 /********************************************************************
6516 * Called by spoolss_api_setprinter
6517 * when updating a printer description.
6518 ********************************************************************/
6520 static WERROR update_printer(struct pipes_struct *p,
6521 struct policy_handle *handle,
6522 struct spoolss_SetPrinterInfoCtr *info_ctr,
6523 struct spoolss_DeviceMode *devmode)
6525 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6526 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6527 struct spoolss_PrinterInfo2 *old_printer;
6528 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6529 int snum;
6530 WERROR result = WERR_OK;
6531 TALLOC_CTX *tmp_ctx;
6532 struct dcerpc_binding_handle *b;
6534 DEBUG(8,("update_printer\n"));
6536 tmp_ctx = talloc_new(p->mem_ctx);
6537 if (tmp_ctx == NULL) {
6538 return WERR_NOMEM;
6541 if (!Printer) {
6542 result = WERR_BADFID;
6543 goto done;
6546 if (!get_printer_snum(p, handle, &snum, NULL)) {
6547 result = WERR_BADFID;
6548 goto done;
6551 result = winreg_printer_binding_handle(tmp_ctx,
6552 get_session_info_system(),
6553 p->msg_ctx,
6554 &b);
6555 if (!W_ERROR_IS_OK(result)) {
6556 goto done;
6559 result = winreg_get_printer(tmp_ctx, b,
6560 lp_const_servicename(snum),
6561 &old_printer);
6562 if (!W_ERROR_IS_OK(result)) {
6563 result = WERR_BADFID;
6564 goto done;
6567 /* Do sanity check on the requested changes for Samba */
6568 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6569 result = WERR_INVALID_PARAM;
6570 goto done;
6573 /* FIXME!!! If the driver has changed we really should verify that
6574 it is installed before doing much else --jerry */
6576 /* Check calling user has permission to update printer description */
6577 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6578 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6579 result = WERR_ACCESS_DENIED;
6580 goto done;
6583 /* Call addprinter hook */
6584 /* Check changes to see if this is really needed */
6586 if (*lp_addprinter_cmd() &&
6587 (!strequal(printer->drivername, old_printer->drivername) ||
6588 !strequal(printer->comment, old_printer->comment) ||
6589 !strequal(printer->portname, old_printer->portname) ||
6590 !strequal(printer->location, old_printer->location)) )
6592 /* add_printer_hook() will call reload_services() */
6593 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6594 printer, p->client_id->addr,
6595 p->msg_ctx)) {
6596 result = WERR_ACCESS_DENIED;
6597 goto done;
6601 update_dsspooler(tmp_ctx,
6602 get_session_info_system(),
6603 p->msg_ctx,
6604 snum,
6605 printer,
6606 old_printer);
6608 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6610 if (devmode == NULL) {
6611 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6613 result = winreg_update_printer(tmp_ctx, b,
6614 printer->sharename,
6615 printer_mask,
6616 printer,
6617 devmode,
6618 NULL);
6620 done:
6621 talloc_free(tmp_ctx);
6623 return result;
6626 /****************************************************************************
6627 ****************************************************************************/
6628 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6629 struct policy_handle *handle,
6630 struct spoolss_SetPrinterInfo7 *info7)
6632 #ifdef HAVE_ADS
6633 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6634 WERROR result;
6635 int snum;
6636 struct printer_handle *Printer;
6638 if ( lp_security() != SEC_ADS ) {
6639 return WERR_UNKNOWN_LEVEL;
6642 Printer = find_printer_index_by_hnd(p, handle);
6644 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6646 if (!Printer)
6647 return WERR_BADFID;
6649 if (!get_printer_snum(p, handle, &snum, NULL))
6650 return WERR_BADFID;
6652 result = winreg_get_printer_internal(p->mem_ctx,
6653 get_session_info_system(),
6654 p->msg_ctx,
6655 lp_servicename(snum),
6656 &pinfo2);
6657 if (!W_ERROR_IS_OK(result)) {
6658 return WERR_BADFID;
6661 nt_printer_publish(pinfo2,
6662 get_session_info_system(),
6663 p->msg_ctx,
6664 pinfo2,
6665 info7->action);
6667 TALLOC_FREE(pinfo2);
6668 return WERR_OK;
6669 #else
6670 return WERR_UNKNOWN_LEVEL;
6671 #endif
6674 /********************************************************************
6675 ********************************************************************/
6677 static WERROR update_printer_devmode(struct pipes_struct *p,
6678 struct policy_handle *handle,
6679 struct spoolss_DeviceMode *devmode)
6681 int snum;
6682 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6683 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6685 DEBUG(8,("update_printer_devmode\n"));
6687 if (!Printer) {
6688 return WERR_BADFID;
6691 if (!get_printer_snum(p, handle, &snum, NULL)) {
6692 return WERR_BADFID;
6695 /* Check calling user has permission to update printer description */
6696 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6697 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6698 return WERR_ACCESS_DENIED;
6701 return winreg_update_printer_internal(p->mem_ctx,
6702 get_session_info_system(),
6703 p->msg_ctx,
6704 lp_const_servicename(snum),
6705 info2_mask,
6706 NULL,
6707 devmode,
6708 NULL);
6712 /****************************************************************
6713 _spoolss_SetPrinter
6714 ****************************************************************/
6716 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6717 struct spoolss_SetPrinter *r)
6719 WERROR result;
6721 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6723 if (!Printer) {
6724 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6725 OUR_HANDLE(r->in.handle)));
6726 return WERR_BADFID;
6729 /* check the level */
6730 switch (r->in.info_ctr->level) {
6731 case 0:
6732 return control_printer(r->in.handle, r->in.command, p);
6733 case 2:
6734 result = update_printer(p, r->in.handle,
6735 r->in.info_ctr,
6736 r->in.devmode_ctr->devmode);
6737 if (!W_ERROR_IS_OK(result))
6738 return result;
6739 if (r->in.secdesc_ctr->sd)
6740 result = update_printer_sec(r->in.handle, p,
6741 r->in.secdesc_ctr);
6742 return result;
6743 case 3:
6744 return update_printer_sec(r->in.handle, p,
6745 r->in.secdesc_ctr);
6746 case 7:
6747 return publish_or_unpublish_printer(p, r->in.handle,
6748 r->in.info_ctr->info.info7);
6749 case 8:
6750 return update_printer_devmode(p, r->in.handle,
6751 r->in.devmode_ctr->devmode);
6752 default:
6753 return WERR_UNKNOWN_LEVEL;
6757 /****************************************************************
6758 _spoolss_FindClosePrinterNotify
6759 ****************************************************************/
6761 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6762 struct spoolss_FindClosePrinterNotify *r)
6764 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6766 if (!Printer) {
6767 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6768 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6769 return WERR_BADFID;
6772 if (Printer->notify.cli_chan != NULL &&
6773 Printer->notify.cli_chan->active_connections > 0) {
6774 int snum = -1;
6776 if (Printer->printer_type == SPLHND_PRINTER) {
6777 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6778 return WERR_BADFID;
6782 srv_spoolss_replycloseprinter(snum, Printer);
6785 Printer->notify.flags=0;
6786 Printer->notify.options=0;
6787 Printer->notify.localmachine[0]='\0';
6788 Printer->notify.printerlocal=0;
6789 TALLOC_FREE(Printer->notify.option);
6791 return WERR_OK;
6794 /****************************************************************
6795 _spoolss_AddJob
6796 ****************************************************************/
6798 WERROR _spoolss_AddJob(struct pipes_struct *p,
6799 struct spoolss_AddJob *r)
6801 if (!r->in.buffer && (r->in.offered != 0)) {
6802 return WERR_INVALID_PARAM;
6805 /* this is what a NT server returns for AddJob. AddJob must fail on
6806 * non-local printers */
6808 if (r->in.level != 1) {
6809 return WERR_UNKNOWN_LEVEL;
6812 return WERR_INVALID_PARAM;
6815 /****************************************************************************
6816 fill_job_info1
6817 ****************************************************************************/
6819 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6820 struct spoolss_JobInfo1 *r,
6821 const print_queue_struct *queue,
6822 int position, int snum,
6823 struct spoolss_PrinterInfo2 *pinfo2)
6825 struct tm *t;
6827 t = gmtime(&queue->time);
6829 r->job_id = queue->job;
6831 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6832 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6833 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6834 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6835 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6836 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6837 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6838 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6839 r->data_type = talloc_strdup(mem_ctx, "RAW");
6840 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6841 r->text_status = talloc_strdup(mem_ctx, "");
6842 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6844 r->status = nt_printj_status(queue->status);
6845 r->priority = queue->priority;
6846 r->position = position;
6847 r->total_pages = queue->page_count;
6848 r->pages_printed = 0; /* ??? */
6850 init_systemtime(&r->submitted, t);
6852 return WERR_OK;
6855 /****************************************************************************
6856 fill_job_info2
6857 ****************************************************************************/
6859 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6860 struct spoolss_JobInfo2 *r,
6861 const print_queue_struct *queue,
6862 int position, int snum,
6863 struct spoolss_PrinterInfo2 *pinfo2,
6864 struct spoolss_DeviceMode *devmode)
6866 struct tm *t;
6868 t = gmtime(&queue->time);
6870 r->job_id = queue->job;
6872 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6873 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6874 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6875 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6876 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6877 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6878 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6879 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6880 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6881 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6882 r->data_type = talloc_strdup(mem_ctx, "RAW");
6883 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6884 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6885 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6886 r->parameters = talloc_strdup(mem_ctx, "");
6887 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6888 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6889 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6891 r->devmode = devmode;
6893 r->text_status = talloc_strdup(mem_ctx, "");
6894 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6896 r->secdesc = NULL;
6898 r->status = nt_printj_status(queue->status);
6899 r->priority = queue->priority;
6900 r->position = position;
6901 r->start_time = 0;
6902 r->until_time = 0;
6903 r->total_pages = queue->page_count;
6904 r->size = queue->size;
6905 init_systemtime(&r->submitted, t);
6906 r->time = 0;
6907 r->pages_printed = 0; /* ??? */
6909 return WERR_OK;
6912 /****************************************************************************
6913 fill_job_info3
6914 ****************************************************************************/
6916 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6917 struct spoolss_JobInfo3 *r,
6918 const print_queue_struct *queue,
6919 const print_queue_struct *next_queue,
6920 int position, int snum,
6921 struct spoolss_PrinterInfo2 *pinfo2)
6923 r->job_id = queue->job;
6924 r->next_job_id = 0;
6925 if (next_queue) {
6926 r->next_job_id = next_queue->job;
6928 r->reserved = 0;
6930 return WERR_OK;
6933 /****************************************************************************
6934 Enumjobs at level 1.
6935 ****************************************************************************/
6937 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6938 const print_queue_struct *queue,
6939 uint32_t num_queues, int snum,
6940 struct spoolss_PrinterInfo2 *pinfo2,
6941 union spoolss_JobInfo **info_p,
6942 uint32_t *count)
6944 union spoolss_JobInfo *info;
6945 int i;
6946 WERROR result = WERR_OK;
6948 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6949 W_ERROR_HAVE_NO_MEMORY(info);
6951 *count = num_queues;
6953 for (i=0; i<*count; i++) {
6954 result = fill_job_info1(info,
6955 &info[i].info1,
6956 &queue[i],
6958 snum,
6959 pinfo2);
6960 if (!W_ERROR_IS_OK(result)) {
6961 goto out;
6965 out:
6966 if (!W_ERROR_IS_OK(result)) {
6967 TALLOC_FREE(info);
6968 *count = 0;
6969 return result;
6972 *info_p = info;
6974 return WERR_OK;
6977 /****************************************************************************
6978 Enumjobs at level 2.
6979 ****************************************************************************/
6981 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6982 const print_queue_struct *queue,
6983 uint32_t num_queues, int snum,
6984 struct spoolss_PrinterInfo2 *pinfo2,
6985 union spoolss_JobInfo **info_p,
6986 uint32_t *count)
6988 union spoolss_JobInfo *info;
6989 int i;
6990 WERROR result = WERR_OK;
6992 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6993 W_ERROR_HAVE_NO_MEMORY(info);
6995 *count = num_queues;
6997 for (i=0; i<*count; i++) {
6998 struct spoolss_DeviceMode *devmode;
7000 result = spoolss_create_default_devmode(info,
7001 pinfo2->printername,
7002 &devmode);
7003 if (!W_ERROR_IS_OK(result)) {
7004 DEBUG(3, ("Can't proceed w/o a devmode!"));
7005 goto out;
7008 result = fill_job_info2(info,
7009 &info[i].info2,
7010 &queue[i],
7012 snum,
7013 pinfo2,
7014 devmode);
7015 if (!W_ERROR_IS_OK(result)) {
7016 goto out;
7020 out:
7021 if (!W_ERROR_IS_OK(result)) {
7022 TALLOC_FREE(info);
7023 *count = 0;
7024 return result;
7027 *info_p = info;
7029 return WERR_OK;
7032 /****************************************************************************
7033 Enumjobs at level 3.
7034 ****************************************************************************/
7036 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7037 const print_queue_struct *queue,
7038 uint32_t num_queues, int snum,
7039 struct spoolss_PrinterInfo2 *pinfo2,
7040 union spoolss_JobInfo **info_p,
7041 uint32_t *count)
7043 union spoolss_JobInfo *info;
7044 int i;
7045 WERROR result = WERR_OK;
7047 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7048 W_ERROR_HAVE_NO_MEMORY(info);
7050 *count = num_queues;
7052 for (i=0; i<*count; i++) {
7053 const print_queue_struct *next_queue = NULL;
7055 if (i+1 < *count) {
7056 next_queue = &queue[i+1];
7059 result = fill_job_info3(info,
7060 &info[i].info3,
7061 &queue[i],
7062 next_queue,
7064 snum,
7065 pinfo2);
7066 if (!W_ERROR_IS_OK(result)) {
7067 goto out;
7071 out:
7072 if (!W_ERROR_IS_OK(result)) {
7073 TALLOC_FREE(info);
7074 *count = 0;
7075 return result;
7078 *info_p = info;
7080 return WERR_OK;
7083 /****************************************************************
7084 _spoolss_EnumJobs
7085 ****************************************************************/
7087 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7088 struct spoolss_EnumJobs *r)
7090 WERROR result;
7091 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7092 int snum;
7093 print_status_struct prt_status;
7094 print_queue_struct *queue = NULL;
7095 uint32_t count;
7097 /* that's an [in out] buffer */
7099 if (!r->in.buffer && (r->in.offered != 0)) {
7100 return WERR_INVALID_PARAM;
7103 DEBUG(4,("_spoolss_EnumJobs\n"));
7105 *r->out.needed = 0;
7106 *r->out.count = 0;
7107 *r->out.info = NULL;
7109 /* lookup the printer snum and tdb entry */
7111 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7112 return WERR_BADFID;
7115 result = winreg_get_printer_internal(p->mem_ctx,
7116 get_session_info_system(),
7117 p->msg_ctx,
7118 lp_const_servicename(snum),
7119 &pinfo2);
7120 if (!W_ERROR_IS_OK(result)) {
7121 return result;
7124 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7125 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7126 count, prt_status.status, prt_status.message));
7128 if (count == 0) {
7129 SAFE_FREE(queue);
7130 TALLOC_FREE(pinfo2);
7131 return WERR_OK;
7134 switch (r->in.level) {
7135 case 1:
7136 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7137 pinfo2, r->out.info, r->out.count);
7138 break;
7139 case 2:
7140 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7141 pinfo2, r->out.info, r->out.count);
7142 break;
7143 case 3:
7144 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7145 pinfo2, r->out.info, r->out.count);
7146 break;
7147 default:
7148 result = WERR_UNKNOWN_LEVEL;
7149 break;
7152 SAFE_FREE(queue);
7153 TALLOC_FREE(pinfo2);
7155 if (!W_ERROR_IS_OK(result)) {
7156 return result;
7159 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7160 spoolss_EnumJobs,
7161 *r->out.info, r->in.level,
7162 *r->out.count);
7163 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7164 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7166 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7169 /****************************************************************
7170 _spoolss_ScheduleJob
7171 ****************************************************************/
7173 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7174 struct spoolss_ScheduleJob *r)
7176 return WERR_OK;
7179 /****************************************************************
7180 ****************************************************************/
7182 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7183 struct messaging_context *msg_ctx,
7184 const char *printer_name,
7185 uint32_t job_id,
7186 struct spoolss_SetJobInfo1 *r)
7188 char *old_doc_name;
7190 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7191 return WERR_BADFID;
7194 if (strequal(old_doc_name, r->document_name)) {
7195 return WERR_OK;
7198 if (!print_job_set_name(server_event_context(), msg_ctx,
7199 printer_name, job_id, r->document_name)) {
7200 return WERR_BADFID;
7203 return WERR_OK;
7206 /****************************************************************
7207 _spoolss_SetJob
7208 ****************************************************************/
7210 WERROR _spoolss_SetJob(struct pipes_struct *p,
7211 struct spoolss_SetJob *r)
7213 const struct auth_serversupplied_info *session_info = p->session_info;
7214 int snum;
7215 WERROR errcode = WERR_BADFUNC;
7217 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7218 return WERR_BADFID;
7221 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7222 return WERR_INVALID_PRINTER_NAME;
7225 switch (r->in.command) {
7226 case SPOOLSS_JOB_CONTROL_CANCEL:
7227 case SPOOLSS_JOB_CONTROL_DELETE:
7228 errcode = print_job_delete(session_info, p->msg_ctx,
7229 snum, r->in.job_id);
7230 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7231 errcode = WERR_OK;
7233 break;
7234 case SPOOLSS_JOB_CONTROL_PAUSE:
7235 if (print_job_pause(session_info, p->msg_ctx,
7236 snum, r->in.job_id, &errcode)) {
7237 errcode = WERR_OK;
7239 break;
7240 case SPOOLSS_JOB_CONTROL_RESTART:
7241 case SPOOLSS_JOB_CONTROL_RESUME:
7242 if (print_job_resume(session_info, p->msg_ctx,
7243 snum, r->in.job_id, &errcode)) {
7244 errcode = WERR_OK;
7246 break;
7247 case 0:
7248 errcode = WERR_OK;
7249 break;
7250 default:
7251 return WERR_UNKNOWN_LEVEL;
7254 if (!W_ERROR_IS_OK(errcode)) {
7255 return errcode;
7258 if (r->in.ctr == NULL) {
7259 return errcode;
7262 switch (r->in.ctr->level) {
7263 case 1:
7264 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7265 lp_const_servicename(snum),
7266 r->in.job_id,
7267 r->in.ctr->info.info1);
7268 break;
7269 case 2:
7270 case 3:
7271 case 4:
7272 default:
7273 return WERR_UNKNOWN_LEVEL;
7276 return errcode;
7279 /****************************************************************************
7280 Enumerates all printer drivers by level and architecture.
7281 ****************************************************************************/
7283 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7284 const struct auth_serversupplied_info *session_info,
7285 struct messaging_context *msg_ctx,
7286 const char *servername,
7287 const char *architecture,
7288 uint32_t level,
7289 union spoolss_DriverInfo **info_p,
7290 uint32_t *count_p)
7292 int i;
7293 uint32_t version;
7294 struct spoolss_DriverInfo8 *driver;
7295 union spoolss_DriverInfo *info = NULL;
7296 uint32_t count = 0;
7297 WERROR result = WERR_OK;
7298 uint32_t num_drivers;
7299 const char **drivers;
7300 struct dcerpc_binding_handle *b;
7302 *count_p = 0;
7303 *info_p = NULL;
7305 result = winreg_printer_binding_handle(mem_ctx,
7306 session_info,
7307 msg_ctx,
7308 &b);
7309 if (!W_ERROR_IS_OK(result)) {
7310 goto out;
7313 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7314 result = winreg_get_driver_list(mem_ctx, b,
7315 architecture, version,
7316 &num_drivers, &drivers);
7317 if (!W_ERROR_IS_OK(result)) {
7318 goto out;
7320 DEBUG(4, ("we have:[%d] drivers in environment"
7321 " [%s] and version [%d]\n",
7322 num_drivers, architecture, version));
7324 if (num_drivers != 0) {
7325 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7326 union spoolss_DriverInfo,
7327 count + num_drivers);
7328 if (!info) {
7329 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7330 "failed to enlarge driver info buffer!\n"));
7331 result = WERR_NOMEM;
7332 goto out;
7336 for (i = 0; i < num_drivers; i++) {
7337 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7339 result = winreg_get_driver(mem_ctx, b,
7340 architecture, drivers[i],
7341 version, &driver);
7342 if (!W_ERROR_IS_OK(result)) {
7343 goto out;
7346 switch (level) {
7347 case 1:
7348 result = fill_printer_driver_info1(info, &info[count+i].info1,
7349 driver, servername);
7350 break;
7351 case 2:
7352 result = fill_printer_driver_info2(info, &info[count+i].info2,
7353 driver, servername);
7354 break;
7355 case 3:
7356 result = fill_printer_driver_info3(info, &info[count+i].info3,
7357 driver, servername);
7358 break;
7359 case 4:
7360 result = fill_printer_driver_info4(info, &info[count+i].info4,
7361 driver, servername);
7362 break;
7363 case 5:
7364 result = fill_printer_driver_info5(info, &info[count+i].info5,
7365 driver, servername);
7366 break;
7367 case 6:
7368 result = fill_printer_driver_info6(info, &info[count+i].info6,
7369 driver, servername);
7370 break;
7371 case 8:
7372 result = fill_printer_driver_info8(info, &info[count+i].info8,
7373 driver, servername);
7374 break;
7375 default:
7376 result = WERR_UNKNOWN_LEVEL;
7377 break;
7380 TALLOC_FREE(driver);
7382 if (!W_ERROR_IS_OK(result)) {
7383 goto out;
7387 count += num_drivers;
7388 TALLOC_FREE(drivers);
7391 out:
7392 TALLOC_FREE(drivers);
7394 if (!W_ERROR_IS_OK(result)) {
7395 TALLOC_FREE(info);
7396 return result;
7399 *info_p = info;
7400 *count_p = count;
7402 return WERR_OK;
7405 /****************************************************************************
7406 Enumerates all printer drivers by level.
7407 ****************************************************************************/
7409 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7410 const struct auth_serversupplied_info *session_info,
7411 struct messaging_context *msg_ctx,
7412 const char *servername,
7413 const char *architecture,
7414 uint32_t level,
7415 union spoolss_DriverInfo **info_p,
7416 uint32_t *count_p)
7418 uint32_t a,i;
7419 WERROR result = WERR_OK;
7421 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7423 for (a=0; archi_table[a].long_archi != NULL; a++) {
7425 union spoolss_DriverInfo *info = NULL;
7426 uint32_t count = 0;
7428 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7429 session_info,
7430 msg_ctx,
7431 servername,
7432 archi_table[a].long_archi,
7433 level,
7434 &info,
7435 &count);
7436 if (!W_ERROR_IS_OK(result)) {
7437 continue;
7440 for (i=0; i < count; i++) {
7441 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7442 info[i], info_p, count_p);
7446 return result;
7449 return enumprinterdrivers_level_by_architecture(mem_ctx,
7450 session_info,
7451 msg_ctx,
7452 servername,
7453 architecture,
7454 level,
7455 info_p,
7456 count_p);
7459 /****************************************************************
7460 _spoolss_EnumPrinterDrivers
7461 ****************************************************************/
7463 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7464 struct spoolss_EnumPrinterDrivers *r)
7466 const char *cservername;
7467 WERROR result;
7469 /* that's an [in out] buffer */
7471 if (!r->in.buffer && (r->in.offered != 0)) {
7472 return WERR_INVALID_PARAM;
7475 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7477 *r->out.needed = 0;
7478 *r->out.count = 0;
7479 *r->out.info = NULL;
7481 cservername = canon_servername(r->in.server);
7483 if (!is_myname_or_ipaddr(cservername)) {
7484 return WERR_UNKNOWN_PRINTER_DRIVER;
7487 result = enumprinterdrivers_level(p->mem_ctx,
7488 get_session_info_system(),
7489 p->msg_ctx,
7490 cservername,
7491 r->in.environment,
7492 r->in.level,
7493 r->out.info,
7494 r->out.count);
7495 if (!W_ERROR_IS_OK(result)) {
7496 return result;
7499 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7500 spoolss_EnumPrinterDrivers,
7501 *r->out.info, r->in.level,
7502 *r->out.count);
7503 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7504 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7506 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7509 /****************************************************************
7510 _spoolss_EnumForms
7511 ****************************************************************/
7513 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7514 struct spoolss_EnumForms *r)
7516 WERROR result;
7518 *r->out.count = 0;
7519 *r->out.needed = 0;
7520 *r->out.info = NULL;
7522 /* that's an [in out] buffer */
7524 if (!r->in.buffer && (r->in.offered != 0) ) {
7525 return WERR_INVALID_PARAM;
7528 DEBUG(4,("_spoolss_EnumForms\n"));
7529 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7530 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7532 switch (r->in.level) {
7533 case 1:
7534 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7535 get_session_info_system(),
7536 p->msg_ctx,
7537 r->out.count,
7538 r->out.info);
7539 break;
7540 default:
7541 result = WERR_UNKNOWN_LEVEL;
7542 break;
7545 if (!W_ERROR_IS_OK(result)) {
7546 return result;
7549 if (*r->out.count == 0) {
7550 return WERR_NO_MORE_ITEMS;
7553 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7554 spoolss_EnumForms,
7555 *r->out.info, r->in.level,
7556 *r->out.count);
7557 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7558 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7560 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7563 /****************************************************************
7564 _spoolss_GetForm
7565 ****************************************************************/
7567 WERROR _spoolss_GetForm(struct pipes_struct *p,
7568 struct spoolss_GetForm *r)
7570 WERROR result;
7572 /* that's an [in out] buffer */
7574 if (!r->in.buffer && (r->in.offered != 0)) {
7575 return WERR_INVALID_PARAM;
7578 DEBUG(4,("_spoolss_GetForm\n"));
7579 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7580 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7582 switch (r->in.level) {
7583 case 1:
7584 result = winreg_printer_getform1_internal(p->mem_ctx,
7585 get_session_info_system(),
7586 p->msg_ctx,
7587 r->in.form_name,
7588 &r->out.info->info1);
7589 break;
7590 default:
7591 result = WERR_UNKNOWN_LEVEL;
7592 break;
7595 if (!W_ERROR_IS_OK(result)) {
7596 TALLOC_FREE(r->out.info);
7597 return result;
7600 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7601 r->out.info, r->in.level);
7602 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7604 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7607 /****************************************************************************
7608 ****************************************************************************/
7610 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7611 struct spoolss_PortInfo1 *r,
7612 const char *name)
7614 r->port_name = talloc_strdup(mem_ctx, name);
7615 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7617 return WERR_OK;
7620 /****************************************************************************
7621 TODO: This probably needs distinguish between TCP/IP and Local ports
7622 somehow.
7623 ****************************************************************************/
7625 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7626 struct spoolss_PortInfo2 *r,
7627 const char *name)
7629 r->port_name = talloc_strdup(mem_ctx, name);
7630 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7632 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7633 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7635 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7636 W_ERROR_HAVE_NO_MEMORY(r->description);
7638 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7639 r->reserved = 0;
7641 return WERR_OK;
7645 /****************************************************************************
7646 wrapper around the enumer ports command
7647 ****************************************************************************/
7649 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7651 char *cmd = lp_enumports_cmd();
7652 char **qlines = NULL;
7653 char *command = NULL;
7654 int numlines;
7655 int ret;
7656 int fd;
7658 *count = 0;
7659 *lines = NULL;
7661 /* if no hook then just fill in the default port */
7663 if ( !*cmd ) {
7664 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7665 return WERR_NOMEM;
7667 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7668 TALLOC_FREE(qlines);
7669 return WERR_NOMEM;
7671 qlines[1] = NULL;
7672 numlines = 1;
7674 else {
7675 /* we have a valid enumport command */
7677 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7678 if (!command) {
7679 return WERR_NOMEM;
7682 DEBUG(10,("Running [%s]\n", command));
7683 ret = smbrun(command, &fd);
7684 DEBUG(10,("Returned [%d]\n", ret));
7685 TALLOC_FREE(command);
7686 if (ret != 0) {
7687 if (fd != -1) {
7688 close(fd);
7690 return WERR_ACCESS_DENIED;
7693 numlines = 0;
7694 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7695 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7696 close(fd);
7699 *count = numlines;
7700 *lines = qlines;
7702 return WERR_OK;
7705 /****************************************************************************
7706 enumports level 1.
7707 ****************************************************************************/
7709 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7710 union spoolss_PortInfo **info_p,
7711 uint32_t *count)
7713 union spoolss_PortInfo *info = NULL;
7714 int i=0;
7715 WERROR result = WERR_OK;
7716 char **qlines = NULL;
7717 int numlines = 0;
7719 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7720 if (!W_ERROR_IS_OK(result)) {
7721 goto out;
7724 if (numlines) {
7725 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7726 if (!info) {
7727 DEBUG(10,("Returning WERR_NOMEM\n"));
7728 result = WERR_NOMEM;
7729 goto out;
7732 for (i=0; i<numlines; i++) {
7733 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7734 result = fill_port_1(info, &info[i].info1, qlines[i]);
7735 if (!W_ERROR_IS_OK(result)) {
7736 goto out;
7740 TALLOC_FREE(qlines);
7742 out:
7743 if (!W_ERROR_IS_OK(result)) {
7744 TALLOC_FREE(info);
7745 TALLOC_FREE(qlines);
7746 *count = 0;
7747 *info_p = NULL;
7748 return result;
7751 *info_p = info;
7752 *count = numlines;
7754 return WERR_OK;
7757 /****************************************************************************
7758 enumports level 2.
7759 ****************************************************************************/
7761 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7762 union spoolss_PortInfo **info_p,
7763 uint32_t *count)
7765 union spoolss_PortInfo *info = NULL;
7766 int i=0;
7767 WERROR result = WERR_OK;
7768 char **qlines = NULL;
7769 int numlines = 0;
7771 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7772 if (!W_ERROR_IS_OK(result)) {
7773 goto out;
7776 if (numlines) {
7777 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7778 if (!info) {
7779 DEBUG(10,("Returning WERR_NOMEM\n"));
7780 result = WERR_NOMEM;
7781 goto out;
7784 for (i=0; i<numlines; i++) {
7785 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7786 result = fill_port_2(info, &info[i].info2, qlines[i]);
7787 if (!W_ERROR_IS_OK(result)) {
7788 goto out;
7792 TALLOC_FREE(qlines);
7794 out:
7795 if (!W_ERROR_IS_OK(result)) {
7796 TALLOC_FREE(info);
7797 TALLOC_FREE(qlines);
7798 *count = 0;
7799 *info_p = NULL;
7800 return result;
7803 *info_p = info;
7804 *count = numlines;
7806 return WERR_OK;
7809 /****************************************************************
7810 _spoolss_EnumPorts
7811 ****************************************************************/
7813 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7814 struct spoolss_EnumPorts *r)
7816 WERROR result;
7818 /* that's an [in out] buffer */
7820 if (!r->in.buffer && (r->in.offered != 0)) {
7821 return WERR_INVALID_PARAM;
7824 DEBUG(4,("_spoolss_EnumPorts\n"));
7826 *r->out.count = 0;
7827 *r->out.needed = 0;
7828 *r->out.info = NULL;
7830 switch (r->in.level) {
7831 case 1:
7832 result = enumports_level_1(p->mem_ctx, r->out.info,
7833 r->out.count);
7834 break;
7835 case 2:
7836 result = enumports_level_2(p->mem_ctx, r->out.info,
7837 r->out.count);
7838 break;
7839 default:
7840 return WERR_UNKNOWN_LEVEL;
7843 if (!W_ERROR_IS_OK(result)) {
7844 return result;
7847 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7848 spoolss_EnumPorts,
7849 *r->out.info, r->in.level,
7850 *r->out.count);
7851 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7852 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7854 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7857 /****************************************************************************
7858 ****************************************************************************/
7860 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7861 const char *server,
7862 struct spoolss_SetPrinterInfoCtr *info_ctr,
7863 struct spoolss_DeviceMode *devmode,
7864 struct security_descriptor *secdesc,
7865 struct spoolss_UserLevelCtr *user_ctr,
7866 struct policy_handle *handle)
7868 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7869 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7870 int snum;
7871 WERROR err = WERR_OK;
7873 /* samba does not have a concept of local, non-shared printers yet, so
7874 * make sure we always setup sharename - gd */
7875 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7876 (info2->printername != NULL && info2->printername[0] != '\0')) {
7877 DEBUG(5, ("spoolss_addprinterex_level_2: "
7878 "no sharename has been set, setting printername %s as sharename\n",
7879 info2->printername));
7880 info2->sharename = info2->printername;
7883 /* check to see if the printer already exists */
7884 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7885 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7886 info2->sharename));
7887 return WERR_PRINTER_ALREADY_EXISTS;
7890 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7891 if ((snum = print_queue_snum(info2->printername)) != -1) {
7892 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7893 info2->printername));
7894 return WERR_PRINTER_ALREADY_EXISTS;
7898 /* validate printer info struct */
7899 if (!info2->printername || strlen(info2->printername) == 0) {
7900 return WERR_INVALID_PRINTER_NAME;
7902 if (!info2->portname || strlen(info2->portname) == 0) {
7903 return WERR_UNKNOWN_PORT;
7905 if (!info2->drivername || strlen(info2->drivername) == 0) {
7906 return WERR_UNKNOWN_PRINTER_DRIVER;
7908 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7909 return WERR_UNKNOWN_PRINTPROCESSOR;
7912 /* FIXME!!! smbd should check to see if the driver is installed before
7913 trying to add a printer like this --jerry */
7915 if (*lp_addprinter_cmd() ) {
7916 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7917 info2, p->client_id->addr,
7918 p->msg_ctx) ) {
7919 return WERR_ACCESS_DENIED;
7921 } else {
7922 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7923 "smb.conf parameter \"addprinter command\" is defined. This "
7924 "parameter must exist for this call to succeed\n",
7925 info2->sharename ));
7928 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7929 return WERR_ACCESS_DENIED;
7932 /* you must be a printer admin to add a new printer */
7933 if (!print_access_check(p->session_info,
7934 p->msg_ctx,
7935 snum,
7936 PRINTER_ACCESS_ADMINISTER)) {
7937 return WERR_ACCESS_DENIED;
7941 * Do sanity check on the requested changes for Samba.
7944 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7945 return WERR_INVALID_PARAM;
7948 if (devmode == NULL) {
7949 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7952 update_dsspooler(p->mem_ctx,
7953 get_session_info_system(),
7954 p->msg_ctx,
7956 info2,
7957 NULL);
7959 err = winreg_update_printer_internal(p->mem_ctx,
7960 get_session_info_system(),
7961 p->msg_ctx,
7962 info2->sharename,
7963 info2_mask,
7964 info2,
7965 devmode,
7966 secdesc);
7967 if (!W_ERROR_IS_OK(err)) {
7968 return err;
7971 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7972 if (!W_ERROR_IS_OK(err)) {
7973 /* Handle open failed - remove addition. */
7974 ZERO_STRUCTP(handle);
7975 return err;
7978 return WERR_OK;
7981 /****************************************************************
7982 _spoolss_AddPrinterEx
7983 ****************************************************************/
7985 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7986 struct spoolss_AddPrinterEx *r)
7988 switch (r->in.info_ctr->level) {
7989 case 1:
7990 /* we don't handle yet */
7991 /* but I know what to do ... */
7992 return WERR_UNKNOWN_LEVEL;
7993 case 2:
7994 return spoolss_addprinterex_level_2(p, r->in.server,
7995 r->in.info_ctr,
7996 r->in.devmode_ctr->devmode,
7997 r->in.secdesc_ctr->sd,
7998 r->in.userlevel_ctr,
7999 r->out.handle);
8000 default:
8001 return WERR_UNKNOWN_LEVEL;
8005 /****************************************************************
8006 _spoolss_AddPrinter
8007 ****************************************************************/
8009 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8010 struct spoolss_AddPrinter *r)
8012 struct spoolss_AddPrinterEx a;
8013 struct spoolss_UserLevelCtr userlevel_ctr;
8015 ZERO_STRUCT(userlevel_ctr);
8017 userlevel_ctr.level = 1;
8019 a.in.server = r->in.server;
8020 a.in.info_ctr = r->in.info_ctr;
8021 a.in.devmode_ctr = r->in.devmode_ctr;
8022 a.in.secdesc_ctr = r->in.secdesc_ctr;
8023 a.in.userlevel_ctr = &userlevel_ctr;
8024 a.out.handle = r->out.handle;
8026 return _spoolss_AddPrinterEx(p, &a);
8029 /****************************************************************
8030 _spoolss_AddPrinterDriverEx
8031 ****************************************************************/
8033 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8034 struct spoolss_AddPrinterDriverEx *r)
8036 WERROR err = WERR_OK;
8037 const char *driver_name = NULL;
8038 uint32_t version;
8039 const char *fn;
8041 switch (p->opnum) {
8042 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8043 fn = "_spoolss_AddPrinterDriver";
8044 break;
8045 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8046 fn = "_spoolss_AddPrinterDriverEx";
8047 break;
8048 default:
8049 return WERR_INVALID_PARAM;
8053 * we only support the semantics of AddPrinterDriver()
8054 * i.e. only copy files that are newer than existing ones
8057 if (r->in.flags == 0) {
8058 return WERR_INVALID_PARAM;
8061 if (r->in.flags != APD_COPY_NEW_FILES) {
8062 return WERR_ACCESS_DENIED;
8065 /* FIXME */
8066 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8067 /* Clever hack from Martin Zielinski <mz@seh.de>
8068 * to allow downgrade from level 8 (Vista).
8070 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8071 r->in.info_ctr->level));
8072 return WERR_UNKNOWN_LEVEL;
8075 DEBUG(5,("Cleaning driver's information\n"));
8076 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8077 if (!W_ERROR_IS_OK(err))
8078 goto done;
8080 DEBUG(5,("Moving driver to final destination\n"));
8081 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8082 if (!W_ERROR_IS_OK(err)) {
8083 goto done;
8086 err = winreg_add_driver_internal(p->mem_ctx,
8087 get_session_info_system(),
8088 p->msg_ctx,
8089 r->in.info_ctr,
8090 &driver_name,
8091 &version);
8092 if (!W_ERROR_IS_OK(err)) {
8093 goto done;
8097 * I think this is where he DrvUpgradePrinter() hook would be
8098 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8099 * server. Right now, we just need to send ourselves a message
8100 * to update each printer bound to this driver. --jerry
8103 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8104 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8105 fn, driver_name));
8108 done:
8109 return err;
8112 /****************************************************************
8113 _spoolss_AddPrinterDriver
8114 ****************************************************************/
8116 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8117 struct spoolss_AddPrinterDriver *r)
8119 struct spoolss_AddPrinterDriverEx a;
8121 switch (r->in.info_ctr->level) {
8122 case 2:
8123 case 3:
8124 case 4:
8125 case 5:
8126 break;
8127 default:
8128 return WERR_UNKNOWN_LEVEL;
8131 a.in.servername = r->in.servername;
8132 a.in.info_ctr = r->in.info_ctr;
8133 a.in.flags = APD_COPY_NEW_FILES;
8135 return _spoolss_AddPrinterDriverEx(p, &a);
8138 /****************************************************************************
8139 ****************************************************************************/
8141 struct _spoolss_paths {
8142 int type;
8143 const char *share;
8144 const char *dir;
8147 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8149 static const struct _spoolss_paths spoolss_paths[]= {
8150 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8151 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8154 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8155 const char *servername,
8156 const char *environment,
8157 int component,
8158 char **path)
8160 const char *pservername = NULL;
8161 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8162 const char *short_archi;
8164 *path = NULL;
8166 /* environment may be empty */
8167 if (environment && strlen(environment)) {
8168 long_archi = environment;
8171 /* servername may be empty */
8172 if (servername && strlen(servername)) {
8173 pservername = canon_servername(servername);
8175 if (!is_myname_or_ipaddr(pservername)) {
8176 return WERR_INVALID_PARAM;
8180 if (!(short_archi = get_short_archi(long_archi))) {
8181 return WERR_INVALID_ENVIRONMENT;
8184 switch (component) {
8185 case SPOOLSS_PRTPROCS_PATH:
8186 case SPOOLSS_DRIVER_PATH:
8187 if (pservername) {
8188 *path = talloc_asprintf(mem_ctx,
8189 "\\\\%s\\%s\\%s",
8190 pservername,
8191 spoolss_paths[component].share,
8192 short_archi);
8193 } else {
8194 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8195 SPOOLSS_DEFAULT_SERVER_PATH,
8196 spoolss_paths[component].dir,
8197 short_archi);
8199 break;
8200 default:
8201 return WERR_INVALID_PARAM;
8204 if (!*path) {
8205 return WERR_NOMEM;
8208 return WERR_OK;
8211 /****************************************************************************
8212 ****************************************************************************/
8214 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8215 const char *servername,
8216 const char *environment,
8217 struct spoolss_DriverDirectoryInfo1 *r)
8219 WERROR werr;
8220 char *path = NULL;
8222 werr = compose_spoolss_server_path(mem_ctx,
8223 servername,
8224 environment,
8225 SPOOLSS_DRIVER_PATH,
8226 &path);
8227 if (!W_ERROR_IS_OK(werr)) {
8228 return werr;
8231 DEBUG(4,("printer driver directory: [%s]\n", path));
8233 r->directory_name = path;
8235 return WERR_OK;
8238 /****************************************************************
8239 _spoolss_GetPrinterDriverDirectory
8240 ****************************************************************/
8242 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8243 struct spoolss_GetPrinterDriverDirectory *r)
8245 WERROR werror;
8247 /* that's an [in out] buffer */
8249 if (!r->in.buffer && (r->in.offered != 0)) {
8250 return WERR_INVALID_PARAM;
8253 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8254 r->in.level));
8256 *r->out.needed = 0;
8258 /* r->in.level is ignored */
8260 werror = getprinterdriverdir_level_1(p->mem_ctx,
8261 r->in.server,
8262 r->in.environment,
8263 &r->out.info->info1);
8264 if (!W_ERROR_IS_OK(werror)) {
8265 TALLOC_FREE(r->out.info);
8266 return werror;
8269 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8270 r->out.info, r->in.level);
8271 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8273 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8276 /****************************************************************
8277 _spoolss_EnumPrinterData
8278 ****************************************************************/
8280 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8281 struct spoolss_EnumPrinterData *r)
8283 WERROR result;
8284 struct spoolss_EnumPrinterDataEx r2;
8285 uint32_t count;
8286 struct spoolss_PrinterEnumValues *info, *val = NULL;
8287 uint32_t needed;
8289 r2.in.handle = r->in.handle;
8290 r2.in.key_name = "PrinterDriverData";
8291 r2.in.offered = 0;
8292 r2.out.count = &count;
8293 r2.out.info = &info;
8294 r2.out.needed = &needed;
8296 result = _spoolss_EnumPrinterDataEx(p, &r2);
8297 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8298 r2.in.offered = needed;
8299 result = _spoolss_EnumPrinterDataEx(p, &r2);
8301 if (!W_ERROR_IS_OK(result)) {
8302 return result;
8306 * The NT machine wants to know the biggest size of value and data
8308 * cf: MSDN EnumPrinterData remark section
8311 if (!r->in.value_offered && !r->in.data_offered) {
8312 uint32_t biggest_valuesize = 0;
8313 uint32_t biggest_datasize = 0;
8314 int i, name_length;
8316 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8318 for (i=0; i<count; i++) {
8320 name_length = strlen(info[i].value_name);
8321 if (strlen(info[i].value_name) > biggest_valuesize) {
8322 biggest_valuesize = name_length;
8325 if (info[i].data_length > biggest_datasize) {
8326 biggest_datasize = info[i].data_length;
8329 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8330 biggest_datasize));
8333 /* the value is an UNICODE string but real_value_size is the length
8334 in bytes including the trailing 0 */
8336 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8337 *r->out.data_needed = biggest_datasize;
8339 DEBUG(6,("final values: [%d], [%d]\n",
8340 *r->out.value_needed, *r->out.data_needed));
8342 return WERR_OK;
8345 if (r->in.enum_index < count) {
8346 val = &info[r->in.enum_index];
8349 if (val == NULL) {
8350 /* out_value should default to "" or else NT4 has
8351 problems unmarshalling the response */
8353 if (r->in.value_offered) {
8354 *r->out.value_needed = 1;
8355 r->out.value_name = talloc_strdup(r, "");
8356 if (!r->out.value_name) {
8357 return WERR_NOMEM;
8359 } else {
8360 r->out.value_name = NULL;
8361 *r->out.value_needed = 0;
8364 /* the data is counted in bytes */
8366 *r->out.data_needed = r->in.data_offered;
8368 result = WERR_NO_MORE_ITEMS;
8369 } else {
8371 * the value is:
8372 * - counted in bytes in the request
8373 * - counted in UNICODE chars in the max reply
8374 * - counted in bytes in the real size
8376 * take a pause *before* coding not *during* coding
8379 /* name */
8380 if (r->in.value_offered) {
8381 r->out.value_name = talloc_strdup(r, val->value_name);
8382 if (!r->out.value_name) {
8383 return WERR_NOMEM;
8385 *r->out.value_needed = val->value_name_len;
8386 } else {
8387 r->out.value_name = NULL;
8388 *r->out.value_needed = 0;
8391 /* type */
8393 *r->out.type = val->type;
8395 /* data - counted in bytes */
8398 * See the section "Dynamically Typed Query Parameters"
8399 * in MS-RPRN.
8402 if (r->out.data && val->data && val->data->data &&
8403 val->data_length && r->in.data_offered) {
8404 memcpy(r->out.data, val->data->data,
8405 MIN(val->data_length,r->in.data_offered));
8408 *r->out.data_needed = val->data_length;
8410 result = WERR_OK;
8413 return result;
8416 /****************************************************************
8417 _spoolss_SetPrinterData
8418 ****************************************************************/
8420 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8421 struct spoolss_SetPrinterData *r)
8423 struct spoolss_SetPrinterDataEx r2;
8425 r2.in.handle = r->in.handle;
8426 r2.in.key_name = "PrinterDriverData";
8427 r2.in.value_name = r->in.value_name;
8428 r2.in.type = r->in.type;
8429 r2.in.data = r->in.data;
8430 r2.in.offered = r->in.offered;
8432 return _spoolss_SetPrinterDataEx(p, &r2);
8435 /****************************************************************
8436 _spoolss_ResetPrinter
8437 ****************************************************************/
8439 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8440 struct spoolss_ResetPrinter *r)
8442 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8443 int snum;
8445 DEBUG(5,("_spoolss_ResetPrinter\n"));
8448 * All we do is to check to see if the handle and queue is valid.
8449 * This call really doesn't mean anything to us because we only
8450 * support RAW printing. --jerry
8453 if (!Printer) {
8454 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8455 OUR_HANDLE(r->in.handle)));
8456 return WERR_BADFID;
8459 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8460 return WERR_BADFID;
8463 /* blindly return success */
8464 return WERR_OK;
8467 /****************************************************************
8468 _spoolss_DeletePrinterData
8469 ****************************************************************/
8471 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8472 struct spoolss_DeletePrinterData *r)
8474 struct spoolss_DeletePrinterDataEx r2;
8476 r2.in.handle = r->in.handle;
8477 r2.in.key_name = "PrinterDriverData";
8478 r2.in.value_name = r->in.value_name;
8480 return _spoolss_DeletePrinterDataEx(p, &r2);
8483 /****************************************************************
8484 _spoolss_AddForm
8485 ****************************************************************/
8487 WERROR _spoolss_AddForm(struct pipes_struct *p,
8488 struct spoolss_AddForm *r)
8490 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8491 int snum = -1;
8492 WERROR status = WERR_OK;
8493 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8494 struct dcerpc_binding_handle *b;
8496 DEBUG(5,("_spoolss_AddForm\n"));
8498 if (!Printer) {
8499 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8500 OUR_HANDLE(r->in.handle)));
8501 return WERR_BADFID;
8504 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8505 and not a printer admin, then fail */
8507 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8508 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8509 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8510 p->session_info->info3->base.domain.string,
8511 NULL,
8512 p->session_info->security_token,
8513 lp_printer_admin(snum))) {
8514 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8515 return WERR_ACCESS_DENIED;
8518 switch (form->flags) {
8519 case SPOOLSS_FORM_USER:
8520 case SPOOLSS_FORM_BUILTIN:
8521 case SPOOLSS_FORM_PRINTER:
8522 break;
8523 default:
8524 return WERR_INVALID_PARAM;
8527 status = winreg_printer_binding_handle(p->mem_ctx,
8528 get_session_info_system(),
8529 p->msg_ctx,
8530 &b);
8531 if (!W_ERROR_IS_OK(status)) {
8532 return status;
8535 status = winreg_printer_addform1(p->mem_ctx, b,
8536 form);
8537 if (!W_ERROR_IS_OK(status)) {
8538 return status;
8542 * ChangeID must always be set if this is a printer
8544 if (Printer->printer_type == SPLHND_PRINTER) {
8545 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8546 return WERR_BADFID;
8549 status = winreg_printer_update_changeid(p->mem_ctx, b,
8550 lp_const_servicename(snum));
8551 if (!W_ERROR_IS_OK(status)) {
8552 return status;
8556 return status;
8559 /****************************************************************
8560 _spoolss_DeleteForm
8561 ****************************************************************/
8563 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8564 struct spoolss_DeleteForm *r)
8566 const char *form_name = r->in.form_name;
8567 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8568 int snum = -1;
8569 WERROR status = WERR_OK;
8570 struct dcerpc_binding_handle *b;
8572 DEBUG(5,("_spoolss_DeleteForm\n"));
8574 if (!Printer) {
8575 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8576 OUR_HANDLE(r->in.handle)));
8577 return WERR_BADFID;
8580 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8581 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8582 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8583 p->session_info->info3->base.domain.string,
8584 NULL,
8585 p->session_info->security_token,
8586 lp_printer_admin(snum))) {
8587 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8588 return WERR_ACCESS_DENIED;
8591 status = winreg_printer_binding_handle(p->mem_ctx,
8592 get_session_info_system(),
8593 p->msg_ctx,
8594 &b);
8595 if (!W_ERROR_IS_OK(status)) {
8596 return status;
8599 status = winreg_printer_deleteform1(p->mem_ctx, b,
8600 form_name);
8601 if (!W_ERROR_IS_OK(status)) {
8602 return status;
8606 * ChangeID must always be set if this is a printer
8608 if (Printer->printer_type == SPLHND_PRINTER) {
8609 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8610 return WERR_BADFID;
8613 status = winreg_printer_update_changeid(p->mem_ctx, b,
8614 lp_const_servicename(snum));
8615 if (!W_ERROR_IS_OK(status)) {
8616 return status;
8620 return status;
8623 /****************************************************************
8624 _spoolss_SetForm
8625 ****************************************************************/
8627 WERROR _spoolss_SetForm(struct pipes_struct *p,
8628 struct spoolss_SetForm *r)
8630 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8631 const char *form_name = r->in.form_name;
8632 int snum = -1;
8633 WERROR status = WERR_OK;
8634 struct dcerpc_binding_handle *b;
8636 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8638 DEBUG(5,("_spoolss_SetForm\n"));
8640 if (!Printer) {
8641 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8642 OUR_HANDLE(r->in.handle)));
8643 return WERR_BADFID;
8646 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8647 and not a printer admin, then fail */
8649 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8650 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8651 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8652 p->session_info->info3->base.domain.string,
8653 NULL,
8654 p->session_info->security_token,
8655 lp_printer_admin(snum))) {
8656 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8657 return WERR_ACCESS_DENIED;
8660 status = winreg_printer_binding_handle(p->mem_ctx,
8661 get_session_info_system(),
8662 p->msg_ctx,
8663 &b);
8664 if (!W_ERROR_IS_OK(status)) {
8665 return status;
8668 status = winreg_printer_setform1(p->mem_ctx, b,
8669 form_name,
8670 form);
8671 if (!W_ERROR_IS_OK(status)) {
8672 return status;
8676 * ChangeID must always be set if this is a printer
8678 if (Printer->printer_type == SPLHND_PRINTER) {
8679 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8680 return WERR_BADFID;
8683 status = winreg_printer_update_changeid(p->mem_ctx, b,
8684 lp_const_servicename(snum));
8685 if (!W_ERROR_IS_OK(status)) {
8686 return status;
8690 return status;
8693 /****************************************************************************
8694 fill_print_processor1
8695 ****************************************************************************/
8697 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8698 struct spoolss_PrintProcessorInfo1 *r,
8699 const char *print_processor_name)
8701 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8702 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8704 return WERR_OK;
8707 /****************************************************************************
8708 enumprintprocessors level 1.
8709 ****************************************************************************/
8711 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8712 union spoolss_PrintProcessorInfo **info_p,
8713 uint32_t *count)
8715 union spoolss_PrintProcessorInfo *info;
8716 WERROR result;
8718 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8719 W_ERROR_HAVE_NO_MEMORY(info);
8721 *count = 1;
8723 result = fill_print_processor1(info, &info[0].info1, "winprint");
8724 if (!W_ERROR_IS_OK(result)) {
8725 goto out;
8728 out:
8729 if (!W_ERROR_IS_OK(result)) {
8730 TALLOC_FREE(info);
8731 *count = 0;
8732 return result;
8735 *info_p = info;
8737 return WERR_OK;
8740 /****************************************************************
8741 _spoolss_EnumPrintProcessors
8742 ****************************************************************/
8744 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8745 struct spoolss_EnumPrintProcessors *r)
8747 WERROR result;
8749 /* that's an [in out] buffer */
8751 if (!r->in.buffer && (r->in.offered != 0)) {
8752 return WERR_INVALID_PARAM;
8755 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8758 * Enumerate the print processors ...
8760 * Just reply with "winprint", to keep NT happy
8761 * and I can use my nice printer checker.
8764 *r->out.count = 0;
8765 *r->out.needed = 0;
8766 *r->out.info = NULL;
8768 if (!get_short_archi(r->in.environment)) {
8769 return WERR_INVALID_ENVIRONMENT;
8772 switch (r->in.level) {
8773 case 1:
8774 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8775 r->out.count);
8776 break;
8777 default:
8778 return WERR_UNKNOWN_LEVEL;
8781 if (!W_ERROR_IS_OK(result)) {
8782 return result;
8785 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8786 spoolss_EnumPrintProcessors,
8787 *r->out.info, r->in.level,
8788 *r->out.count);
8789 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8790 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8792 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8795 /****************************************************************************
8796 fill_printprocdatatype1
8797 ****************************************************************************/
8799 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8800 struct spoolss_PrintProcDataTypesInfo1 *r,
8801 const char *name_array)
8803 r->name_array = talloc_strdup(mem_ctx, name_array);
8804 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8806 return WERR_OK;
8809 /****************************************************************************
8810 enumprintprocdatatypes level 1.
8811 ****************************************************************************/
8813 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8814 union spoolss_PrintProcDataTypesInfo **info_p,
8815 uint32_t *count)
8817 WERROR result;
8818 union spoolss_PrintProcDataTypesInfo *info;
8820 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8821 W_ERROR_HAVE_NO_MEMORY(info);
8823 *count = 1;
8825 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8826 if (!W_ERROR_IS_OK(result)) {
8827 goto out;
8830 out:
8831 if (!W_ERROR_IS_OK(result)) {
8832 TALLOC_FREE(info);
8833 *count = 0;
8834 return result;
8837 *info_p = info;
8839 return WERR_OK;
8842 /****************************************************************
8843 _spoolss_EnumPrintProcDataTypes
8844 ****************************************************************/
8846 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8847 struct spoolss_EnumPrintProcDataTypes *r)
8849 WERROR result;
8851 /* that's an [in out] buffer */
8853 if (!r->in.buffer && (r->in.offered != 0)) {
8854 return WERR_INVALID_PARAM;
8857 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8859 *r->out.count = 0;
8860 *r->out.needed = 0;
8861 *r->out.info = NULL;
8863 if (r->in.print_processor_name == NULL ||
8864 !strequal(r->in.print_processor_name, "winprint")) {
8865 return WERR_UNKNOWN_PRINTPROCESSOR;
8868 switch (r->in.level) {
8869 case 1:
8870 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8871 r->out.count);
8872 break;
8873 default:
8874 return WERR_UNKNOWN_LEVEL;
8877 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8878 spoolss_EnumPrintProcDataTypes,
8879 *r->out.info, r->in.level,
8880 *r->out.count);
8881 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8882 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8884 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8887 /****************************************************************************
8888 fill_monitor_1
8889 ****************************************************************************/
8891 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8892 struct spoolss_MonitorInfo1 *r,
8893 const char *monitor_name)
8895 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8896 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8898 return WERR_OK;
8901 /****************************************************************************
8902 fill_monitor_2
8903 ****************************************************************************/
8905 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8906 struct spoolss_MonitorInfo2 *r,
8907 const char *monitor_name,
8908 const char *environment,
8909 const char *dll_name)
8911 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8912 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8913 r->environment = talloc_strdup(mem_ctx, environment);
8914 W_ERROR_HAVE_NO_MEMORY(r->environment);
8915 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8916 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8918 return WERR_OK;
8921 /****************************************************************************
8922 enumprintmonitors level 1.
8923 ****************************************************************************/
8925 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8926 union spoolss_MonitorInfo **info_p,
8927 uint32_t *count)
8929 union spoolss_MonitorInfo *info;
8930 WERROR result = WERR_OK;
8932 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8933 W_ERROR_HAVE_NO_MEMORY(info);
8935 *count = 2;
8937 result = fill_monitor_1(info, &info[0].info1,
8938 SPL_LOCAL_PORT);
8939 if (!W_ERROR_IS_OK(result)) {
8940 goto out;
8943 result = fill_monitor_1(info, &info[1].info1,
8944 SPL_TCPIP_PORT);
8945 if (!W_ERROR_IS_OK(result)) {
8946 goto out;
8949 out:
8950 if (!W_ERROR_IS_OK(result)) {
8951 TALLOC_FREE(info);
8952 *count = 0;
8953 return result;
8956 *info_p = info;
8958 return WERR_OK;
8961 /****************************************************************************
8962 enumprintmonitors level 2.
8963 ****************************************************************************/
8965 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8966 union spoolss_MonitorInfo **info_p,
8967 uint32_t *count)
8969 union spoolss_MonitorInfo *info;
8970 WERROR result = WERR_OK;
8972 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8973 W_ERROR_HAVE_NO_MEMORY(info);
8975 *count = 2;
8977 result = fill_monitor_2(info, &info[0].info2,
8978 SPL_LOCAL_PORT,
8979 "Windows NT X86", /* FIXME */
8980 "localmon.dll");
8981 if (!W_ERROR_IS_OK(result)) {
8982 goto out;
8985 result = fill_monitor_2(info, &info[1].info2,
8986 SPL_TCPIP_PORT,
8987 "Windows NT X86", /* FIXME */
8988 "tcpmon.dll");
8989 if (!W_ERROR_IS_OK(result)) {
8990 goto out;
8993 out:
8994 if (!W_ERROR_IS_OK(result)) {
8995 TALLOC_FREE(info);
8996 *count = 0;
8997 return result;
9000 *info_p = info;
9002 return WERR_OK;
9005 /****************************************************************
9006 _spoolss_EnumMonitors
9007 ****************************************************************/
9009 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9010 struct spoolss_EnumMonitors *r)
9012 WERROR result;
9014 /* that's an [in out] buffer */
9016 if (!r->in.buffer && (r->in.offered != 0)) {
9017 return WERR_INVALID_PARAM;
9020 DEBUG(5,("_spoolss_EnumMonitors\n"));
9023 * Enumerate the print monitors ...
9025 * Just reply with "Local Port", to keep NT happy
9026 * and I can use my nice printer checker.
9029 *r->out.count = 0;
9030 *r->out.needed = 0;
9031 *r->out.info = NULL;
9033 switch (r->in.level) {
9034 case 1:
9035 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9036 r->out.count);
9037 break;
9038 case 2:
9039 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9040 r->out.count);
9041 break;
9042 default:
9043 return WERR_UNKNOWN_LEVEL;
9046 if (!W_ERROR_IS_OK(result)) {
9047 return result;
9050 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9051 spoolss_EnumMonitors,
9052 *r->out.info, r->in.level,
9053 *r->out.count);
9054 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9055 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9057 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9060 /****************************************************************************
9061 ****************************************************************************/
9063 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9064 const print_queue_struct *queue,
9065 int count, int snum,
9066 struct spoolss_PrinterInfo2 *pinfo2,
9067 uint32_t jobid,
9068 struct spoolss_JobInfo1 *r)
9070 int i = 0;
9071 bool found = false;
9073 for (i=0; i<count; i++) {
9074 if (queue[i].job == (int)jobid) {
9075 found = true;
9076 break;
9080 if (found == false) {
9081 /* NT treats not found as bad param... yet another bad choice */
9082 return WERR_INVALID_PARAM;
9085 return fill_job_info1(mem_ctx,
9087 &queue[i],
9089 snum,
9090 pinfo2);
9093 /****************************************************************************
9094 ****************************************************************************/
9096 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9097 const print_queue_struct *queue,
9098 int count, int snum,
9099 struct spoolss_PrinterInfo2 *pinfo2,
9100 uint32_t jobid,
9101 struct spoolss_JobInfo2 *r)
9103 int i = 0;
9104 bool found = false;
9105 struct spoolss_DeviceMode *devmode;
9106 WERROR result;
9108 for (i=0; i<count; i++) {
9109 if (queue[i].job == (int)jobid) {
9110 found = true;
9111 break;
9115 if (found == false) {
9116 /* NT treats not found as bad param... yet another bad
9117 choice */
9118 return WERR_INVALID_PARAM;
9122 * if the print job does not have a DEVMODE associated with it,
9123 * just use the one for the printer. A NULL devicemode is not
9124 * a failure condition
9127 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9128 if (!devmode) {
9129 result = spoolss_create_default_devmode(mem_ctx,
9130 pinfo2->printername,
9131 &devmode);
9132 if (!W_ERROR_IS_OK(result)) {
9133 DEBUG(3, ("Can't proceed w/o a devmode!"));
9134 return result;
9138 return fill_job_info2(mem_ctx,
9140 &queue[i],
9142 snum,
9143 pinfo2,
9144 devmode);
9147 /****************************************************************
9148 _spoolss_GetJob
9149 ****************************************************************/
9151 WERROR _spoolss_GetJob(struct pipes_struct *p,
9152 struct spoolss_GetJob *r)
9154 WERROR result = WERR_OK;
9155 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9156 int snum;
9157 int count;
9158 print_queue_struct *queue = NULL;
9159 print_status_struct prt_status;
9161 /* that's an [in out] buffer */
9163 if (!r->in.buffer && (r->in.offered != 0)) {
9164 return WERR_INVALID_PARAM;
9167 DEBUG(5,("_spoolss_GetJob\n"));
9169 *r->out.needed = 0;
9171 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9172 return WERR_BADFID;
9175 result = winreg_get_printer_internal(p->mem_ctx,
9176 get_session_info_system(),
9177 p->msg_ctx,
9178 lp_const_servicename(snum),
9179 &pinfo2);
9180 if (!W_ERROR_IS_OK(result)) {
9181 return result;
9184 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9186 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9187 count, prt_status.status, prt_status.message));
9189 switch (r->in.level) {
9190 case 1:
9191 result = getjob_level_1(p->mem_ctx,
9192 queue, count, snum, pinfo2,
9193 r->in.job_id, &r->out.info->info1);
9194 break;
9195 case 2:
9196 result = getjob_level_2(p->mem_ctx,
9197 queue, count, snum, pinfo2,
9198 r->in.job_id, &r->out.info->info2);
9199 break;
9200 default:
9201 result = WERR_UNKNOWN_LEVEL;
9202 break;
9205 SAFE_FREE(queue);
9206 TALLOC_FREE(pinfo2);
9208 if (!W_ERROR_IS_OK(result)) {
9209 TALLOC_FREE(r->out.info);
9210 return result;
9213 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9214 r->in.level);
9215 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9217 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9220 /****************************************************************
9221 _spoolss_GetPrinterDataEx
9222 ****************************************************************/
9224 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9225 struct spoolss_GetPrinterDataEx *r)
9228 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9229 const char *printer;
9230 int snum = 0;
9231 WERROR result = WERR_OK;
9232 DATA_BLOB blob;
9233 enum winreg_Type val_type = REG_NONE;
9234 uint8_t *val_data = NULL;
9235 uint32_t val_size = 0;
9236 struct dcerpc_binding_handle *b;
9238 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9240 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9241 r->in.key_name, r->in.value_name));
9243 /* in case of problem, return some default values */
9245 *r->out.needed = 0;
9246 *r->out.type = REG_NONE;
9248 if (!Printer) {
9249 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9250 OUR_HANDLE(r->in.handle)));
9251 result = WERR_BADFID;
9252 goto done;
9255 /* Is the handle to a printer or to the server? */
9257 if (Printer->printer_type == SPLHND_SERVER) {
9259 union spoolss_PrinterData data;
9261 result = getprinterdata_printer_server(p->mem_ctx,
9262 r->in.value_name,
9263 r->out.type,
9264 &data);
9265 if (!W_ERROR_IS_OK(result)) {
9266 return result;
9269 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9270 *r->out.type, &data);
9271 if (!W_ERROR_IS_OK(result)) {
9272 return result;
9275 *r->out.needed = blob.length;
9277 if (r->in.offered >= *r->out.needed) {
9278 memcpy(r->out.data, blob.data, blob.length);
9281 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9284 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9285 return WERR_BADFID;
9287 printer = lp_const_servicename(snum);
9289 /* check to see if the keyname is valid */
9290 if (!strlen(r->in.key_name)) {
9291 return WERR_INVALID_PARAM;
9294 result = winreg_printer_binding_handle(p->mem_ctx,
9295 get_session_info_system(),
9296 p->msg_ctx,
9297 &b);
9298 if (!W_ERROR_IS_OK(result)) {
9299 return result;
9302 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9303 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9304 strequal(r->in.value_name, "ChangeId")) {
9305 *r->out.type = REG_DWORD;
9306 *r->out.needed = 4;
9307 if (r->in.offered >= *r->out.needed) {
9308 uint32_t changeid = 0;
9310 result = winreg_printer_get_changeid(p->mem_ctx, b,
9311 printer,
9312 &changeid);
9313 if (!W_ERROR_IS_OK(result)) {
9314 return result;
9317 SIVAL(r->out.data, 0, changeid);
9318 result = WERR_OK;
9320 goto done;
9323 result = winreg_get_printer_dataex(p->mem_ctx, b,
9324 printer,
9325 r->in.key_name,
9326 r->in.value_name,
9327 &val_type,
9328 &val_data,
9329 &val_size);
9330 if (!W_ERROR_IS_OK(result)) {
9331 return result;
9334 *r->out.needed = val_size;
9335 *r->out.type = val_type;
9337 if (r->in.offered >= *r->out.needed) {
9338 memcpy(r->out.data, val_data, val_size);
9341 done:
9342 /* retain type when returning WERR_MORE_DATA */
9343 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9345 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9348 /****************************************************************
9349 _spoolss_SetPrinterDataEx
9350 ****************************************************************/
9352 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9353 struct spoolss_SetPrinterDataEx *r)
9355 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9356 int snum = 0;
9357 WERROR result = WERR_OK;
9358 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9359 char *oid_string;
9360 struct dcerpc_binding_handle *b;
9362 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9364 /* From MSDN documentation of SetPrinterDataEx: pass request to
9365 SetPrinterData if key is "PrinterDriverData" */
9367 if (!Printer) {
9368 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9369 OUR_HANDLE(r->in.handle)));
9370 return WERR_BADFID;
9373 if (Printer->printer_type == SPLHND_SERVER) {
9374 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9375 "Not implemented for server handles yet\n"));
9376 return WERR_INVALID_PARAM;
9379 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9380 return WERR_BADFID;
9384 * Access check : NT returns "access denied" if you make a
9385 * SetPrinterData call without the necessary privildge.
9386 * we were originally returning OK if nothing changed
9387 * which made Win2k issue **a lot** of SetPrinterData
9388 * when connecting to a printer --jerry
9391 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9392 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9393 "change denied by handle access permissions\n"));
9394 return WERR_ACCESS_DENIED;
9397 result = winreg_printer_binding_handle(p->mem_ctx,
9398 get_session_info_system(),
9399 p->msg_ctx,
9400 &b);
9401 if (!W_ERROR_IS_OK(result)) {
9402 return result;
9405 result = winreg_get_printer(Printer, b,
9406 lp_servicename(snum),
9407 &pinfo2);
9408 if (!W_ERROR_IS_OK(result)) {
9409 return result;
9412 /* check for OID in valuename */
9414 oid_string = strchr(r->in.value_name, ',');
9415 if (oid_string) {
9416 *oid_string = '\0';
9417 oid_string++;
9420 /* save the registry data */
9422 result = winreg_set_printer_dataex(p->mem_ctx, b,
9423 pinfo2->sharename,
9424 r->in.key_name,
9425 r->in.value_name,
9426 r->in.type,
9427 r->in.data,
9428 r->in.offered);
9430 if (W_ERROR_IS_OK(result)) {
9431 /* save the OID if one was specified */
9432 if (oid_string) {
9433 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9434 r->in.key_name, SPOOL_OID_KEY);
9435 if (!str) {
9436 result = WERR_NOMEM;
9437 goto done;
9441 * I'm not checking the status here on purpose. Don't know
9442 * if this is right, but I'm returning the status from the
9443 * previous set_printer_dataex() call. I have no idea if
9444 * this is right. --jerry
9446 winreg_set_printer_dataex(p->mem_ctx, b,
9447 pinfo2->sharename,
9448 str,
9449 r->in.value_name,
9450 REG_SZ,
9451 (uint8_t *) oid_string,
9452 strlen(oid_string) + 1);
9455 result = winreg_printer_update_changeid(p->mem_ctx, b,
9456 lp_const_servicename(snum));
9460 done:
9461 talloc_free(pinfo2);
9462 return result;
9465 /****************************************************************
9466 _spoolss_DeletePrinterDataEx
9467 ****************************************************************/
9469 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9470 struct spoolss_DeletePrinterDataEx *r)
9472 const char *printer;
9473 int snum=0;
9474 WERROR status = WERR_OK;
9475 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9477 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9479 if (!Printer) {
9480 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9481 "Invalid handle (%s:%u:%u).\n",
9482 OUR_HANDLE(r->in.handle)));
9483 return WERR_BADFID;
9486 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9487 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9488 "printer properties change denied by handle\n"));
9489 return WERR_ACCESS_DENIED;
9492 if (!r->in.value_name || !r->in.key_name) {
9493 return WERR_NOMEM;
9496 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9497 return WERR_BADFID;
9499 printer = lp_const_servicename(snum);
9501 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9502 get_session_info_system(),
9503 p->msg_ctx,
9504 printer,
9505 r->in.key_name,
9506 r->in.value_name);
9507 if (W_ERROR_IS_OK(status)) {
9508 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9509 get_session_info_system(),
9510 p->msg_ctx,
9511 printer);
9514 return status;
9517 /****************************************************************
9518 _spoolss_EnumPrinterKey
9519 ****************************************************************/
9521 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9522 struct spoolss_EnumPrinterKey *r)
9524 uint32_t num_keys;
9525 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9526 int snum = 0;
9527 WERROR result = WERR_BADFILE;
9528 const char **array = NULL;
9529 DATA_BLOB blob;
9531 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9533 if (!Printer) {
9534 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9535 OUR_HANDLE(r->in.handle)));
9536 return WERR_BADFID;
9539 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9540 return WERR_BADFID;
9543 result = winreg_enum_printer_key_internal(p->mem_ctx,
9544 get_session_info_system(),
9545 p->msg_ctx,
9546 lp_const_servicename(snum),
9547 r->in.key_name,
9548 &num_keys,
9549 &array);
9550 if (!W_ERROR_IS_OK(result)) {
9551 goto done;
9554 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9555 result = WERR_NOMEM;
9556 goto done;
9559 *r->out._ndr_size = r->in.offered / 2;
9560 *r->out.needed = blob.length;
9562 if (r->in.offered < *r->out.needed) {
9563 result = WERR_MORE_DATA;
9564 } else {
9565 result = WERR_OK;
9566 r->out.key_buffer->string_array = array;
9569 done:
9570 if (!W_ERROR_IS_OK(result)) {
9571 TALLOC_FREE(array);
9572 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9573 *r->out.needed = 0;
9577 return result;
9580 /****************************************************************
9581 _spoolss_DeletePrinterKey
9582 ****************************************************************/
9584 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9585 struct spoolss_DeletePrinterKey *r)
9587 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9588 int snum=0;
9589 WERROR status;
9590 const char *printer;
9591 struct dcerpc_binding_handle *b;
9593 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9595 if (!Printer) {
9596 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9597 OUR_HANDLE(r->in.handle)));
9598 return WERR_BADFID;
9601 /* if keyname == NULL, return error */
9602 if ( !r->in.key_name )
9603 return WERR_INVALID_PARAM;
9605 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9606 return WERR_BADFID;
9609 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9610 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9611 "printer properties change denied by handle\n"));
9612 return WERR_ACCESS_DENIED;
9615 printer = lp_const_servicename(snum);
9617 status = winreg_printer_binding_handle(p->mem_ctx,
9618 get_session_info_system(),
9619 p->msg_ctx,
9620 &b);
9621 if (!W_ERROR_IS_OK(status)) {
9622 return status;
9625 /* delete the key and all subkeys */
9626 status = winreg_delete_printer_key(p->mem_ctx, b,
9627 printer,
9628 r->in.key_name);
9629 if (W_ERROR_IS_OK(status)) {
9630 status = winreg_printer_update_changeid(p->mem_ctx, b,
9631 printer);
9634 return status;
9637 /****************************************************************
9638 _spoolss_EnumPrinterDataEx
9639 ****************************************************************/
9641 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9642 struct spoolss_EnumPrinterDataEx *r)
9644 uint32_t count = 0;
9645 struct spoolss_PrinterEnumValues *info = NULL;
9646 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9647 int snum;
9648 WERROR result;
9650 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9652 *r->out.count = 0;
9653 *r->out.needed = 0;
9654 *r->out.info = NULL;
9656 if (!Printer) {
9657 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9658 OUR_HANDLE(r->in.handle)));
9659 return WERR_BADFID;
9663 * first check for a keyname of NULL or "". Win2k seems to send
9664 * this a lot and we should send back WERR_INVALID_PARAM
9665 * no need to spend time looking up the printer in this case.
9666 * --jerry
9669 if (!strlen(r->in.key_name)) {
9670 result = WERR_INVALID_PARAM;
9671 goto done;
9674 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9675 return WERR_BADFID;
9678 /* now look for a match on the key name */
9679 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9680 get_session_info_system(),
9681 p->msg_ctx,
9682 lp_const_servicename(snum),
9683 r->in.key_name,
9684 &count,
9685 &info);
9686 if (!W_ERROR_IS_OK(result)) {
9687 goto done;
9690 #if 0 /* FIXME - gd */
9691 /* housekeeping information in the reply */
9693 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9694 * the hand marshalled container size is a multiple
9695 * of 4 bytes for RPC alignment.
9698 if (needed % 4) {
9699 needed += 4-(needed % 4);
9701 #endif
9702 *r->out.count = count;
9703 *r->out.info = info;
9705 done:
9706 if (!W_ERROR_IS_OK(result)) {
9707 return result;
9710 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9711 spoolss_EnumPrinterDataEx,
9712 *r->out.info,
9713 *r->out.count);
9714 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9715 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9717 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9720 /****************************************************************************
9721 ****************************************************************************/
9723 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9724 const char *servername,
9725 const char *environment,
9726 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9728 WERROR werr;
9729 char *path = NULL;
9731 werr = compose_spoolss_server_path(mem_ctx,
9732 servername,
9733 environment,
9734 SPOOLSS_PRTPROCS_PATH,
9735 &path);
9736 if (!W_ERROR_IS_OK(werr)) {
9737 return werr;
9740 DEBUG(4,("print processor directory: [%s]\n", path));
9742 r->directory_name = path;
9744 return WERR_OK;
9747 /****************************************************************
9748 _spoolss_GetPrintProcessorDirectory
9749 ****************************************************************/
9751 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9752 struct spoolss_GetPrintProcessorDirectory *r)
9754 WERROR result;
9755 char *prnproc_share = NULL;
9756 bool prnproc_share_exists = false;
9757 int snum;
9759 /* that's an [in out] buffer */
9761 if (!r->in.buffer && (r->in.offered != 0)) {
9762 return WERR_INVALID_PARAM;
9765 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9766 r->in.level));
9768 *r->out.needed = 0;
9770 /* r->in.level is ignored */
9772 /* We always should reply with a local print processor directory so that
9773 * users are not forced to have a [prnproc$] share on the Samba spoolss
9774 * server, if users decide to do so, lets announce it though - Guenther */
9776 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9777 if (!prnproc_share) {
9778 return WERR_NOMEM;
9780 if (snum != -1) {
9781 prnproc_share_exists = true;
9784 result = getprintprocessordirectory_level_1(p->mem_ctx,
9785 prnproc_share_exists ? r->in.server : NULL,
9786 r->in.environment,
9787 &r->out.info->info1);
9788 if (!W_ERROR_IS_OK(result)) {
9789 TALLOC_FREE(r->out.info);
9790 return result;
9793 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9794 r->out.info, r->in.level);
9795 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9797 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9800 /*******************************************************************
9801 ********************************************************************/
9803 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9804 const char *dllname)
9806 enum ndr_err_code ndr_err;
9807 struct spoolss_MonitorUi ui;
9809 ui.dll_name = dllname;
9811 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9812 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9813 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9814 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9816 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9819 /*******************************************************************
9820 Streams the monitor UI DLL name in UNICODE
9821 *******************************************************************/
9823 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9824 struct security_token *token, DATA_BLOB *in,
9825 DATA_BLOB *out, uint32_t *needed)
9827 const char *dllname = "tcpmonui.dll";
9829 *needed = (strlen(dllname)+1) * 2;
9831 if (out->length < *needed) {
9832 return WERR_INSUFFICIENT_BUFFER;
9835 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9836 return WERR_NOMEM;
9839 return WERR_OK;
9842 /*******************************************************************
9843 ********************************************************************/
9845 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9846 struct spoolss_PortData1 *port1,
9847 const DATA_BLOB *buf)
9849 enum ndr_err_code ndr_err;
9850 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9851 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9852 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9853 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9855 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9858 /*******************************************************************
9859 ********************************************************************/
9861 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9862 struct spoolss_PortData2 *port2,
9863 const DATA_BLOB *buf)
9865 enum ndr_err_code ndr_err;
9866 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9867 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9868 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9869 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9871 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9874 /*******************************************************************
9875 Create a new TCP/IP port
9876 *******************************************************************/
9878 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9879 struct security_token *token, DATA_BLOB *in,
9880 DATA_BLOB *out, uint32_t *needed)
9882 struct spoolss_PortData1 port1;
9883 struct spoolss_PortData2 port2;
9884 char *device_uri = NULL;
9885 uint32_t version;
9887 const char *portname;
9888 const char *hostaddress;
9889 const char *queue;
9890 uint32_t port_number;
9891 uint32_t protocol;
9893 /* peek for spoolss_PortData version */
9895 if (!in || (in->length < (128 + 4))) {
9896 return WERR_GENERAL_FAILURE;
9899 version = IVAL(in->data, 128);
9901 switch (version) {
9902 case 1:
9903 ZERO_STRUCT(port1);
9905 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9906 return WERR_NOMEM;
9909 portname = port1.portname;
9910 hostaddress = port1.hostaddress;
9911 queue = port1.queue;
9912 protocol = port1.protocol;
9913 port_number = port1.port_number;
9915 break;
9916 case 2:
9917 ZERO_STRUCT(port2);
9919 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9920 return WERR_NOMEM;
9923 portname = port2.portname;
9924 hostaddress = port2.hostaddress;
9925 queue = port2.queue;
9926 protocol = port2.protocol;
9927 port_number = port2.port_number;
9929 break;
9930 default:
9931 DEBUG(1,("xcvtcp_addport: "
9932 "unknown version of port_data: %d\n", version));
9933 return WERR_UNKNOWN_PORT;
9936 /* create the device URI and call the add_port_hook() */
9938 switch (protocol) {
9939 case PROTOCOL_RAWTCP_TYPE:
9940 device_uri = talloc_asprintf(mem_ctx,
9941 "socket://%s:%d/", hostaddress,
9942 port_number);
9943 break;
9945 case PROTOCOL_LPR_TYPE:
9946 device_uri = talloc_asprintf(mem_ctx,
9947 "lpr://%s/%s", hostaddress, queue );
9948 break;
9950 default:
9951 return WERR_UNKNOWN_PORT;
9954 if (!device_uri) {
9955 return WERR_NOMEM;
9958 return add_port_hook(mem_ctx, token, portname, device_uri);
9961 /*******************************************************************
9962 *******************************************************************/
9964 struct xcv_api_table xcvtcp_cmds[] = {
9965 { "MonitorUI", xcvtcp_monitorui },
9966 { "AddPort", xcvtcp_addport},
9967 { NULL, NULL }
9970 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9971 struct security_token *token, const char *command,
9972 DATA_BLOB *inbuf,
9973 DATA_BLOB *outbuf,
9974 uint32_t *needed )
9976 int i;
9978 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9980 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9981 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9982 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9985 return WERR_BADFUNC;
9988 /*******************************************************************
9989 *******************************************************************/
9990 #if 0 /* don't support management using the "Local Port" monitor */
9992 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9993 struct security_token *token, DATA_BLOB *in,
9994 DATA_BLOB *out, uint32_t *needed)
9996 const char *dllname = "localui.dll";
9998 *needed = (strlen(dllname)+1) * 2;
10000 if (out->length < *needed) {
10001 return WERR_INSUFFICIENT_BUFFER;
10004 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10005 return WERR_NOMEM;
10008 return WERR_OK;
10011 /*******************************************************************
10012 *******************************************************************/
10014 struct xcv_api_table xcvlocal_cmds[] = {
10015 { "MonitorUI", xcvlocal_monitorui },
10016 { NULL, NULL }
10018 #else
10019 struct xcv_api_table xcvlocal_cmds[] = {
10020 { NULL, NULL }
10022 #endif
10026 /*******************************************************************
10027 *******************************************************************/
10029 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10030 struct security_token *token, const char *command,
10031 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10032 uint32_t *needed)
10034 int i;
10036 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10038 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10039 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10040 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10042 return WERR_BADFUNC;
10045 /****************************************************************
10046 _spoolss_XcvData
10047 ****************************************************************/
10049 WERROR _spoolss_XcvData(struct pipes_struct *p,
10050 struct spoolss_XcvData *r)
10052 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10053 DATA_BLOB out_data = data_blob_null;
10054 WERROR werror;
10056 if (!Printer) {
10057 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10058 OUR_HANDLE(r->in.handle)));
10059 return WERR_BADFID;
10062 /* Has to be a handle to the TCP/IP port monitor */
10064 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10065 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10066 return WERR_BADFID;
10069 /* requires administrative access to the server */
10071 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10072 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10073 return WERR_ACCESS_DENIED;
10076 /* Allocate the outgoing buffer */
10078 if (r->in.out_data_size) {
10079 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10080 if (out_data.data == NULL) {
10081 return WERR_NOMEM;
10085 switch ( Printer->printer_type ) {
10086 case SPLHND_PORTMON_TCP:
10087 werror = process_xcvtcp_command(p->mem_ctx,
10088 p->session_info->security_token,
10089 r->in.function_name,
10090 &r->in.in_data, &out_data,
10091 r->out.needed);
10092 break;
10093 case SPLHND_PORTMON_LOCAL:
10094 werror = process_xcvlocal_command(p->mem_ctx,
10095 p->session_info->security_token,
10096 r->in.function_name,
10097 &r->in.in_data, &out_data,
10098 r->out.needed);
10099 break;
10100 default:
10101 werror = WERR_INVALID_PRINT_MONITOR;
10104 if (!W_ERROR_IS_OK(werror)) {
10105 return werror;
10108 *r->out.status_code = 0;
10110 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10111 memcpy(r->out.out_data, out_data.data,
10112 MIN(r->in.out_data_size, out_data.length));
10115 return WERR_OK;
10118 /****************************************************************
10119 _spoolss_AddPrintProcessor
10120 ****************************************************************/
10122 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10123 struct spoolss_AddPrintProcessor *r)
10125 /* for now, just indicate success and ignore the add. We'll
10126 automatically set the winprint processor for printer
10127 entries later. Used to debug the LexMark Optra S 1855 PCL
10128 driver --jerry */
10130 return WERR_OK;
10133 /****************************************************************
10134 _spoolss_AddPort
10135 ****************************************************************/
10137 WERROR _spoolss_AddPort(struct pipes_struct *p,
10138 struct spoolss_AddPort *r)
10140 /* do what w2k3 does */
10142 return WERR_NOT_SUPPORTED;
10145 /****************************************************************
10146 _spoolss_GetPrinterDriver
10147 ****************************************************************/
10149 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10150 struct spoolss_GetPrinterDriver *r)
10152 p->rng_fault_state = true;
10153 return WERR_NOT_SUPPORTED;
10156 /****************************************************************
10157 _spoolss_ReadPrinter
10158 ****************************************************************/
10160 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10161 struct spoolss_ReadPrinter *r)
10163 p->rng_fault_state = true;
10164 return WERR_NOT_SUPPORTED;
10167 /****************************************************************
10168 _spoolss_WaitForPrinterChange
10169 ****************************************************************/
10171 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10172 struct spoolss_WaitForPrinterChange *r)
10174 p->rng_fault_state = true;
10175 return WERR_NOT_SUPPORTED;
10178 /****************************************************************
10179 _spoolss_ConfigurePort
10180 ****************************************************************/
10182 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10183 struct spoolss_ConfigurePort *r)
10185 p->rng_fault_state = true;
10186 return WERR_NOT_SUPPORTED;
10189 /****************************************************************
10190 _spoolss_DeletePort
10191 ****************************************************************/
10193 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10194 struct spoolss_DeletePort *r)
10196 p->rng_fault_state = true;
10197 return WERR_NOT_SUPPORTED;
10200 /****************************************************************
10201 _spoolss_CreatePrinterIC
10202 ****************************************************************/
10204 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10205 struct spoolss_CreatePrinterIC *r)
10207 p->rng_fault_state = true;
10208 return WERR_NOT_SUPPORTED;
10211 /****************************************************************
10212 _spoolss_PlayGDIScriptOnPrinterIC
10213 ****************************************************************/
10215 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10216 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10218 p->rng_fault_state = true;
10219 return WERR_NOT_SUPPORTED;
10222 /****************************************************************
10223 _spoolss_DeletePrinterIC
10224 ****************************************************************/
10226 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10227 struct spoolss_DeletePrinterIC *r)
10229 p->rng_fault_state = true;
10230 return WERR_NOT_SUPPORTED;
10233 /****************************************************************
10234 _spoolss_AddPrinterConnection
10235 ****************************************************************/
10237 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10238 struct spoolss_AddPrinterConnection *r)
10240 p->rng_fault_state = true;
10241 return WERR_NOT_SUPPORTED;
10244 /****************************************************************
10245 _spoolss_DeletePrinterConnection
10246 ****************************************************************/
10248 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10249 struct spoolss_DeletePrinterConnection *r)
10251 p->rng_fault_state = true;
10252 return WERR_NOT_SUPPORTED;
10255 /****************************************************************
10256 _spoolss_PrinterMessageBox
10257 ****************************************************************/
10259 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10260 struct spoolss_PrinterMessageBox *r)
10262 p->rng_fault_state = true;
10263 return WERR_NOT_SUPPORTED;
10266 /****************************************************************
10267 _spoolss_AddMonitor
10268 ****************************************************************/
10270 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10271 struct spoolss_AddMonitor *r)
10273 p->rng_fault_state = true;
10274 return WERR_NOT_SUPPORTED;
10277 /****************************************************************
10278 _spoolss_DeleteMonitor
10279 ****************************************************************/
10281 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10282 struct spoolss_DeleteMonitor *r)
10284 p->rng_fault_state = true;
10285 return WERR_NOT_SUPPORTED;
10288 /****************************************************************
10289 _spoolss_DeletePrintProcessor
10290 ****************************************************************/
10292 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10293 struct spoolss_DeletePrintProcessor *r)
10295 p->rng_fault_state = true;
10296 return WERR_NOT_SUPPORTED;
10299 /****************************************************************
10300 _spoolss_AddPrintProvidor
10301 ****************************************************************/
10303 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10304 struct spoolss_AddPrintProvidor *r)
10306 p->rng_fault_state = true;
10307 return WERR_NOT_SUPPORTED;
10310 /****************************************************************
10311 _spoolss_DeletePrintProvidor
10312 ****************************************************************/
10314 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10315 struct spoolss_DeletePrintProvidor *r)
10317 p->rng_fault_state = true;
10318 return WERR_NOT_SUPPORTED;
10321 /****************************************************************
10322 _spoolss_FindFirstPrinterChangeNotification
10323 ****************************************************************/
10325 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10326 struct spoolss_FindFirstPrinterChangeNotification *r)
10328 p->rng_fault_state = true;
10329 return WERR_NOT_SUPPORTED;
10332 /****************************************************************
10333 _spoolss_FindNextPrinterChangeNotification
10334 ****************************************************************/
10336 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10337 struct spoolss_FindNextPrinterChangeNotification *r)
10339 p->rng_fault_state = true;
10340 return WERR_NOT_SUPPORTED;
10343 /****************************************************************
10344 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10345 ****************************************************************/
10347 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10348 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10350 p->rng_fault_state = true;
10351 return WERR_NOT_SUPPORTED;
10354 /****************************************************************
10355 _spoolss_ReplyOpenPrinter
10356 ****************************************************************/
10358 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10359 struct spoolss_ReplyOpenPrinter *r)
10361 p->rng_fault_state = true;
10362 return WERR_NOT_SUPPORTED;
10365 /****************************************************************
10366 _spoolss_RouterReplyPrinter
10367 ****************************************************************/
10369 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10370 struct spoolss_RouterReplyPrinter *r)
10372 p->rng_fault_state = true;
10373 return WERR_NOT_SUPPORTED;
10376 /****************************************************************
10377 _spoolss_ReplyClosePrinter
10378 ****************************************************************/
10380 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10381 struct spoolss_ReplyClosePrinter *r)
10383 p->rng_fault_state = true;
10384 return WERR_NOT_SUPPORTED;
10387 /****************************************************************
10388 _spoolss_AddPortEx
10389 ****************************************************************/
10391 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10392 struct spoolss_AddPortEx *r)
10394 p->rng_fault_state = true;
10395 return WERR_NOT_SUPPORTED;
10398 /****************************************************************
10399 _spoolss_RouterFindFirstPrinterChangeNotification
10400 ****************************************************************/
10402 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10403 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10405 p->rng_fault_state = true;
10406 return WERR_NOT_SUPPORTED;
10409 /****************************************************************
10410 _spoolss_SpoolerInit
10411 ****************************************************************/
10413 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10414 struct spoolss_SpoolerInit *r)
10416 p->rng_fault_state = true;
10417 return WERR_NOT_SUPPORTED;
10420 /****************************************************************
10421 _spoolss_ResetPrinterEx
10422 ****************************************************************/
10424 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10425 struct spoolss_ResetPrinterEx *r)
10427 p->rng_fault_state = true;
10428 return WERR_NOT_SUPPORTED;
10431 /****************************************************************
10432 _spoolss_RouterReplyPrinterEx
10433 ****************************************************************/
10435 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10436 struct spoolss_RouterReplyPrinterEx *r)
10438 p->rng_fault_state = true;
10439 return WERR_NOT_SUPPORTED;
10442 /****************************************************************
10443 _spoolss_44
10444 ****************************************************************/
10446 WERROR _spoolss_44(struct pipes_struct *p,
10447 struct spoolss_44 *r)
10449 p->rng_fault_state = true;
10450 return WERR_NOT_SUPPORTED;
10453 /****************************************************************
10454 _spoolss_SetPort
10455 ****************************************************************/
10457 WERROR _spoolss_SetPort(struct pipes_struct *p,
10458 struct spoolss_SetPort *r)
10460 p->rng_fault_state = true;
10461 return WERR_NOT_SUPPORTED;
10464 /****************************************************************
10465 _spoolss_4a
10466 ****************************************************************/
10468 WERROR _spoolss_4a(struct pipes_struct *p,
10469 struct spoolss_4a *r)
10471 p->rng_fault_state = true;
10472 return WERR_NOT_SUPPORTED;
10475 /****************************************************************
10476 _spoolss_4b
10477 ****************************************************************/
10479 WERROR _spoolss_4b(struct pipes_struct *p,
10480 struct spoolss_4b *r)
10482 p->rng_fault_state = true;
10483 return WERR_NOT_SUPPORTED;
10486 /****************************************************************
10487 _spoolss_4c
10488 ****************************************************************/
10490 WERROR _spoolss_4c(struct pipes_struct *p,
10491 struct spoolss_4c *r)
10493 p->rng_fault_state = true;
10494 return WERR_NOT_SUPPORTED;
10497 /****************************************************************
10498 _spoolss_53
10499 ****************************************************************/
10501 WERROR _spoolss_53(struct pipes_struct *p,
10502 struct spoolss_53 *r)
10504 p->rng_fault_state = true;
10505 return WERR_NOT_SUPPORTED;
10508 /****************************************************************
10509 _spoolss_AddPerMachineConnection
10510 ****************************************************************/
10512 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10513 struct spoolss_AddPerMachineConnection *r)
10515 p->rng_fault_state = true;
10516 return WERR_NOT_SUPPORTED;
10519 /****************************************************************
10520 _spoolss_DeletePerMachineConnection
10521 ****************************************************************/
10523 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10524 struct spoolss_DeletePerMachineConnection *r)
10526 p->rng_fault_state = true;
10527 return WERR_NOT_SUPPORTED;
10530 /****************************************************************
10531 _spoolss_EnumPerMachineConnections
10532 ****************************************************************/
10534 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10535 struct spoolss_EnumPerMachineConnections *r)
10537 p->rng_fault_state = true;
10538 return WERR_NOT_SUPPORTED;
10541 /****************************************************************
10542 _spoolss_5a
10543 ****************************************************************/
10545 WERROR _spoolss_5a(struct pipes_struct *p,
10546 struct spoolss_5a *r)
10548 p->rng_fault_state = true;
10549 return WERR_NOT_SUPPORTED;
10552 /****************************************************************
10553 _spoolss_5b
10554 ****************************************************************/
10556 WERROR _spoolss_5b(struct pipes_struct *p,
10557 struct spoolss_5b *r)
10559 p->rng_fault_state = true;
10560 return WERR_NOT_SUPPORTED;
10563 /****************************************************************
10564 _spoolss_5c
10565 ****************************************************************/
10567 WERROR _spoolss_5c(struct pipes_struct *p,
10568 struct spoolss_5c *r)
10570 p->rng_fault_state = true;
10571 return WERR_NOT_SUPPORTED;
10574 /****************************************************************
10575 _spoolss_5d
10576 ****************************************************************/
10578 WERROR _spoolss_5d(struct pipes_struct *p,
10579 struct spoolss_5d *r)
10581 p->rng_fault_state = true;
10582 return WERR_NOT_SUPPORTED;
10585 /****************************************************************
10586 _spoolss_5e
10587 ****************************************************************/
10589 WERROR _spoolss_5e(struct pipes_struct *p,
10590 struct spoolss_5e *r)
10592 p->rng_fault_state = true;
10593 return WERR_NOT_SUPPORTED;
10596 /****************************************************************
10597 _spoolss_5f
10598 ****************************************************************/
10600 WERROR _spoolss_5f(struct pipes_struct *p,
10601 struct spoolss_5f *r)
10603 p->rng_fault_state = true;
10604 return WERR_NOT_SUPPORTED;
10607 /****************************************************************
10608 _spoolss_60
10609 ****************************************************************/
10611 WERROR _spoolss_60(struct pipes_struct *p,
10612 struct spoolss_60 *r)
10614 p->rng_fault_state = true;
10615 return WERR_NOT_SUPPORTED;
10618 /****************************************************************
10619 _spoolss_61
10620 ****************************************************************/
10622 WERROR _spoolss_61(struct pipes_struct *p,
10623 struct spoolss_61 *r)
10625 p->rng_fault_state = true;
10626 return WERR_NOT_SUPPORTED;
10629 /****************************************************************
10630 _spoolss_62
10631 ****************************************************************/
10633 WERROR _spoolss_62(struct pipes_struct *p,
10634 struct spoolss_62 *r)
10636 p->rng_fault_state = true;
10637 return WERR_NOT_SUPPORTED;
10640 /****************************************************************
10641 _spoolss_63
10642 ****************************************************************/
10644 WERROR _spoolss_63(struct pipes_struct *p,
10645 struct spoolss_63 *r)
10647 p->rng_fault_state = true;
10648 return WERR_NOT_SUPPORTED;
10651 /****************************************************************
10652 _spoolss_64
10653 ****************************************************************/
10655 WERROR _spoolss_64(struct pipes_struct *p,
10656 struct spoolss_64 *r)
10658 p->rng_fault_state = true;
10659 return WERR_NOT_SUPPORTED;
10662 /****************************************************************
10663 _spoolss_65
10664 ****************************************************************/
10666 WERROR _spoolss_65(struct pipes_struct *p,
10667 struct spoolss_65 *r)
10669 p->rng_fault_state = true;
10670 return WERR_NOT_SUPPORTED;
10673 /****************************************************************
10674 _spoolss_GetCorePrinterDrivers
10675 ****************************************************************/
10677 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10678 struct spoolss_GetCorePrinterDrivers *r)
10680 p->rng_fault_state = true;
10681 return WERR_NOT_SUPPORTED;
10684 /****************************************************************
10685 _spoolss_67
10686 ****************************************************************/
10688 WERROR _spoolss_67(struct pipes_struct *p,
10689 struct spoolss_67 *r)
10691 p->rng_fault_state = true;
10692 return WERR_NOT_SUPPORTED;
10695 /****************************************************************
10696 _spoolss_GetPrinterDriverPackagePath
10697 ****************************************************************/
10699 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10700 struct spoolss_GetPrinterDriverPackagePath *r)
10702 p->rng_fault_state = true;
10703 return WERR_NOT_SUPPORTED;
10706 /****************************************************************
10707 _spoolss_69
10708 ****************************************************************/
10710 WERROR _spoolss_69(struct pipes_struct *p,
10711 struct spoolss_69 *r)
10713 p->rng_fault_state = true;
10714 return WERR_NOT_SUPPORTED;
10717 /****************************************************************
10718 _spoolss_6a
10719 ****************************************************************/
10721 WERROR _spoolss_6a(struct pipes_struct *p,
10722 struct spoolss_6a *r)
10724 p->rng_fault_state = true;
10725 return WERR_NOT_SUPPORTED;
10728 /****************************************************************
10729 _spoolss_6b
10730 ****************************************************************/
10732 WERROR _spoolss_6b(struct pipes_struct *p,
10733 struct spoolss_6b *r)
10735 p->rng_fault_state = true;
10736 return WERR_NOT_SUPPORTED;
10739 /****************************************************************
10740 _spoolss_6c
10741 ****************************************************************/
10743 WERROR _spoolss_6c(struct pipes_struct *p,
10744 struct spoolss_6c *r)
10746 p->rng_fault_state = true;
10747 return WERR_NOT_SUPPORTED;
10750 /****************************************************************
10751 _spoolss_6d
10752 ****************************************************************/
10754 WERROR _spoolss_6d(struct pipes_struct *p,
10755 struct spoolss_6d *r)
10757 p->rng_fault_state = true;
10758 return WERR_NOT_SUPPORTED;